From b165183b4258696610598af83ffe0f168c9937f1 Mon Sep 17 00:00:00 2001 From: chiri Date: Sat, 11 Jul 2026 14:27:12 +0300 Subject: [PATCH 01/53] a bit optimize four-digit chunks in integer formatting --- library/core/src/fmt/num.rs | 72 +++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 050822da8f12a..7523bc64942d6 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -690,15 +690,11 @@ impl u128 { unsafe { core::hint::assert_unchecked(offset <= buf.len()) } offset -= 4; - // pull two pairs let quad = remain % 1_00_00; remain /= 1_00_00; - let pair1 = (quad / 100) as usize; - let pair2 = (quad % 100) as usize; - buf[offset + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]); - buf[offset + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]); - buf[offset + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]); - buf[offset + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]); + // SAFETY: quad is a remainder modulo 10_000. The offset checks + // above reserve exactly four bytes in buf. + unsafe { write_quad(buf, offset, quad) }; } // Format per two digits from the lookup table. @@ -814,32 +810,64 @@ impl i128 { } } +/// Writes `quad` as exactly four digits (for example: `42` becomes `"0042"`). +/// +/// # Safety +/// +/// `quad` must be below 10_000 and `buf[offset..offset + 4]` must be in bounds. +#[inline(always)] +unsafe fn write_quad(buf: &mut [MaybeUninit], offset: usize, quad: u64) { + // SAFETY: These are this function's caller-provided invariants. + unsafe { + core::hint::assert_unchecked(quad < 10_000); + core::hint::assert_unchecked(offset <= buf.len() - 4); + } + + // For the documented range, ceil(2^19 / 100) gives an exact quotiet. + const DIV100_SHIFT: u32 = 19; + const DIV100_RECIPROCAL: u32 = (1 << DIV100_SHIFT) / 100 + 1; + + let quad = quad as u32; + let high = (quad * DIV100_RECIPROCAL) >> DIV100_SHIFT; + let low = quad - high * 100; + let high = high as usize; + let low = low as usize; + + // SAFETY: `high` and `low` are below 100 because quad is below 10_000. The + // destination has four bytes by the precondition, and the two source pairs + // are disjoint from it because `DECIMAL_PAIRS` is static RO storage. + unsafe { + let pairs = DECIMAL_PAIRS.as_ptr(); + let dst = buf.as_mut_ptr().add(offset).cast::(); + core::ptr::copy_nonoverlapping(pairs.add(high * 2), dst, 2); + core::ptr::copy_nonoverlapping(pairs.add(low * 2), dst.add(2), 2); + } +} + /// Encodes the 16 least-significant decimals of n into `buf[OFFSET .. OFFSET + /// 16 ]`. fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { - // Consume the least-significant decimals from a working copy. + // Callers pass a remainder modulo 10^16 and reserve sixteen output bytes. + unsafe { + core::hint::assert_unchecked(n < 10_000_000_000_000_000); + core::hint::assert_unchecked(OFFSET <= buf.len() - 16); + } + + // Peel four digits at a time from right to left (12345678 -> 1234 | 5678). + // Since 10_000 is constant, LLVM replaces each division with multiply or shift. let mut remain = n; - // Format per four digits from the lookup table. for quad_index in (1..4).rev() { // pull two pairs let quad = remain % 1_00_00; remain /= 1_00_00; - let pair1 = (quad / 100) as usize; - let pair2 = (quad % 100) as usize; - buf[quad_index * 4 + OFFSET + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]); - buf[quad_index * 4 + OFFSET + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]); - buf[quad_index * 4 + OFFSET + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]); - buf[quad_index * 4 + OFFSET + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]); + // SAFETY: modulo bounds quad; OFFSET and quad_index select one of the + // four non-overlapping four-byte regions proven in bounds above. + unsafe { write_quad(buf, quad_index * 4 + OFFSET, quad) }; } - // final two pairs - let pair1 = (remain / 100) as usize; - let pair2 = (remain % 100) as usize; - buf[OFFSET + 0].write(DECIMAL_PAIRS[pair1 * 2 + 0]); - buf[OFFSET + 1].write(DECIMAL_PAIRS[pair1 * 2 + 1]); - buf[OFFSET + 2].write(DECIMAL_PAIRS[pair2 * 2 + 0]); - buf[OFFSET + 3].write(DECIMAL_PAIRS[pair2 * 2 + 1]); + // SAFETY: OFFSET starts the first four-byte region proven in bounds above. + unsafe { write_quad(buf, OFFSET, remain) }; } /// Euclidean division plus remainder with constant 1E16 basically consumes 16 From 25435a0fb5db893e578c9132574661a1c40eb9d4 Mon Sep 17 00:00:00 2001 From: chiri Date: Sat, 11 Jul 2026 14:55:42 +0300 Subject: [PATCH 02/53] add SAFETY --- library/core/src/fmt/num.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 7523bc64942d6..53c3e2c60d4d2 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -847,7 +847,8 @@ unsafe fn write_quad(buf: &mut [MaybeUninit], offset: usize, quad: u64) { /// Encodes the 16 least-significant decimals of n into `buf[OFFSET .. OFFSET + /// 16 ]`. fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { - // Callers pass a remainder modulo 10^16 and reserve sixteen output bytes. + // SAFETY: Every caller passes a remainder produced by division by 10^16, + // and every used `OFFSET` specialization reserves sixteen bytes in `buf`. unsafe { core::hint::assert_unchecked(n < 10_000_000_000_000_000); core::hint::assert_unchecked(OFFSET <= buf.len() - 16); From 19c60651fe11f17087a0fd659142d1e65ba0912e Mon Sep 17 00:00:00 2001 From: SomeFlyingThing <306498559+SomeFlyingThing@users.noreply.github.com> Date: Sat, 18 Jul 2026 20:23:30 +0100 Subject: [PATCH 03/53] Optimize slice::contains for bytewise types --- library/core/src/slice/cmp.rs | 10 ++++-- library/coretests/tests/slice.rs | 33 +++++++++++++++++ .../lib-optimizations/slice-contains.rs | 36 +++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/codegen-llvm/lib-optimizations/slice-contains.rs diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 10a0088477162..3a62e7f61b2b4 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -391,10 +391,16 @@ where } } -impl SliceContains for u8 { +impl SliceContains for T { #[inline] fn slice_contains(&self, x: &[Self]) -> bool { - memchr::memchr(*self, x).is_some() + // SAFETY: `UnsignedBytewiseOrd` guarantees that `Self` has the same + // layout as `u8` and is initialized, so both the value and slice can + // be read as bytes. + let (byte, bytes) = unsafe { + (*(self as *const Self).cast::(), from_raw_parts(x.as_ptr().cast::(), x.len())) + }; + memchr::memchr(byte, bytes).is_some() } } diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs index a4db7304fff90..22b1ba7738af9 100644 --- a/library/coretests/tests/slice.rs +++ b/library/coretests/tests/slice.rs @@ -5,6 +5,39 @@ use core::num::NonZero; use core::ops::{Range, RangeInclusive}; use core::slice; +#[test] +fn test_contains_bytewise_types() { + let mut bools = [false; 64]; + assert!(bools.contains(&false)); + assert!(!bools.contains(&true)); + bools[31] = true; + assert!(bools.contains(&true)); + + let one = NonZero::new(1_u8).unwrap(); + let two = NonZero::new(2_u8).unwrap(); + let three = NonZero::new(3_u8).unwrap(); + let mut nonzeros = [one; 64]; + nonzeros[31] = two; + assert!(nonzeros.contains(&one)); + assert!(nonzeros.contains(&two)); + assert!(!nonzeros.contains(&three)); + + let mut optional_nonzeros = [Some(one); 64]; + optional_nonzeros[31] = None; + assert!(optional_nonzeros.contains(&Some(one))); + assert!(optional_nonzeros.contains(&None)); + assert!(!optional_nonzeros.contains(&Some(two))); + + let a = core::ascii::Char::CapitalA; + let q = core::ascii::Char::CapitalQ; + let z = core::ascii::Char::CapitalZ; + let mut ascii = [a; 64]; + ascii[31] = z; + assert!(ascii.contains(&a)); + assert!(ascii.contains(&z)); + assert!(!ascii.contains(&q)); +} + #[test] fn test_position() { let b = [1, 2, 3, 5, 5]; diff --git a/tests/codegen-llvm/lib-optimizations/slice-contains.rs b/tests/codegen-llvm/lib-optimizations/slice-contains.rs new file mode 100644 index 0000000000000..ecca007875148 --- /dev/null +++ b/tests/codegen-llvm/lib-optimizations/slice-contains.rs @@ -0,0 +1,36 @@ +// Ensure one-byte slice `contains` specializations use the optimized byte search. +//@ compile-flags: -Copt-level=3 -Zinline-mir=false + +#![crate_type = "lib"] +#![feature(ascii_char)] + +use std::ascii::Char as AsciiChar; +use std::num::NonZeroU8; + +// CHECK-LABEL: @contains_bool +#[no_mangle] +pub fn contains_bool(x: bool, data: &[bool]) -> bool { + // CHECK: call core::slice::memchr + data.contains(&x) +} + +// CHECK-LABEL: @contains_nonzero_u8 +#[no_mangle] +pub fn contains_nonzero_u8(x: NonZeroU8, data: &[NonZeroU8]) -> bool { + // CHECK: call core::slice::memchr + data.contains(&x) +} + +// CHECK-LABEL: @contains_option_nonzero_u8 +#[no_mangle] +pub fn contains_option_nonzero_u8(x: Option, data: &[Option]) -> bool { + // CHECK: call core::slice::memchr + data.contains(&x) +} + +// CHECK-LABEL: @contains_ascii_char +#[no_mangle] +pub fn contains_ascii_char(x: AsciiChar, data: &[AsciiChar]) -> bool { + // CHECK: call core::slice::memchr + data.contains(&x) +} From 40d419f33247bfcd91ebab2b1ba8089786bcc031 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Fri, 17 Jul 2026 10:48:59 +0800 Subject: [PATCH 04/53] ci: loongarch64-linux: Bump binutils to 2.46.1 and gcc to 16.1 --- src/ci/docker/README.md | 8 ++--- .../dist-loongarch64-linux/Dockerfile | 4 +-- .../loongarch64-unknown-linux-gnu.defconfig | 4 +-- .../dist-loongarch64-musl/Dockerfile | 4 +-- .../loongarch64-unknown-linux-musl.defconfig | 4 +-- src/ci/docker/scripts/crosstool-ng-git.sh | 30 +++++++++++++++++++ 6 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 src/ci/docker/scripts/crosstool-ng-git.sh diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 6e5a38a3c515a..f8c5b3dac16f8 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -261,9 +261,9 @@ For targets: `loongarch64-unknown-linux-gnu` - Target options > Bitness = 64-bit - Operating System > Target OS = linux - Operating System > Linux kernel version = 5.19.16 -- Binary utilities > Version of binutils = 2.45 +- Binary utilities > Version of binutils = 2.46.1 - C-library > glibc version = 2.36 -- C compiler > gcc version = 15.2.0 +- C compiler > gcc version = 16.1.0 - C compiler > C++ = ENABLE -- to cross compile LLVM ### `loongarch64-unknown-linux-musl.defconfig` @@ -277,9 +277,9 @@ For targets: `loongarch64-unknown-linux-musl` - Target options > Bitness = 64-bit - Operating System > Target OS = linux - Operating System > Linux kernel version = 5.19.16 -- Binary utilities > Version of binutils = 2.45 +- Binary utilities > Version of binutils = 2.46.1 - C-library > musl version = 1.2.5 -- C compiler > gcc version = 15.2.0 +- C compiler > gcc version = 16.1.0 - C compiler > C++ = ENABLE -- to cross compile LLVM ### `mips-linux-gnu.defconfig` 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 c4f8351bd9466..218b711f66fc0 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -3,9 +3,9 @@ FROM ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/crosstool-ng.sh /scripts/ +COPY scripts/crosstool-ng-git.sh /scripts/ COPY scripts/crosstool-ng-sha256-20260705.diff /scripts/ -RUN sh /scripts/crosstool-ng.sh +RUN sh /scripts/crosstool-ng-git.sh COPY scripts/rustbuild-setup.sh /scripts/ RUN sh /scripts/rustbuild-setup.sh diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig index 60c9cc7ef7252..5b3f1a270edfa 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig @@ -14,7 +14,7 @@ CT_KERNEL_LINUX=y CT_LINUX_V_5_19=y CT_LINUX_VERSION="5.19.16" CT_GLIBC_V_2_36=y -CT_BINUTILS_V_2_45=y -CT_GCC_V_15=y +CT_BINUTILS_V_2_46=y +CT_GCC_V_16=y CT_CC_GCC_ENABLE_DEFAULT_PIE=y CT_CC_LANG_CXX=y 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 61b28e4189a4a..2ff6da0d3814b 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile @@ -3,9 +3,9 @@ FROM ubuntu:22.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/crosstool-ng.sh /scripts/ +COPY scripts/crosstool-ng-git.sh /scripts/ COPY scripts/crosstool-ng-sha256-20260705.diff /scripts/ -RUN sh /scripts/crosstool-ng.sh +RUN sh /scripts/crosstool-ng-git.sh COPY scripts/rustbuild-setup.sh /scripts/ RUN sh /scripts/rustbuild-setup.sh diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig index 73e29d7aca725..07fed33600f29 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig +++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig @@ -15,8 +15,8 @@ CT_LINUX_V_5_19=y CT_LINUX_VERSION="5.19.16" CT_LIBC_MUSL=y CT_MUSL_V_1_2_5=y -CT_BINUTILS_V_2_45=y -CT_GCC_V_15=y +CT_BINUTILS_V_2_46=y +CT_GCC_V_16=y CT_CC_GCC_ENABLE_DEFAULT_PIE=y CT_CC_LANG_CXX=y CT_GETTEXT_NEEDED=y diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh new file mode 100644 index 0000000000000..faccd7dc9bbf5 --- /dev/null +++ b/src/ci/docker/scripts/crosstool-ng-git.sh @@ -0,0 +1,30 @@ +#!/bin/sh +set -ex + +# ignore-tidy-file-linelength + +URL=https://github.com/crosstool-ng/crosstool-ng +REV=27cd8380e72bb1cf3e7cf4a06a9cdbdc57df6f72 + +mkdir crosstool-ng +cd crosstool-ng +git init +git fetch --depth=1 ${URL} ${REV} +git reset --hard FETCH_HEAD + +# https://github.com/crosstool-ng/crosstool-ng/issues/1832 +# "download source of zlib is invalid now" +sed -e "s|zlib.net/'|zlib.net/fossils'|" -i packages/zlib/package.desc + +# FIXME(#158718): patch crosstools-ng known-good kernel artifact SHA256 +# checksums to the artifacts we mirror in `ci-mirrors`. +# See +# . +patch -p1 Date: Mon, 20 Jul 2026 16:50:37 +0800 Subject: [PATCH 05/53] Promote loongarch32-unknown-none* to Tier 2 MCP: https://github.com/rust-lang/compiler-team/issues/968 --- .../src/spec/targets/loongarch32_unknown_none.rs | 2 +- .../targets/loongarch32_unknown_none_softfloat.rs | 2 +- .../host-x86_64/dist-loongarch64-linux/Dockerfile | 14 +++++++++++++- src/doc/rustc/src/platform-support.md | 4 ++-- .../rustc/src/platform-support/loongarch-none.md | 4 ++-- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none.rs index 7e074b73919f3..cbf8cec1e6865 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none.rs @@ -8,7 +8,7 @@ pub(crate) fn target() -> Target { llvm_target: "loongarch32-unknown-none".into(), metadata: TargetMetadata { description: Some("Freestanding/bare-metal LoongArch32".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none_softfloat.rs index 4e6807012e891..3fd12e50d0ae3 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch32_unknown_none_softfloat.rs @@ -8,7 +8,7 @@ pub(crate) fn target() -> Target { llvm_target: "loongarch32-unknown-none".into(), metadata: TargetMetadata { description: Some("Freestanding/bare-metal LoongArch32 softfloat".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(false), }, 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 218b711f66fc0..17206c911aabc 100644 --- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile @@ -39,12 +39,24 @@ ENV CC_loongarch64_unknown_none=loongarch64-unknown-linux-gnu-gcc \ AR_loongarch64_unknown_none_softfloat=loongarch64-unknown-linux-gnu-ar \ CXX_loongarch64_unknown_none_softfloat=loongarch64-unknown-linux-gnu-g++ \ CFLAGS_loongarch64_unknown_none_softfloat="-ffreestanding -mabi=lp64s -mfpu=none" \ - CXXFLAGS_loongarch64_unknown_none_softfloat="-ffreestanding -mabi=lp64s -mfpu=none" + CXXFLAGS_loongarch64_unknown_none_softfloat="-ffreestanding -mabi=lp64s -mfpu=none" \ + CC_loongarch32_unknown_none=loongarch64-unknown-linux-gnu-gcc \ + AR_loongarch32_unknown_none=loongarch64-unknown-linux-gnu-ar \ + CXX_loongarch32_unknown_none=loongarch64-unknown-linux-gnu-g++ \ + CFLAGS_loongarch32_unknown_none="-ffreestanding -march=la32rv1.0 -mabi=ilp32d" \ + CXXFLAGS_loongarch32_unknown_none="-ffreestanding -march=la32rv1.0 -mabi=ilp32d" \ + CC_loongarch32_unknown_none_softfloat=loongarch64-unknown-linux-gnu-gcc \ + AR_loongarch32_unknown_none_softfloat=loongarch64-unknown-linux-gnu-ar \ + CXX_loongarch32_unknown_none_softfloat=loongarch64-unknown-linux-gnu-g++ \ + CFLAGS_loongarch32_unknown_none_softfloat="-ffreestanding -march=la32rv1.0 -mabi=ilp32s -mfpu=none" \ + CXXFLAGS_loongarch32_unknown_none_softfloat="-ffreestanding -march=la32rv1.0 -mabi=ilp32s -mfpu=none" ENV HOSTS=loongarch64-unknown-linux-gnu ENV TARGETS=$HOSTS ENV TARGETS=$TARGETS,loongarch64-unknown-none ENV TARGETS=$TARGETS,loongarch64-unknown-none-softfloat +ENV TARGETS=$TARGETS,loongarch32-unknown-none +ENV TARGETS=$TARGETS,loongarch32-unknown-none-softfloat ENV RUST_CONFIGURE_ARGS="--enable-extended \ --enable-full-tools \ diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index ce4d55c2d2b00..f360637e216bf 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -187,6 +187,8 @@ target | std | notes [`i686-unknown-freebsd`](platform-support/freebsd.md) | ✓ | 32-bit x86 FreeBSD (Pentium 4) [^x86_32-floats-return-ABI] `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.5 (Pentium 4) [^x86_32-floats-return-ABI] [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | ? | 32-bit UEFI (Pentium 4, softfloat) [^win32-msvc-alignment] +[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32D ABI) +[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32S ABI) [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64D ABI) [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64S ABI) [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] @@ -352,8 +354,6 @@ target | std | host | notes [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI] [^win32-msvc-alignment] [`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [^x86_32-floats-return-ABI] [`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | LoongArch64 OpenHarmony -[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch32 Bare-metal (ILP32D ABI) -[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch32 Bare-metal (ILP32S ABI) [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux [`m68k-unknown-none-elf`](platform-support/m68k-unknown-none-elf.md) | | | Motorola 680x0 `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) [^snan-inverted] diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md index 7c3a7e6c8bc57..bf8db72e71646 100644 --- a/src/doc/rustc/src/platform-support/loongarch-none.md +++ b/src/doc/rustc/src/platform-support/loongarch-none.md @@ -4,8 +4,8 @@ Freestanding/bare-metal LoongArch binaries in ELF format: firmware, kernels, etc | Target | Description | Tier | |--------|-------------|------| -| `loongarch32-unknown-none` | LoongArch 32-bit, ILP32D ABI (freestanding, hard-float) | Tier 3 | -| `loongarch32-unknown-none-softfloat` | LoongArch 32-bit, ILP32S ABI (freestanding, soft-float) | Tier 3 | +| `loongarch32-unknown-none` | LoongArch 32-bit, ILP32D ABI (freestanding, hard-float) | Tier 2 | +| `loongarch32-unknown-none-softfloat` | LoongArch 32-bit, ILP32S ABI (freestanding, soft-float) | Tier 2 | | `loongarch64-unknown-none` | LoongArch 64-bit, LP64D ABI (freestanding, hard-float) | Tier 2 | | `loongarch64-unknown-none-softfloat` | LoongArch 64-bit, LP64S ABI (freestanding, soft-float) | Tier 2 | From ad3ce248b6afcc6d255e6ea08f67ddc0b7f76600 Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Sun, 26 Jul 2026 21:29:02 +0330 Subject: [PATCH 06/53] test: add regression test for bool indexing codegen Signed-off-by: Amirhossein Akhlaghpour --- ...ng-with-bools-no-redundant-instructions.rs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs diff --git a/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs b/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs new file mode 100644 index 0000000000000..628f4faab6d06 --- /dev/null +++ b/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs @@ -0,0 +1,35 @@ +//@ assembly-output: emit-asm +//@ only-x86_64 +//@ ignore-sgx Test incompatible with LVI mitigations +//@ compile-flags: -Copt-level=3 + +//! Regression test for https://github.com/rust-lang/rust/issues/123216. +//! Indexing with a `bool` should not generate redundant `jmp` or `and` +//! instructions. + +#![crate_type = "lib"] + +#[no_mangle] +pub fn bool_index(a: u32, b: bool, c: bool, d: &mut [u128; 2]) { + // CHECK-LABEL: bool_index: + // CHECK: testl %esi, %esi + // CHECK: je + // CHECK: xorb %dl, %dil + // CHECK: orb $1, (%rcx) + // CHECK-NOT: jmp + // CHECK-NOT: andb $1, %dil + // CHECK: movzbl %dil, %eax + // CHECK: andl $1, %eax + // CHECK: shll $4, %eax + // CHECK: orb $1, (%rcx,%rax) + // CHECK: retq + + let mut a = a & 1 != 0; + + if b { + a ^= c; + d[0] |= 1; + } + + d[a as usize] |= 1; +} From bf7eb64ae797d184b7fd559ea4838b4ac9391930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 18 Jun 2026 20:28:36 +0000 Subject: [PATCH 07/53] When compiling without a specified `--edition`, emit a note --- compiler/rustc_driver_impl/src/lib.rs | 6 ++-- compiler/rustc_interface/src/tests.rs | 4 +-- compiler/rustc_session/src/config.rs | 30 ++++++++++++---- src/librustdoc/config.rs | 2 +- src/tools/compiletest/src/directives.rs | 9 +++-- tests/run-make/broken-pipe-no-ice/rmake.rs | 2 +- tests/run-make/compressed-debuginfo/rmake.rs | 1 + .../const-trait-stable-toolchain/rmake.rs | 4 +++ .../rmake.rs | 3 +- .../rmake.rs | 15 ++++++-- tests/run-make/crate-loading/rmake.rs | 11 ++++-- tests/run-make/emit-to-stdout/rmake.rs | 22 +++++++++--- tests/run-make/jobserver-error/rmake.rs | 2 ++ tests/run-make/linker-warning/rmake.rs | 10 ++++-- .../missing-unstable-trait-bound/rmake.rs | 1 + tests/run-make/multiline-args-value/rmake.rs | 3 +- tests/run-make/non-unicode-env/rmake.rs | 6 +++- .../run-make/option-output-no-space/rmake.rs | 34 ++++++++++++++++--- tests/run-make/overwrite-input/rmake.rs | 5 +-- .../pointer-auth-link-with-c/rmake.rs | 3 ++ .../rmake.rs | 4 ++- .../rustdoc/doctest/test_harness/rmake.rs | 1 + tests/run-make/target-cpu-native/rmake.rs | 1 + tests/run-make/unknown-mod-stdin/rmake.rs | 3 +- tests/run-make/unspecified-edition/main.rs | 1 + tests/run-make/unspecified-edition/rmake.rs | 18 ++++++++++ ...specified-edition-without-compiling.stderr | 4 +++ .../unspecified-edition.stderr | 2 ++ 28 files changed, 164 insertions(+), 43 deletions(-) create mode 100644 tests/run-make/unspecified-edition/main.rs create mode 100644 tests/run-make/unspecified-edition/rmake.rs create mode 100644 tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr create mode 100644 tests/run-make/unspecified-edition/unspecified-edition.stderr diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 4411ecb4f128b..65f5c5d61997d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -189,7 +189,9 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) HandledOptions::HelpOnly(matches) => (matches, true), }; - let sopts = config::build_session_options(&mut default_early_dcx, &matches); + let input = make_input(&default_early_dcx, &matches.free); + let has_input = input.is_some(); + let sopts = config::build_session_options(&mut default_early_dcx, &matches, has_input); // fully initialize ice path static once unstable options are available as context let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone(); @@ -198,8 +200,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) return; } - let input = make_input(&default_early_dcx, &matches.free); - let has_input = input.is_some(); let (odir, ofile) = make_output(&matches); drop(default_early_dcx); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 22b643e74e582..e9b5b9fefbeaa 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -39,7 +39,7 @@ where { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(args).unwrap(); - let sessopts = build_session_options(&mut early_dcx, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches, true); let target = rustc_session::config::build_target_config( &early_dcx, &sessopts.target_triple, @@ -932,6 +932,6 @@ fn test_edition_parsing() { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(&["--edition=2018".to_string()]).unwrap(); - let sessopts = build_session_options(&mut early_dcx, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches, true); assert!(sessopts.edition == Edition::Edition2018) } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 37488ebbf1e8f..2b62a37223a6c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2169,22 +2169,34 @@ pub fn parse_error_format( error_format } -pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Edition { +pub fn parse_crate_edition( + early_dcx: &EarlyDiagCtxt, + matches: &getopts::Matches, + has_input: bool, +) -> Edition { let edition = match matches.opt_str("edition") { Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| { early_dcx.early_fatal(format!( - "argument for `--edition` must be one of: \ - {EDITION_NAME_LIST}. (instead was `{arg}`)" + "argument for `--edition` must be one of: {EDITION_NAME_LIST} (instead was `{arg}`)" )) }), - None => DEFAULT_EDITION, + None => { + if has_input { + early_dcx.early_note(format!( + "it is advisable to explicitly specify the `--edition` argument (the default \ + implies `2015`); it must be one of: {EDITION_NAME_LIST}" + )); + } + DEFAULT_EDITION + } }; if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) { let is_nightly = nightly_options::match_is_nightly_build(matches); let msg = if !is_nightly { format!( - "the crate requires edition {edition}, but the latest edition supported by this Rust version is {LATEST_STABLE_EDITION}" + "the crate requires edition {edition}, but the latest edition supported by this \ + Rust version is {LATEST_STABLE_EDITION}" ) } else { format!("edition {edition} is unstable and only available with -Z unstable-options") @@ -2498,10 +2510,14 @@ fn parse_logical_env( // JUSTIFICATION: before wrapper fn is available #[allow(rustc::bad_opt_access)] -pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches) -> Options { +pub fn build_session_options( + early_dcx: &mut EarlyDiagCtxt, + matches: &getopts::Matches, + has_input: bool, +) -> Options { let color = parse_color(early_dcx, matches); - let edition = parse_crate_edition(early_dcx, matches); + let edition = parse_crate_edition(early_dcx, matches, has_input); let crate_name = matches.opt_str("crate-name"); let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref()); diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 840f9d025c3cf..c60853400b2e9 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -789,7 +789,7 @@ impl Options { } } - let edition = config::parse_crate_edition(early_dcx, matches); + let edition = config::parse_crate_edition(early_dcx, matches, true); let mut id_map = html::markdown::IdMap::new(); let Some(external_html) = ExternalHtml::load( diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index dc10430f038ec..0f78a30f7686b 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -398,11 +398,10 @@ impl TestProps { } } - if let Some(edition) = self.edition.or(config.edition) { - // The edition is added at the start, since flags from //@compile-flags must be passed - // to rustc last. - self.compile_flags.insert(0, format!("--edition={edition}")); - } + let edition = self.edition.or(config.edition).unwrap_or(Edition::Year(2015)); + // The edition is added at the start, since flags from //@compile-flags must be passed + // to rustc last. + self.compile_flags.insert(0, format!("--edition={edition}")); } fn update_pass_fail_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) { diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs index b0a28b6c899da..0e43ebda9c3e1 100644 --- a/tests/run-make/broken-pipe-no-ice/rmake.rs +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -68,7 +68,7 @@ fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) { fn main() { let mut rustc = bare_rustc(); - rustc.arg("--print=sysroot"); + rustc.arg("--print=sysroot").edition("2015"); let rustc = rustc.into_raw_command(); check_broken_pipe_handled_gracefully(Binary::Rustc, rustc); diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs index c8bde9cfa221f..c24343061ba73 100644 --- a/tests/run-make/compressed-debuginfo/rmake.rs +++ b/tests/run-make/compressed-debuginfo/rmake.rs @@ -10,6 +10,7 @@ use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc}; fn check_compression(compression: &str, to_find: &str) { run_in_tmpdir(|| { let out = rustc() + .edition("2015") .crate_name("foo") .crate_type("lib") .emit("obj") diff --git a/tests/run-make/const-trait-stable-toolchain/rmake.rs b/tests/run-make/const-trait-stable-toolchain/rmake.rs index 729b71457e9e8..d23cd47db48e4 100644 --- a/tests/run-make/const-trait-stable-toolchain/rmake.rs +++ b/tests/run-make/const-trait-stable-toolchain/rmake.rs @@ -7,6 +7,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() + .edition("2015") .input("const-super-trait.rs") .env("RUSTC_BOOTSTRAP", "-1") .cfg("feature_enabled") @@ -22,6 +23,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .cfg("feature_enabled") .ui_testing() @@ -34,6 +36,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .env("RUSTC_BOOTSTRAP", "-1") .run_fail() @@ -45,6 +48,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .ui_testing() .run_fail() diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs index 57e0cab92f1ef..f49a848052411 100644 --- a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs +++ b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs @@ -10,9 +10,10 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("foo-prev.rs").run(); + rustc().edition("2015").input("foo-prev.rs").run(); let out = rustc() + .edition("2015") .extra_filename("current") .metadata("current") .input("foo-current.rs") diff --git a/tests/run-make/crate-loading-multiple-candidates/rmake.rs b/tests/run-make/crate-loading-multiple-candidates/rmake.rs index ce090850500b8..9775a1672f0cb 100644 --- a/tests/run-make/crate-loading-multiple-candidates/rmake.rs +++ b/tests/run-make/crate-loading-multiple-candidates/rmake.rs @@ -9,8 +9,18 @@ use run_make_support::{bare_rustc, diff, rfs, rustc}; fn main() { // Check that relative paths are preserved in the diagnostic rfs::create_dir("mylibs"); - rustc().input("crateresolve1-1.rs").out_dir("mylibs").extra_filename("-1").run(); - rustc().input("crateresolve1-2.rs").out_dir("mylibs").extra_filename("-2").run(); + rustc() + .edition("2015") + .input("crateresolve1-1.rs") + .out_dir("mylibs") + .extra_filename("-1") + .run(); + rustc() + .edition("2015") + .input("crateresolve1-2.rs") + .out_dir("mylibs") + .extra_filename("-2") + .run(); check("./mylibs"); // Check that symlinks aren't followed when printing the diagnostic @@ -21,6 +31,7 @@ fn main() { fn check(library_path: &str) { let out = rustc() + .edition("2015") .input("multiple-candidates.rs") .library_search_path(library_path) .ui_testing() diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 8f2577861239d..79f14e1851eff 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -6,11 +6,16 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("dependency-1.rs").run(); - rustc().input("dependency-2.rs").extra_filename("2").metadata("2").run(); - rustc().input("dep-2-reexport.rs").extern_("dependency", rust_lib_name("dependency2")).run(); + rustc().edition("2015").input("dependency-1.rs").run(); + rustc().edition("2015").input("dependency-2.rs").extra_filename("2").metadata("2").run(); + rustc() + .edition("2015") + .input("dep-2-reexport.rs") + .extern_("dependency", rust_lib_name("dependency2")) + .run(); let out = rustc() + .edition("2015") .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("foo")) diff --git a/tests/run-make/emit-to-stdout/rmake.rs b/tests/run-make/emit-to-stdout/rmake.rs index 19c15b72fe475..851ab3cb45881 100644 --- a/tests/run-make/emit-to-stdout/rmake.rs +++ b/tests/run-make/emit-to-stdout/rmake.rs @@ -13,8 +13,9 @@ use run_make_support::{diff, run_in_tmpdir, rustc}; // Test emitting text outputs to stdout works correctly fn run_diff(name: &str, file_args: &[&str]) { - rustc().emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); - let out = rustc().emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); + rustc().edition("2015").emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); + let out = + rustc().edition("2015").emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); diff().expected_file(name).actual_text("stdout", &out).run(); } @@ -29,7 +30,13 @@ fn run_terminal_err_diff(name: &str) { let terminal = File::options().read(true).write(true).open(r"\\.\CONOUT$").unwrap(); let err = File::create(name).unwrap(); - rustc().emit(format!("{name}=-")).input("test.rs").stdout(terminal).stderr(err).run_fail(); + rustc() + .edition("2015") + .emit(format!("{name}=-")) + .input("test.rs") + .stdout(terminal) + .stderr(err) + .run_fail(); diff().expected_file(format!("emit-{name}.stderr")).actual_file(name).run(); } @@ -47,6 +54,7 @@ fn main() { // Test error for emitting multiple types to stdout rustc() + .edition("2015") .input("test.rs") .emit("asm=-") .emit("llvm-ir=-") @@ -58,6 +66,7 @@ fn main() { // Same as above, but using `-o` rustc() + .edition("2015") .input("test.rs") .output("-") .emit("asm,llvm-ir,dep-info,mir") @@ -69,6 +78,11 @@ fn main() { .run(); // Test that `-o -` redirected to a file works correctly (#26719) - rustc().input("test.rs").output("-").stdout(File::create("out-stdout").unwrap()).run(); + rustc() + .edition("2015") + .input("test.rs") + .output("-") + .stdout(File::create("out-stdout").unwrap()) + .run(); }); } diff --git a/tests/run-make/jobserver-error/rmake.rs b/tests/run-make/jobserver-error/rmake.rs index 265eec7190d4e..80c1562299e72 100644 --- a/tests/run-make/jobserver-error/rmake.rs +++ b/tests/run-make/jobserver-error/rmake.rs @@ -16,6 +16,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() + .edition("2015") .stdin_buf(("fn main() {}").as_bytes()) .env("MAKEFLAGS", "--jobserver-auth=1000,1000") .run_fail() @@ -23,6 +24,7 @@ fn main() { diff().expected_file("cannot_open_fd.stderr").actual_text("actual", out).run(); let out = rustc() + .edition("2015") .stdin_buf(("fn main() {}").as_bytes()) .input("-") .env("MAKEFLAGS", "--jobserver-auth=3,3") diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index b25d892507907..bf6ef980265f1 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -5,6 +5,7 @@ use run_make_support::{Rustc, diff, regex, rustc}; fn run_rustc() -> Rustc { let mut rustc = rustc(); rustc + .edition("2015") .arg("main.rs") // NOTE: `link-self-contained` can vary depending on bootstrap.toml. // Make sure we use a consistent value. @@ -23,9 +24,9 @@ fn run_rustc() -> Rustc { fn main() { // first, compile our linker and our dependencies - rustc().arg("fake-linker.rs").output("fake-linker").run(); - rustc().arg("foo.rs").crate_type("rlib").run(); - rustc().arg("bar.rs").crate_type("rlib").run(); + rustc().edition("2015").arg("fake-linker.rs").output("fake-linker").run(); + rustc().edition("2015").arg("foo.rs").crate_type("rlib").run(); + rustc().edition("2015").arg("bar.rs").crate_type("rlib").run(); // Run rustc with our fake linker, and make sure it shows warnings let warnings = run_rustc().link_arg("run_make_warn").run(); @@ -92,12 +93,14 @@ fn main() { // Make sure we show linker warnings even across `-Z no-link` rustc() + .edition("2015") .arg("-Zno-link") .input("-") .stdin_buf("#![deny(linker_messages)] \n fn main() {}") .run() .assert_stderr_equals(""); rustc() + .edition("2015") .arg("-Zlink-only") .arg("rust_out.rlink") .linker("./fake-linker") @@ -111,6 +114,7 @@ fn main() { // Same thing, but with json output. rustc() + .edition("2015") .error_format("json") .arg("-Zlink-only") .arg("rust_out.rlink") diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs index 3f76c65247d8c..766b1dfe56487 100644 --- a/tests/run-make/missing-unstable-trait-bound/rmake.rs +++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs @@ -10,6 +10,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() + .edition("2015") .env("RUSTC_BOOTSTRAP", "-1") .input("missing-bound.rs") .run_fail() diff --git a/tests/run-make/multiline-args-value/rmake.rs b/tests/run-make/multiline-args-value/rmake.rs index 3964cbbc1e605..f9e6290f7d919 100644 --- a/tests/run-make/multiline-args-value/rmake.rs +++ b/tests/run-make/multiline-args-value/rmake.rs @@ -3,7 +3,8 @@ use run_make_support::{cwd, diff, rustc}; fn test_and_compare(test_name: &str, flag: &str, val: &str) { let mut cmd = rustc(); - let output = cmd.input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail(); + let output = + cmd.edition("2015").input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail(); assert_eq!(output.stdout_utf8(), ""); diff() diff --git a/tests/run-make/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs index b7a3c51db5bfd..7a1c7e4322ddc 100644 --- a/tests/run-make/non-unicode-env/rmake.rs +++ b/tests/run-make/non-unicode-env/rmake.rs @@ -6,7 +6,11 @@ fn main() { let non_unicode: &std::ffi::OsStr = std::os::unix::ffi::OsStrExt::from_bytes(&[0xFF]); #[cfg(windows)] let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]); - let output = rustc().input("non_unicode_env.rs").env("NON_UNICODE_VAR", non_unicode).run_fail(); + let output = rustc() + .edition("2015") + .input("non_unicode_env.rs") + .env("NON_UNICODE_VAR", non_unicode) + .run_fail(); let expected = rfs::read_to_string("non_unicode_env.stderr"); output.assert_stderr_equals(expected); } diff --git a/tests/run-make/option-output-no-space/rmake.rs b/tests/run-make/option-output-no-space/rmake.rs index 2c42f15aa89a6..a34a57fa9c1be 100644 --- a/tests/run-make/option-output-no-space/rmake.rs +++ b/tests/run-make/option-output-no-space/rmake.rs @@ -7,6 +7,7 @@ use run_make_support::rustc; fn main() { // test fake args rustc() + .edition("2015") .input("main.rs") .arg("-optimize") .run() @@ -17,6 +18,7 @@ fn main() { "note: output filename `-o ptimize` is applied instead of a flag named `optimize`", ); rustc() + .edition("2015") .input("main.rs") .arg("-o0") .run() @@ -26,9 +28,10 @@ fn main() { .assert_stderr_contains( "note: output filename `-o 0` is applied instead of a flag named `o0`", ); - rustc().input("main.rs").arg("-o1").run(); + rustc().edition("2015").input("main.rs").arg("-o1").run(); // test real args by iter optgroups rustc() + .edition("2015") .input("main.rs") .arg("-out-dir") .run() @@ -43,6 +46,7 @@ fn main() { ); // test real args by iter CG_OPTIONS rustc() + .edition("2015") .input("main.rs") .arg("-opt_level") .run() @@ -57,6 +61,7 @@ fn main() { ); // separater in-sensitive rustc() + .edition("2015") .input("main.rs") .arg("-opt-level") .run() @@ -70,6 +75,7 @@ fn main() { "help: insert a space between `-o` and `pt-level` if this is intentional: `-o pt-level`" ); rustc() + .edition("2015") .input("main.rs") .arg("-overflow-checks") .run() @@ -86,10 +92,28 @@ fn main() { ); // No warning for Z_OPTIONS - rustc().input("main.rs").arg("-oom").run().assert_stderr_equals(""); + rustc().edition("2015").input("main.rs").arg("-oom").run().assert_stderr_equals(""); // test no warning when there is space between `-o` and arg - rustc().input("main.rs").arg("-o").arg("ptimize").run().assert_stderr_equals(""); - rustc().input("main.rs").arg("--out-dir").arg("xxx").run().assert_stderr_equals(""); - rustc().input("main.rs").arg("-o").arg("out-dir").run().assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("-o") + .arg("ptimize") + .run() + .assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("--out-dir") + .arg("xxx") + .run() + .assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("-o") + .arg("out-dir") + .run() + .assert_stderr_equals(""); } diff --git a/tests/run-make/overwrite-input/rmake.rs b/tests/run-make/overwrite-input/rmake.rs index bdf7860caa8a0..581fee8fe0136 100644 --- a/tests/run-make/overwrite-input/rmake.rs +++ b/tests/run-make/overwrite-input/rmake.rs @@ -8,8 +8,9 @@ use run_make_support::{diff, rustc}; fn main() { - let file_out = rustc().input("main.rs").output("main.rs").run_fail().stderr_utf8(); - let folder_out = rustc().input("main.rs").output(".").run_fail().stderr_utf8(); + let file_out = + rustc().edition("2015").input("main.rs").output("main.rs").run_fail().stderr_utf8(); + let folder_out = rustc().edition("2015").input("main.rs").output(".").run_fail().stderr_utf8(); diff().expected_file("file.stderr").actual_text("actual-file-stderr", file_out).run(); diff().expected_file("folder.stderr").actual_text("actual-folder-stderr", folder_out).run(); } diff --git a/tests/run-make/pointer-auth-link-with-c/rmake.rs b/tests/run-make/pointer-auth-link-with-c/rmake.rs index 1ac68c95559c6..e5793130c6550 100644 --- a/tests/run-make/pointer-auth-link-with-c/rmake.rs +++ b/tests/run-make/pointer-auth-link-with-c/rmake.rs @@ -16,6 +16,7 @@ use run_make_support::{build_native_static_lib, cc, is_windows_msvc, llvm_ar, ru fn main() { build_native_static_lib("test"); rustc() + .edition("2015") .arg("-Cunsafe-allow-abi-mismatch=branch-protection") .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") @@ -30,6 +31,7 @@ fn main() { let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); rustc() + .edition("2015") .arg("-Cunsafe-allow-abi-mismatch=branch-protection") .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") @@ -46,6 +48,7 @@ fn main() { // let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; // llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); // rustc() + // .edition("2015") // .arg("-Cunsafe-allow-abi-mismatch=branch-protection") // .arg("-Zbranch-protection=bti,pac-ret,pc,leaf") // .input("test.rs") diff --git a/tests/run-make/print-request-help-stable-unstable/rmake.rs b/tests/run-make/print-request-help-stable-unstable/rmake.rs index a59963da5c497..a1d02f177bcef 100644 --- a/tests/run-make/print-request-help-stable-unstable/rmake.rs +++ b/tests/run-make/print-request-help-stable-unstable/rmake.rs @@ -5,6 +5,7 @@ use run_make_support::{diff, rustc, similar}; fn main() { let stable_invalid_print_request_help = rustc() + .edition("2015") .env("RUSTC_BOOTSTRAP", "-1") .cfg("force_stable") .print("xxx") @@ -16,7 +17,8 @@ fn main() { .actual_text("stable_invalid_print_request_help", &stable_invalid_print_request_help) .run(); - let unstable_invalid_print_request_help = rustc().print("xxx").run_fail().stderr_utf8(); + let unstable_invalid_print_request_help = + rustc().edition("2015").print("xxx").run_fail().stderr_utf8(); assert!(unstable_invalid_print_request_help.contains("all-target-specs-json")); diff() .expected_file("unstable-invalid-print-request-help.err") diff --git a/tests/run-make/rustdoc/doctest/test_harness/rmake.rs b/tests/run-make/rustdoc/doctest/test_harness/rmake.rs index 608adebbd54f2..87d57ca1f76ac 100644 --- a/tests/run-make/rustdoc/doctest/test_harness/rmake.rs +++ b/tests/run-make/rustdoc/doctest/test_harness/rmake.rs @@ -19,6 +19,7 @@ fn main() { rustc().input(runtool_path).run(); let output = rustdoc() + .edition("2015") .input(doctests_path) .arg("--test") // for the outer test suite diff --git a/tests/run-make/target-cpu-native/rmake.rs b/tests/run-make/target-cpu-native/rmake.rs index 5791bf01bba2b..dbea1bda2cab5 100644 --- a/tests/run-make/target-cpu-native/rmake.rs +++ b/tests/run-make/target-cpu-native/rmake.rs @@ -9,6 +9,7 @@ use run_make_support::{run, rustc}; fn main() { let out = rustc() + .edition("2015") .input("foo.rs") .arg("-Ctarget-cpu=native") .arg("-Zverify-llvm-ir") diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs index 101711b0d2c70..56833569e54bf 100644 --- a/tests/run-make/unknown-mod-stdin/rmake.rs +++ b/tests/run-make/unknown-mod-stdin/rmake.rs @@ -14,7 +14,8 @@ use run_make_support::{diff, rustc}; fn main() { - let out = rustc().crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); + let out = + rustc().edition("2015").crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); diff() .actual_text("actual-stdout", out.stdout_utf8()) .expected_file("unknown-mod.stdout") diff --git a/tests/run-make/unspecified-edition/main.rs b/tests/run-make/unspecified-edition/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/unspecified-edition/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/unspecified-edition/rmake.rs b/tests/run-make/unspecified-edition/rmake.rs new file mode 100644 index 0000000000000..0d902e5bdb9f9 --- /dev/null +++ b/tests/run-make/unspecified-edition/rmake.rs @@ -0,0 +1,18 @@ +// When calling `rustc` without an explicit edition, emit a note asking the user to specify one, +// clarifying that the default is 2015. + +use run_make_support::{bare_rustc, diff, rustc}; + +fn main() { + rustc().edition("2015").input("main.rs").run().assert_stderr_not_contains("--edition"); + let out = rustc().input("main.rs").run().assert_stderr_contains("--edition").stderr_utf8(); + diff().expected_file("unspecified-edition.stderr").actual_text("(rustc)", &out).run(); + + // Ensure that we only mention --edition when compiling code. + let out = rustc().run_fail().assert_stderr_not_contains("--edition").stderr_utf8(); + diff() + .expected_file("unspecified-edition-without-compiling.stderr") + .actual_text("(rustc)", &out) + .run(); + bare_rustc().arg("--version").run().assert_stderr_not_contains("--edition"); +} diff --git a/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr b/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr new file mode 100644 index 0000000000000..c36ecca4af4a2 --- /dev/null +++ b/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr @@ -0,0 +1,4 @@ +error: no input filename given + +error: aborting due to 1 previous error + diff --git a/tests/run-make/unspecified-edition/unspecified-edition.stderr b/tests/run-make/unspecified-edition/unspecified-edition.stderr new file mode 100644 index 0000000000000..8ca896f264fb0 --- /dev/null +++ b/tests/run-make/unspecified-edition/unspecified-edition.stderr @@ -0,0 +1,2 @@ +note: it is advisable to explicitly specify the `--edition` argument (the default implies `2015`); it must be one of: <2015|2018|2021|2024|future> + From 69db212b3b0b80a9c7c7cf07f2377a1d73bd0cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 19 Jun 2026 19:30:24 +0000 Subject: [PATCH 08/53] Use same wording as cargo does when `package.edition` is unspecified --- compiler/rustc_session/src/config.rs | 4 ++-- tests/run-make/unspecified-edition/unspecified-edition.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 2b62a37223a6c..8b7ff3375945e 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2183,8 +2183,8 @@ pub fn parse_crate_edition( None => { if has_input { early_dcx.early_note(format!( - "it is advisable to explicitly specify the `--edition` argument (the default \ - implies `2015`); it must be one of: {EDITION_NAME_LIST}" + "`--edition` is unspecified, defaulting to `{DEFAULT_EDITION}` while the \ + latest is `{LATEST_STABLE_EDITION}`; it must be one of: {EDITION_NAME_LIST}", )); } DEFAULT_EDITION diff --git a/tests/run-make/unspecified-edition/unspecified-edition.stderr b/tests/run-make/unspecified-edition/unspecified-edition.stderr index 8ca896f264fb0..4749764866aea 100644 --- a/tests/run-make/unspecified-edition/unspecified-edition.stderr +++ b/tests/run-make/unspecified-edition/unspecified-edition.stderr @@ -1,2 +1,2 @@ -note: it is advisable to explicitly specify the `--edition` argument (the default implies `2015`); it must be one of: <2015|2018|2021|2024|future> +note: `--edition` is unspecified, defaulting to `2015` while the latest is `2024`; it must be one of: <2015|2018|2021|2024|future> From f95bf574cf06eff9d56e0883a1475a3f3d5a5ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 21 Jun 2026 18:13:46 -0700 Subject: [PATCH 09/53] Remove `--edition=2015` from rustdoc-gui tests only --- src/tools/compiletest/src/rustdoc_gui_test.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/rustdoc_gui_test.rs b/src/tools/compiletest/src/rustdoc_gui_test.rs index 215fee768f254..d7b4351a42528 100644 --- a/src/tools/compiletest/src/rustdoc_gui_test.rs +++ b/src/tools/compiletest/src/rustdoc_gui_test.rs @@ -33,7 +33,10 @@ impl RustdocGuiTestProps { let props = TestProps::from_file(test_file_path, None, &config); - let TestProps { compile_flags, run_flags, .. } = props; + let TestProps { mut compile_flags, run_flags, .. } = props; + // We don't want to pass `--edition=2015` in, which is being set by default by + // `TestProps::from_file`. + compile_flags.remove(0); Self { compile_flags, run_flags } } } From a1d6de2ffab1575bc0e69086e77f760a6691c44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 27 Jul 2026 06:55:57 +0000 Subject: [PATCH 10/53] fix run-make test --- tests/run-make/const-destruct-stable-toolchain/rmake.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/run-make/const-destruct-stable-toolchain/rmake.rs b/tests/run-make/const-destruct-stable-toolchain/rmake.rs index c1ff48b3214f0..f8c0c5fcb4c56 100644 --- a/tests/run-make/const-destruct-stable-toolchain/rmake.rs +++ b/tests/run-make/const-destruct-stable-toolchain/rmake.rs @@ -9,6 +9,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() .input("const-drop.rs") + .edition("2015") .env("RUSTC_BOOTSTRAP", "-1") .run_fail() .assert_stderr_not_contains("consider restricting type parameter `T`") @@ -16,6 +17,7 @@ fn main() { diff().expected_file("const-drop-stable.stderr").actual_text("(rustc)", &out).run(); let out = rustc() .input("const-drop.rs") + .edition("2015") .ui_testing() .run_fail() .assert_stderr_contains( From 87e2c0b041f21819bb5edc3825481dd1dc7cc2d2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 27 Jul 2026 15:05:40 +0200 Subject: [PATCH 11/53] remove InterpError::map_err_info --- .../src/interpret/eval_context.rs | 18 +++------------ .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../src/interpret/validity.rs | 6 ++--- .../rustc_middle/src/mir/interpret/error.rs | 23 +++++++++++-------- .../src/known_panics_lint.rs | 9 +++----- src/tools/miri/src/diagnostics.rs | 6 ++--- 6 files changed, 25 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index b6e3f9c3009c6..45d57f77a4079 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -21,9 +21,9 @@ use rustc_target::callconv::FnAbi; use tracing::{debug, trace}; use super::{ - Frame, FrameInfo, GlobalId, InterpErrorInfo, InterpErrorKind, InterpResult, MPlaceTy, Machine, - MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance, - err_inval, interp_ok, throw_inval, throw_ub, throw_ub_format, + Frame, FrameInfo, GlobalId, InterpErrorKind, InterpResult, MPlaceTy, Machine, MemPlaceMeta, + Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance, err_inval, interp_ok, + throw_inval, throw_ub, throw_ub_format, }; use crate::{enter_trace_span, util}; @@ -239,18 +239,6 @@ pub(super) fn from_known_layout<'tcx>( } } -/// Turn the given error into a human-readable string. Expects the string to be printed, so if -/// `RUSTC_CTFE_BACKTRACE` is set this will show a backtrace of the rustc internals that -/// triggered the error. -/// -/// This is NOT the preferred way to render an error; use `report` from `const_eval` instead. -/// However, this is useful when error messages appear in ICEs. -pub fn format_interp_error<'tcx>(e: InterpErrorInfo<'tcx>) -> String { - let (e, backtrace) = e.into_parts(); - backtrace.print_backtrace(); - e.to_string() -} - impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn new( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index d52c1f9306444..a02dd509b507e 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -23,7 +23,7 @@ mod visitor; pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here pub use self::call::FnArg; -pub use self::eval_context::{InterpCx, format_interp_error}; +pub use self::eval_context::InterpCx; use self::eval_context::{from_known_layout, mir_assign_valid_types}; pub use self::intern::{ HasStaticRootDefId, InternError, InternKind, intern_const_alloc_for_constprop, diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 75a6753fe3d0e..312fc3c5e3f11 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -32,7 +32,6 @@ use super::machine::AllocMap; use super::{ AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, PlaceTy, Pointer, Projectable, Scalar, ValueVisitor, err_ub, - format_interp_error, }; use crate::enter_trace_span; @@ -1604,7 +1603,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { v.reset_padding(val)?; interp_ok(()) }) - .map_err_info(|err| { + .inspect_err_info(|err| { if !matches!( err.kind(), InterpErrorKind::UndefinedBehavior(ValidationError { .. }) @@ -1614,9 +1613,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // during validation. | InterpErrorKind::MachineStop(_) ) { - bug!("Unexpected error during validation: {}", format_interp_error(err)); + bug!("Unexpected error during validation: {}", err.to_string()); } - err }) } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e2c67b29943d6..3a1954065a829 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -218,6 +218,17 @@ impl<'tcx> InterpErrorInfo<'tcx> { pub fn kind(&self) -> &InterpErrorKind<'tcx> { &self.0.kind } + + /// Turn the given error into a human-readable string. Expects the string to be printed, so if + /// `RUSTC_CTFE_BACKTRACE` is set this will show a backtrace of the rustc internals that + /// triggered the error. + /// + /// This is NOT the preferred way to render an error; use `report` from `const_eval` instead. + /// However, this is useful when error messages appear in ICEs. + pub fn to_string(&self) -> String { + self.0.backtrace.print_backtrace(); + self.0.kind.to_string() + } } fn print_backtrace(backtrace: &Backtrace) { @@ -1043,14 +1054,6 @@ impl<'tcx, T> InterpResult<'tcx, T> { InterpResult::new(self.disarm().map(f)) } - #[inline] - pub fn map_err_info( - self, - f: impl FnOnce(InterpErrorInfo<'tcx>) -> InterpErrorInfo<'tcx>, - ) -> InterpResult<'tcx, T> { - InterpResult::new(self.disarm().map_err(f)) - } - #[inline] pub fn map_err_kind( self, @@ -1063,8 +1066,8 @@ impl<'tcx, T> InterpResult<'tcx, T> { } #[inline] - pub fn inspect_err_kind(self, f: impl FnOnce(&InterpErrorKind<'tcx>)) -> InterpResult<'tcx, T> { - InterpResult::new(self.disarm().inspect_err(|e| f(&e.0.kind))) + pub fn inspect_err_info(self, f: impl FnOnce(&InterpErrorInfo<'tcx>)) -> InterpResult<'tcx, T> { + InterpResult::new(self.disarm().inspect_err(f)) } #[inline] diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index e762821724231..b865323e50b6c 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -6,9 +6,7 @@ use std::fmt::Debug; use rustc_abi::{BackendRepr, FieldIdx, HasDataLayout, Size, TargetDataLayout, VariantIdx}; use rustc_const_eval::const_eval::DummyMachine; -use rustc_const_eval::interpret::{ - ImmTy, InterpCx, InterpResult, Projectable, Scalar, format_interp_error, interp_ok, -}; +use rustc_const_eval::interpret::{ImmTy, InterpCx, InterpResult, Projectable, Scalar, interp_ok}; use rustc_data_structures::fx::FxHashSet; use rustc_hir::HirId; use rustc_hir::def::DefKind; @@ -233,7 +231,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { F: FnOnce(&mut Self) -> InterpResult<'tcx, T>, { f(self) - .map_err_info(|err| { + .inspect_err_info(|err| { trace!("InterpCx operation failed: {:?}", err); // Some errors shouldn't come up because creating them causes // an allocation, which we should avoid. When that happens, @@ -241,9 +239,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { assert!( !err.kind().formatted_string(), "known panics lint encountered formatting error: {}", - format_interp_error(err), + err.to_string(), ); - err }) .discard_err() } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 4f853d5ca02ff..d4fe89d4f0258 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -374,7 +374,7 @@ pub fn report_result<'tcx>( ecx.handle_ice(); // print interpreter backtrace (this is outside the eval `catch_unwind`) bug!( "This validation error should be impossible in Miri: {}", - format_interp_error(res) + res.to_string() ); } UndefinedBehavior(_) => "Undefined Behavior", @@ -391,7 +391,7 @@ pub fn report_result<'tcx>( ) => "post-monomorphization error", _ => { ecx.handle_ice(); // print interpreter backtrace (this is outside the eval `catch_unwind`) - bug!("This error should be impossible in Miri: {}", format_interp_error(res)); + bug!("This error should be impossible in Miri: {}", res.to_string()); } }; #[rustfmt::skip] @@ -468,7 +468,7 @@ pub fn report_result<'tcx>( if let Some(title) = title { write!(primary_msg, "{title}: ").unwrap(); } - write!(primary_msg, "{}", format_interp_error(res)).unwrap(); + write!(primary_msg, "{}", res.to_string()).unwrap(); if labels.is_empty() { labels.push(format!( From 6618eb62011cf486566afafb42a1e134c9b19f79 Mon Sep 17 00:00:00 2001 From: chiri Date: Tue, 28 Jul 2026 11:12:57 +0300 Subject: [PATCH 12/53] review --- library/core/src/fmt/num.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 53c3e2c60d4d2..315c2cca3f829 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -820,7 +820,7 @@ unsafe fn write_quad(buf: &mut [MaybeUninit], offset: usize, quad: u64) { // SAFETY: These are this function's caller-provided invariants. unsafe { core::hint::assert_unchecked(quad < 10_000); - core::hint::assert_unchecked(offset <= buf.len() - 4); + core::hint::assert_unchecked(offset + 4 <= buf.len()); } // For the documented range, ceil(2^19 / 100) gives an exact quotiet. @@ -851,7 +851,7 @@ fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { // and every used `OFFSET` specialization reserves sixteen bytes in `buf`. unsafe { core::hint::assert_unchecked(n < 10_000_000_000_000_000); - core::hint::assert_unchecked(OFFSET <= buf.len() - 16); + core::hint::assert_unchecked(OFFSET + 16 <= buf.len()); } // Peel four digits at a time from right to left (12345678 -> 1234 | 5678). From 20ec372d195698fb9a68c5a21f75307f626adeac Mon Sep 17 00:00:00 2001 From: chiri Date: Tue, 28 Jul 2026 11:18:23 +0300 Subject: [PATCH 13/53] Update library/core/src/fmt/num.rs Co-authored-by: Clar Fon <15850505+clarfonthey@users.noreply.github.com> --- library/core/src/fmt/num.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 315c2cca3f829..bb6006f86df52 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -823,12 +823,9 @@ unsafe fn write_quad(buf: &mut [MaybeUninit], offset: usize, quad: u64) { core::hint::assert_unchecked(offset + 4 <= buf.len()); } - // For the documented range, ceil(2^19 / 100) gives an exact quotiet. - const DIV100_SHIFT: u32 = 19; - const DIV100_RECIPROCAL: u32 = (1 << DIV100_SHIFT) / 100 + 1; - let quad = quad as u32; - let high = (quad * DIV100_RECIPROCAL) >> DIV100_SHIFT; + // Note: this is equivalent to `quad / 100`, but contains no division instructions + let high = (quad * const { (1 << 19) / 100 + 1 }) >> 19; let low = quad - high * 100; let high = high as usize; let low = low as usize; From c10ff542ea713c9897837107ac30848271360eff Mon Sep 17 00:00:00 2001 From: chiri Date: Tue, 28 Jul 2026 11:39:50 +0300 Subject: [PATCH 14/53] review (x3) --- library/core/src/fmt/num.rs | 41 ++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index bb6006f86df52..9c3d5adb8fe23 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -694,7 +694,9 @@ impl u128 { remain /= 1_00_00; // SAFETY: quad is a remainder modulo 10_000. The offset checks // above reserve exactly four bytes in buf. - unsafe { write_quad(buf, offset, quad) }; + unsafe { + write_quad(buf.get_unchecked_mut(offset..offset + 4), quad); + } } // Format per two digits from the lookup table. @@ -814,28 +816,30 @@ impl i128 { /// /// # Safety /// -/// `quad` must be below 10_000 and `buf[offset..offset + 4]` must be in bounds. +/// `quad` must be below 10_000 and `buf` must contain exactly four bytes. #[inline(always)] -unsafe fn write_quad(buf: &mut [MaybeUninit], offset: usize, quad: u64) { +unsafe fn write_quad(buf: &mut [MaybeUninit], quad: u64) { // SAFETY: These are this function's caller-provided invariants. unsafe { core::hint::assert_unchecked(quad < 10_000); - core::hint::assert_unchecked(offset + 4 <= buf.len()); + core::hint::assert_unchecked(buf.len() == 4); } let quad = quad as u32; - // Note: this is equivalent to `quad / 100`, but contains no division instructions + + // Note: this is equivalent to `quad / 100`, but contains no division instructions. let high = (quad * const { (1 << 19) / 100 + 1 }) >> 19; let low = quad - high * 100; let high = high as usize; let low = low as usize; - // SAFETY: `high` and `low` are below 100 because quad is below 10_000. The - // destination has four bytes by the precondition, and the two source pairs - // are disjoint from it because `DECIMAL_PAIRS` is static RO storage. + // SAFETY: `high` and `low` are below 100 because `quad` is below 10_000. + // The destination has four bytes by the precondition, and the two source + // pairs are disjoint from it because `DECIMAL_PAIRS` is static RO storage. unsafe { let pairs = DECIMAL_PAIRS.as_ptr(); - let dst = buf.as_mut_ptr().add(offset).cast::(); + let dst = buf.as_mut_ptr().cast::(); + core::ptr::copy_nonoverlapping(pairs.add(high * 2), dst, 2); core::ptr::copy_nonoverlapping(pairs.add(low * 2), dst.add(2), 2); } @@ -856,16 +860,25 @@ fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { let mut remain = n; for quad_index in (1..4).rev() { - // pull two pairs let quad = remain % 1_00_00; remain /= 1_00_00; - // SAFETY: modulo bounds quad; OFFSET and quad_index select one of the - // four non-overlapping four-byte regions proven in bounds above. - unsafe { write_quad(buf, quad_index * 4 + OFFSET, quad) }; + + // SAFETY: `OFFSET + quad_index * 4` starts one of the four + // non-overlapping four-byte regions proven in bounds above. + unsafe { + write_quad( + buf.get_unchecked_mut( + OFFSET + quad_index * 4..OFFSET + (quad_index + 1) * 4, + ), + quad, + ); + } } // SAFETY: OFFSET starts the first four-byte region proven in bounds above. - unsafe { write_quad(buf, OFFSET, remain) }; + unsafe { + write_quad(buf.get_unchecked_mut(OFFSET..OFFSET + 4), remain); + } } /// Euclidean division plus remainder with constant 1E16 basically consumes 16 From dedf120b21c6dd0c0531c99201592cd1bef36756 Mon Sep 17 00:00:00 2001 From: chiri Date: Tue, 28 Jul 2026 11:46:35 +0300 Subject: [PATCH 15/53] fix tidy --- library/core/src/fmt/num.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 9c3d5adb8fe23..7398c9b40b19d 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -867,9 +867,7 @@ fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { // non-overlapping four-byte regions proven in bounds above. unsafe { write_quad( - buf.get_unchecked_mut( - OFFSET + quad_index * 4..OFFSET + (quad_index + 1) * 4, - ), + buf.get_unchecked_mut(OFFSET + quad_index * 4..OFFSET + (quad_index + 1) * 4), quad, ); } From 917aa16059e3f0d9d4be7077f3fc4a4a5df7fea3 Mon Sep 17 00:00:00 2001 From: chiri Date: Wed, 29 Jul 2026 11:10:07 +0300 Subject: [PATCH 16/53] review --- library/core/src/fmt/num.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 7398c9b40b19d..d703b817b5a25 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -838,7 +838,7 @@ unsafe fn write_quad(buf: &mut [MaybeUninit], quad: u64) { // pairs are disjoint from it because `DECIMAL_PAIRS` is static RO storage. unsafe { let pairs = DECIMAL_PAIRS.as_ptr(); - let dst = buf.as_mut_ptr().cast::(); + let dst = buf.as_mut_ptr().cast_init(); core::ptr::copy_nonoverlapping(pairs.add(high * 2), dst, 2); core::ptr::copy_nonoverlapping(pairs.add(low * 2), dst.add(2), 2); From af98396a161e714ff6f8aae8976f012bed99da89 Mon Sep 17 00:00:00 2001 From: chiri Date: Wed, 29 Jul 2026 11:27:34 +0300 Subject: [PATCH 17/53] review (x2) --- library/core/src/fmt/num.rs | 52 ++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index d703b817b5a25..f94e5433a5183 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -692,11 +692,12 @@ impl u128 { let quad = remain % 1_00_00; remain /= 1_00_00; - // SAFETY: quad is a remainder modulo 10_000. The offset checks - // above reserve exactly four bytes in buf. - unsafe { - write_quad(buf.get_unchecked_mut(offset..offset + 4), quad); - } + + write_quad( + // SAFETY: `offset >= 4` was asserted above. + unsafe { buf.get_unchecked_mut(offset..offset + 4) }, + quad, + ); } // Format per two digits from the lookup table. @@ -813,12 +814,8 @@ impl i128 { } /// Writes `quad` as exactly four digits (for example: `42` becomes `"0042"`). -/// -/// # Safety -/// -/// `quad` must be below 10_000 and `buf` must contain exactly four bytes. #[inline(always)] -unsafe fn write_quad(buf: &mut [MaybeUninit], quad: u64) { +fn write_quad(buf: &mut [MaybeUninit], quad: u64) { // SAFETY: These are this function's caller-provided invariants. unsafe { core::hint::assert_unchecked(quad < 10_000); @@ -834,15 +831,10 @@ unsafe fn write_quad(buf: &mut [MaybeUninit], quad: u64) { let low = low as usize; // SAFETY: `high` and `low` are below 100 because `quad` is below 10_000. - // The destination has four bytes by the precondition, and the two source - // pairs are disjoint from it because `DECIMAL_PAIRS` is static RO storage. - unsafe { - let pairs = DECIMAL_PAIRS.as_ptr(); - let dst = buf.as_mut_ptr().cast_init(); + unsafe { core::hint::assert_unchecked(high < 100 && low < 100) } - core::ptr::copy_nonoverlapping(pairs.add(high * 2), dst, 2); - core::ptr::copy_nonoverlapping(pairs.add(low * 2), dst.add(2), 2); - } + buf[0..2].write_copy_of_slice(&DECIMAL_PAIRS[high * 2..high * 2 + 2]); + buf[2..4].write_copy_of_slice(&DECIMAL_PAIRS[low * 2..low * 2 + 2]); } /// Encodes the 16 least-significant decimals of n into `buf[OFFSET .. OFFSET + @@ -863,20 +855,20 @@ fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { let quad = remain % 1_00_00; remain /= 1_00_00; - // SAFETY: `OFFSET + quad_index * 4` starts one of the four - // non-overlapping four-byte regions proven in bounds above. - unsafe { - write_quad( - buf.get_unchecked_mut(OFFSET + quad_index * 4..OFFSET + (quad_index + 1) * 4), - quad, - ); - } + write_quad( + // SAFETY: `OFFSET + 16 <= buf.len()` and `quad_index < 4`, so this range is within `buf`. + unsafe { + buf.get_unchecked_mut(OFFSET + quad_index * 4..OFFSET + (quad_index + 1) * 4) + }, + quad, + ); } - // SAFETY: OFFSET starts the first four-byte region proven in bounds above. - unsafe { - write_quad(buf.get_unchecked_mut(OFFSET..OFFSET + 4), remain); - } + write_quad( + // SAFETY: `OFFSET + 16 <= buf.len()` was asserted above. + unsafe { buf.get_unchecked_mut(OFFSET..OFFSET + 4) }, + remain, + ); } /// Euclidean division plus remainder with constant 1E16 basically consumes 16 From a61412069d0fbddffa223faef5212e3c796d47ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 11 Mar 2026 23:37:14 +0000 Subject: [PATCH 18/53] Account for ownership mismatch on argument that doesn't meet bound ``` error[E0277]: the trait bound `needs_borrow::Hello: needs_borrow::Tr` is not satisfied --> $DIR/ownership-mismatch-on-arg.rs:42:13 | LL | foo(hi, hi, hi); | ^^^ -- -- `needs_borrow::Hello` doesn't satisfy the trait bound | | | | | `needs_borrow::Hello` doesn't satisfy the trait bound | unsatisfied trait bound | help: the trait `needs_borrow::Tr` is not implemented for `needs_borrow::Hello` --> $DIR/ownership-mismatch-on-arg.rs:27:5 | LL | struct Hello; | ^^^^^^^^^^^^ help: the trait `needs_borrow::Tr` is implemented for `&needs_borrow::Hello` --> $DIR/ownership-mismatch-on-arg.rs:30:5 | LL | impl Tr for &Hello {} | ^^^^^^^^^^^^^^^^^^ note: required by a bound in `needs_borrow::foo` --> $DIR/ownership-mismatch-on-arg.rs:32:15 | LL | fn foo(_v: T, _w: T, _k: K) {} | ^^ required by this bound in `foo` help: consider borrowing these argument | LL | foo(&hi, &hi, hi); | + + ``` --- .../src/error_reporting/traits/suggestions.rs | 256 +++++++++++++----- .../self-mapping-arguments-errors.stderr | 15 +- .../as_expression.current.stderr | 4 +- ...d-intrinsic-monomorphization-bounds.stderr | 5 +- .../trait-bounds/ownership-mismatch-on-arg.rs | 47 ++++ .../ownership-mismatch-on-arg.stderr | 96 +++++++ 6 files changed, 353 insertions(+), 70 deletions(-) create mode 100644 tests/ui/trait-bounds/ownership-mismatch-on-arg.rs create mode 100644 tests/ui/trait-bounds/ownership-mismatch-on-arg.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 8c72f0d90bb58..7301f29b0fd7f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1643,85 +1643,215 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.predicate_must_hold_modulo_regions(&obligation) }; + let trait_pred_and_imm_ref = poly_trait_pred.map_bound(|p| { + (p, Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty())) + }); + let trait_pred_and_mut_ref = poly_trait_pred.map_bound(|p| { + (p, Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty())) + }); + + let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref); + let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref); + let code = match obligation.cause.code() { ObligationCauseCode::FunctionArg { parent_code, .. } => parent_code, // FIXME(compiler-errors): This is kind of a mess, but required for obligations // that come from a path expr to affect the *call* expr. - c @ ObligationCauseCode::WhereClauseInExpr(_, _, hir_id, _) + c @ ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) if self.tcx.hir_span(*hir_id).lo() == span.lo() => { // `hir_id` corresponds to the HIR node that introduced a `where`-clause obligation. - // If that obligation comes from a type in an associated method call, we need - // special handling here. - if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(*hir_id) - && let hir::ExprKind::Call(base, _) = expr.kind - && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, segment)) = base.kind - && let hir::Node::Expr(outer) = self.tcx.parent_hir_node(expr.hir_id) - && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mtbl, _) = outer.kind - && ty.span == span - { - // We've encountered something like `&str::from("")`, where the intended code - // was likely `<&str>::from("")`. The former is interpreted as "call method - // `from` on `str` and borrow the result", while the latter means "call method - // `from` on `&str`". - - let trait_pred_and_imm_ref = poly_trait_pred.map_bound(|p| { - (p, Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty())) - }); - let trait_pred_and_mut_ref = poly_trait_pred.map_bound(|p| { - (p, Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_static, p.self_ty())) - }); + if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(*hir_id) { + // If that obligation comes from a type in an associated method call, we need + // special handling here. + if let hir::ExprKind::Call(base, _) = expr.kind + && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, segment)) = + base.kind + && let hir::Node::Expr(outer) = self.tcx.parent_hir_node(expr.hir_id) + && let hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mtbl, _) = outer.kind + && ty.span == span + { + // We've encountered something like `&str::from("")`, where the intended code + // was likely `<&str>::from("")`. The former is interpreted as "call method + // `from` on `str` and borrow the result", while the latter means "call method + // `from` on `&str`". - let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref); - let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref); - let sugg_msg = |pre: &str| { - format!( - "you likely meant to call the associated function `{FN}` for type \ - `&{pre}{TY}`, but the code as written calls associated function `{FN}` on \ - type `{TY}`", - FN = segment.ident, - TY = poly_trait_pred.self_ty(), - ) - }; - match (imm_ref_self_ty_satisfies_pred, mut_ref_self_ty_satisfies_pred, mtbl) { - (true, _, hir::Mutability::Not) | (_, true, hir::Mutability::Mut) => { - err.multipart_suggestion( - sugg_msg(mtbl.prefix_str()), - vec![ - (outer.span.shrink_to_lo(), "<".to_string()), - (span.shrink_to_hi(), ">".to_string()), - ], - Applicability::MachineApplicable, - ); + let sugg_msg = |pre: &str| { + format!( + "you likely meant to call the associated function `{FN}` for type \ + `&{pre}{TY}`, but the code as written calls associated function `{FN}` on \ + type `{TY}`", + FN = segment.ident, + TY = poly_trait_pred.self_ty(), + ) + }; + match (imm_ref_self_ty_satisfies_pred, mut_ref_self_ty_satisfies_pred, mtbl) + { + (true, _, hir::Mutability::Not) | (_, true, hir::Mutability::Mut) => { + err.multipart_suggestion( + sugg_msg(mtbl.prefix_str()), + vec![ + (outer.span.shrink_to_lo(), "<".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + } + (true, _, hir::Mutability::Mut) => { + // There's an associated function found on the immutable borrow of the + err.multipart_suggestion( + sugg_msg("mut "), + vec![ + (outer.span.shrink_to_lo().until(span), "<&".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + } + (_, true, hir::Mutability::Not) => { + err.multipart_suggestion( + sugg_msg(""), + vec![ + ( + outer.span.shrink_to_lo().until(span), + "<&mut ".to_string(), + ), + (span.shrink_to_hi(), ">".to_string()), + ], + Applicability::MachineApplicable, + ); + } + _ => {} } - (true, _, hir::Mutability::Mut) => { - // There's an associated function found on the immutable borrow of the - err.multipart_suggestion( - sugg_msg("mut "), - vec![ - (outer.span.shrink_to_lo().until(span), "<&".to_string()), - (span.shrink_to_hi(), ">".to_string()), - ], - Applicability::MachineApplicable, + // If we didn't return early here, we would instead suggest `&&str::from("")`. + return false; + } else if let hir::ExprKind::Call(_, args) = expr.kind { + if let Some(typeck_results) = &self.typeck_results + && let Some(pred) = self + .tcx + .predicates_of(*def_id) + .instantiate_identity(self.tcx) + .predicates + .into_iter() + .nth(*idx) + && let Some(pred) = pred.as_trait_clause() + // This feature allows for `for T: Trait`, which fails + // `instantiate_bound_regions_with_erased`. Avoid suggesting for now. + && !self.tcx.features().non_lifetime_binders() + { + let pred_ty = self.tcx.instantiate_bound_regions_with_erased( + pred.self_ty().skip_norm_wip(), ); - } - (_, true, hir::Mutability::Not) => { - err.multipart_suggestion( - sugg_msg(""), - vec![ - (outer.span.shrink_to_lo().until(span), "<&mut ".to_string()), - (span.shrink_to_hi(), ">".to_string()), - ], - Applicability::MachineApplicable, + let fn_sig = self.tcx.instantiate_bound_regions_with_erased( + self.tcx.fn_sig(*def_id).instantiate_identity().skip_norm_wip(), ); + + let mut spans = vec![]; + for (arg, input) in args.into_iter().zip(fn_sig.inputs()) { + if let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(arg) { + let ty = self.tcx.instantiate_bound_regions_with_erased( + poly_trait_pred.self_ty(), + ); + let pred_has_arg_type = + self.infcx.can_eq(param_env, arg_ty, ty); + let arg_is_type_param = + self.infcx.can_eq(param_env, pred_ty, *input); + if pred_has_arg_type && arg_is_type_param { + err.span_label( + arg.span, + format!("`{arg_ty}` doesn't satisfy the trait bound"), + ); + spans.push(arg.span); + } + } + } + let this = pluralize!("this", spans.len()); + if !spans.is_empty() { + if imm_ref_self_ty_satisfies_pred { + err.multipart_suggestion( + format!("consider borrowing {this} argument"), + spans + .iter() + .map(|sp| (sp.shrink_to_lo(), "&".into())) + .collect(), + Applicability::MaybeIncorrect, + ); + } + if mut_ref_self_ty_satisfies_pred { + err.multipart_suggestion( + format!("consider mutably borrowing {this} argument"), + spans + .iter() + .map(|sp| (sp.shrink_to_lo(), "&mut ".into())) + .collect(), + Applicability::MaybeIncorrect, + ); + } + return false; + } } - _ => {} } - // If we didn't return early here, we would instead suggest `&&str::from("")`. - return false; } c } + ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) + if let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id) + && let hir::ExprKind::MethodCall(_segment, rcvr, args, ..) = expr.kind + && let Some(typeck_results) = &self.typeck_results + && let Some(pred) = self + .tcx + .predicates_of(*def_id) + .instantiate_identity(self.tcx) + .predicates + .into_iter() + .nth(*idx) + && let Some(pred) = pred.as_trait_clause() + // This feature allows for `for T: Trait`, which fails + // `instantiate_bound_regions_with_erased`. Avoid suggesting for now. + && !self.tcx.features().non_lifetime_binders() => + { + // We've got a method call where likely one of the arguments didn't meet a bound. + let pred_ty = + self.tcx.instantiate_bound_regions_with_erased(pred.self_ty().skip_norm_wip()); + let fn_sig = self.tcx.instantiate_bound_regions_with_erased( + self.tcx.fn_sig(*def_id).instantiate_identity().skip_norm_wip(), + ); + + let mut spans = vec![]; + for (arg, input) in [rcvr].into_iter().chain(args.into_iter()).zip(fn_sig.inputs()) + { + let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(arg) else { continue }; + let ty = + self.tcx.instantiate_bound_regions_with_erased(poly_trait_pred.self_ty()); + let pred_has_arg_type = self.infcx.can_eq(param_env, arg_ty, ty); + let arg_is_type_param = self.infcx.can_eq(param_env, pred_ty, *input); + if pred_has_arg_type && arg_is_type_param { + err.span_label( + arg.span, + format!("`{arg_ty}` doesn't satisfy the trait bound"), + ); + spans.push(arg.span); + } + } + let this = pluralize!("this", spans.len()); + if !spans.is_empty() { + if imm_ref_self_ty_satisfies_pred { + err.multipart_suggestion( + format!("consider borrowing {this} argument"), + spans.iter().map(|sp| (sp.shrink_to_lo(), "&".into())).collect(), + Applicability::MaybeIncorrect, + ); + } + if mut_ref_self_ty_satisfies_pred { + err.multipart_suggestion( + format!("consider mutably borrowing {this} argument"), + spans.iter().map(|sp| (sp.shrink_to_lo(), "&mut ".into())).collect(), + Applicability::MaybeIncorrect, + ); + } + } + return false; + } c if matches!( span.ctxt().outer_expn_data().kind, ExpnKind::Desugaring(DesugaringKind::ForLoop) diff --git a/tests/ui/delegation/self-mapping-arguments-errors.stderr b/tests/ui/delegation/self-mapping-arguments-errors.stderr index a508721e68640..cd38ad84aeabf 100644 --- a/tests/ui/delegation/self-mapping-arguments-errors.stderr +++ b/tests/ui/delegation/self-mapping-arguments-errors.stderr @@ -22,11 +22,16 @@ LL | | } error[E0277]: the trait bound `(): target_expr_doesnt_relower_when_defs_inside::MyAdd` is not satisfied --> $DIR/self-mapping-arguments-errors.rs:14:5 | -LL | / reuse impl MyAdd for W { -... | -LL | | self.0 -LL | | } - | |_____^ the trait `target_expr_doesnt_relower_when_defs_inside::MyAdd` is not implemented for `()` +LL | reuse impl MyAdd for W { + | _____^ - + | |____________________________| +... || +LL | || self.0 +LL | || } + | || ^ + | ||_____| + | |_____`{type error}` doesn't satisfy the trait bound + | the trait `target_expr_doesnt_relower_when_defs_inside::MyAdd` is not implemented for `()` | help: the following other types implement trait `target_expr_doesnt_relower_when_defs_inside::MyAdd` --> $DIR/self-mapping-arguments-errors.rs:8:5 diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr index 0cb117d3fc4c3..fb5a3e2172da5 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr @@ -16,7 +16,9 @@ error[E0277]: the trait bound `X: A` is not satisfied --> $DIR/as_expression.rs:60:15 | LL | X.start().foo().finish(); - | ^^^ unsatisfied trait bound + | --------- ^^^ unsatisfied trait bound + | | + | `X` doesn't satisfy the trait bound | help: the trait `A` is not implemented for `X` --> $DIR/as_expression.rs:70:1 diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.stderr b/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.stderr index db2a222c8f2c4..148e6ea1e6aca 100644 --- a/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.stderr +++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.stderr @@ -2,7 +2,10 @@ error[E0277]: the trait bound `Foo: intrinsics::bounds::FloatPrimitive` is not s --> $DIR/bad-intrinsic-monomorphization-bounds.rs:16:5 | LL | intrinsics::fadd_fast(a, b) - | ^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | ^^^^^^^^^^^^^^^^^^^^^ - - `Foo` doesn't satisfy the trait bound + | | | + | | `Foo` doesn't satisfy the trait bound + | unsatisfied trait bound | help: the nightly-only, unstable trait `intrinsics::bounds::FloatPrimitive` is not implemented for `Foo` --> $DIR/bad-intrinsic-monomorphization-bounds.rs:13:1 diff --git a/tests/ui/trait-bounds/ownership-mismatch-on-arg.rs b/tests/ui/trait-bounds/ownership-mismatch-on-arg.rs new file mode 100644 index 0000000000000..a3d3b8a9a0826 --- /dev/null +++ b/tests/ui/trait-bounds/ownership-mismatch-on-arg.rs @@ -0,0 +1,47 @@ +// #134805 +mod needs_deref { + #[derive(Clone, Copy, Debug)] + struct Hello; + + trait Tr: Clone + Copy {} + impl Tr for Hello {} + + fn foo(_v: T, _w: T, _k: K) {} + + struct S; + impl S { + fn foo(&self, _v: T, _w: T, _k: K) {} + } + + fn bar() { + let hellos = [Hello; 3]; + for hi in hellos.iter() { + foo(hi, hi, hi); //~ ERROR: the trait bound `&needs_deref::Hello: needs_deref::Tr` is not satisfied + S.foo(hi, hi, hi); //~ ERROR: the trait bound `&needs_deref::Hello: needs_deref::Tr` is not satisfied + } + } +} + +mod needs_borrow { + #[derive(Clone, Copy, Debug)] + struct Hello; + + trait Tr: Clone + Copy {} + impl Tr for &Hello {} + + fn foo(_v: T, _w: T, _k: K) {} + + struct S; + impl S { + fn foo(&self, _v: T, _w: T, _k: K) {} + } + + fn bar() { + let hellos = [Hello; 3]; + for hi in hellos { + foo(hi, hi, hi); //~ ERROR: the trait bound `needs_borrow::Hello: needs_borrow::Tr` is not satisfied + S.foo(hi, hi, hi); //~ ERROR: the trait bound `needs_borrow::Hello: needs_borrow::Tr` is not satisfied + } + } +} +fn main() {} diff --git a/tests/ui/trait-bounds/ownership-mismatch-on-arg.stderr b/tests/ui/trait-bounds/ownership-mismatch-on-arg.stderr new file mode 100644 index 0000000000000..0d1f944dacfe8 --- /dev/null +++ b/tests/ui/trait-bounds/ownership-mismatch-on-arg.stderr @@ -0,0 +1,96 @@ +error[E0277]: the trait bound `&needs_deref::Hello: needs_deref::Tr` is not satisfied + --> $DIR/ownership-mismatch-on-arg.rs:19:13 + | +LL | foo(hi, hi, hi); + | ^^^ -- -- `&needs_deref::Hello` doesn't satisfy the trait bound + | | | + | | `&needs_deref::Hello` doesn't satisfy the trait bound + | the trait `needs_deref::Tr` is not implemented for `&needs_deref::Hello` + | +note: required by a bound in `needs_deref::foo` + --> $DIR/ownership-mismatch-on-arg.rs:9:15 + | +LL | fn foo(_v: T, _w: T, _k: K) {} + | ^^ required by this bound in `foo` + +error[E0277]: the trait bound `&needs_deref::Hello: needs_deref::Tr` is not satisfied + --> $DIR/ownership-mismatch-on-arg.rs:20:15 + | +LL | S.foo(hi, hi, hi); + | ^^^ -- -- `&needs_deref::Hello` doesn't satisfy the trait bound + | | | + | | `&needs_deref::Hello` doesn't satisfy the trait bound + | the trait `needs_deref::Tr` is not implemented for `&needs_deref::Hello` + | +help: the trait `needs_deref::Tr` is implemented for `needs_deref::Hello` + --> $DIR/ownership-mismatch-on-arg.rs:7:5 + | +LL | impl Tr for Hello {} + | ^^^^^^^^^^^^^^^^^ +note: required by a bound in `needs_deref::S::foo` + --> $DIR/ownership-mismatch-on-arg.rs:13:39 + | +LL | fn foo(&self, _v: T, _w: T, _k: K) {} + | ^^ required by this bound in `S::foo` + +error[E0277]: the trait bound `needs_borrow::Hello: needs_borrow::Tr` is not satisfied + --> $DIR/ownership-mismatch-on-arg.rs:42:13 + | +LL | foo(hi, hi, hi); + | ^^^ -- -- `needs_borrow::Hello` doesn't satisfy the trait bound + | | | + | | `needs_borrow::Hello` doesn't satisfy the trait bound + | unsatisfied trait bound + | +help: the trait `needs_borrow::Tr` is not implemented for `needs_borrow::Hello` + --> $DIR/ownership-mismatch-on-arg.rs:27:5 + | +LL | struct Hello; + | ^^^^^^^^^^^^ +help: the trait `needs_borrow::Tr` is implemented for `&needs_borrow::Hello` + --> $DIR/ownership-mismatch-on-arg.rs:30:5 + | +LL | impl Tr for &Hello {} + | ^^^^^^^^^^^^^^^^^^ +note: required by a bound in `needs_borrow::foo` + --> $DIR/ownership-mismatch-on-arg.rs:32:15 + | +LL | fn foo(_v: T, _w: T, _k: K) {} + | ^^ required by this bound in `foo` +help: consider borrowing these argument + | +LL | foo(&hi, &hi, hi); + | + + + +error[E0277]: the trait bound `needs_borrow::Hello: needs_borrow::Tr` is not satisfied + --> $DIR/ownership-mismatch-on-arg.rs:43:15 + | +LL | S.foo(hi, hi, hi); + | ^^^ -- -- `needs_borrow::Hello` doesn't satisfy the trait bound + | | | + | | `needs_borrow::Hello` doesn't satisfy the trait bound + | unsatisfied trait bound + | +help: the trait `needs_borrow::Tr` is not implemented for `needs_borrow::Hello` + --> $DIR/ownership-mismatch-on-arg.rs:27:5 + | +LL | struct Hello; + | ^^^^^^^^^^^^ +help: the trait `needs_borrow::Tr` is implemented for `&needs_borrow::Hello` + --> $DIR/ownership-mismatch-on-arg.rs:30:5 + | +LL | impl Tr for &Hello {} + | ^^^^^^^^^^^^^^^^^^ +note: required by a bound in `needs_borrow::S::foo` + --> $DIR/ownership-mismatch-on-arg.rs:36:19 + | +LL | fn foo(&self, _v: T, _w: T, _k: K) {} + | ^^ required by this bound in `S::foo` +help: consider borrowing these argument + | +LL | S.foo(&hi, &hi, hi); + | + + + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. From 1e1a6990917f1f0292e35387659a3260e99f09d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 29 Jul 2026 08:47:59 +0000 Subject: [PATCH 19/53] deduplicate method/function call "point at arg" logic --- .../src/error_reporting/traits/suggestions.rs | 152 ++++++++---------- 1 file changed, 65 insertions(+), 87 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 7301f29b0fd7f..75937ff5531b5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1653,6 +1653,44 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref); let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref); + let mut point_at_relevant_args = + |pred_ty: Ty<'tcx>, args_and_inputs: Vec<(hir::Expr<'_>, Ty<'tcx>)>| { + let Some(typeck_results) = &self.typeck_results else { return false }; + + let erased_self_ty = + self.tcx.instantiate_bound_regions_with_erased(poly_trait_pred.self_ty()); + let mut spans = vec![]; + for (arg, input) in args_and_inputs { + let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(&arg) else { continue }; + let pred_has_arg_type = self.infcx.can_eq(param_env, arg_ty, erased_self_ty); + let arg_is_type_param = self.infcx.can_eq(param_env, pred_ty, input); + if pred_has_arg_type && arg_is_type_param { + err.span_label( + arg.span, + format!("`{arg_ty}` doesn't satisfy the trait bound"), + ); + spans.push(arg.span); + } + } + let this = pluralize!("this", spans.len()); + if !spans.is_empty() { + if imm_ref_self_ty_satisfies_pred { + err.multipart_suggestion( + format!("consider borrowing {this} argument"), + spans.iter().map(|sp| (sp.shrink_to_lo(), "&".into())).collect(), + Applicability::MaybeIncorrect, + ); + } + if mut_ref_self_ty_satisfies_pred { + err.multipart_suggestion( + format!("consider mutably borrowing {this} argument"), + spans.iter().map(|sp| (sp.shrink_to_lo(), "&mut ".into())).collect(), + Applicability::MaybeIncorrect, + ); + } + } + !spans.is_empty() + }; let code = match obligation.cause.code() { ObligationCauseCode::FunctionArg { parent_code, .. } => parent_code, // FIXME(compiler-errors): This is kind of a mess, but required for obligations @@ -1726,12 +1764,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // If we didn't return early here, we would instead suggest `&&str::from("")`. return false; } else if let hir::ExprKind::Call(_, args) = expr.kind { - if let Some(typeck_results) = &self.typeck_results - && let Some(pred) = self + if let Some(pred) = self .tcx - .predicates_of(*def_id) + .clauses_of(*def_id) .instantiate_identity(self.tcx) - .predicates + .clauses .into_iter() .nth(*idx) && let Some(pred) = pred.as_trait_clause() @@ -1745,48 +1782,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let fn_sig = self.tcx.instantiate_bound_regions_with_erased( self.tcx.fn_sig(*def_id).instantiate_identity().skip_norm_wip(), ); - - let mut spans = vec![]; - for (arg, input) in args.into_iter().zip(fn_sig.inputs()) { - if let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(arg) { - let ty = self.tcx.instantiate_bound_regions_with_erased( - poly_trait_pred.self_ty(), - ); - let pred_has_arg_type = - self.infcx.can_eq(param_env, arg_ty, ty); - let arg_is_type_param = - self.infcx.can_eq(param_env, pred_ty, *input); - if pred_has_arg_type && arg_is_type_param { - err.span_label( - arg.span, - format!("`{arg_ty}` doesn't satisfy the trait bound"), - ); - spans.push(arg.span); - } - } - } - let this = pluralize!("this", spans.len()); - if !spans.is_empty() { - if imm_ref_self_ty_satisfies_pred { - err.multipart_suggestion( - format!("consider borrowing {this} argument"), - spans - .iter() - .map(|sp| (sp.shrink_to_lo(), "&".into())) - .collect(), - Applicability::MaybeIncorrect, - ); - } - if mut_ref_self_ty_satisfies_pred { - err.multipart_suggestion( - format!("consider mutably borrowing {this} argument"), - spans - .iter() - .map(|sp| (sp.shrink_to_lo(), "&mut ".into())) - .collect(), - Applicability::MaybeIncorrect, - ); - } + if point_at_relevant_args( + pred_ty, + args.into_iter() + .zip(fn_sig.inputs()) + .map(|(e, t)| (*e, *t)) + .collect(), + ) { return false; } } @@ -1794,15 +1796,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } c } - ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) + c @ ObligationCauseCode::WhereClauseInExpr(def_id, _, hir_id, idx) if let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id) && let hir::ExprKind::MethodCall(_segment, rcvr, args, ..) = expr.kind - && let Some(typeck_results) = &self.typeck_results && let Some(pred) = self .tcx - .predicates_of(*def_id) + .clauses_of(*def_id) .instantiate_identity(self.tcx) - .predicates + .clauses .into_iter() .nth(*idx) && let Some(pred) = pred.as_trait_clause() @@ -1810,47 +1811,24 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // `instantiate_bound_regions_with_erased`. Avoid suggesting for now. && !self.tcx.features().non_lifetime_binders() => { - // We've got a method call where likely one of the arguments didn't meet a bound. - let pred_ty = - self.tcx.instantiate_bound_regions_with_erased(pred.self_ty().skip_norm_wip()); let fn_sig = self.tcx.instantiate_bound_regions_with_erased( self.tcx.fn_sig(*def_id).instantiate_identity().skip_norm_wip(), ); - - let mut spans = vec![]; - for (arg, input) in [rcvr].into_iter().chain(args.into_iter()).zip(fn_sig.inputs()) - { - let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(arg) else { continue }; - let ty = - self.tcx.instantiate_bound_regions_with_erased(poly_trait_pred.self_ty()); - let pred_has_arg_type = self.infcx.can_eq(param_env, arg_ty, ty); - let arg_is_type_param = self.infcx.can_eq(param_env, pred_ty, *input); - if pred_has_arg_type && arg_is_type_param { - err.span_label( - arg.span, - format!("`{arg_ty}` doesn't satisfy the trait bound"), - ); - spans.push(arg.span); - } - } - let this = pluralize!("this", spans.len()); - if !spans.is_empty() { - if imm_ref_self_ty_satisfies_pred { - err.multipart_suggestion( - format!("consider borrowing {this} argument"), - spans.iter().map(|sp| (sp.shrink_to_lo(), "&".into())).collect(), - Applicability::MaybeIncorrect, - ); - } - if mut_ref_self_ty_satisfies_pred { - err.multipart_suggestion( - format!("consider mutably borrowing {this} argument"), - spans.iter().map(|sp| (sp.shrink_to_lo(), "&mut ".into())).collect(), - Applicability::MaybeIncorrect, - ); - } + // We've got a method call where likely one of the arguments didn't meet a bound. + let pred_ty = + self.tcx.instantiate_bound_regions_with_erased(pred.self_ty().skip_norm_wip()); + if point_at_relevant_args( + pred_ty, + [rcvr] + .into_iter() + .chain(args.into_iter()) + .zip(fn_sig.inputs()) + .map(|(e, t)| (*e, *t)) + .collect(), + ) { + return false; } - return false; + c } c if matches!( span.ctxt().outer_expn_data().kind, From c257aefd56c79af1ac53265f74d225c9660c70bd Mon Sep 17 00:00:00 2001 From: chiri Date: Wed, 29 Jul 2026 18:29:20 +0300 Subject: [PATCH 20/53] review (x3) --- library/core/src/fmt/num.rs | 40 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index f94e5433a5183..1a986d88e0e0d 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -693,11 +693,11 @@ impl u128 { let quad = remain % 1_00_00; remain /= 1_00_00; - write_quad( - // SAFETY: `offset >= 4` was asserted above. - unsafe { buf.get_unchecked_mut(offset..offset + 4) }, - quad, - ); + // SAFETY: quad is a remainder modulo 10_000. The offset checks + // above reserve exactly four bytes in buf. + unsafe { + write_quad(buf.get_unchecked_mut(offset..offset + 4), quad); + } } // Format per two digits from the lookup table. @@ -814,8 +814,12 @@ impl i128 { } /// Writes `quad` as exactly four digits (for example: `42` becomes `"0042"`). +/// +/// # Safety +/// +/// `quad` must be below 10_000 and `buf` must contain exactly four bytes. #[inline(always)] -fn write_quad(buf: &mut [MaybeUninit], quad: u64) { +unsafe fn write_quad(buf: &mut [MaybeUninit], quad: u64) { // SAFETY: These are this function's caller-provided invariants. unsafe { core::hint::assert_unchecked(quad < 10_000); @@ -855,20 +859,20 @@ fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { let quad = remain % 1_00_00; remain /= 1_00_00; - write_quad( - // SAFETY: `OFFSET + 16 <= buf.len()` and `quad_index < 4`, so this range is within `buf`. - unsafe { - buf.get_unchecked_mut(OFFSET + quad_index * 4..OFFSET + (quad_index + 1) * 4) - }, - quad, - ); + // SAFETY: `OFFSET + quad_index * 4` starts one of the four + // non-overlapping four-byte regions proven in bounds above. + unsafe { + write_quad( + buf.get_unchecked_mut(OFFSET + quad_index * 4..OFFSET + (quad_index + 1) * 4), + quad, + ); + } } - write_quad( - // SAFETY: `OFFSET + 16 <= buf.len()` was asserted above. - unsafe { buf.get_unchecked_mut(OFFSET..OFFSET + 4) }, - remain, - ); + // SAFETY: OFFSET starts the first four-byte region proven in bounds above. + unsafe { + write_quad(buf.get_unchecked_mut(OFFSET..OFFSET + 4), remain); + } } /// Euclidean division plus remainder with constant 1E16 basically consumes 16 From 1d77f8a61e245f45c13a8fe863cc7521dc59b818 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 29 Jul 2026 18:21:29 +0200 Subject: [PATCH 21/53] reject varargs without pattern post-expansion --- .../rustc_ast_passes/src/ast_validation.rs | 7 + compiler/rustc_ast_passes/src/diagnostics.rs | 12 ++ ...-varargs-without-pattern-post-expansion.rs | 55 +++++ ...args-without-pattern-post-expansion.stderr | 191 ++++++++++++++++++ tests/ui/thir-print/c-variadic.rs | 4 +- tests/ui/thir-print/c-variadic.stderr | 12 -- tests/ui/thir-print/c-variadic.stdout | 14 +- 7 files changed, 273 insertions(+), 22 deletions(-) create mode 100644 tests/ui/c-variadic/reject-varargs-without-pattern-post-expansion.rs create mode 100644 tests/ui/c-variadic/reject-varargs-without-pattern-post-expansion.stderr delete mode 100644 tests/ui/thir-print/c-variadic.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0e47424ba1aa4..587f950a67720 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -929,6 +929,13 @@ impl<'a> AstValidator<'a> { match fn_ctxt { FnCtxt::Foreign => return, FnCtxt::Free | FnCtxt::Assoc(_) => { + // Reject `...` without a pattern post-expansion. The varargs_without_pattern + // FCW is already triggered pre-expansion. + if let PatKind::Missing = variadic_param.pat.kind { + self.dcx() + .emit_err(diagnostics::VarargsWithoutPattern { span: variadic_param.span }); + } + match self.sess.target.supports_c_variadic_definitions() { CVariadicStatus::NotSupported => { self.dcx().emit_err(diagnostics::CVariadicNotSupported { diff --git a/compiler/rustc_ast_passes/src/diagnostics.rs b/compiler/rustc_ast_passes/src/diagnostics.rs index af22ead1332d1..0ed0c2095808c 100644 --- a/compiler/rustc_ast_passes/src/diagnostics.rs +++ b/compiler/rustc_ast_passes/src/diagnostics.rs @@ -1243,3 +1243,15 @@ pub(crate) enum DeprecatedWhereClauseLocationSugg { span: Span, }, } + +#[derive(Diagnostic)] +#[diag("missing pattern for `...` argument")] +pub(crate) struct VarargsWithoutPattern { + #[suggestion( + "add a pattern for this argument", + applicability = "machine-applicable", + code = "_: ..." + )] + #[primary_span] + pub span: Span, +} diff --git a/tests/ui/c-variadic/reject-varargs-without-pattern-post-expansion.rs b/tests/ui/c-variadic/reject-varargs-without-pattern-post-expansion.rs new file mode 100644 index 0000000000000..d68cf940290bf --- /dev/null +++ b/tests/ui/c-variadic/reject-varargs-without-pattern-post-expansion.rs @@ -0,0 +1,55 @@ +#![crate_type = "lib"] +#![warn(varargs_without_pattern)] + +// Test that we reject a bare `...` without a pattern post-expansion in function definitons and +// trait method declarations. On foreign function declarations it is allowed. +// +// We have the `varargs_without_pattern` FCW for this idiom, with the intent to eventually also +// reject this idiom pre-expansion. + +// Bare `...` is allowed in extern blocks. +extern "C" { + fn g(...); +} + +// When the `...` argument does not make it past expansion, that only lints. +macro_rules! discard_item { + ($item:item) => {}; +} + +discard_item! { + unsafe extern "C" fn f(...) -> i32 { + //~^ WARN missing pattern for `...` argument + //~| WARN this was previously accepted by the compiler but is being phased out + 0 + } +} + +// But when it does make it post-expansion, that is a hard error. +macro_rules! identity_item { + ($item:item) => { + $item + }; +} + +identity_item! { + unsafe extern "C" fn f(...) {} + //~^ ERROR missing pattern for `...` argument + //~| WARN missing pattern for `...` argument + //~| WARN this was previously accepted by the compiler but is being phased out + //~| WARN missing pattern for `...` argument + //~| WARN this was previously accepted by the compiler but is being phased out +} + +trait T { + identity_item! { + unsafe extern "C" fn f(...); + //~^ ERROR missing pattern for `...` argument + //~| WARN missing pattern for `...` argument + //~| WARN this was previously accepted by the compiler but is being phased out + //~| WARN missing pattern for `...` argument + //~| WARN this was previously accepted by the compiler but is being phased out + //~| WARN anonymous_parameters + //~| WARN this is accepted in the current edition (Rust 2015) + } +} diff --git a/tests/ui/c-variadic/reject-varargs-without-pattern-post-expansion.stderr b/tests/ui/c-variadic/reject-varargs-without-pattern-post-expansion.stderr new file mode 100644 index 0000000000000..f9243c97f2522 --- /dev/null +++ b/tests/ui/c-variadic/reject-varargs-without-pattern-post-expansion.stderr @@ -0,0 +1,191 @@ +error: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:36:28 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ help: add a pattern for this argument: `_: ...` + +error: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:46:32 + | +LL | unsafe extern "C" fn f(...); + | ^^^ help: add a pattern for this argument: `_: ...` + +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:21:28 + | +LL | unsafe extern "C" fn f(...) -> i32 { + | ^^^ + | + = 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 #145544 +note: the lint level is defined here + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:2:9 + | +LL | #![warn(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) -> i32 { + | ++ + +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:36:28 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = 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 #145544 +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:36:28 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = 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 #145544 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:46:32 + | +LL | unsafe extern "C" fn f(...); + | ^^^ + | + = 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 #145544 +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...); + | ++ + +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:46:32 + | +LL | unsafe extern "C" fn f(...); + | ^^^ + | + = 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 #145544 + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...); + | ++ + +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:46:32 + | +LL | unsafe extern "C" fn f(...); + | ^^^ help: try naming the parameter or explicitly ignoring it: `_: ...` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see + = note: `#[warn(anonymous_parameters)]` (part of `#[warn(rust_2018_compatibility)]`) on by default + +error: aborting due to 2 previous errors; 6 warnings emitted + +Future incompatibility report: Future breakage diagnostic: +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:21:28 + | +LL | unsafe extern "C" fn f(...) -> i32 { + | ^^^ + | + = 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 #145544 +note: the lint level is defined here + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:2:9 + | +LL | #![warn(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) -> i32 { + | ++ + +Future breakage diagnostic: +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:36:28 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = 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 #145544 +note: the lint level is defined here + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:2:9 + | +LL | #![warn(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +Future breakage diagnostic: +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:36:28 + | +LL | unsafe extern "C" fn f(...) {} + | ^^^ + | + = 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 #145544 +note: the lint level is defined here + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:2:9 + | +LL | #![warn(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...) {} + | ++ + +Future breakage diagnostic: +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:46:32 + | +LL | unsafe extern "C" fn f(...); + | ^^^ + | + = 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 #145544 +note: the lint level is defined here + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:2:9 + | +LL | #![warn(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...); + | ++ + +Future breakage diagnostic: +warning: missing pattern for `...` argument + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:46:32 + | +LL | unsafe extern "C" fn f(...); + | ^^^ + | + = 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 #145544 +note: the lint level is defined here + --> $DIR/reject-varargs-without-pattern-post-expansion.rs:2:9 + | +LL | #![warn(varargs_without_pattern)] + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: name the argument, or use `_` to continue ignoring it + | +LL | unsafe extern "C" fn f(_: ...); + | ++ + diff --git a/tests/ui/thir-print/c-variadic.rs b/tests/ui/thir-print/c-variadic.rs index b07c422ea3cd4..2dbf2d5179190 100644 --- a/tests/ui/thir-print/c-variadic.rs +++ b/tests/ui/thir-print/c-variadic.rs @@ -1,6 +1,4 @@ //@ compile-flags: -Zunpretty=thir-tree --crate-type=lib //@ check-pass -#![expect(varargs_without_pattern)] -// The `...` argument uses `PatKind::Missing`. -unsafe extern "C" fn foo(_: i32, ...) {} +unsafe extern "C" fn foo(_: i32, _: ...) {} diff --git a/tests/ui/thir-print/c-variadic.stderr b/tests/ui/thir-print/c-variadic.stderr deleted file mode 100644 index e05e50a93f57d..0000000000000 --- a/tests/ui/thir-print/c-variadic.stderr +++ /dev/null @@ -1,12 +0,0 @@ -Future incompatibility report: Future breakage diagnostic: -warning: missing pattern for `...` argument - --> $DIR/c-variadic.rs:6:34 - | -LL | unsafe extern "C" fn foo(_: i32, ...) {} - | ^^^ - | -help: name the argument, or use `_` to continue ignoring it - | -LL | unsafe extern "C" fn foo(_: i32, _: ...) {} - | ++ - diff --git a/tests/ui/thir-print/c-variadic.stdout b/tests/ui/thir-print/c-variadic.stdout index ad6dacb4753b3..466825e4dc116 100644 --- a/tests/ui/thir-print/c-variadic.stdout +++ b/tests/ui/thir-print/c-variadic.stdout @@ -2,13 +2,13 @@ DefId(0:3 ~ c_variadic[a5de]::foo): params: [ Param { ty: i32 - ty_span: Some($DIR/c-variadic.rs:6:29: 6:32 (#0)) + ty_span: Some($DIR/c-variadic.rs:4:29: 4:32 (#0)) self_kind: None hir_id: Some(HirId(DefId(0:3 ~ c_variadic[a5de]::foo).1)) param: Some( Pat { ty: i32 - span: $DIR/c-variadic.rs:6:26: 6:27 (#0) + span: $DIR/c-variadic.rs:4:26: 4:27 (#0) kind: PatKind { Wild } @@ -23,9 +23,9 @@ params: [ param: Some( Pat { ty: std::ffi::VaList<'{erased}> - span: $DIR/c-variadic.rs:6:34: 6:37 (#0) + span: $DIR/c-variadic.rs:4:34: 4:35 (#0) kind: PatKind { - Missing + Wild } } ) @@ -35,7 +35,7 @@ body: Expr { ty: () temp_scope_id: 6 - span: $DIR/c-variadic.rs:6:39: 6:41 (#0) + span: $DIR/c-variadic.rs:4:42: 4:44 (#0) kind: Scope { region_scope: Node(6) @@ -44,11 +44,11 @@ body: Expr { ty: () temp_scope_id: 6 - span: $DIR/c-variadic.rs:6:39: 6:41 (#0) + span: $DIR/c-variadic.rs:4:42: 4:44 (#0) kind: Block { targeted_by_break: false - span: $DIR/c-variadic.rs:6:39: 6:41 (#0) + span: $DIR/c-variadic.rs:4:42: 4:44 (#0) region_scope: Node(5) safety_mode: Safe stmts: [] From 2851362dad76921eed9226244984301290ad2b44 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 29 Jul 2026 18:43:03 +0300 Subject: [PATCH 22/53] tests: Enable `feature(stmt_expr_attributes)` in `2229_closure_analysis` tests --- .../arrays-completely-captured.rs | 5 +- .../arrays-completely-captured.stderr | 23 +- .../2229_closure_analysis/by_value.rs | 5 +- .../2229_closure_analysis/by_value.stderr | 25 +-- .../capture-analysis-1.rs | 5 +- .../capture-analysis-1.stderr | 29 +-- .../capture-analysis-2.rs | 5 +- .../capture-analysis-2.stderr | 23 +- .../capture-analysis-3.rs | 5 +- .../capture-analysis-3.stderr | 23 +- .../capture-analysis-4.rs | 5 +- .../capture-analysis-4.stderr | 23 +- .../capture-disjoint-field-struct.rs | 5 +- .../capture-disjoint-field-struct.stderr | 21 +- .../capture-disjoint-field-tuple.rs | 5 +- .../capture-disjoint-field-tuple.stderr | 21 +- .../deep-multilevel-struct.rs | 5 +- .../deep-multilevel-struct.stderr | 25 +-- .../deep-multilevel-tuple.rs | 5 +- .../deep-multilevel-tuple.stderr | 25 +-- .../destructure_patterns.rs | 11 +- .../destructure_patterns.stderr | 73 ++----- .../feature-gate-capture_disjoint_fields.rs | 5 +- ...eature-gate-capture_disjoint_fields.stderr | 21 +- .../2229_closure_analysis/issue-87378.rs | 5 +- .../2229_closure_analysis/issue-87378.stderr | 21 +- .../2229_closure_analysis/issue-88476.rs | 12 +- .../2229_closure_analysis/issue-88476.stderr | 47 ++-- .../2229_closure_analysis/move_closure.rs | 41 +--- .../2229_closure_analysis/move_closure.stderr | 201 ++++-------------- .../multilevel-path-1.rs | 5 +- .../multilevel-path-1.stderr | 21 +- .../multilevel-path-2.rs | 5 +- .../multilevel-path-2.stderr | 21 +- .../2229_closure_analysis/nested-closure.rs | 8 +- .../nested-closure.stderr | 49 ++--- .../optimization/edge_case.rs | 7 +- .../optimization/edge_case.stderr | 13 +- .../path-with-array-access.rs | 5 +- .../path-with-array-access.stderr | 21 +- .../preserve_field_drop_order.rs | 11 +- .../preserve_field_drop_order.stderr | 93 +++----- .../2229_closure_analysis/repr_packed.rs | 11 +- .../2229_closure_analysis/repr_packed.stderr | 63 ++---- .../simple-struct-min-capture.rs | 5 +- .../simple-struct-min-capture.stderr | 23 +- .../2229_closure_analysis/unsafe_ptr.rs | 8 +- .../2229_closure_analysis/unsafe_ptr.stderr | 39 +--- .../2229_closure_analysis/wild_patterns.rs | 11 +- .../wild_patterns.stderr | 57 ++--- 50 files changed, 295 insertions(+), 906 deletions(-) diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs index 27b17a56f129f..01271313d54dd 100644 --- a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs +++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs @@ -1,14 +1,11 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] // Ensure that capture analysis results in arrays being completely captured. fn main() { let mut m = [1, 2, 3, 4, 5]; let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr index cb351d3cebd40..2599927e9c602 100644 --- a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr +++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/arrays-completely-captured.rs:8:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/arrays-completely-captured.rs:12:5 + --> $DIR/arrays-completely-captured.rs:9:5 | LL | / || { LL | | @@ -20,18 +10,18 @@ LL | | }; | |_____^ | note: Capturing m[] -> Mutable - --> $DIR/arrays-completely-captured.rs:15:9 + --> $DIR/arrays-completely-captured.rs:12:9 | LL | m[0] += 10; | ^ note: Capturing m[] -> Mutable - --> $DIR/arrays-completely-captured.rs:18:9 + --> $DIR/arrays-completely-captured.rs:15:9 | LL | m[1] += 40; | ^ error: Min Capture analysis includes: - --> $DIR/arrays-completely-captured.rs:12:5 + --> $DIR/arrays-completely-captured.rs:9:5 | LL | / || { LL | | @@ -42,11 +32,10 @@ LL | | }; | |_____^ | note: Min Capture m[] -> Mutable - --> $DIR/arrays-completely-captured.rs:15:9 + --> $DIR/arrays-completely-captured.rs:12:9 | LL | m[0] += 10; | ^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/by_value.rs b/tests/ui/closures/2229_closure_analysis/by_value.rs index 605b8ea35e51f..9c382f77f6395 100644 --- a/tests/ui/closures/2229_closure_analysis/by_value.rs +++ b/tests/ui/closures/2229_closure_analysis/by_value.rs @@ -2,7 +2,7 @@ // Test that we handle derferences properly when only some of the captures are being moved with // `capture_disjoint_fields` enabled. -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #[derive(Debug, Default)] struct SomeLargeType; @@ -16,9 +16,6 @@ fn big_box() { let t = (b, 10); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/by_value.stderr b/tests/ui/closures/2229_closure_analysis/by_value.stderr index af4ae34ad64e3..2201c7039f452 100644 --- a/tests/ui/closures/2229_closure_analysis/by_value.stderr +++ b/tests/ui/closures/2229_closure_analysis/by_value.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/by_value.rs:18:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/by_value.rs:22:5 + --> $DIR/by_value.rs:19:5 | LL | / || { LL | | @@ -20,18 +10,18 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue - --> $DIR/by_value.rs:25:17 + --> $DIR/by_value.rs:22:17 | LL | let p = t.0.0; | ^^^^^ note: Capturing t[(1, 0)] -> Immutable - --> $DIR/by_value.rs:28:29 + --> $DIR/by_value.rs:25:29 | LL | println!("{} {:?}", t.1, p); | ^^^ error: Min Capture analysis includes: - --> $DIR/by_value.rs:22:5 + --> $DIR/by_value.rs:19:5 | LL | / || { LL | | @@ -42,16 +32,15 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/by_value.rs:25:17 + --> $DIR/by_value.rs:22:17 | LL | let p = t.0.0; | ^^^^^ note: Min Capture t[(1, 0)] -> Immutable - --> $DIR/by_value.rs:28:29 + --> $DIR/by_value.rs:25:29 | LL | println!("{} {:?}", t.1, p); | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs index 3eb5cef30056d..dcb19d63f6784 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #[derive(Debug)] struct Point { @@ -13,9 +13,6 @@ fn main() { let q = Point { x: 10, y: 10 }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr index eef201792c634..bd94e2b1857f7 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-1.rs:15:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/capture-analysis-1.rs:19:5 + --> $DIR/capture-analysis-1.rs:16:5 | LL | / || { LL | | @@ -20,28 +10,28 @@ LL | | }; | |_____^ | note: Capturing p[] -> Immutable - --> $DIR/capture-analysis-1.rs:22:26 + --> $DIR/capture-analysis-1.rs:19:26 | LL | println!("{:?}", p); | ^ note: Capturing p[(0, 0)] -> Immutable - --> $DIR/capture-analysis-1.rs:25:26 + --> $DIR/capture-analysis-1.rs:22:26 | LL | println!("{:?}", p.x); | ^^^ note: Capturing q[(0, 0)] -> Immutable - --> $DIR/capture-analysis-1.rs:28:26 + --> $DIR/capture-analysis-1.rs:25:26 | LL | println!("{:?}", q.x); | ^^^ note: Capturing q[] -> Immutable - --> $DIR/capture-analysis-1.rs:30:26 + --> $DIR/capture-analysis-1.rs:27:26 | LL | println!("{:?}", q); | ^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-1.rs:19:5 + --> $DIR/capture-analysis-1.rs:16:5 | LL | / || { LL | | @@ -52,16 +42,15 @@ LL | | }; | |_____^ | note: Min Capture p[] -> Immutable - --> $DIR/capture-analysis-1.rs:22:26 + --> $DIR/capture-analysis-1.rs:19:26 | LL | println!("{:?}", p); | ^ note: Min Capture q[] -> Immutable - --> $DIR/capture-analysis-1.rs:30:26 + --> $DIR/capture-analysis-1.rs:27:26 | LL | println!("{:?}", q); | ^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs index e6cda82480937..cc995943abe90 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #[derive(Debug)] struct Point { @@ -12,9 +12,6 @@ fn main() { let mut p = Point { x: String::new(), y: 10 }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr index 8fe4d2d57ab0a..b0fcf19a3db20 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-2.rs:14:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/capture-analysis-2.rs:18:5 + --> $DIR/capture-analysis-2.rs:15:5 | LL | / || { LL | | @@ -20,18 +10,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> ByValue - --> $DIR/capture-analysis-2.rs:21:18 + --> $DIR/capture-analysis-2.rs:18:18 | LL | let _x = p.x; | ^^^ note: Capturing p[] -> Immutable - --> $DIR/capture-analysis-2.rs:24:26 + --> $DIR/capture-analysis-2.rs:21:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-2.rs:18:5 + --> $DIR/capture-analysis-2.rs:15:5 | LL | / || { LL | | @@ -42,7 +32,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> ByValue - --> $DIR/capture-analysis-2.rs:21:18 + --> $DIR/capture-analysis-2.rs:18:18 | LL | let _x = p.x; | ^^^ p[] captured as ByValue here @@ -50,6 +40,5 @@ LL | let _x = p.x; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs index b25b613b61c02..d086ba87b870b 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #[derive(Debug)] struct Child { @@ -17,9 +17,6 @@ fn main() { let mut a = Parent { b: Child {c: String::new(), d: String::new()} }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr index f1dbefe15d525..e7f79acba50b8 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-3.rs:19:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/capture-analysis-3.rs:23:5 + --> $DIR/capture-analysis-3.rs:20:5 | LL | / || { LL | | @@ -20,18 +10,18 @@ LL | | }; | |_____^ | note: Capturing a[(0, 0),(0, 0)] -> ByValue - --> $DIR/capture-analysis-3.rs:26:18 + --> $DIR/capture-analysis-3.rs:23:18 | LL | let _x = a.b.c; | ^^^^^ note: Capturing a[(0, 0)] -> Immutable - --> $DIR/capture-analysis-3.rs:29:26 + --> $DIR/capture-analysis-3.rs:26:26 | LL | println!("{:?}", a.b); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-3.rs:23:5 + --> $DIR/capture-analysis-3.rs:20:5 | LL | / || { LL | | @@ -42,7 +32,7 @@ LL | | }; | |_____^ | note: Min Capture a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-3.rs:26:18 + --> $DIR/capture-analysis-3.rs:23:18 | LL | let _x = a.b.c; | ^^^^^ a[(0, 0)] captured as ByValue here @@ -50,6 +40,5 @@ LL | let _x = a.b.c; LL | println!("{:?}", a.b); | ^^^ a[(0, 0)] used here -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs index 355e36c1463be..54e5acd19687b 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #[derive(Debug)] struct Child { @@ -17,9 +17,6 @@ fn main() { let mut a = Parent { b: Child {c: String::new(), d: String::new()} }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr index 91c3d6d16745e..01aa344b12c67 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/capture-analysis-4.rs:19:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/capture-analysis-4.rs:23:5 + --> $DIR/capture-analysis-4.rs:20:5 | LL | / || { LL | | @@ -20,18 +10,18 @@ LL | | }; | |_____^ | note: Capturing a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-4.rs:26:18 + --> $DIR/capture-analysis-4.rs:23:18 | LL | let _x = a.b; | ^^^ note: Capturing a[(0, 0),(0, 0)] -> Immutable - --> $DIR/capture-analysis-4.rs:29:26 + --> $DIR/capture-analysis-4.rs:26:26 | LL | println!("{:?}", a.b.c); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/capture-analysis-4.rs:23:5 + --> $DIR/capture-analysis-4.rs:20:5 | LL | / || { LL | | @@ -42,11 +32,10 @@ LL | | }; | |_____^ | note: Min Capture a[(0, 0)] -> ByValue - --> $DIR/capture-analysis-4.rs:26:18 + --> $DIR/capture-analysis-4.rs:23:18 | LL | let _x = a.b; | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs index 52f0dcba6bee9..636936eecd7f1 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] struct Point { x: i32, @@ -11,9 +11,6 @@ fn main() { let mut p = Point { x: 10, y: 10 }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr index c9c227335a9e6..92e32c4b4a10a 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/capture-disjoint-field-struct.rs:13:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/capture-disjoint-field-struct.rs:17:5 + --> $DIR/capture-disjoint-field-struct.rs:14:5 | LL | / || { LL | | @@ -20,13 +10,13 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> Immutable - --> $DIR/capture-disjoint-field-struct.rs:20:24 + --> $DIR/capture-disjoint-field-struct.rs:17:24 | LL | println!("{}", p.x); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-disjoint-field-struct.rs:17:5 + --> $DIR/capture-disjoint-field-struct.rs:14:5 | LL | / || { LL | | @@ -37,11 +27,10 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> Immutable - --> $DIR/capture-disjoint-field-struct.rs:20:24 + --> $DIR/capture-disjoint-field-struct.rs:17:24 | LL | println!("{}", p.x); | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs index bac79ad2860f7..d29aa04f656a8 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs @@ -1,14 +1,11 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] fn main() { let mut t = (10, 10); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR First Pass analysis includes: //~| ERROR Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr index 84aac180fbb0c..2f618d2d103fc 100644 --- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr +++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/capture-disjoint-field-tuple.rs:8:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/capture-disjoint-field-tuple.rs:12:5 + --> $DIR/capture-disjoint-field-tuple.rs:9:5 | LL | / || { LL | | @@ -20,13 +10,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> Immutable - --> $DIR/capture-disjoint-field-tuple.rs:15:24 + --> $DIR/capture-disjoint-field-tuple.rs:12:24 | LL | println!("{}", t.0); | ^^^ error: Min Capture analysis includes: - --> $DIR/capture-disjoint-field-tuple.rs:12:5 + --> $DIR/capture-disjoint-field-tuple.rs:9:5 | LL | / || { LL | | @@ -37,11 +27,10 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> Immutable - --> $DIR/capture-disjoint-field-tuple.rs:15:24 + --> $DIR/capture-disjoint-field-tuple.rs:12:24 | LL | println!("{}", t.0); | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs index 61b707605c2d6..09fb7b5d03df3 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #![allow(unused)] #[derive(Debug)] @@ -32,9 +32,6 @@ fn main() { }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr index 447ad8f4a68e1..02056e09abbc6 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/deep-multilevel-struct.rs:34:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/deep-multilevel-struct.rs:38:5 + --> $DIR/deep-multilevel-struct.rs:35:5 | LL | / || { LL | | @@ -20,23 +10,23 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0),(0, 0),(0, 0)] -> Immutable - --> $DIR/deep-multilevel-struct.rs:41:18 + --> $DIR/deep-multilevel-struct.rs:38:18 | LL | let x = &p.a.p.x; | ^^^^^^^ note: Capturing p[(1, 0),(1, 0),(1, 0)] -> Mutable - --> $DIR/deep-multilevel-struct.rs:43:9 + --> $DIR/deep-multilevel-struct.rs:40:9 | LL | p.b.q.y = 9; | ^^^^^^^ note: Capturing p[] -> Immutable - --> $DIR/deep-multilevel-struct.rs:46:26 + --> $DIR/deep-multilevel-struct.rs:43:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/deep-multilevel-struct.rs:38:5 + --> $DIR/deep-multilevel-struct.rs:35:5 | LL | / || { LL | | @@ -47,7 +37,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> Mutable - --> $DIR/deep-multilevel-struct.rs:43:9 + --> $DIR/deep-multilevel-struct.rs:40:9 | LL | p.b.q.y = 9; | ^^^^^^^ p[] captured as Mutable here @@ -55,6 +45,5 @@ LL | p.b.q.y = 9; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs index 6c7eab1eeb7cd..640ba76a67543 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs @@ -1,14 +1,11 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #![allow(unused)] fn main() { let mut t = (((1,2),(3,4)),((5,6),(7,8))); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr index 639d1714721db..32e8cf312f3c2 100644 --- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr +++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/deep-multilevel-tuple.rs:8:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/deep-multilevel-tuple.rs:12:5 + --> $DIR/deep-multilevel-tuple.rs:9:5 | LL | / || { LL | | @@ -20,23 +10,23 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),(0, 0),(0, 0)] -> Immutable - --> $DIR/deep-multilevel-tuple.rs:15:18 + --> $DIR/deep-multilevel-tuple.rs:12:18 | LL | let x = &t.0.0.0; | ^^^^^^^ note: Capturing t[(1, 0),(1, 0),(1, 0)] -> Mutable - --> $DIR/deep-multilevel-tuple.rs:17:9 + --> $DIR/deep-multilevel-tuple.rs:14:9 | LL | t.1.1.1 = 9; | ^^^^^^^ note: Capturing t[] -> Immutable - --> $DIR/deep-multilevel-tuple.rs:20:26 + --> $DIR/deep-multilevel-tuple.rs:17:26 | LL | println!("{:?}", t); | ^ error: Min Capture analysis includes: - --> $DIR/deep-multilevel-tuple.rs:12:5 + --> $DIR/deep-multilevel-tuple.rs:9:5 | LL | / || { LL | | @@ -47,7 +37,7 @@ LL | | }; | |_____^ | note: Min Capture t[] -> Mutable - --> $DIR/deep-multilevel-tuple.rs:17:9 + --> $DIR/deep-multilevel-tuple.rs:14:9 | LL | t.1.1.1 = 9; | ^^^^^^^ t[] captured as Mutable here @@ -55,6 +45,5 @@ LL | t.1.1.1 = 9; LL | println!("{:?}", t); | ^ t[] used here -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs b/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs index 68e8d66762ddf..f4e1051fd0e5e 100644 --- a/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs +++ b/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] // Test to ensure Index projections are handled properly during capture analysis // The array should be moved in entirety, even though only some elements are used. @@ -8,9 +8,6 @@ fn arrays() { let arr: [String; 5] = [format!("A"), format!("B"), format!("C"), format!("D"), format!("E")]; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -37,9 +34,6 @@ fn structs() { let mut p = Point { x: 10, y: 10, id: String::new() }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -58,9 +52,6 @@ fn tuples() { let mut t = (10, String::new(), (String::new(), 42)); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr b/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr index 6f8295ac09553..0b2ccde0d8b84 100644 --- a/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr +++ b/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr @@ -1,35 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:10:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:39:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/destructure_patterns.rs:60:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:14:5 + --> $DIR/destructure_patterns.rs:11:5 | LL | / || { LL | | @@ -41,23 +11,23 @@ LL | | }; | |_____^ | note: Capturing arr[Index] -> ByValue - --> $DIR/destructure_patterns.rs:17:29 + --> $DIR/destructure_patterns.rs:14:29 | LL | let [a, b, .., e] = arr; | ^^^ note: Capturing arr[Index] -> ByValue - --> $DIR/destructure_patterns.rs:17:29 + --> $DIR/destructure_patterns.rs:14:29 | LL | let [a, b, .., e] = arr; | ^^^ note: Capturing arr[Index] -> ByValue - --> $DIR/destructure_patterns.rs:17:29 + --> $DIR/destructure_patterns.rs:14:29 | LL | let [a, b, .., e] = arr; | ^^^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:14:5 + --> $DIR/destructure_patterns.rs:11:5 | LL | / || { LL | | @@ -69,13 +39,13 @@ LL | | }; | |_____^ | note: Min Capture arr[] -> ByValue - --> $DIR/destructure_patterns.rs:17:29 + --> $DIR/destructure_patterns.rs:14:29 | LL | let [a, b, .., e] = arr; | ^^^ error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:43:5 + --> $DIR/destructure_patterns.rs:37:5 | LL | / || { LL | | @@ -87,18 +57,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> Mutable - --> $DIR/destructure_patterns.rs:46:58 + --> $DIR/destructure_patterns.rs:40:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ note: Capturing p[(2, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:46:58 + --> $DIR/destructure_patterns.rs:40:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:43:5 + --> $DIR/destructure_patterns.rs:37:5 | LL | / || { LL | | @@ -110,18 +80,18 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> Mutable - --> $DIR/destructure_patterns.rs:46:58 + --> $DIR/destructure_patterns.rs:40:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ note: Min Capture p[(2, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:46:58 + --> $DIR/destructure_patterns.rs:40:58 | LL | let Point { x: ref mut x, y: _, id: moved_id } = p; | ^ error: First Pass analysis includes: - --> $DIR/destructure_patterns.rs:64:5 + --> $DIR/destructure_patterns.rs:55:5 | LL | / || { LL | | @@ -133,23 +103,23 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> Mutable - --> $DIR/destructure_patterns.rs:67:54 + --> $DIR/destructure_patterns.rs:58:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Capturing t[(1, 0)] -> Immutable - --> $DIR/destructure_patterns.rs:67:54 + --> $DIR/destructure_patterns.rs:58:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Capturing t[(2, 0),(0, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:67:54 + --> $DIR/destructure_patterns.rs:58:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ error: Min Capture analysis includes: - --> $DIR/destructure_patterns.rs:64:5 + --> $DIR/destructure_patterns.rs:55:5 | LL | / || { LL | | @@ -161,21 +131,20 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> Mutable - --> $DIR/destructure_patterns.rs:67:54 + --> $DIR/destructure_patterns.rs:58:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Min Capture t[(1, 0)] -> Immutable - --> $DIR/destructure_patterns.rs:67:54 + --> $DIR/destructure_patterns.rs:58:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ note: Min Capture t[(2, 0),(0, 0)] -> ByValue - --> $DIR/destructure_patterns.rs:67:54 + --> $DIR/destructure_patterns.rs:58:54 | LL | let (ref mut x, ref ref_str, (moved_s, _)) = t; | ^ -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs index 7467c13b337eb..e5cf89fbc52fe 100644 --- a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs +++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs @@ -1,14 +1,11 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] fn main() { let s = format!("s"); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr index 3e4c4d3ccd39c..09c607a3d4a34 100644 --- a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr +++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/feature-gate-capture_disjoint_fields.rs:8:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/feature-gate-capture_disjoint_fields.rs:12:5 + --> $DIR/feature-gate-capture_disjoint_fields.rs:9:5 | LL | / || { LL | | @@ -20,13 +10,13 @@ LL | | }; | |_____^ | note: Capturing s[] -> Immutable - --> $DIR/feature-gate-capture_disjoint_fields.rs:15:69 + --> $DIR/feature-gate-capture_disjoint_fields.rs:12:69 | LL | println!("This uses new capture analyysis to capture s={}", s); | ^ error: Min Capture analysis includes: - --> $DIR/feature-gate-capture_disjoint_fields.rs:12:5 + --> $DIR/feature-gate-capture_disjoint_fields.rs:9:5 | LL | / || { LL | | @@ -37,11 +27,10 @@ LL | | }; | |_____^ | note: Min Capture s[] -> Immutable - --> $DIR/feature-gate-capture_disjoint_fields.rs:15:69 + --> $DIR/feature-gate-capture_disjoint_fields.rs:12:69 | LL | println!("This uses new capture analyysis to capture s={}", s); | ^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.rs b/tests/ui/closures/2229_closure_analysis/issue-87378.rs index 9c89a4538bee8..d60ecbef78e4a 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-87378.rs +++ b/tests/ui/closures/2229_closure_analysis/issue-87378.rs @@ -1,4 +1,4 @@ -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] //@ edition:2021 @@ -12,9 +12,6 @@ fn main() { let u = Union { value: 42 }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr index 862ae7445e8f1..d47ec5a9cae23 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr +++ b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/issue-87378.rs:14:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/issue-87378.rs:18:5 + --> $DIR/issue-87378.rs:15:5 | LL | / || { LL | | @@ -20,13 +10,13 @@ LL | | }; | |_____^ | note: Capturing u[(0, 0)] -> Immutable - --> $DIR/issue-87378.rs:21:17 + --> $DIR/issue-87378.rs:18:17 | LL | unsafe { u.value } | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/issue-87378.rs:18:5 + --> $DIR/issue-87378.rs:15:5 | LL | / || { LL | | @@ -37,11 +27,10 @@ LL | | }; | |_____^ | note: Min Capture u[] -> Immutable - --> $DIR/issue-87378.rs:21:17 + --> $DIR/issue-87378.rs:18:17 | LL | unsafe { u.value } | ^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.rs b/tests/ui/closures/2229_closure_analysis/issue-88476.rs index 45fe73b76e2a7..b1d740cb1c07d 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-88476.rs +++ b/tests/ui/closures/2229_closure_analysis/issue-88476.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] // Test that we can't move out of struct that impls `Drop`. @@ -18,10 +18,7 @@ pub fn test1() { let f = Foo(Rc::new(1)); let x = #[rustc_capture_analysis] move || { - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| ERROR: First Pass analysis includes: + //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{:?}", f.0); //~^ NOTE: Capturing f[(0, 0)] -> Immutable @@ -46,10 +43,7 @@ fn test2() { let character = Character { hp: 100, name: format!("A") }; let c = #[rustc_capture_analysis] move || { - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| ERROR: First Pass analysis includes: + //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: println!("{}", character.hp) //~^ NOTE: Capturing character[(0, 0)] -> Immutable diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr index 225b0335cf535..ed4fe4a965fff 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr +++ b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr @@ -1,34 +1,17 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/issue-88476.rs:20:13 - | -LL | let x = #[rustc_capture_analysis] move || { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/issue-88476.rs:48:13 - | -LL | let c = #[rustc_capture_analysis] move || { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: --> $DIR/issue-88476.rs:20:39 | LL | let x = #[rustc_capture_analysis] move || { | _______________________________________^ +LL | | +LL | | +LL | | println!("{:?}", f.0); ... | LL | | }; | |_____^ | note: Capturing f[(0, 0)] -> Immutable - --> $DIR/issue-88476.rs:26:26 + --> $DIR/issue-88476.rs:23:26 | LL | println!("{:?}", f.0); | ^^^ @@ -38,46 +21,54 @@ error: Min Capture analysis includes: | LL | let x = #[rustc_capture_analysis] move || { | _______________________________________^ +LL | | +LL | | +LL | | println!("{:?}", f.0); ... | LL | | }; | |_____^ | note: Min Capture f[] -> ByValue - --> $DIR/issue-88476.rs:26:26 + --> $DIR/issue-88476.rs:23:26 | LL | println!("{:?}", f.0); | ^^^ error: First Pass analysis includes: - --> $DIR/issue-88476.rs:48:39 + --> $DIR/issue-88476.rs:45:39 | LL | let c = #[rustc_capture_analysis] move || { | _______________________________________^ +LL | | +LL | | +LL | | println!("{}", character.hp) ... | LL | | }; | |_____^ | note: Capturing character[(0, 0)] -> Immutable - --> $DIR/issue-88476.rs:54:24 + --> $DIR/issue-88476.rs:48:24 | LL | println!("{}", character.hp) | ^^^^^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/issue-88476.rs:48:39 + --> $DIR/issue-88476.rs:45:39 | LL | let c = #[rustc_capture_analysis] move || { | _______________________________________^ +LL | | +LL | | +LL | | println!("{}", character.hp) ... | LL | | }; | |_____^ | note: Min Capture character[(0, 0)] -> ByValue - --> $DIR/issue-88476.rs:54:24 + --> $DIR/issue-88476.rs:48:24 | LL | println!("{}", character.hp) | ^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.rs b/tests/ui/closures/2229_closure_analysis/move_closure.rs index c681559f61904..60d76ac525395 100644 --- a/tests/ui/closures/2229_closure_analysis/move_closure.rs +++ b/tests/ui/closures/2229_closure_analysis/move_closure.rs @@ -2,7 +2,7 @@ // Test that move closures drop derefs with `capture_disjoint_fields` enabled. -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] fn simple_move_closure() { struct S(String); @@ -10,9 +10,6 @@ fn simple_move_closure() { let t = T(S("s".into())); let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -29,9 +26,6 @@ fn simple_ref() { let ref_s = &mut s; let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -51,9 +45,6 @@ fn struct_contains_ref_to_another_struct_1() { let t = T(&mut s); let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -75,9 +66,6 @@ fn struct_contains_ref_to_another_struct_2() { let t = T(&s); let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -98,9 +86,6 @@ fn struct_contains_ref_to_another_struct_3() { let t = T(&s); let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -120,9 +105,6 @@ fn truncate_box_derefs() { // Content within the box is moved within the closure let b = Box::new(S(10)); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -137,9 +119,6 @@ fn truncate_box_derefs() { let b = Box::new(S(10)); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -155,9 +134,6 @@ fn truncate_box_derefs() { let t = (0, b); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date move || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -178,10 +154,7 @@ fn box_mut_1() { let box_p_foo = Box::new(p_foo); let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| ERROR First Pass analysis includes: + //~^ ERROR First Pass analysis includes: //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> Mutable //~| ERROR Min Capture analysis includes: //~| NOTE: Min Capture box_p_foo[] -> ByValue @@ -196,10 +169,7 @@ fn box_mut_2() { let p_foo = &mut box_foo; let c = #[rustc_capture_analysis] move || p_foo.x += 10; - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| ERROR First Pass analysis includes: + //~^ ERROR First Pass analysis includes: //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> Mutable //~| ERROR Min Capture analysis includes: //~| NOTE: Min Capture p_foo[] -> ByValue @@ -210,10 +180,7 @@ fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 { let x = 10; let c = #[rustc_capture_analysis] move || x; - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| ERROR First Pass analysis includes: + //~^ ERROR First Pass analysis includes: //~| NOTE: Capturing x[] -> Immutable //~| ERROR Min Capture analysis includes: //~| NOTE: Min Capture x[] -> ByValue diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.stderr b/tests/ui/closures/2229_closure_analysis/move_closure.stderr index a4919d488d1ef..b889423245053 100644 --- a/tests/ui/closures/2229_closure_analysis/move_closure.stderr +++ b/tests/ui/closures/2229_closure_analysis/move_closure.stderr @@ -1,139 +1,29 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/move_closure.rs:12:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:31:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:53:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:77:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:100:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:122:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:139:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:157:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:180:13 - | -LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:198:13 - | -LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/move_closure.rs:212:13 - | -LL | let c = #[rustc_capture_analysis] move || x; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/move_closure.rs:212:39 + --> $DIR/move_closure.rs:182:39 | LL | let c = #[rustc_capture_analysis] move || x; | ^^^^^^^^^ | note: Capturing x[] -> Immutable - --> $DIR/move_closure.rs:212:47 + --> $DIR/move_closure.rs:182:47 | LL | let c = #[rustc_capture_analysis] move || x; | ^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:212:39 + --> $DIR/move_closure.rs:182:39 | LL | let c = #[rustc_capture_analysis] move || x; | ^^^^^^^^^ | note: Min Capture x[] -> ByValue - --> $DIR/move_closure.rs:212:47 + --> $DIR/move_closure.rs:182:47 | LL | let c = #[rustc_capture_analysis] move || x; | ^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:16:5 + --> $DIR/move_closure.rs:13:5 | LL | / move || { LL | | @@ -144,13 +34,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),(0, 0)] -> Mutable - --> $DIR/move_closure.rs:19:9 + --> $DIR/move_closure.rs:16:9 | LL | t.0.0 = "new S".into(); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:16:5 + --> $DIR/move_closure.rs:13:5 | LL | / move || { LL | | @@ -161,13 +51,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0),(0, 0)] -> ByValue - --> $DIR/move_closure.rs:19:9 + --> $DIR/move_closure.rs:16:9 | LL | t.0.0 = "new S".into(); | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:35:5 + --> $DIR/move_closure.rs:29:5 | LL | / move || { LL | | @@ -178,13 +68,13 @@ LL | | }; | |_____^ | note: Capturing ref_s[Deref] -> Mutable - --> $DIR/move_closure.rs:38:9 + --> $DIR/move_closure.rs:32:9 | LL | *ref_s += 10; | ^^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:35:5 + --> $DIR/move_closure.rs:29:5 | LL | / move || { LL | | @@ -195,13 +85,13 @@ LL | | }; | |_____^ | note: Min Capture ref_s[] -> ByValue - --> $DIR/move_closure.rs:38:9 + --> $DIR/move_closure.rs:32:9 | LL | *ref_s += 10; | ^^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:57:5 + --> $DIR/move_closure.rs:48:5 | LL | / move || { LL | | @@ -212,13 +102,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> Mutable - --> $DIR/move_closure.rs:60:9 + --> $DIR/move_closure.rs:51:9 | LL | t.0.0 = "new s".into(); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:57:5 + --> $DIR/move_closure.rs:48:5 | LL | / move || { LL | | @@ -229,13 +119,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/move_closure.rs:60:9 + --> $DIR/move_closure.rs:51:9 | LL | t.0.0 = "new s".into(); | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:81:5 + --> $DIR/move_closure.rs:69:5 | LL | / move || { LL | | @@ -246,13 +136,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable - --> $DIR/move_closure.rs:84:18 + --> $DIR/move_closure.rs:72:18 | LL | let _t = t.0.0; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:81:5 + --> $DIR/move_closure.rs:69:5 | LL | / move || { LL | | @@ -263,13 +153,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/move_closure.rs:84:18 + --> $DIR/move_closure.rs:72:18 | LL | let _t = t.0.0; | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:104:5 + --> $DIR/move_closure.rs:89:5 | LL | / move || { LL | | @@ -280,13 +170,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue - --> $DIR/move_closure.rs:107:18 + --> $DIR/move_closure.rs:92:18 | LL | let _t = t.0.0; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:104:5 + --> $DIR/move_closure.rs:89:5 | LL | / move || { LL | | @@ -297,13 +187,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/move_closure.rs:107:18 + --> $DIR/move_closure.rs:92:18 | LL | let _t = t.0.0; | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:126:5 + --> $DIR/move_closure.rs:108:5 | LL | / move || { LL | | @@ -314,13 +204,13 @@ LL | | }; | |_____^ | note: Capturing b[Deref,(0, 0)] -> Immutable - --> $DIR/move_closure.rs:129:18 + --> $DIR/move_closure.rs:111:18 | LL | let _t = b.0; | ^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:126:5 + --> $DIR/move_closure.rs:108:5 | LL | / move || { LL | | @@ -331,13 +221,13 @@ LL | | }; | |_____^ | note: Min Capture b[] -> ByValue - --> $DIR/move_closure.rs:129:18 + --> $DIR/move_closure.rs:111:18 | LL | let _t = b.0; | ^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:143:5 + --> $DIR/move_closure.rs:122:5 | LL | / move || { LL | | @@ -348,13 +238,13 @@ LL | | }; | |_____^ | note: Capturing b[Deref,(0, 0)] -> Immutable - --> $DIR/move_closure.rs:146:24 + --> $DIR/move_closure.rs:125:24 | LL | println!("{}", b.0); | ^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:143:5 + --> $DIR/move_closure.rs:122:5 | LL | / move || { LL | | @@ -365,13 +255,13 @@ LL | | }; | |_____^ | note: Min Capture b[] -> ByValue - --> $DIR/move_closure.rs:146:24 + --> $DIR/move_closure.rs:125:24 | LL | println!("{}", b.0); | ^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:161:5 + --> $DIR/move_closure.rs:137:5 | LL | / move || { LL | | @@ -382,13 +272,13 @@ LL | | }; | |_____^ | note: Capturing t[(1, 0),Deref,(0, 0)] -> Immutable - --> $DIR/move_closure.rs:164:24 + --> $DIR/move_closure.rs:140:24 | LL | println!("{}", t.1.0); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:161:5 + --> $DIR/move_closure.rs:137:5 | LL | / move || { LL | | @@ -399,59 +289,58 @@ LL | | }; | |_____^ | note: Min Capture t[(1, 0)] -> ByValue - --> $DIR/move_closure.rs:164:24 + --> $DIR/move_closure.rs:140:24 | LL | println!("{}", t.1.0); | ^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:180:39 + --> $DIR/move_closure.rs:156:39 | LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> Mutable - --> $DIR/move_closure.rs:180:47 + --> $DIR/move_closure.rs:156:47 | LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; | ^^^^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:180:39 + --> $DIR/move_closure.rs:156:39 | LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: Min Capture box_p_foo[] -> ByValue - --> $DIR/move_closure.rs:180:47 + --> $DIR/move_closure.rs:156:47 | LL | let c = #[rustc_capture_analysis] move || box_p_foo.x += 10; | ^^^^^^^^^^^ error: First Pass analysis includes: - --> $DIR/move_closure.rs:198:39 + --> $DIR/move_closure.rs:171:39 | LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; | ^^^^^^^^^^^^^^^^^^^^^ | note: Capturing p_foo[Deref,Deref,(0, 0)] -> Mutable - --> $DIR/move_closure.rs:198:47 + --> $DIR/move_closure.rs:171:47 | LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; | ^^^^^^^ error: Min Capture analysis includes: - --> $DIR/move_closure.rs:198:39 + --> $DIR/move_closure.rs:171:39 | LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; | ^^^^^^^^^^^^^^^^^^^^^ | note: Min Capture p_foo[] -> ByValue - --> $DIR/move_closure.rs:198:47 + --> $DIR/move_closure.rs:171:47 | LL | let c = #[rustc_capture_analysis] move || p_foo.x += 10; | ^^^^^^^ -error: aborting due to 33 previous errors +error: aborting due to 22 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs index 501aebe725aad..5bed3ced8d68f 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #![allow(unused)] struct Point { @@ -20,9 +20,6 @@ fn main() { // Therefore `w.p` is captured // Note that `wp.x` doesn't start off a variable defined outside the closure. let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr index 000d929f07f31..54d46529612f9 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/multilevel-path-1.rs:22:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/multilevel-path-1.rs:26:5 + --> $DIR/multilevel-path-1.rs:23:5 | LL | / || { LL | | @@ -21,13 +11,13 @@ LL | | }; | |_____^ | note: Capturing w[(0, 0)] -> Immutable - --> $DIR/multilevel-path-1.rs:29:19 + --> $DIR/multilevel-path-1.rs:26:19 | LL | let wp = &w.p; | ^^^ error: Min Capture analysis includes: - --> $DIR/multilevel-path-1.rs:26:5 + --> $DIR/multilevel-path-1.rs:23:5 | LL | / || { LL | | @@ -39,11 +29,10 @@ LL | | }; | |_____^ | note: Min Capture w[(0, 0)] -> Immutable - --> $DIR/multilevel-path-1.rs:29:19 + --> $DIR/multilevel-path-1.rs:26:19 | LL | let wp = &w.p; | ^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs index f73627d14daa2..3d3266577859b 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #![allow(unused)] struct Point { @@ -15,9 +15,6 @@ fn main() { let mut w = Wrapper { p: Point { x: 10, y: 10 } }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr index cbc7188a4ec4d..97eb0b7488804 100644 --- a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr +++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/multilevel-path-2.rs:17:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/multilevel-path-2.rs:21:5 + --> $DIR/multilevel-path-2.rs:18:5 | LL | / || { LL | | @@ -20,13 +10,13 @@ LL | | }; | |_____^ | note: Capturing w[(0, 0),(0, 0)] -> Immutable - --> $DIR/multilevel-path-2.rs:24:24 + --> $DIR/multilevel-path-2.rs:21:24 | LL | println!("{}", w.p.x); | ^^^^^ error: Min Capture analysis includes: - --> $DIR/multilevel-path-2.rs:21:5 + --> $DIR/multilevel-path-2.rs:18:5 | LL | / || { LL | | @@ -37,11 +27,10 @@ LL | | }; | |_____^ | note: Min Capture w[(0, 0),(0, 0)] -> Immutable - --> $DIR/multilevel-path-2.rs:24:24 + --> $DIR/multilevel-path-2.rs:21:24 | LL | println!("{}", w.p.x); | ^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.rs b/tests/ui/closures/2229_closure_analysis/nested-closure.rs index 54166d068cb1d..81cce83b728fc 100644 --- a/tests/ui/closures/2229_closure_analysis/nested-closure.rs +++ b/tests/ui/closures/2229_closure_analysis/nested-closure.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] struct Point { x: i32, @@ -17,9 +17,6 @@ fn main() { let mut p = Point { x: 5, y: 20 }; let mut c1 = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -28,9 +25,6 @@ fn main() { //~| NOTE: Min Capture p[(0, 0)] -> Immutable let incr = 10; let mut c2 = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || p.y += incr; //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr index 3b36069e62427..b3d06f1b5196e 100644 --- a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr +++ b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr @@ -1,59 +1,39 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/nested-closure.rs:19:18 - | -LL | let mut c1 = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/nested-closure.rs:30:22 - | -LL | let mut c2 = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/nested-closure.rs:34:9 + --> $DIR/nested-closure.rs:28:9 | LL | || p.y += incr; | ^^^^^^^^^^^^^^ | note: Capturing p[(1, 0)] -> Mutable - --> $DIR/nested-closure.rs:34:12 + --> $DIR/nested-closure.rs:28:12 | LL | || p.y += incr; | ^^^ note: Capturing incr[] -> Immutable - --> $DIR/nested-closure.rs:34:19 + --> $DIR/nested-closure.rs:28:19 | LL | || p.y += incr; | ^^^^ error: Min Capture analysis includes: - --> $DIR/nested-closure.rs:34:9 + --> $DIR/nested-closure.rs:28:9 | LL | || p.y += incr; | ^^^^^^^^^^^^^^ | note: Min Capture p[(1, 0)] -> Mutable - --> $DIR/nested-closure.rs:34:12 + --> $DIR/nested-closure.rs:28:12 | LL | || p.y += incr; | ^^^ note: Min Capture incr[] -> Immutable - --> $DIR/nested-closure.rs:34:19 + --> $DIR/nested-closure.rs:28:19 | LL | || p.y += incr; | ^^^^ error: First Pass analysis includes: - --> $DIR/nested-closure.rs:23:5 + --> $DIR/nested-closure.rs:20:5 | LL | / || { LL | | @@ -64,23 +44,23 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> Immutable - --> $DIR/nested-closure.rs:26:24 + --> $DIR/nested-closure.rs:23:24 | LL | println!("{}", p.x); | ^^^ note: Capturing p[(1, 0)] -> Mutable - --> $DIR/nested-closure.rs:34:12 + --> $DIR/nested-closure.rs:28:12 | LL | || p.y += incr; | ^^^ note: Capturing p[(1, 0)] -> Immutable - --> $DIR/nested-closure.rs:44:24 + --> $DIR/nested-closure.rs:38:24 | LL | println!("{}", p.y); | ^^^ error: Min Capture analysis includes: - --> $DIR/nested-closure.rs:23:5 + --> $DIR/nested-closure.rs:20:5 | LL | / || { LL | | @@ -91,16 +71,15 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> Immutable - --> $DIR/nested-closure.rs:26:24 + --> $DIR/nested-closure.rs:23:24 | LL | println!("{}", p.x); | ^^^ note: Min Capture p[(1, 0)] -> Mutable - --> $DIR/nested-closure.rs:34:12 + --> $DIR/nested-closure.rs:28:12 | LL | || p.y += incr; | ^^^ -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs index 70c20cf5aef84..821ca2b3c14f1 100644 --- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs +++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #![allow(unused)] #![allow(dead_code)] @@ -18,10 +18,7 @@ struct MyStruct<'a> { fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static { let c = #[rustc_capture_analysis] || drop(&m.a.0); - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - //~| ERROR: First Pass analysis includes: + //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> Immutable //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> Immutable diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr index 86f7a6a6bca2a..66a36022a225c 100644 --- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr +++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr @@ -1,13 +1,3 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/edge_case.rs:20:13 - | -LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: --> $DIR/edge_case.rs:20:39 | @@ -32,6 +22,5 @@ note: Min Capture m[Deref,(0, 0),Deref] -> Immutable LL | let c = #[rustc_capture_analysis] || drop(&m.a.0); | ^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs b/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs index ed740f3a16773..3fd88241219c3 100644 --- a/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs +++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] struct Point { x: f32, @@ -21,9 +21,6 @@ fn main() { let pent = Pentagon { points: [p1, p2, p3, p4, p5] }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr index c6608c0590013..5731824dc2c55 100644 --- a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr +++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/path-with-array-access.rs:23:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/path-with-array-access.rs:27:5 + --> $DIR/path-with-array-access.rs:24:5 | LL | / || { LL | | @@ -20,13 +10,13 @@ LL | | }; | |_____^ | note: Capturing pent[(0, 0)] -> Immutable - --> $DIR/path-with-array-access.rs:30:24 + --> $DIR/path-with-array-access.rs:27:24 | LL | println!("{}", pent.points[5].x); | ^^^^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/path-with-array-access.rs:27:5 + --> $DIR/path-with-array-access.rs:24:5 | LL | / || { LL | | @@ -37,11 +27,10 @@ LL | | }; | |_____^ | note: Min Capture pent[(0, 0)] -> Immutable - --> $DIR/path-with-array-access.rs:30:24 + --> $DIR/path-with-array-access.rs:27:24 | LL | println!("{}", pent.points[5].x); | ^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs index 159be843edb0b..1fb31f8c0625d 100644 --- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs @@ -6,7 +6,7 @@ // NOTE: It is *critical* that the order of the min capture NOTES in the stderr output // does *not* change! -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #[derive(Debug)] struct HasDrop; @@ -21,9 +21,6 @@ fn test_one() { let b = (HasDrop, HasDrop); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: Min Capture analysis includes: //~| ERROR @@ -48,9 +45,6 @@ fn test_two() { let b = (HasDrop, HasDrop); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: Min Capture analysis includes: //~| ERROR @@ -75,9 +69,6 @@ fn test_three() { let b = (HasDrop, HasDrop); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: Min Capture analysis includes: //~| ERROR diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr index ff3cd5b8f01a3..3c7f16531e149 100644 --- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr +++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr @@ -1,35 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/preserve_field_drop_order.rs:23:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/preserve_field_drop_order.rs:50:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/preserve_field_drop_order.rs:77:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/preserve_field_drop_order.rs:27:5 + --> $DIR/preserve_field_drop_order.rs:24:5 | LL | / || { LL | | @@ -40,28 +10,28 @@ LL | | }; | |_____^ | note: Capturing a[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:30:26 + --> $DIR/preserve_field_drop_order.rs:27:26 | LL | println!("{:?}", a.0); | ^^^ note: Capturing a[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:33:26 + --> $DIR/preserve_field_drop_order.rs:30:26 | LL | println!("{:?}", a.1); | ^^^ note: Capturing b[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:37:26 + --> $DIR/preserve_field_drop_order.rs:34:26 | LL | println!("{:?}", b.0); | ^^^ note: Capturing b[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:40:26 + --> $DIR/preserve_field_drop_order.rs:37:26 | LL | println!("{:?}", b.1); | ^^^ error: Min Capture analysis includes: - --> $DIR/preserve_field_drop_order.rs:27:5 + --> $DIR/preserve_field_drop_order.rs:24:5 | LL | / || { LL | | @@ -72,28 +42,28 @@ LL | | }; | |_____^ | note: Min Capture a[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:30:26 + --> $DIR/preserve_field_drop_order.rs:27:26 | LL | println!("{:?}", a.0); | ^^^ note: Min Capture a[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:33:26 + --> $DIR/preserve_field_drop_order.rs:30:26 | LL | println!("{:?}", a.1); | ^^^ note: Min Capture b[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:37:26 + --> $DIR/preserve_field_drop_order.rs:34:26 | LL | println!("{:?}", b.0); | ^^^ note: Min Capture b[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:40:26 + --> $DIR/preserve_field_drop_order.rs:37:26 | LL | println!("{:?}", b.1); | ^^^ error: First Pass analysis includes: - --> $DIR/preserve_field_drop_order.rs:54:5 + --> $DIR/preserve_field_drop_order.rs:48:5 | LL | / || { LL | | @@ -104,28 +74,28 @@ LL | | }; | |_____^ | note: Capturing a[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:57:26 + --> $DIR/preserve_field_drop_order.rs:51:26 | LL | println!("{:?}", a.1); | ^^^ note: Capturing a[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:60:26 + --> $DIR/preserve_field_drop_order.rs:54:26 | LL | println!("{:?}", a.0); | ^^^ note: Capturing b[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:64:26 + --> $DIR/preserve_field_drop_order.rs:58:26 | LL | println!("{:?}", b.1); | ^^^ note: Capturing b[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:67:26 + --> $DIR/preserve_field_drop_order.rs:61:26 | LL | println!("{:?}", b.0); | ^^^ error: Min Capture analysis includes: - --> $DIR/preserve_field_drop_order.rs:54:5 + --> $DIR/preserve_field_drop_order.rs:48:5 | LL | / || { LL | | @@ -136,28 +106,28 @@ LL | | }; | |_____^ | note: Min Capture a[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:60:26 + --> $DIR/preserve_field_drop_order.rs:54:26 | LL | println!("{:?}", a.0); | ^^^ note: Min Capture a[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:57:26 + --> $DIR/preserve_field_drop_order.rs:51:26 | LL | println!("{:?}", a.1); | ^^^ note: Min Capture b[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:67:26 + --> $DIR/preserve_field_drop_order.rs:61:26 | LL | println!("{:?}", b.0); | ^^^ note: Min Capture b[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:64:26 + --> $DIR/preserve_field_drop_order.rs:58:26 | LL | println!("{:?}", b.1); | ^^^ error: First Pass analysis includes: - --> $DIR/preserve_field_drop_order.rs:81:5 + --> $DIR/preserve_field_drop_order.rs:72:5 | LL | / || { LL | | @@ -168,28 +138,28 @@ LL | | }; | |_____^ | note: Capturing b[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:84:26 + --> $DIR/preserve_field_drop_order.rs:75:26 | LL | println!("{:?}", b.1); | ^^^ note: Capturing a[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:87:26 + --> $DIR/preserve_field_drop_order.rs:78:26 | LL | println!("{:?}", a.1); | ^^^ note: Capturing a[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:90:26 + --> $DIR/preserve_field_drop_order.rs:81:26 | LL | println!("{:?}", a.0); | ^^^ note: Capturing b[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:94:26 + --> $DIR/preserve_field_drop_order.rs:85:26 | LL | println!("{:?}", b.0); | ^^^ error: Min Capture analysis includes: - --> $DIR/preserve_field_drop_order.rs:81:5 + --> $DIR/preserve_field_drop_order.rs:72:5 | LL | / || { LL | | @@ -200,26 +170,25 @@ LL | | }; | |_____^ | note: Min Capture b[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:94:26 + --> $DIR/preserve_field_drop_order.rs:85:26 | LL | println!("{:?}", b.0); | ^^^ note: Min Capture b[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:84:26 + --> $DIR/preserve_field_drop_order.rs:75:26 | LL | println!("{:?}", b.1); | ^^^ note: Min Capture a[(0, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:90:26 + --> $DIR/preserve_field_drop_order.rs:81:26 | LL | println!("{:?}", a.0); | ^^^ note: Min Capture a[(1, 0)] -> Immutable - --> $DIR/preserve_field_drop_order.rs:87:26 + --> $DIR/preserve_field_drop_order.rs:78:26 | LL | println!("{:?}", a.1); | ^^^ -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.rs b/tests/ui/closures/2229_closure_analysis/repr_packed.rs index 2525af37eaaaa..3908765d87286 100644 --- a/tests/ui/closures/2229_closure_analysis/repr_packed.rs +++ b/tests/ui/closures/2229_closure_analysis/repr_packed.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] // `u8` aligned at a byte and are unaffected by repr(packed). // Therefore we *could* precisely (and safely) capture references to both the fields, @@ -12,9 +12,6 @@ fn test_alignment_not_affected() { let mut foo = Foo { x: 0, y: 0 }; let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -43,9 +40,6 @@ fn test_alignment_affected() { let mut foo = Foo { x: String::new(), y: 0 }; let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -79,9 +73,6 @@ fn test_truncation_when_ref_and_move() { let mut foo = Foo { x: String::new() }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr index bab1e8f9977fe..2c18229b2e09e 100644 --- a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr +++ b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr @@ -1,35 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:14:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:45:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/repr_packed.rs:81:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/repr_packed.rs:18:5 + --> $DIR/repr_packed.rs:15:5 | LL | / || { LL | | @@ -41,18 +11,18 @@ LL | | }; | |_____^ | note: Capturing foo[] -> Immutable - --> $DIR/repr_packed.rs:21:24 + --> $DIR/repr_packed.rs:18:24 | LL | let z1: &u8 = &foo.x; | ^^^^^ note: Capturing foo[] -> Mutable - --> $DIR/repr_packed.rs:23:32 + --> $DIR/repr_packed.rs:20:32 | LL | let z2: &mut u8 = &mut foo.y; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:18:5 + --> $DIR/repr_packed.rs:15:5 | LL | / || { LL | | @@ -64,13 +34,13 @@ LL | | }; | |_____^ | note: Min Capture foo[] -> Mutable - --> $DIR/repr_packed.rs:23:32 + --> $DIR/repr_packed.rs:20:32 | LL | let z2: &mut u8 = &mut foo.y; | ^^^^^ error: First Pass analysis includes: - --> $DIR/repr_packed.rs:49:5 + --> $DIR/repr_packed.rs:43:5 | LL | / || { LL | | @@ -82,18 +52,18 @@ LL | | }; | |_____^ | note: Capturing foo[] -> Immutable - --> $DIR/repr_packed.rs:52:28 + --> $DIR/repr_packed.rs:46:28 | LL | let z1: &String = &foo.x; | ^^^^^ note: Capturing foo[] -> Mutable - --> $DIR/repr_packed.rs:54:33 + --> $DIR/repr_packed.rs:48:33 | LL | let z2: &mut u16 = &mut foo.y; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:49:5 + --> $DIR/repr_packed.rs:43:5 | LL | / || { LL | | @@ -105,13 +75,13 @@ LL | | }; | |_____^ | note: Min Capture foo[] -> Mutable - --> $DIR/repr_packed.rs:54:33 + --> $DIR/repr_packed.rs:48:33 | LL | let z2: &mut u16 = &mut foo.y; | ^^^^^ error: First Pass analysis includes: - --> $DIR/repr_packed.rs:85:5 + --> $DIR/repr_packed.rs:76:5 | LL | / || { LL | | @@ -122,18 +92,18 @@ LL | | }; | |_____^ | note: Capturing foo[] -> Immutable - --> $DIR/repr_packed.rs:88:24 + --> $DIR/repr_packed.rs:79:24 | LL | println!("{}", foo.x); | ^^^^^ note: Capturing foo[(0, 0)] -> ByValue - --> $DIR/repr_packed.rs:92:18 + --> $DIR/repr_packed.rs:83:18 | LL | let _z = foo.x; | ^^^^^ error: Min Capture analysis includes: - --> $DIR/repr_packed.rs:85:5 + --> $DIR/repr_packed.rs:76:5 | LL | / || { LL | | @@ -144,7 +114,7 @@ LL | | }; | |_____^ | note: Min Capture foo[] -> ByValue - --> $DIR/repr_packed.rs:88:24 + --> $DIR/repr_packed.rs:79:24 | LL | println!("{}", foo.x); | ^^^^^ foo[] used here @@ -152,6 +122,5 @@ LL | println!("{}", foo.x); LL | let _z = foo.x; | ^^^^^ foo[] captured as ByValue here -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs index 38aa76999fb44..49b62c1647797 100644 --- a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs +++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] // Test to ensure that min analysis meets capture kind for all paths captured. @@ -21,9 +21,6 @@ fn main() { // Requirements met when p is captured via MutBorrow // let mut c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr index d4201b2d4c22b..6b5ec8b89950f 100644 --- a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr +++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr @@ -1,15 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/simple-struct-min-capture.rs:23:17 - | -LL | let mut c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/simple-struct-min-capture.rs:27:5 + --> $DIR/simple-struct-min-capture.rs:24:5 | LL | / || { LL | | @@ -20,18 +10,18 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> Mutable - --> $DIR/simple-struct-min-capture.rs:30:9 + --> $DIR/simple-struct-min-capture.rs:27:9 | LL | p.x += 10; | ^^^ note: Capturing p[] -> Immutable - --> $DIR/simple-struct-min-capture.rs:33:26 + --> $DIR/simple-struct-min-capture.rs:30:26 | LL | println!("{:?}", p); | ^ error: Min Capture analysis includes: - --> $DIR/simple-struct-min-capture.rs:27:5 + --> $DIR/simple-struct-min-capture.rs:24:5 | LL | / || { LL | | @@ -42,7 +32,7 @@ LL | | }; | |_____^ | note: Min Capture p[] -> Mutable - --> $DIR/simple-struct-min-capture.rs:30:9 + --> $DIR/simple-struct-min-capture.rs:27:9 | LL | p.x += 10; | ^^^ p[] captured as Mutable here @@ -50,6 +40,5 @@ LL | p.x += 10; LL | println!("{:?}", p); | ^ p[] used here -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs index 667f244f612e8..788156054d10e 100644 --- a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs +++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs @@ -4,7 +4,7 @@ // i.e. the capture doesn't deref the raw ptr. -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] #[derive(Debug)] struct S { @@ -23,9 +23,6 @@ fn unsafe_imm() { let t = T(p); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || unsafe { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -44,9 +41,6 @@ fn unsafe_mut() { let p : *mut S = &mut *my_speed; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr index 9f3c6576c7213..e2ccc1be71716 100644 --- a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr +++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr @@ -1,25 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/unsafe_ptr.rs:25:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/unsafe_ptr.rs:46:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/unsafe_ptr.rs:29:6 + --> $DIR/unsafe_ptr.rs:26:6 | LL | / || unsafe { LL | | @@ -30,13 +10,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable - --> $DIR/unsafe_ptr.rs:32:26 + --> $DIR/unsafe_ptr.rs:29:26 | LL | println!("{:?}", (*t.0).s); | ^^^^^^^^ error: Min Capture analysis includes: - --> $DIR/unsafe_ptr.rs:29:6 + --> $DIR/unsafe_ptr.rs:26:6 | LL | / || unsafe { LL | | @@ -47,13 +27,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> Immutable - --> $DIR/unsafe_ptr.rs:32:26 + --> $DIR/unsafe_ptr.rs:29:26 | LL | println!("{:?}", (*t.0).s); | ^^^^^^^^ error: First Pass analysis includes: - --> $DIR/unsafe_ptr.rs:50:5 + --> $DIR/unsafe_ptr.rs:44:5 | LL | / || { LL | | @@ -65,13 +45,13 @@ LL | | }; | |_____^ | note: Capturing p[Deref,(0, 0)] -> Immutable - --> $DIR/unsafe_ptr.rs:53:31 + --> $DIR/unsafe_ptr.rs:47:31 | LL | let x = unsafe { &mut (*p).s }; | ^^^^^^ error: Min Capture analysis includes: - --> $DIR/unsafe_ptr.rs:50:5 + --> $DIR/unsafe_ptr.rs:44:5 | LL | / || { LL | | @@ -83,11 +63,10 @@ LL | | }; | |_____^ | note: Min Capture p[] -> Immutable - --> $DIR/unsafe_ptr.rs:53:31 + --> $DIR/unsafe_ptr.rs:47:31 | LL | let x = unsafe { &mut (*p).s }; | ^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.rs b/tests/ui/closures/2229_closure_analysis/wild_patterns.rs index d220cfce9ce44..c0054c6cf66e3 100644 --- a/tests/ui/closures/2229_closure_analysis/wild_patterns.rs +++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.rs @@ -1,6 +1,6 @@ //@ edition:2021 -#![feature(rustc_attrs)] +#![feature(rustc_attrs, stmt_expr_attributes)] // Test to ensure that we can handle cases where // let statements create no bindings are initialized @@ -20,9 +20,6 @@ fn wild_struct() { let p = Point { x: 10, y: 20 }; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -39,9 +36,6 @@ fn wild_tuple() { let t = (String::new(), 10); let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: @@ -58,9 +52,6 @@ fn wild_arr() { let arr = [String::new(), String::new()]; let c = #[rustc_capture_analysis] - //~^ ERROR: attributes on expressions are experimental - //~| NOTE: see issue #15701 - //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date || { //~^ ERROR: First Pass analysis includes: //~| ERROR: Min Capture analysis includes: diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr index 4cb0f4a4a9274..776ac7f20d27d 100644 --- a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr +++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr @@ -1,35 +1,5 @@ -error[E0658]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:22:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:41:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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]: attributes on expressions are experimental - --> $DIR/wild_patterns.rs:60:13 - | -LL | let c = #[rustc_capture_analysis] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #15701 for more information - = help: add `#![feature(stmt_expr_attributes)]` 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: First Pass analysis includes: - --> $DIR/wild_patterns.rs:26:5 + --> $DIR/wild_patterns.rs:23:5 | LL | / || { ... | @@ -37,13 +7,13 @@ LL | | }; | |_____^ | note: Capturing p[(0, 0)] -> Immutable - --> $DIR/wild_patterns.rs:30:37 + --> $DIR/wild_patterns.rs:27:37 | LL | let Point { x: _x, y: _ } = p; | ^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:26:5 + --> $DIR/wild_patterns.rs:23:5 | LL | / || { ... | @@ -51,13 +21,13 @@ LL | | }; | |_____^ | note: Min Capture p[(0, 0)] -> Immutable - --> $DIR/wild_patterns.rs:30:37 + --> $DIR/wild_patterns.rs:27:37 | LL | let Point { x: _x, y: _ } = p; | ^ error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:45:5 + --> $DIR/wild_patterns.rs:39:5 | LL | / || { ... | @@ -65,13 +35,13 @@ LL | | }; | |_____^ | note: Capturing t[(0, 0)] -> ByValue - --> $DIR/wild_patterns.rs:49:23 + --> $DIR/wild_patterns.rs:43:23 | LL | let (_x, _) = t; | ^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:45:5 + --> $DIR/wild_patterns.rs:39:5 | LL | / || { ... | @@ -79,13 +49,13 @@ LL | | }; | |_____^ | note: Min Capture t[(0, 0)] -> ByValue - --> $DIR/wild_patterns.rs:49:23 + --> $DIR/wild_patterns.rs:43:23 | LL | let (_x, _) = t; | ^ error: First Pass analysis includes: - --> $DIR/wild_patterns.rs:64:5 + --> $DIR/wild_patterns.rs:55:5 | LL | / || { ... | @@ -93,13 +63,13 @@ LL | | }; | |_____^ | note: Capturing arr[Index] -> ByValue - --> $DIR/wild_patterns.rs:68:23 + --> $DIR/wild_patterns.rs:59:23 | LL | let [_x, _] = arr; | ^^^ error: Min Capture analysis includes: - --> $DIR/wild_patterns.rs:64:5 + --> $DIR/wild_patterns.rs:55:5 | LL | / || { ... | @@ -107,11 +77,10 @@ LL | | }; | |_____^ | note: Min Capture arr[] -> ByValue - --> $DIR/wild_patterns.rs:68:23 + --> $DIR/wild_patterns.rs:59:23 | LL | let [_x, _] = arr; | ^^^ -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0658`. From b5e581ffb28d29a2382e461498b45221177bde82 Mon Sep 17 00:00:00 2001 From: chiri Date: Wed, 29 Jul 2026 22:00:27 +0300 Subject: [PATCH 23/53] mark `enc_16lsd` as `unsafe` --- library/core/src/fmt/num.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 1a986d88e0e0d..23d2d5d3a9e3d 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -666,7 +666,9 @@ impl u128 { (mod_1e16, U128_MAX_DEC_N) } else { // Write digits at buf[23..39]. - enc_16lsd::<{ U128_MAX_DEC_N - 16 }>(buf, mod_1e16); + // + // SAFETY: `mod_1e16 < 1e16` (remainder), and `U128_MAX_DEC_N - 16 + 16 == buf.len()`. + unsafe { enc_16lsd::<{ U128_MAX_DEC_N - 16 }>(buf, mod_1e16) }; // Take another 16 decimals. let (quot2, mod2) = div_rem_1e16(quot_1e16); @@ -674,7 +676,10 @@ impl u128 { (mod2, U128_MAX_DEC_N - 16) } else { // Write digits at buf[7..23]. - enc_16lsd::<{ U128_MAX_DEC_N - 32 }>(buf, mod2); + // + // SAFETY: `mod2 < 1e16` (remainder), and `U128_MAX_DEC_N - 32 + 16 <= buf.len()`. + unsafe { enc_16lsd::<{ U128_MAX_DEC_N - 32 }>(buf, mod2) }; + // Quot2 has at most 7 decimals remaining after two 1e16 divisions. (quot2 as u64, U128_MAX_DEC_N - 32) } @@ -843,7 +848,7 @@ unsafe fn write_quad(buf: &mut [MaybeUninit], quad: u64) { /// Encodes the 16 least-significant decimals of n into `buf[OFFSET .. OFFSET + /// 16 ]`. -fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { +unsafe fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { // SAFETY: Every caller passes a remainder produced by division by 10^16, // and every used `OFFSET` specialization reserves sixteen bytes in `buf`. unsafe { From 8d309d2eed9092a967b7b37c200063c91b48d44f Mon Sep 17 00:00:00 2001 From: zakrad <49591476+zakrad@users.noreply.github.com> Date: Thu, 30 Jul 2026 01:11:23 +0330 Subject: [PATCH 24/53] Add regression test for supertrait projection normalization through dyn --- ...lize-supertrait-projection-in-dyn-61083.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/ui/associated-types/normalize-supertrait-projection-in-dyn-61083.rs diff --git a/tests/ui/associated-types/normalize-supertrait-projection-in-dyn-61083.rs b/tests/ui/associated-types/normalize-supertrait-projection-in-dyn-61083.rs new file mode 100644 index 0000000000000..fb93a97328bf4 --- /dev/null +++ b/tests/ui/associated-types/normalize-supertrait-projection-in-dyn-61083.rs @@ -0,0 +1,28 @@ +//! Regression test for . +//! +//! An associated type projection in a supertrait bound (`Bar: Foo`) +//! failed to normalize when the `Bar` bound was reached through a trait object, +//! so passing the object to a function expecting `Foo` was rejected. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +trait Foo {} + +trait Bar: Foo {} + +fn a(_x: &(impl Foo + ?Sized)) {} + +// The `dyn` form is the one that used to fail to normalize `T::Item` to `u32`. +fn b(y: &dyn Bar>) { + a(y) +} + +// The equivalent `impl Trait` form always compiled; keep it so both paths stay pinned. +fn c(y: &(impl Bar> + ?Sized)) { + a(y) +} + +fn main() {} From 3874adb16be9a05a9191538c7c0533753a8f892d Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Wed, 29 Jul 2026 16:39:43 -0500 Subject: [PATCH 25/53] Add -Zinstrument-mcount={fentry-nop-record,fentry-record} The linux kernel still uses fentry for x86 and s390x arches. s390x depends entirely on the compiler to record and nop these sections. This facilitates support for inserting nop's and/or recording the location of each mcount call in a special section named `__mcount_loc`. These attributes are currently only supported with fentry on the s390x target, otherwise they are quietly ignored (except on s390x). --- compiler/rustc_codegen_llvm/src/attributes.rs | 18 +++++++--- compiler/rustc_interface/src/tests.rs | 12 +++---- compiler/rustc_session/src/config.rs | 24 +++++++++---- compiler/rustc_session/src/options.rs | 35 ++++++++++++++----- compiler/rustc_session/src/session.rs | 13 ++++--- .../src/compiler-flags/instrument-mcount.md | 24 +++++++------ tests/codegen-llvm/instrument-mcount-opts.rs | 26 ++++++++++++++ 7 files changed, 111 insertions(+), 41 deletions(-) create mode 100644 tests/codegen-llvm/instrument-mcount-opts.rs diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 1f00e47a89927..cdadc6cc73386 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -8,7 +8,8 @@ use rustc_middle::middle::codegen_fn_attrs::{ }; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_session::config::{ - BranchProtection, FunctionReturn, InstrumentMcount, OptLevel, PAuthKey, PacRet, + BranchProtection, FunctionReturn, InstrumentMcount, InstrumentMcountOpts, OptLevel, PAuthKey, + PacRet, }; use rustc_span::sym; use rustc_symbol_mangling::mangle_internal_symbol; @@ -201,7 +202,7 @@ pub(crate) fn frame_pointer(sess: &Session) -> FramePointer { let opts = &sess.opts; // "mcount" function relies on stack pointer. // See . - if opts.unstable_opts.instrument_mcount == InstrumentMcount::Mcount { + if let InstrumentMcount::Mcount(_) = opts.unstable_opts.instrument_mcount { fp.ratchet(FramePointer::Always); } fp.ratchet(opts.cg.force_frame_pointers); @@ -248,8 +249,9 @@ fn instrument_function_attr<'ll>( }; if instrument_entry { + let mut opts = InstrumentMcountOpts::default(); match sess.opts.unstable_opts.instrument_mcount { - InstrumentMcount::Mcount => { + InstrumentMcount::Mcount(mopts) => { // The function name varies on platforms. // See test/CodeGen/mcount.c in clang. let mcount_name = match &sess.target.llvm_mcount_intrinsic { @@ -262,12 +264,20 @@ fn instrument_function_attr<'ll>( "instrument-function-entry-inlined", mcount_name, )); + opts = mopts; } - InstrumentMcount::Fentry => { + InstrumentMcount::Fentry(fopts) => { attrs.push(llvm::CreateAttrStringValue(cx.llcx, "fentry-call", "true")); + opts = fopts; } InstrumentMcount::Disabled => {} } + if opts.no_call { + attrs.push(llvm::CreateAttrString(cx.llcx, "mnop-mcount")); + } + if opts.record { + attrs.push(llvm::CreateAttrString(cx.llcx, "mrecord-mcount")); + } } } if let Some(options) = &sess.opts.unstable_opts.instrument_xray { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 22b643e74e582..67a820388cbec 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -13,11 +13,11 @@ use rustc_session::config::{ AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CodegenRetagOptions, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, FmtDebug, FunctionReturn, IncrementalStateAssertion, InliningThreshold, Input, - InstrumentCoverage, InstrumentMcount, InstrumentXRay, LinkSelfContained, LinkerPluginLto, - LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig, Offload, Options, OutFileName, - OutputType, OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius, - ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, - build_configuration, build_session_options, rustc_optgroups, + InstrumentCoverage, InstrumentMcount, InstrumentMcountOpts, InstrumentXRay, LinkSelfContained, + LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, NextSolverConfig, Offload, Options, + OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, PatchableFunctionEntry, + Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, + WasiExecModel, build_configuration, build_session_options, rustc_optgroups, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -833,7 +833,7 @@ fn test_unstable_options_tracking_hash() { tracked!(inline_mir, Some(true)); tracked!(inline_mir_hint_threshold, Some(123)); tracked!(inline_mir_threshold, Some(123)); - tracked!(instrument_mcount, InstrumentMcount::Mcount); + tracked!(instrument_mcount, InstrumentMcount::Mcount(InstrumentMcountOpts::default())); tracked!(instrument_xray, Some(InstrumentXRay::default())); tracked!(link_directives, false); tracked!(link_only, true); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 37488ebbf1e8f..2ac1db7ddb89e 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -258,15 +258,23 @@ pub enum AnnotateMoves { Enabled(Option), } +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct InstrumentMcountOpts { + // Insert a nop which could be replaced by an mcount call. + pub no_call: bool, + // Record the location of the call instrument in a special linker section. + pub record: bool, +} + /// The different settings that the `-Z Instrument-mcount` flag can have. #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] pub enum InstrumentMcount { /// `-Z instrument-mcount=no` Disabled, /// `-Z instrument-mcount=yes` - Mcount, + Mcount(InstrumentMcountOpts), /// `-Z instrument-mcount=fentry` - Fentry, + Fentry(InstrumentMcountOpts), } /// Settings for `-Z instrument-xray` flag. @@ -3141,11 +3149,12 @@ pub(crate) mod dep_tracking { use super::{ AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CodegenRetagOptions, CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, - FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentMcount, InstrumentXRay, - LinkerPluginLto, LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, - OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, PointerAuthOption, - Polonius, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, - SymbolManglingVersion, WasiExecModel, + FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentMcount, + InstrumentMcountOpts, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, + MirStripDebugInfo, NextSolverConfig, Offload, OptLevel, OutFileName, OutputType, + OutputTypes, PatchableFunctionEntry, PointerAuthOption, Polonius, ResolveDocLinks, + SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, + WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3208,6 +3217,7 @@ pub(crate) mod dep_tracking { InstrumentCoverage, CoverageOptions, InstrumentMcount, + InstrumentMcountOpts, InstrumentXRay, CrateType, MergeFunctions, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 5b71c0435185a..deb70ccf7cd2b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -852,8 +852,7 @@ mod desc { pub(crate) const parse_coverage_options: &str = "`block` | `branch` | `condition`"; pub(crate) const parse_codegen_retag_options: &str = "either no value or a comma-separated list of settings: `no-precise-im`, `no-precise-pin`"; - pub(crate) const parse_instrument_mcount: &str = - "either a boolean (`yes`, `no`, `on`, `off`, etc), or `fentry` on supported targets."; + pub(crate) const parse_instrument_mcount: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or `fentry`, `fentry-record`, `fentry-nop-record` on supported targets"; pub(crate) const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub(crate) const parse_unpretty: &str = "`string` or `string=string`"; pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; @@ -1670,15 +1669,33 @@ pub mod parse { pub(crate) fn parse_instrument_mcount(slot: &mut InstrumentMcount, v: Option<&str>) -> bool { let mut use_mcount = false; + let mut opts = InstrumentMcountOpts::default(); if parse_bool(&mut use_mcount, v) { - *slot = if use_mcount { InstrumentMcount::Mcount } else { InstrumentMcount::Disabled }; - true - } else if let Some("fentry") = v { - *slot = InstrumentMcount::Fentry; - true - } else { - false + *slot = if use_mcount { + InstrumentMcount::Mcount(opts) + } else { + InstrumentMcount::Disabled + }; + return true; } + match v { + Some("fentry") => { + *slot = InstrumentMcount::Fentry(opts); + } + Some("fentry-record") => { + opts.record = true; + *slot = InstrumentMcount::Fentry(opts); + } + Some("fentry-nop-record") => { + opts.record = true; + opts.no_call = true; + *slot = InstrumentMcount::Fentry(opts); + } + _ => { + return false; + } + } + true } pub(crate) fn parse_instrument_xray( diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index eebead6fc1f47..da20c7ef088a4 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1612,10 +1612,15 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } - if sess.opts.unstable_opts.instrument_mcount == InstrumentMcount::Fentry - && !sess.target.options.supports_fentry - { - sess.dcx().emit_err(diagnostics::InstrumentationNotSupported { us: "fentry".to_string() }); + if let InstrumentMcount::Fentry(opts) = sess.opts.unstable_opts.instrument_mcount { + if !sess.target.options.supports_fentry { + sess.dcx() + .emit_err(diagnostics::InstrumentationNotSupported { us: "fentry".to_string() }); + } + if (opts.no_call || opts.record) && sess.target.arch != Arch::S390x { + sess.dcx() + .emit_err(diagnostics::InstrumentationNotSupported { us: "fentry-*".to_string() }); + } } if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray { diff --git a/src/doc/unstable-book/src/compiler-flags/instrument-mcount.md b/src/doc/unstable-book/src/compiler-flags/instrument-mcount.md index 376b509048dab..07af4435bc7c1 100644 --- a/src/doc/unstable-book/src/compiler-flags/instrument-mcount.md +++ b/src/doc/unstable-book/src/compiler-flags/instrument-mcount.md @@ -12,17 +12,19 @@ Supported options: - `no`, `n`, `off`: Do no enable instrumentation. The default option. This requires, and enables frame pointer generation. - `yes`, `y`, `on`: Enable mcount based function instrumentation. - `fentry`: Enable fentry based function instrument, where supported. The calling conventions for this are different than mcount, with less overhead, and no frame pointer requirements. This counting function is always named `__fentry__`. This is only available on x86 and s390x targets. - -|target |mcount function|supports fentry|ABI notes| -|--- |--- |--- |--- | -|aarch64-apple-darwin | `\u{1}mcount` | | | -|aarch64-pc-windows-msvc | `mcount` | | | -|aarch64-unknown-linux-gnu| `_mcount` | | | -|i686-pc-windows-msvc | `mcount` | x| | -|i686-unknown-linux-gnu | `mcount` | x| | -|x86_64-pc-windows-gnu | `_mcount` | x| | -|x86_64-pc-windows-msvc | `mcount` | x| | -|x86_64-unknown-linux-gnu | `mcount` | x| 1| + - `fentry-nop-record` and `fentry-record`: These options extend the `fentry` option by recording each call site into a section named `__mcount_loc` in the output object file, and optionally replacing the call to `__fentry__` with a nop. These options are not implemented for all targets. Support is noted the supports fentry recording column below. + +|target |mcount function|supports fentry|supports fentry recording|ABI notes| +|--- |--- |--- |---- |-- | +|aarch64-apple-darwin | `\u{1}mcount` | | | | +|aarch64-pc-windows-msvc | `mcount` | | | | +|aarch64-unknown-linux-gnu| `_mcount` | | | | +|i686-pc-windows-msvc | `mcount` | x| | | +|i686-unknown-linux-gnu | `mcount` | x| | | +|x86_64-pc-windows-gnu | `_mcount` | x| | | +|x86_64-pc-windows-msvc | `mcount` | x| | | +|x86_64-unknown-linux-gnu | `mcount` | x| | 1| +|s390x-unknown-linux-gnu | `mcount` | x| x| | On arm eabi targets, the mcount function is usually named `__gnu_mcount_nc`, though some targets may use different names. Implementers of counting function should consult the target specific documentation for quirks of each ABI function. diff --git a/tests/codegen-llvm/instrument-mcount-opts.rs b/tests/codegen-llvm/instrument-mcount-opts.rs new file mode 100644 index 0000000000000..c2dc72614cc64 --- /dev/null +++ b/tests/codegen-llvm/instrument-mcount-opts.rs @@ -0,0 +1,26 @@ +//@ revisions: ncyr ycyr ycnr +//@ add-minicore +//@ needs-llvm-components: systemz +//@ compile-flags: -Copt-level=0 --target=s390x-unknown-linux-gnu +//@[ncyr] compile-flags: -Zinstrument-mcount=fentry-nop-record +//@[ycyr] compile-flags: -Zinstrument-mcount=fentry-record +//@[ycnr] compile-flags: -Zinstrument-mcount=fentry +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] + +extern crate minicore; +use minicore::*; + +// ncyr: attributes #{{.*}} {{.*}} "fentry-call"="true" "mnop-mcount" "mrecord-mcount" +// +// ncnr: attributes #{{.*}} {{.*}} "fentry-call"="true" "mnop-mcount" +// ncnr-NOT: attributes #{{.*}} {{.*}} "mrecord-mcount" +// +// ycnr: attributes #{{.*}} {{.*}} "fentry-call"="true" +// ycnr-NOT: attributes #{{.*}} {{.*}} "mnop-mcount" +// ycnr-NOT: attributes #{{.*}} {{.*}} "mrecord-mcount" +// +// ycyr: attributes #{{.*}} {{.*}} "fentry-call"="true" "mrecord-mcount" +// ycyr-NOT: attributes #{{.*}} {{.*}} "mnop-mcount" +pub fn foo() {} From f48274b37f6fad7575b9c86fefa0e1405a7b9a72 Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 31 Jul 2026 22:49:21 +0100 Subject: [PATCH 26/53] Linkify C-SKY targets in `platform-support.md` --- src/doc/rustc/src/platform-support.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index c527911bc96a2..2da705492f149 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -330,8 +330,8 @@ target | std | host | notes [`avr-none`](platform-support/avr-none.md) | * | | AVR; requires `-Zbuild-std=core` and `-Ctarget-cpu=...` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) -`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian) -`csky-unknown-linux-gnuabiv2hf` | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian) +[`csky-unknown-linux-gnuabiv2`](platform-support/csky-unknown-linux-gnuabiv2.md) | ✓ | | C-SKY abiv2 Linux (little endian) +[`csky-unknown-linux-gnuabiv2hf`](platform-support/csky-unknown-linux-gnuabiv2.md) | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian) [`hexagon-unknown-linux-musl`](platform-support/hexagon-unknown-linux-musl.md) | ✓ | | Hexagon Linux with musl 1.2.5 [`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | | Bare Hexagon (v60+, HVX) [`hexagon-unknown-qurt`](platform-support/hexagon-unknown-qurt.md)| * | | Hexagon QuRT From bacfb80bfda8e0fc22c1f7cd82643e4cd38100db Mon Sep 17 00:00:00 2001 From: Cole Kauder-McMurrich Date: Fri, 31 Jul 2026 13:16:55 -0400 Subject: [PATCH 27/53] Fix rustdoc ICE when checking if a generic arg can be elided --- src/librustdoc/clean/utils.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 9290555f2ef39..597543c957d13 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -117,18 +117,19 @@ pub(crate) fn clean_middle_generic_args<'tcx>( }; let mut elision_has_failed_once_before = false; + let index_offset = generics.count() - args.len(); let clean_arg = |(index, &arg): (usize, &ty::GenericArg<'tcx>)| { // Elide the self type. if has_self && index == 0 { return None; } - let param = generics.param_at(index, cx.tcx); + let param = generics.param_at(index + index_offset, cx.tcx); let arg = ty::Binder::bind_with_vars(arg, bound_vars); // Elide arguments that coincide with their default. if !elision_has_failed_once_before && let Some(default) = param.default_value(cx.tcx) { - let default = default.instantiate(cx.tcx, args.as_ref()).skip_norm_wip(); + let default = default.instantiate(cx.tcx, args.as_ref()).skip_normalization(); if can_elide_generic_arg(arg, arg.rebind(default)) { return None; } From ce8f41367bf4c2b73e5daafb38bce21b82d97345 Mon Sep 17 00:00:00 2001 From: Cole Kauder-McMurrich Date: Fri, 31 Jul 2026 17:11:07 -0400 Subject: [PATCH 28/53] Add regression test for rustdoc ICE when checking if a generic arg can be elided --- .../ice-clean-generic-args-133637.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/rustdoc-ui/ice-clean-generic-args-133637.rs diff --git a/tests/rustdoc-ui/ice-clean-generic-args-133637.rs b/tests/rustdoc-ui/ice-clean-generic-args-133637.rs new file mode 100644 index 0000000000000..b90ff547b9cfa --- /dev/null +++ b/tests/rustdoc-ui/ice-clean-generic-args-133637.rs @@ -0,0 +1,18 @@ +//@ check-pass +// https://github.com/rust-lang/rust/issues/133637 +#![crate_name="foo"] + +// Regression test for issue #133637. Previously we would index into the flattened generics list +// with the children generic indexes. This resulted in an ICE when debug assertions were on. + +struct SomeDefault; + +trait SomeTrait { + type Type<'a, 'b>; +} + +impl SomeTrait for T { + type Type<'a, 'b> = (&'a u8, &'b u8); +} + +type SomeType<'a, 'b, T, Gen = SomeDefault> = >::Type<'a, 'b>; From 6e2de73e9ca4e89f74ddad4bb688d92e85031d72 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Sat, 1 Aug 2026 13:12:37 +0600 Subject: [PATCH 29/53] point at trait definition when it is used as a derive macro fixes https://github.com/rust-lang/rust/issues/159483 --- .../rustc_resolve/src/diagnostics/impls.rs | 35 +++++++++++++++- tests/ui/macros/derive-of-trait.rs | 32 +++++++++++++++ tests/ui/macros/derive-of-trait.stderr | 41 +++++++++++++++++++ tests/ui/macros/issue-88206.rs | 5 +-- tests/ui/macros/issue-88206.stderr | 31 +++++++------- tests/ui/macros/issue-88228.rs | 2 + tests/ui/macros/issue-88228.stderr | 7 +++- 7 files changed, 131 insertions(+), 22 deletions(-) create mode 100644 tests/ui/macros/derive-of-trait.rs create mode 100644 tests/ui/macros/derive-of-trait.stderr diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 212629395c98b..680f87d43e4e9 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -2034,8 +2034,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Don't confuse the user with tool modules or open modules. continue; } - Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => { - "only a trait, without a derive macro".to_string() + Res::Def(DefKind::Trait, trait_def_id) if macro_kind == MacroKind::Derive => { + if let crate::DeclKind::Import { import, .. } = binding.kind + && !import.span.is_dummy() + { + self.record_use(ident, binding, Used::Other); + } + let trait_span = self.def_span(trait_def_id); + err.span_note(trait_span, format!("`{ident}` is a trait, not a derive macro")); + err.help(format!("consider implementing `{ident}` for your type manually")); + return; } res => format!( "{} {}, not {} {}", @@ -2067,6 +2075,29 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; } + // Not in scope: check if the name refers to a trait importable from elsewhere. + if macro_kind == MacroKind::Derive { + let trait_candidates = + self.lookup_import_candidates(ident, TypeNS, parent_scope, |res| { + matches!(res, Res::Def(DefKind::Trait, _)) + }); + let mut seen = FxHashSet::default(); + for candidate in &trait_candidates { + if let Some(def_id) = candidate.did + && seen.insert(def_id) + { + err.span_note( + self.def_span(def_id), + format!("`{ident}` is a trait, not a derive macro"), + ); + } + } + if !seen.is_empty() { + err.help(format!("consider implementing `{ident}` for your type manually")); + return; + } + } + if self.macro_names.contains(&IdentKey::new(ident)) { err.subdiagnostic(AddedMacroUse); return; diff --git a/tests/ui/macros/derive-of-trait.rs b/tests/ui/macros/derive-of-trait.rs new file mode 100644 index 0000000000000..ebabb01f3d587 --- /dev/null +++ b/tests/ui/macros/derive-of-trait.rs @@ -0,0 +1,32 @@ +//@ compile-flags: -Z deduplicate-diagnostics=yes + +// Trait used as a derive target should point at the trait definition and +// suggest a manual implementation — both when the trait is already in scope +// (via import or local definition) and when it is only importable. + +mod inner { + pub trait MyTrait {} //~ NOTE `MyTrait` is a trait, not a derive macro + pub trait OuterTrait {} //~ NOTE `OuterTrait` is a trait, not a derive macro +} + +use inner::MyTrait; + +trait LocalTrait {} +//~^ NOTE `LocalTrait` is a trait, not a derive macro + +// in-scope: locally defined +#[derive(LocalTrait)] +//~^ ERROR cannot find derive macro `LocalTrait` in this scope +struct A; + +// in-scope: imported +#[derive(MyTrait)] +//~^ ERROR cannot find derive macro `MyTrait` in this scope +struct B; + +// out-of-scope: importable but not imported +#[derive(OuterTrait)] +//~^ ERROR cannot find derive macro `OuterTrait` in this scope +struct C; + +fn main() {} diff --git a/tests/ui/macros/derive-of-trait.stderr b/tests/ui/macros/derive-of-trait.stderr new file mode 100644 index 0000000000000..6e40f13d9645f --- /dev/null +++ b/tests/ui/macros/derive-of-trait.stderr @@ -0,0 +1,41 @@ +error: cannot find derive macro `OuterTrait` in this scope + --> $DIR/derive-of-trait.rs:28:10 + | +LL | #[derive(OuterTrait)] + | ^^^^^^^^^^ + | +note: `OuterTrait` is a trait, not a derive macro + --> $DIR/derive-of-trait.rs:9:5 + | +LL | pub trait OuterTrait {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + = help: consider implementing `OuterTrait` for your type manually + +error: cannot find derive macro `MyTrait` in this scope + --> $DIR/derive-of-trait.rs:23:10 + | +LL | #[derive(MyTrait)] + | ^^^^^^^ + | +note: `MyTrait` is a trait, not a derive macro + --> $DIR/derive-of-trait.rs:8:5 + | +LL | pub trait MyTrait {} + | ^^^^^^^^^^^^^^^^^^^^ + = help: consider implementing `MyTrait` for your type manually + +error: cannot find derive macro `LocalTrait` in this scope + --> $DIR/derive-of-trait.rs:18:10 + | +LL | #[derive(LocalTrait)] + | ^^^^^^^^^^ + | +note: `LocalTrait` is a trait, not a derive macro + --> $DIR/derive-of-trait.rs:14:1 + | +LL | trait LocalTrait {} + | ^^^^^^^^^^^^^^^^^^^ + = help: consider implementing `LocalTrait` for your type manually + +error: aborting due to 3 previous errors + diff --git a/tests/ui/macros/issue-88206.rs b/tests/ui/macros/issue-88206.rs index abf58fdcbc815..b78a2d48e0b62 100644 --- a/tests/ui/macros/issue-88206.rs +++ b/tests/ui/macros/issue-88206.rs @@ -8,15 +8,14 @@ use std::str::*; //~| NOTE `from_utf8_unchecked` is imported here, but it is a function mod hey { - pub trait Serialize {} + pub trait Serialize {} //~ NOTE `Serialize` is a trait, not a derive macro pub trait Deserialize {} pub struct X(i32); } use hey::{Serialize, Deserialize, X}; -//~^ NOTE `Serialize` is imported here, but it is only a trait, without a derive macro -//~| NOTE `Deserialize` is imported here, but it is a trait +//~^ NOTE `Deserialize` is imported here, but it is a trait //~| NOTE `X` is imported here, but it is a struct #[derive(Serialize)] diff --git a/tests/ui/macros/issue-88206.stderr b/tests/ui/macros/issue-88206.stderr index f7f5b56488007..93be644650f20 100644 --- a/tests/ui/macros/issue-88206.stderr +++ b/tests/ui/macros/issue-88206.stderr @@ -1,5 +1,5 @@ error: cannot find macro `X` in this scope - --> $DIR/issue-88206.rs:64:5 + --> $DIR/issue-88206.rs:63:5 | LL | X!(); | ^ @@ -11,7 +11,7 @@ LL | use hey::{Serialize, Deserialize, X}; | ^ error: cannot find macro `test` in this scope - --> $DIR/issue-88206.rs:60:5 + --> $DIR/issue-88206.rs:59:5 | LL | test!(); | ^^^^ @@ -19,7 +19,7 @@ LL | test!(); = note: `test` is in scope, but it is an attribute: `#[test]` error: cannot find macro `Copy` in this scope - --> $DIR/issue-88206.rs:56:5 + --> $DIR/issue-88206.rs:55:5 | LL | Copy!(); | ^^^^ @@ -27,7 +27,7 @@ LL | Copy!(); = note: `Copy` is in scope, but it is a derive macro: `#[derive(Copy)]` error: cannot find macro `Box` in this scope - --> $DIR/issue-88206.rs:52:5 + --> $DIR/issue-88206.rs:51:5 | LL | Box!(); | ^^^ @@ -35,7 +35,7 @@ LL | Box!(); = note: `Box` is in scope, but it is a struct, not a macro error: cannot find macro `from_utf8` in this scope - --> $DIR/issue-88206.rs:49:5 + --> $DIR/issue-88206.rs:48:5 | LL | from_utf8!(); | ^^^^^^^^^ @@ -47,7 +47,7 @@ LL | use std::str::*; | ^^^^^^^^^^^ error: cannot find attribute `println` in this scope - --> $DIR/issue-88206.rs:43:3 + --> $DIR/issue-88206.rs:42:3 | LL | #[println] | ^^^^^^^ @@ -55,7 +55,7 @@ LL | #[println] = note: `println` is in scope, but it is a function-like macro error: cannot find attribute `from_utf8_unchecked` in this scope - --> $DIR/issue-88206.rs:39:3 + --> $DIR/issue-88206.rs:38:3 | LL | #[from_utf8_unchecked] | ^^^^^^^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | use std::str::*; | ^^^^^^^^^^^ error: cannot find attribute `Deserialize` in this scope - --> $DIR/issue-88206.rs:35:3 + --> $DIR/issue-88206.rs:34:3 | LL | #[Deserialize] | ^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | use hey::{Serialize, Deserialize, X}; | ^^^^^^^^^^^ error: cannot find derive macro `println` in this scope - --> $DIR/issue-88206.rs:30:10 + --> $DIR/issue-88206.rs:29:10 | LL | #[derive(println)] | ^^^^^^^ @@ -87,7 +87,7 @@ LL | #[derive(println)] = note: `println` is in scope, but it is a function-like macro error: cannot find derive macro `from_utf8_mut` in this scope - --> $DIR/issue-88206.rs:26:10 + --> $DIR/issue-88206.rs:25:10 | LL | #[derive(from_utf8_mut)] | ^^^^^^^^^^^^^ @@ -99,16 +99,17 @@ LL | use std::str::*; | ^^^^^^^^^^^ error: cannot find derive macro `Serialize` in this scope - --> $DIR/issue-88206.rs:22:10 + --> $DIR/issue-88206.rs:21:10 | LL | #[derive(Serialize)] | ^^^^^^^^^ | -note: `Serialize` is imported here, but it is only a trait, without a derive macro - --> $DIR/issue-88206.rs:17:11 +note: `Serialize` is a trait, not a derive macro + --> $DIR/issue-88206.rs:11:5 | -LL | use hey::{Serialize, Deserialize, X}; - | ^^^^^^^^^ +LL | pub trait Serialize {} + | ^^^^^^^^^^^^^^^^^^^^^^ + = help: consider implementing `Serialize` for your type manually error: aborting due to 11 previous errors diff --git a/tests/ui/macros/issue-88228.rs b/tests/ui/macros/issue-88228.rs index b4195a92557ed..e58a90d08cdda 100644 --- a/tests/ui/macros/issue-88228.rs +++ b/tests/ui/macros/issue-88228.rs @@ -9,6 +9,8 @@ mod hey { //~ HELP consider importing this derive macro #[derive(Bla)] //~^ ERROR cannot find derive macro `Bla` +//~| NOTE `Bla` is a trait, not a derive macro +//~| HELP consider implementing `Bla` for your type manually struct A; #[derive(println)] diff --git a/tests/ui/macros/issue-88228.stderr b/tests/ui/macros/issue-88228.stderr index f9d0ac95da756..164af4e07bddf 100644 --- a/tests/ui/macros/issue-88228.stderr +++ b/tests/ui/macros/issue-88228.stderr @@ -1,5 +1,5 @@ error: cannot find macro `bla` in this scope - --> $DIR/issue-88228.rs:20:5 + --> $DIR/issue-88228.rs:22:5 | LL | bla!(); | ^^^ @@ -10,7 +10,7 @@ LL + use crate::hey::bla; | error: cannot find derive macro `println` in this scope - --> $DIR/issue-88228.rs:14:10 + --> $DIR/issue-88228.rs:16:10 | LL | #[derive(println)] | ^^^^^^^ @@ -23,6 +23,9 @@ error: cannot find derive macro `Bla` in this scope LL | #[derive(Bla)] | ^^^ | +note: `Bla` is a trait, not a derive macro + --> $SRC_DIR/core/src/marker.rs:LL:COL + = help: consider implementing `Bla` for your type manually help: consider importing this derive macro through its public re-export | LL + use crate::hey::Bla; From 2ffc259743df2aa6594a825d4964f56f0d31a1ad Mon Sep 17 00:00:00 2001 From: Yukang Date: Sat, 1 Aug 2026 21:44:44 +0800 Subject: [PATCH 30/53] Add regression test for unused_parens on contract clauses --- ...tract-clause-unused-parens-issue-143754.rs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/ui/contracts/contract-clause-unused-parens-issue-143754.rs diff --git a/tests/ui/contracts/contract-clause-unused-parens-issue-143754.rs b/tests/ui/contracts/contract-clause-unused-parens-issue-143754.rs new file mode 100644 index 0000000000000..576d99665f124 --- /dev/null +++ b/tests/ui/contracts/contract-clause-unused-parens-issue-143754.rs @@ -0,0 +1,22 @@ +//@ check-pass +// Regression test for . +// The contract macros wrap the clause in braces rather than parentheses, so `unused_parens` +// must not fire on a contract attribute (and must not emit the attribute-eating suggestion). + +#![expect(incomplete_features)] +#![feature(contracts)] +#![deny(unused_parens)] + +#[core::contracts::requires(x.baz > 0)] +#[core::contracts::ensures(|ret| *ret > 100)] +fn nest(x: Baz) -> i32 { + loop { + return x.baz + 50; + } +} + +struct Baz { + baz: i32, +} + +fn main() {} From d443d457c8884df8881b36b8ffc300ff12892a65 Mon Sep 17 00:00:00 2001 From: im-lunex Date: Sat, 1 Aug 2026 19:12:00 +0000 Subject: [PATCH 31/53] fix borrowck ICE for consts with fn pointer type * fix borrowck ICE for consts with fn pointer type annotate_argument_and_return_for_borrow called tcx.fn_sig on the item being checked whenever its type was FnDef or FnPtr. for a const whose type is a fn pointer that's not a function item, so we ICE'd with "unexpected sort of node in fn_sig". take the signature from the fn ptr type instead and skip the annotation when there's no fn decl. * run rustfmt and refmt * fix borrowck ICE for consts with fn pointer type annotate_argument_and_return_for_borrow called tcx.fn_sig on the item being checked whenever its type was FnDef or FnPtr. for a const whose type is a fn pointer that's not a function item, so we ICE'd with "unexpected sort of node in fn_sig". take the signature from the fn ptr type instead and skip the annotation when there's no fn decl. * edit comment * use ty.fn_sig per review --- .../src/diagnostics/conflict_errors.rs | 7 +++++-- .../borrowck/const-fn-ptr-borrow-annotation.rs | 16 ++++++++++++++++ .../const-fn-ptr-borrow-annotation.stderr | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 tests/ui/borrowck/const-fn-ptr-borrow-annotation.rs create mode 100644 tests/ui/borrowck/const-fn-ptr-borrow-annotation.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8d1f9cea853f9..f2a55194cf0f0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -4277,7 +4277,8 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { ) -> Option> { // Define a fallback for when we can't match a closure. let fallback = || { - let is_closure = self.infcx.tcx.is_closure_like(self.mir_def_id().to_def_id()); + let tcx = self.infcx.tcx; + let is_closure = tcx.is_closure_like(self.mir_def_id().to_def_id()); if is_closure { None } else { @@ -4288,7 +4289,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { .instantiate_identity() .skip_norm_wip(); match ty.kind() { - ty::FnDef(_, _) | ty::FnPtr(..) => self.annotate_fn_sig( + ty::FnDef(_, _) => self.annotate_fn_sig( self.mir_def_id(), self.infcx .tcx @@ -4296,6 +4297,8 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { .instantiate_identity() .skip_norm_wip(), ), + // a const/static can have a fn ptr type, take the sig from the type instead. + ty::FnPtr(_, _) => self.annotate_fn_sig(self.mir_def_id(), ty.fn_sig(tcx)), _ => None, } } diff --git a/tests/ui/borrowck/const-fn-ptr-borrow-annotation.rs b/tests/ui/borrowck/const-fn-ptr-borrow-annotation.rs new file mode 100644 index 0000000000000..7d98d5a739797 --- /dev/null +++ b/tests/ui/borrowck/const-fn-ptr-borrow-annotation.rs @@ -0,0 +1,16 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160255. + +use std::mem; + +const A: fn() = unsafe { + mem::transmute({ + fn fun() {} + let _ = fun as fn(); + { + let s = [0; 10]; + &s //~ ERROR: `s` does not live long enough [E0597] + } + }) +}; + +fn main() {} diff --git a/tests/ui/borrowck/const-fn-ptr-borrow-annotation.stderr b/tests/ui/borrowck/const-fn-ptr-borrow-annotation.stderr new file mode 100644 index 0000000000000..33ab95e4029b4 --- /dev/null +++ b/tests/ui/borrowck/const-fn-ptr-borrow-annotation.stderr @@ -0,0 +1,16 @@ +error[E0597]: `s` does not live long enough + --> $DIR/const-fn-ptr-borrow-annotation.rs:11:13 + | +LL | mem::transmute({ + | -------------- borrow later used by call +... +LL | let s = [0; 10]; + | - binding `s` declared here +LL | &s + | ^^ borrowed value does not live long enough +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0597`. From 2cee42105a5cc121030724e6ac806e3dd509c6e6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 1 Aug 2026 09:43:26 +0200 Subject: [PATCH 32/53] ElaborateBoxDeref: remove unnecessary projection --- compiler/rustc_middle/src/mir/statement.rs | 2 +- .../src/elaborate_box_derefs.rs | 34 ++++++------------- .../transmute.unreachable_box.GVN.32bit.diff | 4 +-- .../transmute.unreachable_box.GVN.64bit.diff | 4 +-- ...reachable_box.DataflowConstProp.32bit.diff | 2 +- ...reachable_box.DataflowConstProp.64bit.diff | 2 +- ...ng_operand.test.GVN.32bit.panic-abort.diff | 2 +- ...g_operand.test.GVN.32bit.panic-unwind.diff | 2 +- ...ng_operand.test.GVN.64bit.panic-abort.diff | 2 +- ...g_operand.test.GVN.64bit.panic-unwind.diff | 2 +- ...ric_rust_call.call.Inline.panic-abort.diff | 4 +-- ...ic_rust_call.call.Inline.panic-unwind.diff | 4 +-- ...inline_box_fn.call.Inline.panic-abort.diff | 4 +-- ...nline_box_fn.call.Inline.panic-unwind.diff | 4 +-- ...67_inline_as_ref_as_mut.b.Inline.after.mir | 4 +-- ...67_inline_as_ref_as_mut.d.Inline.after.mir | 4 +-- .../unsized_argument.caller.Inline.diff | 2 +- ...inhabited.LowerIntrinsics.panic-abort.diff | 2 +- ...nhabited.LowerIntrinsics.panic-unwind.diff | 2 +- 19 files changed, 37 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 17eeb7c3c12aa..e0c8789a8d8b3 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -442,7 +442,7 @@ impl<'tcx> Place<'tcx> { pub fn project_to_field( self, idx: FieldIdx, - local_decls: &impl HasLocalDecls<'tcx>, + local_decls: &(impl HasLocalDecls<'tcx> + ?Sized), tcx: TyCtxt<'tcx>, ) -> Self { let ty = self.ty(local_decls, tcx).ty; diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 5c925b9ecaa42..6ce39aac6a0db 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -26,18 +26,8 @@ fn build_ptr_tys<'tcx>( (unique_ty, nonnull_ty, ptr_ty) } -/// Constructs the projection needed to access a Box's pointer -pub(super) fn build_projection<'tcx>( - unique_ty: Ty<'tcx>, - nonnull_ty: Ty<'tcx>, -) -> [PlaceElem<'tcx>; 2] { - [PlaceElem::Field(FieldIdx::ZERO, unique_ty), PlaceElem::Field(FieldIdx::ZERO, nonnull_ty)] -} - struct ElaborateBoxDerefVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, - unique_def: ty::AdtDef<'tcx>, - nonnull_def: ty::AdtDef<'tcx>, local_decls: &'a mut LocalDecls<'tcx>, patch: MirPatch<'tcx>, } @@ -63,22 +53,18 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> { { let source_info = self.local_decls[place.local].source_info; - let (unique_ty, nonnull_ty, ptr_ty) = - build_ptr_tys(tcx, boxed_ty, self.unique_def, self.nonnull_def); + let ptr_ty = Ty::new_imm_ptr(tcx, boxed_ty); let ptr_local = self.patch.new_temp(ptr_ty, source_info.span); + // Project to the first field (a `Unique`), then transmute that. We could project one + // further but in the end we'd hit a pattern type so we'd always have to transmute. + let field_place = + Place::from(place.local).project_to_field(FieldIdx::ZERO, &*self.local_decls, tcx); self.patch.add_assign( location, Place::from(ptr_local), - Rvalue::Cast( - CastKind::BoxDerefTransmute, - Operand::Copy( - Place::from(place.local) - .project_deeper(&build_projection(unique_ty, nonnull_ty), tcx), - ), - ptr_ty, - ), + Rvalue::Cast(CastKind::BoxDerefTransmute, Operand::Copy(field_place), ptr_ty), ); place.local = ptr_local; @@ -115,8 +101,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { let local_decls = &mut body.local_decls; - let mut visitor = - ElaborateBoxDerefVisitor { tcx, unique_def, nonnull_def, local_decls, patch }; + let mut visitor = ElaborateBoxDerefVisitor { tcx, local_decls, patch }; for (block, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() { visitor.visit_basic_block_data(block, data); @@ -141,7 +126,10 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { let (unique_ty, nonnull_ty, ptr_ty) = build_ptr_tys(tcx, boxed_ty, unique_def, nonnull_def); - new_projections.extend_from_slice(&build_projection(unique_ty, nonnull_ty)); + new_projections.extend_from_slice(&[ + PlaceElem::Field(FieldIdx::ZERO, unique_ty), + PlaceElem::Field(FieldIdx::ZERO, nonnull_ty), + ]); // While we can't project into a pattern type in a basic block, // this is debug info where it's fine. let pat_ty = Ty::new_pat(tcx, ptr_ty, tcx.mk_pat(PatternKind::NotNull)); diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff index a6756ba0245c7..f87e33bd69789 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff @@ -12,9 +12,9 @@ bb0: { StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); -- _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); +- _2 = copy (_1.0: std::ptr::Unique) as *const Never (BoxDerefTransmute); + _1 = const Box::(std::ptr::Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); -+ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }} as *const Never (BoxDerefTransmute); ++ _2 = const std::ptr::Unique:: {{ pointer: std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: std::marker::PhantomData:: }} as *const Never (BoxDerefTransmute); unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff index a6756ba0245c7..f87e33bd69789 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff @@ -12,9 +12,9 @@ bb0: { StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); -- _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); +- _2 = copy (_1.0: std::ptr::Unique) as *const Never (BoxDerefTransmute); + _1 = const Box::(std::ptr::Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); -+ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }} as *const Never (BoxDerefTransmute); ++ _2 = const std::ptr::Unique:: {{ pointer: std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: std::marker::PhantomData:: }} as *const Never (BoxDerefTransmute); unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff index 352d9345eef84..aaa0655d3c60e 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff @@ -13,7 +13,7 @@ StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); + _1 = const Box::(std::ptr::Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); + _2 = copy (_1.0: std::ptr::Unique) as *const Never (BoxDerefTransmute); unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff index 352d9345eef84..aaa0655d3c60e 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff @@ -13,7 +13,7 @@ StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); + _1 = const Box::(std::ptr::Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); + _2 = copy (_1.0: std::ptr::Unique) as *const Never (BoxDerefTransmute); unreachable; } } 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 8b5ad1519d27c..451d639ca2aa4 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 @@ -73,7 +73,7 @@ StorageDead(_2); StorageLive(_5); _10 = no_retag copy (*_1); - _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (BoxDerefTransmute); + _11 = copy (_10.0: std::ptr::Unique<()>) as *const () (BoxDerefTransmute); _5 = &raw const (*_11); StorageLive(_6); StorageLive(_7); 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 14943534b98be..75b00c8885cd0 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 @@ -53,7 +53,7 @@ StorageDead(_2); StorageLive(_5); _10 = no_retag copy (*_1); - _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (BoxDerefTransmute); + _11 = copy (_10.0: std::ptr::Unique<()>) as *const () (BoxDerefTransmute); _5 = &raw const (*_11); StorageLive(_6); StorageLive(_7); 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 f8d47dcae5b27..3473ceb21a0ab 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 @@ -73,7 +73,7 @@ StorageDead(_2); StorageLive(_5); _10 = no_retag copy (*_1); - _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (BoxDerefTransmute); + _11 = copy (_10.0: std::ptr::Unique<()>) as *const () (BoxDerefTransmute); _5 = &raw const (*_11); StorageLive(_6); StorageLive(_7); 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 14943534b98be..75b00c8885cd0 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 @@ -53,7 +53,7 @@ StorageDead(_2); StorageLive(_5); _10 = no_retag copy (*_1); - _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (BoxDerefTransmute); + _11 = copy (_10.0: std::ptr::Unique<()>) as *const () (BoxDerefTransmute); _5 = &raw const (*_11); StorageLive(_6); StorageLive(_7); diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff index ceacf606f3553..92060c211330e 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff @@ -10,7 +10,7 @@ + scope 1 (inlined > as FnMut>::call_mut) { + let mut _5: &mut dyn std::ops::FnMut; + let mut _6: *const dyn std::ops::FnMut; -+ let mut _7: std::ptr::NonNull>; ++ let mut _7: std::ptr::Unique>; + } bb0: { @@ -22,7 +22,7 @@ + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); -+ _7 = no_retag copy (((*_3).0: std::ptr::Unique>).0: std::ptr::NonNull>); ++ _7 = no_retag copy ((*_3).0: std::ptr::Unique>); + _6 = copy _7 as *const dyn std::ops::FnMut (BoxDerefTransmute); + _5 = &mut (*_6); + _0 = as FnMut>::call_mut(move _5, move _4) -> [return: bb2, unwind unreachable]; diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff index 862174fd94bff..085fa453ade13 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff @@ -10,7 +10,7 @@ + scope 1 (inlined > as FnMut>::call_mut) { + let mut _5: &mut dyn std::ops::FnMut; + let mut _6: *const dyn std::ops::FnMut; -+ let mut _7: std::ptr::NonNull>; ++ let mut _7: std::ptr::Unique>; + } bb0: { @@ -22,7 +22,7 @@ + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); -+ _7 = no_retag copy (((*_3).0: std::ptr::Unique>).0: std::ptr::NonNull>); ++ _7 = no_retag copy ((*_3).0: std::ptr::Unique>); + _6 = copy _7 as *const dyn std::ops::FnMut (BoxDerefTransmute); + _5 = &mut (*_6); + _0 = as FnMut>::call_mut(move _5, move _4) -> [return: bb4, unwind: bb2]; diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff index 0dc8adb257423..d04dc8f5ff5b2 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff @@ -10,7 +10,7 @@ + scope 1 (inlined as Fn<(i32,)>>::call) { + let mut _5: &dyn std::ops::Fn(i32); + let mut _6: *const dyn std::ops::Fn(i32); -+ let mut _7: std::ptr::NonNull; ++ let mut _7: std::ptr::Unique; + } bb0: { @@ -23,7 +23,7 @@ + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); -+ _7 = no_retag copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); ++ _7 = no_retag copy ((*_3).0: std::ptr::Unique); + _6 = copy _7 as *const dyn std::ops::Fn(i32) (BoxDerefTransmute); + _5 = &(*_6); + _2 = >::call(move _5, move _4) -> [return: bb2, unwind unreachable]; diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff index 1b320f9200405..f2fc8c7388f7d 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff @@ -10,7 +10,7 @@ + scope 1 (inlined as Fn<(i32,)>>::call) { + let mut _5: &dyn std::ops::Fn(i32); + let mut _6: *const dyn std::ops::Fn(i32); -+ let mut _7: std::ptr::NonNull; ++ let mut _7: std::ptr::Unique; + } bb0: { @@ -23,7 +23,7 @@ + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); -+ _7 = no_retag copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); ++ _7 = no_retag copy ((*_3).0: std::ptr::Unique); + _6 = copy _7 as *const dyn std::ops::Fn(i32) (BoxDerefTransmute); + _5 = &(*_6); + _2 = >::call(move _5, move _4) -> [return: bb4, unwind: bb2]; diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index f4972c7d1437e..1d56fa0860654 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -9,7 +9,7 @@ fn b(_1: &mut Box) -> &mut T { scope 1 (inlined as AsMut>::as_mut) { debug self => _4; let mut _5: *const T; - let mut _6: std::ptr::NonNull; + let mut _6: std::ptr::Unique; } bb0: { @@ -19,7 +19,7 @@ fn b(_1: &mut Box) -> &mut T { _4 = no_retag copy _1; StorageLive(_5); StorageLive(_6); - _6 = no_retag copy (((*_4).0: std::ptr::Unique).0: std::ptr::NonNull); + _6 = no_retag copy ((*_4).0: std::ptr::Unique); _5 = copy _6 as *const T (BoxDerefTransmute); _3 = &mut (*_5); StorageDead(_6); diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index d5a0450af828e..a74065283737b 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -8,7 +8,7 @@ fn d(_1: &Box) -> &T { scope 1 (inlined as AsRef>::as_ref) { debug self => _3; let mut _4: *const T; - let mut _5: std::ptr::NonNull; + let mut _5: std::ptr::Unique; } bb0: { @@ -17,7 +17,7 @@ fn d(_1: &Box) -> &T { _3 = copy _1; StorageLive(_4); StorageLive(_5); - _5 = no_retag copy (((*_3).0: std::ptr::Unique).0: std::ptr::NonNull); + _5 = no_retag copy ((*_3).0: std::ptr::Unique); _4 = copy _5 as *const T (BoxDerefTransmute); _2 = &(*_4); StorageDead(_5); diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff index 8ca4ca123c829..6865766499a6a 100644 --- a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff +++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff @@ -12,7 +12,7 @@ StorageLive(_2); StorageLive(_3); _3 = move _1; - _4 = copy ((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>) as *const [i32] (BoxDerefTransmute); + _4 = copy (_3.0: std::ptr::Unique<[i32]>) as *const [i32] (BoxDerefTransmute); _2 = callee(move (*_4)) -> [return: bb1, unwind: bb3]; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff index adf61031b3699..3a6a8e137aadc 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-abort.diff @@ -17,7 +17,7 @@ } bb1: { - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); + _2 = copy (_1.0: std::ptr::Unique) as *const Never (BoxDerefTransmute); PlaceMention((*_2)); unreachable; } diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff index adf61031b3699..3a6a8e137aadc 100644 --- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.panic-unwind.diff @@ -17,7 +17,7 @@ } bb1: { - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (BoxDerefTransmute); + _2 = copy (_1.0: std::ptr::Unique) as *const Never (BoxDerefTransmute); PlaceMention((*_2)); unreachable; } From 5ab7f5081214ab5376e61d974735ab1d1016beca Mon Sep 17 00:00:00 2001 From: Cole Kauder-McMurrich Date: Sat, 1 Aug 2026 20:50:39 -0400 Subject: [PATCH 33/53] Comment fix for rustdoc ICE when checking if a generic arg can be elided --- src/librustdoc/clean/utils.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 597543c957d13..20a466fd3dee9 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -117,6 +117,8 @@ pub(crate) fn clean_middle_generic_args<'tcx>( }; let mut elision_has_failed_once_before = false; + + // Calculates where the parent trait's generic parameters end let index_offset = generics.count() - args.len(); let clean_arg = |(index, &arg): (usize, &ty::GenericArg<'tcx>)| { // Elide the self type. @@ -124,6 +126,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>( return None; } + // Skips over the parent trait's generic parameters let param = generics.param_at(index + index_offset, cx.tcx); let arg = ty::Binder::bind_with_vars(arg, bound_vars); From 569e0bc92bdb5beb88c88a9b3cf49e447b6e0463 Mon Sep 17 00:00:00 2001 From: Cole Kauder-McMurrich Date: Sat, 1 Aug 2026 21:13:46 -0400 Subject: [PATCH 34/53] Further minimize regression test for rustdoc ICE --- tests/rustdoc-ui/ice-clean-generic-args-133637.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tests/rustdoc-ui/ice-clean-generic-args-133637.rs b/tests/rustdoc-ui/ice-clean-generic-args-133637.rs index b90ff547b9cfa..9b2b5d9dae4af 100644 --- a/tests/rustdoc-ui/ice-clean-generic-args-133637.rs +++ b/tests/rustdoc-ui/ice-clean-generic-args-133637.rs @@ -5,14 +5,8 @@ // Regression test for issue #133637. Previously we would index into the flattened generics list // with the children generic indexes. This resulted in an ICE when debug assertions were on. -struct SomeDefault; - -trait SomeTrait { +trait Trait { type Type<'a, 'b>; } -impl SomeTrait for T { - type Type<'a, 'b> = (&'a u8, &'b u8); -} - -type SomeType<'a, 'b, T, Gen = SomeDefault> = >::Type<'a, 'b>; +type Type = ::Type<'static, 'static>; From 5ba0b9f70c68aaadf47724a931f38c8ae37d431f Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 1 Aug 2026 23:15:07 -0700 Subject: [PATCH 35/53] Add (failing) test to check for an exact alias before a similar name --- .../suggest-exact-alias-before-similar-name.rs | 15 +++++++++++++++ ...gest-exact-alias-before-similar-name.stderr | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/ui/suggestions/suggest-exact-alias-before-similar-name.rs create mode 100644 tests/ui/suggestions/suggest-exact-alias-before-similar-name.stderr diff --git a/tests/ui/suggestions/suggest-exact-alias-before-similar-name.rs b/tests/ui/suggestions/suggest-exact-alias-before-similar-name.rs new file mode 100644 index 0000000000000..2279dc87ed646 --- /dev/null +++ b/tests/ui/suggestions/suggest-exact-alias-before-similar-name.rs @@ -0,0 +1,15 @@ +struct Reader; +//~^ NOTE method `read_exact_buf` not found for this struct + +impl Reader { + fn read_exact(&self) {} + + #[doc(alias("read_exact_buf"))] + fn read_buf_exact(&self) {} +} + +fn main() { + Reader.read_exact_buf(); + //~^ ERROR no method named `read_exact_buf` found for struct `Reader` in the current scope + //~^^ HELP there is a method `read_exact` with a similar name +} diff --git a/tests/ui/suggestions/suggest-exact-alias-before-similar-name.stderr b/tests/ui/suggestions/suggest-exact-alias-before-similar-name.stderr new file mode 100644 index 0000000000000..422c9e50ac5e7 --- /dev/null +++ b/tests/ui/suggestions/suggest-exact-alias-before-similar-name.stderr @@ -0,0 +1,18 @@ +error[E0599]: no method named `read_exact_buf` found for struct `Reader` in the current scope + --> $DIR/suggest-exact-alias-before-similar-name.rs:12:12 + | +LL | struct Reader; + | ------------- method `read_exact_buf` not found for this struct +... +LL | Reader.read_exact_buf(); + | ^^^^^^^^^^^^^^ + | +help: there is a method `read_exact` with a similar name + | +LL - Reader.read_exact_buf(); +LL + Reader.read_exact(); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From f7596e8603a367e899afd16b96197b07b97bc513 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 1 Aug 2026 23:56:43 -0700 Subject: [PATCH 36/53] Add doc aliases for transpositions `read_exact_buf` and `read_exact_buf_at` When fingers really want to type `read_exact`, that naturally leads to the typo `read_exact_buf` instead of `read_buf_exact`, and `read_exact_buf_at` instead of `read_buf_exact_at`. Add doc aliases. These will help people find them in rustdoc, and once https://github.com/rust-lang/rust/pull/160369 goes in, it'll also help people find them as rustfix suggestions. --- library/alloc/src/io/read.rs | 1 + library/std/src/os/unix/fs.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/library/alloc/src/io/read.rs b/library/alloc/src/io/read.rs index 490a55f9d10dc..c9e639fb92e86 100644 --- a/library/alloc/src/io/read.rs +++ b/library/alloc/src/io/read.rs @@ -429,6 +429,7 @@ pub trait Read { /// [`ErrorKind::Interrupted`]: crate::io::ErrorKind::Interrupted /// [`ErrorKind::UnexpectedEof`]: crate::io::ErrorKind::UnexpectedEof #[unstable(feature = "read_buf", issue = "78485")] + #[doc(alias("read_exact_buf"))] fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_, u8>) -> Result<()> { default_read_buf_exact(self, cursor) } diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index c119912c3b022..9b08f0cb3829f 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -198,6 +198,7 @@ pub trait FileExt { /// } /// ``` #[unstable(feature = "read_buf_at", issue = "140771")] + #[doc(alias("read_exact_buf_at"))] fn read_buf_exact_at( &self, mut buf: BorrowedCursor<'_, u8>, From 32c2ca0099cc13f39b96e684722b0bfd37c0cfeb Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 1 Aug 2026 23:42:38 -0700 Subject: [PATCH 37/53] When suggesting method names, prefer *exact* doc aliases over similar names We currently prefer candidates from a similarity search over doc aliases or `rustc_confusables`, even though the latter requires an *exact* match. Reverse this order, so that an exactly matching doc alias or `rustc_confusables` entry will take precedence. The net result of this is that `read_exact_buf` will now produce a suggestion for `read_buf_exact`, not `read_exact`, if both exist and the former has a doc alias for `read_exact_buf`. --- compiler/rustc_hir_typeck/src/method/probe.rs | 32 +++++++++---------- .../attributes/rustc_confusables_std_cases.rs | 1 - .../rustc_confusables_std_cases.stderr | 10 +++--- ...suggest-exact-alias-before-similar-name.rs | 2 +- ...est-exact-alias-before-similar-name.stderr | 4 +-- 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index eab4e1990455c..51b7d1b0c3e49 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2526,23 +2526,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if applicable_close_candidates.is_empty() { Ok(None) } else { - let best_name = { - let names = applicable_close_candidates - .iter() - .map(|cand| cand.name()) - .collect::>(); - find_best_match_for_name_with_substrings( - &names, - self.method_name.unwrap().name, - None, - ) - } - .or_else(|| { - applicable_close_candidates - .iter() - .find(|cand| self.matches_by_doc_alias(cand.def_id)) - .map(|cand| cand.name()) - }); + let best_name = applicable_close_candidates + .iter() + .find(|cand| self.matches_by_doc_alias(cand.def_id)) + .map(|cand| cand.name()) + .or_else(|| { + let names = applicable_close_candidates + .iter() + .map(|cand| cand.name()) + .collect::>(); + find_best_match_for_name_with_substrings( + &names, + self.method_name.unwrap().name, + None, + ) + }); Ok(best_name.and_then(|best_name| { applicable_close_candidates .into_iter() diff --git a/tests/ui/attributes/rustc_confusables_std_cases.rs b/tests/ui/attributes/rustc_confusables_std_cases.rs index 4f6baea26dfd7..5e5b806d517b6 100644 --- a/tests/ui/attributes/rustc_confusables_std_cases.rs +++ b/tests/ui/attributes/rustc_confusables_std_cases.rs @@ -16,7 +16,6 @@ fn main() { //~^ HELP you might have meant to use `len` x.size(); //~ ERROR E0599 //~^ HELP you might have meant to use `len` - //~| HELP there is a method `resize` with a similar name x.append(42); //~ ERROR E0308 //~^ HELP you might have meant to use `push` String::new().push(""); //~ ERROR E0308 diff --git a/tests/ui/attributes/rustc_confusables_std_cases.stderr b/tests/ui/attributes/rustc_confusables_std_cases.stderr index f58950f3cc618..d9bf05d71f122 100644 --- a/tests/ui/attributes/rustc_confusables_std_cases.stderr +++ b/tests/ui/attributes/rustc_confusables_std_cases.stderr @@ -59,8 +59,6 @@ error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the cu LL | x.size(); | ^^^^ | -help: there is a method `resize` with a similar name, but with different arguments - --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: you might have meant to use `len` | LL - x.size(); @@ -68,7 +66,7 @@ LL + x.len(); | error[E0308]: mismatched types - --> $DIR/rustc_confusables_std_cases.rs:20:14 + --> $DIR/rustc_confusables_std_cases.rs:19:14 | LL | x.append(42); | ------ ^^ expected `&mut Vec<{integer}>`, found integer @@ -86,7 +84,7 @@ LL + x.push(42); | error[E0308]: mismatched types - --> $DIR/rustc_confusables_std_cases.rs:22:24 + --> $DIR/rustc_confusables_std_cases.rs:21:24 | LL | String::new().push(""); | ---- ^^ expected `char`, found `&str` @@ -101,7 +99,7 @@ LL | String::new().push_str(""); | ++++ error[E0599]: no method named `append` found for struct `String` in the current scope - --> $DIR/rustc_confusables_std_cases.rs:24:19 + --> $DIR/rustc_confusables_std_cases.rs:23:19 | LL | String::new().append(""); | ^^^^^^ @@ -113,7 +111,7 @@ LL + String::new().push_str(""); | error[E0599]: no method named `get_line` found for struct `Stdin` in the current scope - --> $DIR/rustc_confusables_std_cases.rs:28:11 + --> $DIR/rustc_confusables_std_cases.rs:27:11 | LL | stdin.get_line(&mut buffer).unwrap(); | ^^^^^^^^ diff --git a/tests/ui/suggestions/suggest-exact-alias-before-similar-name.rs b/tests/ui/suggestions/suggest-exact-alias-before-similar-name.rs index 2279dc87ed646..6478a1c328ef4 100644 --- a/tests/ui/suggestions/suggest-exact-alias-before-similar-name.rs +++ b/tests/ui/suggestions/suggest-exact-alias-before-similar-name.rs @@ -11,5 +11,5 @@ impl Reader { fn main() { Reader.read_exact_buf(); //~^ ERROR no method named `read_exact_buf` found for struct `Reader` in the current scope - //~^^ HELP there is a method `read_exact` with a similar name + //~^^ HELP there is a method `read_buf_exact` with a similar name } diff --git a/tests/ui/suggestions/suggest-exact-alias-before-similar-name.stderr b/tests/ui/suggestions/suggest-exact-alias-before-similar-name.stderr index 422c9e50ac5e7..ba18e84a78868 100644 --- a/tests/ui/suggestions/suggest-exact-alias-before-similar-name.stderr +++ b/tests/ui/suggestions/suggest-exact-alias-before-similar-name.stderr @@ -7,10 +7,10 @@ LL | struct Reader; LL | Reader.read_exact_buf(); | ^^^^^^^^^^^^^^ | -help: there is a method `read_exact` with a similar name +help: there is a method `read_buf_exact` with a similar name | LL - Reader.read_exact_buf(); -LL + Reader.read_exact(); +LL + Reader.read_buf_exact(); | error: aborting due to 1 previous error From ad2ca88d8df5d9ba52182c70b29ea1c2ac22476d Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Sun, 2 Aug 2026 20:34:25 +0330 Subject: [PATCH 38/53] fix: restrict bool indexing assembly test from Windows Signed-off-by: Amirhossein Akhlaghpour --- .../indexing-with-bools-no-redundant-instructions.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs b/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs index 628f4faab6d06..7397f2ec673b0 100644 --- a/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs +++ b/tests/assembly-llvm/indexing-with-bools-no-redundant-instructions.rs @@ -1,5 +1,6 @@ //@ assembly-output: emit-asm //@ only-x86_64 +//@ ignore-windows CHECK patterns use the SysV x86-64 calling convention //@ ignore-sgx Test incompatible with LVI mitigations //@ compile-flags: -Copt-level=3 From 910ec5a8d0e8af22eebcf9f1664826f20844783c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Aug 2026 20:05:43 +1000 Subject: [PATCH 39/53] Simplify `DepKind` constants This commit changes `DEP_KIND_NUM_VARIANTS` so it's an associated const (renamed as `DepKind::NUM_VARIANTS`) obtained via `std::mem::variant_count`, removing the paranoid consecutiveness check. The commit also replaces multiple `DepKind::MAX as usize + 1` occurrences with `DepKind::NUM_VARIANTS`. --- .../rustc_middle/src/dep_graph/dep_node.rs | 33 +++++++------------ .../rustc_middle/src/dep_graph/serialized.rs | 8 ++--- compiler/rustc_middle/src/lib.rs | 1 + 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index b6fda22775c2a..c59d9620b5e53 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -69,7 +69,8 @@ impl DepKind { if u > Self::MAX { panic!("Invalid DepKind {u}"); } - // SAFETY: See comment on DEP_KIND_NUM_VARIANTS + // SAFETY: `DepKind` is `repr(u16)`, its variants are `0..=MAX`, and `u` was checked + // against `MAX` above. unsafe { std::mem::transmute(u) } } @@ -83,9 +84,16 @@ impl DepKind { *self as usize } + /// The number of dep kind variants. + pub(crate) const NUM_VARIANTS: usize = std::mem::variant_count::(); + /// This is the highest value a `DepKind` can have. It's used during encoding to - /// pack information into the unused bits. - pub(crate) const MAX: u16 = DEP_KIND_NUM_VARIANTS - 1; + /// pack information into the unused bits. u16 matches the `repr(u16)` on `DepKind`. + pub(crate) const MAX: u16 = { + let max = Self::NUM_VARIANTS - 1; + assert!(max < u16::MAX as usize); + max as u16 + }; } /// Combination of a [`DepKind`] and a key fingerprint that uniquely identifies @@ -279,25 +287,6 @@ macro_rules! define_dep_nodes { $( $(#[$q_attr])* $q_name, )* } - // This computes the number of dep kind variants. Along the way, it sanity-checks that the - // discriminants of the variants have been assigned consecutively from 0 so that they can - // be used as a dense index, and that all discriminants fit in a `u16`. - pub(crate) const DEP_KIND_NUM_VARIANTS: u16 = { - let deps = &[ - $(DepKind::$nq_name,)* - $(DepKind::$q_name,)* - ]; - let mut i = 0; - while i < deps.len() { - if i != deps[i].as_usize() { - panic!(); - } - i += 1; - } - assert!(deps.len() <= u16::MAX as usize); - deps.len() as u16 - }; - pub(super) fn dep_kind_from_label_string(label: &str) -> Result { match label { $( stringify!($nq_name) => Ok(self::DepKind::$nq_name), )* diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index daebc887055ac..1c476fc91697e 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -387,9 +387,9 @@ impl SerializedDepGraph { // Read the number of nodes of each dep kind, and perform // counting sort for `LazyNodeIndex`. - let mut kinds = Vec::with_capacity(DepKind::MAX as usize + 1); + let mut kinds = Vec::with_capacity(DepKind::NUM_VARIANTS); let mut offset = 0u32; - for _ in 0..(DepKind::MAX + 1) { + for _ in 0..(DepKind::NUM_VARIANTS) { let len = d.read_u32(); kinds.push(LazyKindIndex { start: offset, len, map: OnceLock::new() }); offset += len; @@ -654,7 +654,7 @@ impl EncoderState { edge_count: 0, node_count: 0, encoder: MemEncoder::new(), - kind_stats: iter::repeat_n(0, DepKind::MAX as usize + 1).collect(), + kind_stats: iter::repeat_n(0, DepKind::NUM_VARIANTS).collect(), }) }), } @@ -792,7 +792,7 @@ impl EncoderState { let mut encoder = self.file.lock().take().unwrap(); - let mut kind_stats: Vec = iter::repeat_n(0, DepKind::MAX as usize + 1).collect(); + let mut kind_stats: Vec = iter::repeat_n(0, DepKind::NUM_VARIANTS).collect(); let mut node_max = 0; let mut node_count = 0; diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 69c2e099080c9..ed1a2f7a831b1 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -56,6 +56,7 @@ #![feature(try_trait_v2_residual)] #![feature(try_trait_v2_yeet)] #![feature(type_alias_impl_trait)] +#![feature(variant_count)] #![feature(yeet_expr)] #![recursion_limit = "256"] // tidy-alphabetical-end From c4e9932cacd4508b4fde4e84bc76e177bfd0229d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Aug 2026 20:39:31 +1000 Subject: [PATCH 40/53] Remove `DepKind::label_strs` It contains pre-stringified versions of all the `DepKind` variants. But we can just stringify on demand using `format!("{:?}")`. --- .../rustc_incremental/src/persist/clean.rs | 59 +++++++++---------- .../rustc_middle/src/dep_graph/dep_node.rs | 8 --- compiler/rustc_middle/src/dep_graph/mod.rs | 4 +- 3 files changed, 29 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/clean.rs b/compiler/rustc_incremental/src/persist/clean.rs index d3a04ab5946b7..a311832e62d96 100644 --- a/compiler/rustc_incremental/src/persist/clean.rs +++ b/compiler/rustc_incremental/src/persist/clean.rs @@ -27,7 +27,7 @@ use rustc_hir::{ Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, find_attr, intravisit, }; -use rustc_middle::dep_graph::{DepNode, dep_kind_from_label, label_strs}; +use rustc_middle::dep_graph::{DepKind, DepNode, dep_kind_from_label}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::{Span, Symbol}; @@ -38,81 +38,78 @@ use crate::diagnostics; // Base and Extra labels to build up the labels /// For typedef, constants, and statics -const BASE_CONST: &[&str] = &[label_strs::type_of]; +const BASE_CONST: &[DepKind] = &[DepKind::type_of]; /// DepNodes for functions + methods -const BASE_FN: &[&str] = &[ +const BASE_FN: &[DepKind] = &[ // Callers will depend on the signature of these items, so we better test - label_strs::fn_sig, - label_strs::generics_of, - label_strs::clauses_of, - label_strs::type_of, + DepKind::fn_sig, + DepKind::generics_of, + DepKind::clauses_of, + DepKind::type_of, // And a big part of compilation (that we eventually want to cache) is type inference // information: - label_strs::typeck_root, + DepKind::typeck_root, ]; /// DepNodes for Hir, which is pretty much everything -const BASE_HIR: &[&str] = &[ +const BASE_HIR: &[DepKind] = &[ // hir_owner should be computed for all nodes - label_strs::hir_owner, + DepKind::hir_owner, ]; /// `impl` implementation of struct/trait -const BASE_IMPL: &[&str] = - &[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_header]; +const BASE_IMPL: &[DepKind] = + &[DepKind::associated_item_def_ids, DepKind::generics_of, DepKind::impl_trait_header]; /// DepNodes for exported mir bodies, which is relevant in "executable" /// code, i.e., functions+methods -const BASE_MIR: &[&str] = &[label_strs::optimized_mir, label_strs::promoted_mir]; +const BASE_MIR: &[DepKind] = &[DepKind::optimized_mir, DepKind::promoted_mir]; /// Struct, Enum and Union DepNodes /// /// Note that changing the type of a field does not change the type of the struct or enum, but /// adding/removing fields or changing a fields name or visibility does. -const BASE_STRUCT: &[&str] = - &[label_strs::generics_of, label_strs::clauses_of, label_strs::type_of]; +const BASE_STRUCT: &[DepKind] = &[DepKind::generics_of, DepKind::clauses_of, DepKind::type_of]; /// Trait definition `DepNode`s. /// Extra `DepNode`s for functions and methods. -const EXTRA_ASSOCIATED: &[&str] = &[label_strs::associated_item]; +const EXTRA_ASSOCIATED: &[DepKind] = &[DepKind::associated_item]; -const EXTRA_TRAIT: &[&str] = &[]; +const EXTRA_TRAIT: &[DepKind] = &[]; // Fully Built Labels -const LABELS_CONST: &[&[&str]] = &[BASE_HIR, BASE_CONST]; +const LABELS_CONST: &[&[DepKind]] = &[BASE_HIR, BASE_CONST]; /// Constant/Typedef in an impl -const LABELS_CONST_IN_IMPL: &[&[&str]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED]; +const LABELS_CONST_IN_IMPL: &[&[DepKind]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED]; /// Trait-Const/Typedef DepNodes -const LABELS_CONST_IN_TRAIT: &[&[&str]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED, EXTRA_TRAIT]; +const LABELS_CONST_IN_TRAIT: &[&[DepKind]] = &[BASE_HIR, BASE_CONST, EXTRA_ASSOCIATED, EXTRA_TRAIT]; /// Function `DepNode`s. -const LABELS_FN: &[&[&str]] = &[BASE_HIR, BASE_MIR, BASE_FN]; +const LABELS_FN: &[&[DepKind]] = &[BASE_HIR, BASE_MIR, BASE_FN]; /// Method `DepNode`s. -const LABELS_FN_IN_IMPL: &[&[&str]] = &[BASE_HIR, BASE_MIR, BASE_FN, EXTRA_ASSOCIATED]; +const LABELS_FN_IN_IMPL: &[&[DepKind]] = &[BASE_HIR, BASE_MIR, BASE_FN, EXTRA_ASSOCIATED]; /// Trait method `DepNode`s. -const LABELS_FN_IN_TRAIT: &[&[&str]] = +const LABELS_FN_IN_TRAIT: &[&[DepKind]] = &[BASE_HIR, BASE_MIR, BASE_FN, EXTRA_ASSOCIATED, EXTRA_TRAIT]; /// For generic cases like inline-assembly, modules, etc. -const LABELS_HIR_ONLY: &[&[&str]] = &[BASE_HIR]; +const LABELS_HIR_ONLY: &[&[DepKind]] = &[BASE_HIR]; /// Impl `DepNode`s. -const LABELS_TRAIT: &[&[&str]] = &[ - BASE_HIR, - &[label_strs::associated_item_def_ids, label_strs::clauses_of, label_strs::generics_of], -]; +const LABELS_TRAIT: &[&[DepKind]] = + &[BASE_HIR, &[DepKind::associated_item_def_ids, DepKind::clauses_of, DepKind::generics_of]]; /// Impl `DepNode`s. -const LABELS_IMPL: &[&[&str]] = &[BASE_HIR, BASE_IMPL]; +const LABELS_IMPL: &[&[DepKind]] = &[BASE_HIR, BASE_IMPL]; /// Abstract data type (struct, enum, union) `DepNode`s. -const LABELS_ADT: &[&[&str]] = &[BASE_HIR, BASE_STRUCT]; +const LABELS_ADT: &[&[DepKind]] = &[BASE_HIR, BASE_STRUCT]; // FIXME: Struct/Enum/Unions Fields (there is currently no way to attach these) // @@ -289,7 +286,7 @@ impl<'tcx> CleanVisitor<'tcx> { .emit_fatal(diagnostics::UndefinedCleanDirty { span, kind: format!("{node:?}") }), }; let labels = - Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string()))); + Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| format!("{l:?}")))); (name, labels) } diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index c59d9620b5e53..e2a2bb8f2a552 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -294,14 +294,6 @@ macro_rules! define_dep_nodes { _ => Err(()), } } - - /// Contains variant => str representations for constructing - /// DepNode groups for tests. - #[expect(non_upper_case_globals)] - pub mod label_strs { - $( pub const $nq_name: &str = stringify!($nq_name); )* - $( pub const $q_name: &str = stringify!($q_name); )* - } }; } diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 4f9cb03ff663e..3389c3ec91a5a 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -2,9 +2,7 @@ use std::panic; use tracing::instrument; -pub use self::dep_node::{ - DepKind, DepKindVTable, DepNode, WorkProductId, dep_kind_from_label, label_strs, -}; +pub use self::dep_node::{DepKind, DepKindVTable, DepNode, WorkProductId, dep_kind_from_label}; pub use self::dep_node_key::DepNodeKey; pub use self::graph::{ DepGraph, DepGraphData, DepNodeIndex, QuerySideEffect, TaskDepsRef, WorkProduct, From a707cbff5b5089982d7aaf471c636b2f6de5166c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Aug 2026 07:23:11 +1000 Subject: [PATCH 41/53] Document `dep_kind_from_label_string` --- compiler/rustc_middle/src/dep_graph/dep_node.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index e2a2bb8f2a552..6abec9a4ff465 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -287,7 +287,9 @@ macro_rules! define_dep_nodes { $( $(#[$q_attr])* $q_name, )* } - pub(super) fn dep_kind_from_label_string(label: &str) -> Result { + /// Converts a string to a `DepKind`. Used for handling attributes like `rustc_clean` that + /// name dep kinds. + fn dep_kind_from_label_string(label: &str) -> Result { match label { $( stringify!($nq_name) => Ok(self::DepKind::$nq_name), )* $( stringify!($q_name) => Ok(self::DepKind::$q_name), )* From 2b80cd0814cba1f1a78a4eafb57fbfac46a3947e Mon Sep 17 00:00:00 2001 From: Seth Rollins Date: Sun, 2 Aug 2026 23:00:41 -0400 Subject: [PATCH 42/53] refactor(attrs): move rustc_must_implement_one_of duplicate check into the attribute parser Signed-off-by: Seth Rollins --- .../src/attributes/rustc_internal.rs | 13 +++++++++++++ compiler/rustc_attr_parsing/src/diagnostics.rs | 8 ++++++++ compiler/rustc_passes/src/check_attr.rs | 12 ------------ compiler/rustc_passes/src/diagnostics.rs | 8 -------- .../rustc_must_implement_one_of_misuse.rs | 2 +- .../rustc_must_implement_one_of_misuse.stderr | 2 +- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index de4f9f63a51fe..b101d378bab98 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use rustc_ast::{LitIntType, LitKind, MetaItemLit}; +use rustc_data_structures::fx::FxHashMap; use rustc_feature::AttributeStability; use rustc_hir::LangItem; use rustc_hir::attrs::{ @@ -72,6 +73,18 @@ impl SingleAttributeParser for RustcMustImplementOneOfParser { return None; } + if cx.target == Target::Trait { + // Check for duplicates + let mut seen: FxHashMap = FxHashMap::default(); + for ident in &fn_names { + if let Some(dup) = seen.insert(ident.name, ident.span) { + cx.emit_err(diagnostics::FunctionNamesDuplicated { + spans: vec![dup, ident.span], + }); + } + } + } + Some(AttributeKind::RustcMustImplementOneOf { attr_span: cx.attr_span, fn_names }) } } diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 171c34232411b..f9ebd78580b4c 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -59,6 +59,14 @@ pub(crate) struct MustBeNameOfAssociatedFunction { pub span: Span, } +#[derive(Diagnostic)] +#[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, +} + #[derive(Diagnostic)] #[diag("unsafe attribute used without unsafe")] pub(crate) struct UnsafeAttrOutsideUnsafeLint { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a55d38251c843..e724ca9b609b5 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -12,7 +12,6 @@ use rustc_abi::ExternAbi; use rustc_ast::{AttrStyle, MetaItemKind, ast}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::thin_vec::ThinVec; -use rustc_data_structures::unord::UnordMap; use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, msg}; use rustc_feature::BUILTIN_ATTRIBUTE_MAP; use rustc_hir::attrs::diagnostic::Directive; @@ -459,17 +458,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } } - // Check for duplicates - - let mut set: UnordMap = Default::default(); - - for ident in &*list { - if let Some(dup) = set.insert(ident.name, ident.span) { - self.tcx.dcx().emit_err(diagnostics::FunctionNamesDuplicated { - spans: vec![dup, ident.span], - }); - } - } } fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) { diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 61a32c97b3cc6..c0137b1d023c7 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -1118,14 +1118,6 @@ pub(crate) struct FunctionNotFoundInTrait { pub span: Span, } -#[derive(Diagnostic)] -#[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, -} - #[derive(Diagnostic)] #[diag("there is no parameter `{$argument_name}` on trait `{$trait_name}`")] pub(crate) struct UnknownFormatParameterForOnUnimplementedAttr { diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs index b5e7436de6918..e5f274df06a81 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs @@ -65,7 +65,7 @@ trait TrTwoDefaults { fn c(); //~ ERROR function doesn't have a default implementation } -#[rustc_must_implement_one_of(abc, xyz)] +#[rustc_must_implement_one_of(abc, abc)] //~^ ERROR the `rustc_must_implement_one_of` attribute cannot be used on functions fn function() {} diff --git a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr index a92577cee1e1e..e4312d06041ea 100644 --- a/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr +++ b/tests/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -59,7 +59,7 @@ LL | #[rustc_must_implement_one_of(,)] error: the `rustc_must_implement_one_of` attribute cannot be used on functions --> $DIR/rustc_must_implement_one_of_misuse.rs:68:3 | -LL | #[rustc_must_implement_one_of(abc, xyz)] +LL | #[rustc_must_implement_one_of(abc, abc)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: the `rustc_must_implement_one_of` attribute can only be applied to traits From 3c80f1745f03da76b64b55783199cbd308226119 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 15 Jul 2026 04:47:45 +0900 Subject: [PATCH 43/53] add regression test for direct inline const generic defaults --- .../direct-inline-const-generic-default.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/ui/const-generics/generic_const_exprs/direct-inline-const-generic-default.rs diff --git a/tests/ui/const-generics/generic_const_exprs/direct-inline-const-generic-default.rs b/tests/ui/const-generics/generic_const_exprs/direct-inline-const-generic-default.rs new file mode 100644 index 0000000000000..358d0d997cae8 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/direct-inline-const-generic-default.rs @@ -0,0 +1,10 @@ +//@ check-pass + +// Regression test for https://github.com/rust-lang/rust/issues/159063. + +#![feature(generic_const_exprs)] +#![feature(min_generic_const_args)] + +struct S; + +fn main() {} From a0ac21b64256b99ab2ef5fed2545010538e4cb0b Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 15 Jul 2026 04:47:57 +0900 Subject: [PATCH 44/53] fix generics lookup for direct inline const defaults --- compiler/rustc_hir_analysis/src/collect/generics_of.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index a986ae3964e26..dcc5579e14339 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -140,7 +140,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // // This has some implications for how we get the clauses available to the anon const // see `explicit_clauses_of` for more information on this - let generics = tcx.generics_of(parent_did); + let parent_def_id = tcx.local_parent(param_id); + let generics = tcx.generics_of(parent_def_id); let param_def_idx = generics.param_def_id_to_index[¶m_id.to_def_id()]; // In the above example this would be .params[..N#0] let own_params = generics.params_to(param_def_idx as usize, tcx).to_owned(); From fd3c89da8e3ff4bc0a7f43d35433d26a9108a43f Mon Sep 17 00:00:00 2001 From: MarcoIeni <11428655+MarcoIeni@users.noreply.github.com> Date: Mon, 3 Aug 2026 09:53:21 +0200 Subject: [PATCH 45/53] Add PR body notes for Cargo lock file maintenance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jakub Beránek --- .github/renovate.json5 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 1725fb3426564..1827901fc041e 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -35,11 +35,16 @@ "dependencyDashboardApproval": false }, { - // Update all Cargo.lock files except library/Cargo.lock in one PR. + // Set defaults for all Cargo.lock files. + // library/Cargo.lock is grouped into a dedicated PR by the more + // specific rule below. "matchManagers": ["cargo"], "matchUpdateTypes": ["lockFileMaintenance"], "groupName": "Cargo lock file maintenance", - "commitMessageAction": "Cargo lock file maintenance" + "commitMessageAction": "Compiler and tools lock file update", + // Renovate merges all matching rules, so the lockfiles rules below + // also inherits this note and asks Triagebot for a dep-bumps reviewer. + "prBodyNotes": ["r? dep-bumps"] }, { // Update library/Cargo.lock in a dedicated PR. @@ -47,7 +52,7 @@ "matchUpdateTypes": ["lockFileMaintenance"], "matchFileNames": ["library/Cargo.lock"], "groupName": "library lock file maintenance", - "commitMessageAction": "Library lock file maintenance" + "commitMessageAction": "Library lock file update" }, { // These packages don't have a committed Cargo.lock file. @@ -63,7 +68,7 @@ "matchManagers": ["npm"], "matchUpdateTypes": ["lockFileMaintenance"], "groupName": "Yarn lock file maintenance", - "commitMessageAction": "Yarn lock file maintenance" + "commitMessageAction": "Yarn lock file update" } ], "ignorePaths": [ From ea0c39c9fc04e4340c36afedd7a1cf6a8803cea1 Mon Sep 17 00:00:00 2001 From: chiri Date: Mon, 3 Aug 2026 11:51:12 +0300 Subject: [PATCH 46/53] add `# Safety` for `enc_16lsd` --- library/core/src/fmt/num.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 23d2d5d3a9e3d..34b1de48a16c6 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -848,6 +848,10 @@ unsafe fn write_quad(buf: &mut [MaybeUninit], quad: u64) { /// Encodes the 16 least-significant decimals of n into `buf[OFFSET .. OFFSET + /// 16 ]`. +/// +/// # Safety +/// +/// `n` must be below 1e16, and `buf` must be at least `OFFSET + 16` bytes long. unsafe fn enc_16lsd(buf: &mut [MaybeUninit], n: u64) { // SAFETY: Every caller passes a remainder produced by division by 10^16, // and every used `OFFSET` specialization reserves sixteen bytes in `buf`. From 1a3d919258ff51abc7dfb5ecf6fdc9b15ff8a8c2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 15 Jul 2026 12:14:08 +0200 Subject: [PATCH 47/53] Deny multiple EII impls on a single item This allows implementing EIIs that don't have a default impl without the involvement of symbol aliases by simply changing the mangled symbol name of the implementation, which would make them trivially compatible with all backends and targets. This change will be left to a followup PR. --- compiler/rustc_ast/src/ast.rs | 6 +- compiler/rustc_ast/src/visit.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 24 +++-- .../rustc_ast_passes/src/ast_validation.rs | 30 +++---- .../rustc_ast_pretty/src/pprust/state/item.rs | 20 ++--- .../src/alloc_error_handler.rs | 2 +- compiler/rustc_builtin_macros/src/autodiff.rs | 2 +- .../src/deriving/generic/mod.rs | 2 +- .../rustc_builtin_macros/src/diagnostics.rs | 20 +++-- compiler/rustc_builtin_macros/src/eii.rs | 54 ++++++----- .../src/global_allocator.rs | 2 +- compiler/rustc_builtin_macros/src/offload.rs | 4 +- .../rustc_builtin_macros/src/test_harness.rs | 2 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 90 +++++++++---------- compiler/rustc_expand/src/build.rs | 2 +- compiler/rustc_expand/src/expand.rs | 4 +- .../rustc_hir/src/attrs/data_structures.rs | 2 +- .../rustc_hir/src/attrs/encode_cross_crate.rs | 2 +- .../src/check/compare_eii.rs | 3 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 16 ++-- compiler/rustc_hir_analysis/src/lib.rs | 1 - compiler/rustc_metadata/src/eii.rs | 14 +-- compiler/rustc_parse/src/parser/item.rs | 17 ++-- compiler/rustc_passes/src/check_attr.rs | 85 +++++++++--------- compiler/rustc_resolve/src/def_collector.rs | 2 +- compiler/rustc_resolve/src/late.rs | 11 +-- .../clippy/clippy_utils/src/ast_utils/mod.rs | 20 ++--- tests/ui/eii/duplicate/both_decl_and_impl.rs | 27 ++++++ .../eii/duplicate/both_decl_and_impl.stderr | 28 ++++++ tests/ui/eii/duplicate/multiple_impls.rs | 20 ++++- .../eii/duplicate/multiple_impls.run.stdout | 2 - tests/ui/eii/duplicate/multiple_impls.stderr | 30 +++++++ tests/ui/eii/static/multiple_impls.rs | 20 ----- tests/ui/eii/static/multiple_impls.run.stdout | 1 - tests/ui/eii/static/multiple_impls.stderr | 10 --- 35 files changed, 320 insertions(+), 259 deletions(-) create mode 100644 tests/ui/eii/duplicate/both_decl_and_impl.rs create mode 100644 tests/ui/eii/duplicate/both_decl_and_impl.stderr delete mode 100644 tests/ui/eii/duplicate/multiple_impls.run.stdout create mode 100644 tests/ui/eii/duplicate/multiple_impls.stderr delete mode 100644 tests/ui/eii/static/multiple_impls.rs delete mode 100644 tests/ui/eii/static/multiple_impls.run.stdout delete mode 100644 tests/ui/eii/static/multiple_impls.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1f50fd8ac36e0..110c64c103acb 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3981,7 +3981,7 @@ pub struct Fn { /// This function is an implementation of an externally implementable item (EII). /// This means, there was an EII declared somewhere and this function is the /// implementation that should be run when the declaration is called. - pub eii_impls: ThinVec, + pub eii_impl: Option>, } impl Fn { @@ -4073,9 +4073,7 @@ pub struct StaticItem { /// This static is an implementation of an externally implementable item (EII). /// This means, there was an EII declared somewhere and this static is the /// implementation that should be used for the declaration. - /// - /// For statics, there may be at most one `EiiImpl`, but this is a `ThinVec` to make usages of this field nicer. - pub eii_impls: ThinVec, + pub eii_impl: Option>, } #[derive(Clone, Encodable, Decodable, Debug, Walkable)] diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index a768935f38fc3..9d4c32825e1e4 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -933,12 +933,12 @@ macro_rules! common_visitor_and_walkers { _ctxt, // Visibility is visited as a part of the item. _vis, - Fn { defaultness, ident, sig, generics, contract, body, define_opaque, eii_impls }, + Fn { defaultness, ident, sig, generics, contract, body, define_opaque, eii_impl }, ) => { let FnSig { header, decl, span } = sig; visit_visitable!($($mut)? vis, defaultness, ident, header, generics, decl, - contract, body, span, define_opaque, eii_impls + contract, body, span, define_opaque, eii_impl ); } FnKind::Closure(binder, coroutine_kind, decl, body) => diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 34c7137b8676d..3cc27be600965 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -170,15 +170,13 @@ impl<'hir> LoweringContext<'_, 'hir> { i: &ItemKind, ) -> Vec { match i { - ItemKind::Fn(Fn { eii_impls, .. }) | ItemKind::Static(StaticItem { eii_impls, .. }) - if eii_impls.is_empty() => - { - Vec::new() - } - ItemKind::Fn(Fn { eii_impls, .. }) | ItemKind::Static(StaticItem { eii_impls, .. }) => { - vec![hir::Attribute::Parsed(AttributeKind::EiiImpls( - eii_impls.iter().map(|i| self.lower_eii_impl(i)).collect(), - ))] + ItemKind::Fn(Fn { eii_impl: None, .. }) + | ItemKind::Static(StaticItem { eii_impl: None, .. }) => Vec::new(), + ItemKind::Fn(Fn { eii_impl: Some(eii_impl), .. }) + | ItemKind::Static(StaticItem { eii_impl: Some(eii_impl), .. }) => { + vec![hir::Attribute::Parsed(AttributeKind::EiiImpl(Box::new( + self.lower_eii_impl(eii_impl), + )))] } ItemKind::MacroDef(name, MacroDef { eii_declaration: Some(target), .. }) => self .lower_eii_decl(id, *name, target) @@ -226,7 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind, vis_span, span: self.lower_span(i.span), - eii: find_attr!(attrs, EiiImpls(..) | EiiDeclaration(..)), + eii: find_attr!(attrs, EiiImpl(..) | EiiDeclaration(..)), }; self.arena.alloc(item) } @@ -259,7 +257,7 @@ impl<'hir> LoweringContext<'_, 'hir> { mutability: m, expr: e, define_opaque, - eii_impls: _, + eii_impl: _, }) => { let ident = self.lower_ident(*ident); let ty = self @@ -696,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> { kind, vis_span, span: this.lower_span(use_tree.span()), - eii: find_attr!(attrs, EiiImpls(..) | EiiDeclaration(..)), + eii: find_attr!(attrs, EiiImpl(..) | EiiDeclaration(..)), }; hir::OwnerNode::Item(this.arena.alloc(item)) }); @@ -763,7 +761,7 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: _, safety, define_opaque, - eii_impls: _, + eii_impl: _, }) => { let ty = self .lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 12a345aaeaf1d..62134046746c0 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1259,10 +1259,10 @@ impl<'a> AstValidator<'a> { } // Check EII implementation attributes against an allowlist. - fn check_eii_impl_attrs(&self, attrs: &[Attribute], eii_impls: &[EiiImpl]) { - if eii_impls.is_empty() { + fn check_eii_impl_attrs(&self, attrs: &[Attribute], eii_impl: &Option>) { + let Some(eii_impl) = eii_impl else { return; - } + }; let allowed_attrs: &[Symbol] = &[ sym::allow, @@ -1289,14 +1289,12 @@ impl<'a> AstValidator<'a> { } let attr_name = pprust::path_to_string(&normal.item.path); - for eii_impl in eii_impls { - self.dcx().emit_err(diagnostics::EiiImplAttributeNotSupported { - attr_span: attr.span, - attr_name: &attr_name, - eii_span: eii_impl.span, - eii_name: pprust::path_to_string(&eii_impl.eii_macro_path), - }); - } + self.dcx().emit_err(diagnostics::EiiImplAttributeNotSupported { + attr_span: attr.span, + attr_name: &attr_name, + eii_span: eii_impl.span, + eii_name: pprust::path_to_string(&eii_impl.eii_macro_path), + }); } } } @@ -1479,16 +1477,16 @@ impl Visitor<'_> for AstValidator<'_> { contract: _, body, define_opaque: _, - eii_impls, + eii_impl, }, ) => { self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident); self.check_defaultness(item.span, *defaultness, AllowDefault::No, AllowFinal::No); - for EiiImpl { eii_macro_path, .. } in eii_impls { + if let Some(EiiImpl { eii_macro_path, .. }) = eii_impl { self.visit_path(eii_macro_path); } - self.check_eii_impl_attrs(&item.attrs, eii_impls); + self.check_eii_impl_attrs(&item.attrs, eii_impl); let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)); if body.is_none() && !is_intrinsic && !self.is_sdylib_interface { @@ -1664,9 +1662,9 @@ impl Visitor<'_> for AstValidator<'_> { visit::walk_item(self, item); } - ItemKind::Static(StaticItem { expr, safety, eii_impls, .. }) => { + ItemKind::Static(StaticItem { expr, safety, eii_impl, .. }) => { self.check_item_safety(item.span, *safety); - self.check_eii_impl_attrs(&item.attrs, eii_impls); + self.check_eii_impl_attrs(&item.attrs, eii_impl); if matches!(safety, Safety::Unsafe(_)) { self.dcx().emit_err(diagnostics::UnsafeStatic { span: item.span }); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 1fb71b7b06299..04f78ea7f467a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -42,7 +42,7 @@ impl<'a> State<'a> { expr, safety, define_opaque, - eii_impls, + eii_impl, }) => self.print_item_const( *ident, Some(*mutability), @@ -53,7 +53,7 @@ impl<'a> State<'a> { *safety, ast::Defaultness::Implicit, define_opaque.as_deref(), - eii_impls, + eii_impl.as_deref(), ), ast::ForeignItemKind::TyAlias(ast::TyAlias { defaultness, @@ -94,10 +94,10 @@ impl<'a> State<'a> { safety: ast::Safety, defaultness: ast::Defaultness, define_opaque: Option<&[(ast::NodeId, ast::Path)]>, - eii_impls: &[EiiImpl], + eii_impl: Option<&EiiImpl>, ) { self.print_define_opaques(define_opaque); - for eii_impl in eii_impls { + if let Some(eii_impl) = eii_impl { self.print_eii_impl(eii_impl); } let (cb, ib) = self.head(""); @@ -196,7 +196,7 @@ impl<'a> State<'a> { mutability: mutbl, expr: body, define_opaque, - eii_impls, + eii_impl, }) => { self.print_safety(*safety); self.print_item_const( @@ -209,7 +209,7 @@ impl<'a> State<'a> { ast::Safety::Default, ast::Defaultness::Implicit, define_opaque.as_deref(), - eii_impls, + eii_impl.as_deref(), ); } ast::ItemKind::ConstBlock(ast::ConstBlockItem { id: _, span: _, block }) => { @@ -242,7 +242,7 @@ impl<'a> State<'a> { ast::Safety::Default, *defaultness, define_opaque.as_deref(), - &[], + None, ); } ast::ItemKind::Fn(func) => { @@ -631,7 +631,7 @@ impl<'a> State<'a> { ast::Safety::Default, *defaultness, define_opaque.as_deref(), - &[], + None, ); } ast::AssocItemKind::Type(ast::TyAlias { @@ -731,12 +731,12 @@ impl<'a> State<'a> { } fn print_fn_full(&mut self, vis: &ast::Visibility, attrs: &[ast::Attribute], func: &ast::Fn) { - let ast::Fn { defaultness, ident, generics, sig, contract, body, define_opaque, eii_impls } = + let ast::Fn { defaultness, ident, generics, sig, contract, body, define_opaque, eii_impl } = func; self.print_define_opaques(define_opaque.as_deref()); - for eii_impl in eii_impls { + if let Some(eii_impl) = eii_impl { self.print_eii_impl(eii_impl); } diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index d50fc78b51e14..57e589ac5a1e8 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -96,7 +96,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span contract: None, body, define_opaque: None, - eii_impls: ThinVec::new(), + eii_impl: None, })); let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)]; diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 51ab44d8a03ef..0618c28759a66 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -344,7 +344,7 @@ mod llvm_enzyme { contract: None, body: Some(d_body), define_opaque: None, - eii_impls: ThinVec::new(), + eii_impl: None, }); let mut rustc_ad_attr = Box::new(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff))); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index cc036fab83c9d..03ccdbb902a96 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1083,7 +1083,7 @@ impl<'a> MethodDef<'a> { contract: None, body: Some(body_block), define_opaque: None, - eii_impls: ThinVec::new(), + eii_impl: None, })), tokens: None, }) diff --git a/compiler/rustc_builtin_macros/src/diagnostics.rs b/compiler/rustc_builtin_macros/src/diagnostics.rs index 71dc17b108a97..ce5fb4e86dab6 100644 --- a/compiler/rustc_builtin_macros/src/diagnostics.rs +++ b/compiler/rustc_builtin_macros/src/diagnostics.rs @@ -1094,6 +1094,13 @@ pub(crate) struct CfgSelectNoMatches { pub span: Span, } +#[derive(Diagnostic)] +#[diag("a single item cannot both declare and implement EIIs")] +pub(crate) struct EiiBothDeclAndImpl { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("`#[eii_declaration(...)]` is only valid on macros")] pub(crate) struct EiiExternTargetExpectedMacro { @@ -1117,21 +1124,18 @@ pub(crate) struct EiiExternTargetExpectedUnsafe { } #[derive(Diagnostic)] -#[diag("`#[{$name}]` is only valid on functions and statics")] -pub(crate) struct EiiSharedMacroTarget { +#[diag("a single item cannot implement multiple EIIs")] +pub(crate) struct EiiMultipleImplementations { #[primary_span] pub span: Span, - pub name: String, } #[derive(Diagnostic)] -#[diag("static cannot implement multiple EIIs")] -#[note( - "this is not allowed because multiple externally implementable statics that alias may be unintuitive" -)] -pub(crate) struct EiiStaticMultipleImplementations { +#[diag("`#[{$name}]` is only valid on functions and statics")] +pub(crate) struct EiiSharedMacroTarget { #[primary_span] pub span: Span, + pub name: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index 5a28416900372..cf50460422f52 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -10,10 +10,10 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use crate::diagnostics::{ - EiiAttributeNotSupported, EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, - EiiExternTargetExpectedUnsafe, EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, - EiiSharedMacroInStatementPosition, EiiSharedMacroTarget, EiiStaticArgumentRequired, - EiiStaticDefaultApple, EiiStaticMultipleImplementations, EiiStaticMutable, + EiiAttributeNotSupported, EiiBothDeclAndImpl, EiiExternTargetExpectedList, + EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe, EiiMacroExpectedMaxOneArgument, + EiiMultipleImplementations, EiiOnlyOnce, EiiSharedMacroInStatementPosition, + EiiSharedMacroTarget, EiiStaticArgumentRequired, EiiStaticDefaultApple, EiiStaticMutable, }; /// ```rust @@ -125,6 +125,22 @@ fn eii_( } }; + match kind { + ItemKind::Fn(func) => { + if func.eii_impl.is_some() { + ecx.dcx().emit_err(EiiBothDeclAndImpl { span: eii_attr_span }); + return vec![Annotatable::Item(item)]; + } + } + ItemKind::Static(stat) => { + if stat.eii_impl.is_some() { + ecx.dcx().emit_err(EiiBothDeclAndImpl { span: eii_attr_span }); + return vec![Annotatable::Item(item)]; + } + } + _ => unreachable!("Target was checked earlier"), + }; + // only clone what we need let attrs = attrs.clone(); let vis = vis.clone(); @@ -298,7 +314,7 @@ fn generate_default_impl( _ => unreachable!("Target was checked earlier"), }; - let eii_impl = EiiImpl { + let eii_impl = Box::new(EiiImpl { node_id: DUMMY_NODE_ID, inner_span: macro_name.span, eii_macro_path: ast::Path::from_ident(macro_name), @@ -315,15 +331,17 @@ fn generate_default_impl( // NOTE: this is why EIIs can't be used on statements vec![Ident::from_str_and_span("self", foreign_item_name.span), foreign_item_name], )), - }; + }); let mut item_kind = item_kind.clone(); match &mut item_kind { ItemKind::Fn(func) => { - func.eii_impls.push(eii_impl); + assert!(func.eii_impl.is_none()); + func.eii_impl = Some(eii_impl); } ItemKind::Static(stat) => { - stat.eii_impls.push(eii_impl); + assert!(stat.eii_impl.is_none()); + stat.eii_impl = Some(eii_impl); } _ => unreachable!("Target was checked earlier"), }; @@ -579,16 +597,9 @@ pub(crate) fn eii_shared_macro( return vec![item]; }; - let eii_impls = match &mut i.kind { - ItemKind::Fn(func) => &mut func.eii_impls, - ItemKind::Static(stat) => { - if !stat.eii_impls.is_empty() { - // Reject multiple implementations on one static item - // because it might be unintuitive for libraries defining statics the defined statics may alias - ecx.dcx().emit_err(EiiStaticMultipleImplementations { span }); - } - &mut stat.eii_impls - } + let eii_impl = match &mut i.kind { + ItemKind::Fn(func) => &mut func.eii_impl, + ItemKind::Static(stat) => &mut stat.eii_impl, _ => { ecx.dcx() .emit_err(EiiSharedMacroTarget { span, name: path_to_string(&meta_item.path) }); @@ -611,7 +622,10 @@ pub(crate) fn eii_shared_macro( return vec![item]; }; - eii_impls.push(EiiImpl { + if eii_impl.is_some() { + ecx.dcx().emit_err(EiiMultipleImplementations { span }); + } + *eii_impl = Some(Box::new(EiiImpl { node_id: DUMMY_NODE_ID, inner_span: meta_item.path.span, eii_macro_path: meta_item.path.clone(), @@ -619,7 +633,7 @@ pub(crate) fn eii_shared_macro( span, is_default, known_eii_macro_resolution: None, - }); + })); vec![item] } diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 72b493e313326..00ed0f52d6a6f 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -97,7 +97,7 @@ impl AllocFnFactory<'_, '_> { contract: None, body, define_opaque: None, - eii_impls: ThinVec::new(), + eii_impl: None, })); let item = self.cx.item(self.span, self.attrs(method), kind); self.cx.stmt_item(self.ty_span, item) diff --git a/compiler/rustc_builtin_macros/src/offload.rs b/compiler/rustc_builtin_macros/src/offload.rs index cdb3ba22ec6c8..e47ccc0d85f7d 100644 --- a/compiler/rustc_builtin_macros/src/offload.rs +++ b/compiler/rustc_builtin_macros/src/offload.rs @@ -85,7 +85,7 @@ pub(crate) fn expand_kernel( contract: None, body, define_opaque: None, - eii_impls: Default::default(), + eii_impl: None, }); let extern_gpu_kernel = ast::Extern::from_abi( @@ -157,7 +157,7 @@ pub(crate) fn expand_kernel( contract: None, body: Some(body), define_opaque: None, - eii_impls: Default::default(), + eii_impl: None, }); for param in host_fn.sig.decl.inputs.iter_mut() { diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index ff9d9f10dd4e1..5d20fed223468 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -347,7 +347,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> Box { contract: None, body: Some(main_body), define_opaque: None, - eii_impls: ThinVec::new(), + eii_impl: None, })); let main = Box::new(ast::Item { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 0389aa56bafd6..3e24b62125fea 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -219,32 +219,31 @@ fn process_builtin_attrs( AttributeKind::RustcEiiForeignItem => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM; } - AttributeKind::EiiImpls(impls) => { - for i in impls { - let foreign_item = match i.resolution { - EiiImplResolution::Macro(def_id) => { - let Some(extern_item) = find_attr!(tcx, def_id, EiiDeclaration(target) => target.foreign_item - ) else { - tcx.dcx().span_delayed_bug( - i.span, - "resolved to something that's not an EII", - ); - continue; - }; - extern_item - } - EiiImplResolution::Known(def_id) => def_id, - EiiImplResolution::Error(_eg) => continue, - }; + AttributeKind::EiiImpl(i) => { + let foreign_item = match i.resolution { + EiiImplResolution::Macro(def_id) => { + let Some(extern_item) = find_attr!(tcx, def_id, EiiDeclaration(target) => target.foreign_item + ) else { + tcx.dcx().span_delayed_bug( + i.span, + "resolved to something that's not an EII", + ); + continue; + }; + extern_item + } + EiiImplResolution::Known(def_id) => def_id, + EiiImplResolution::Error(_eg) => continue, + }; - // this is to prevent a bug where a single crate defines both the default and explicit implementation - // for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure - // what happens, either rustc deduplicates the symbol or llvm, or it's random/order-dependent. - // However, the fact that the default one of has weak linkage isn't considered and you sometimes get that - // the default implementation is used while an explicit implementation is given. - if - // if this is a default impl - i.is_default + // this is to prevent a bug where a single crate defines both the default and explicit implementation + // for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure + // what happens, either rustc deduplicates the symbol or llvm, or it's random/order-dependent. + // However, the fact that the default one of has weak linkage isn't considered and you sometimes get that + // the default implementation is used while an explicit implementation is given. + if + // if this is a default impl + i.is_default // iterate over all implementations *in the current crate* // (this is ok since we generate codegen fn attrs in the local crate) // if any of them is *not default* then don't emit the alias. @@ -252,28 +251,27 @@ fn process_builtin_attrs( let (_, impls) = tcx.externally_implementable_items(LOCAL_CRATE).get(&foreign_item).unwrap_or_else(|| bug!("EII impl should have an entry")); impls.iter().any(|(_, imp)| !imp.is_default) } - { - continue; - } + { + continue; + } - codegen_fn_attrs.foreign_item_symbol_aliases.push(( - foreign_item, - if i.is_default { Linkage::WeakAny } else { Linkage::External }, - Visibility::Default, - )); - codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM; - - // If the declaration is `#[track_caller]`, derive it onto the implementation - // too. The shim that forwards to this impl (see `add_function_aliases`) takes - // its ABI from the impl's `fn_abi`, so every impl must agree on whether the - // caller-location argument is present, otherwise it would be silently dropped. - if tcx - .codegen_fn_attrs(foreign_item) - .flags - .contains(CodegenFnAttrFlags::TRACK_CALLER) - { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; - } + codegen_fn_attrs.foreign_item_symbol_aliases.push(( + foreign_item, + if i.is_default { Linkage::WeakAny } else { Linkage::External }, + Visibility::Default, + )); + codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM; + + // If the declaration is `#[track_caller]`, derive it onto the implementation + // too. The shim that forwards to this impl (see `add_function_aliases`) takes + // its ABI from the impl's `fn_abi`, so every impl must agree on whether the + // caller-location argument is present, otherwise it would be silently dropped. + if tcx + .codegen_fn_attrs(foreign_item) + .flags + .contains(CodegenFnAttrFlags::TRACK_CALLER) + { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; } } AttributeKind::ThreadLocal => { diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index b87dfd0198efc..4a8541ed4c6b7 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -707,7 +707,7 @@ impl<'a> ExtCtxt<'a> { mutability, expr: Some(expr), define_opaque: None, - eii_impls: Default::default(), + eii_impl: None, } .into(), ), diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 187dcea4f91a5..045233c0c4d21 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -804,7 +804,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { None, ) } - // When a function has EII implementations attached (via `eii_impls`), + // When a function has EII implementations attached (via `eii_impl`), // use fake tokens so the pretty-printer re-emits the EII attribute // (e.g. `#[hello]`) in the token stream. Without this, the EII // attribute is lost during the token roundtrip performed by @@ -812,7 +812,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // breaking the EII link on the resulting re-parsed item. Annotatable::Item(item_inner) if matches!(&item_inner.kind, - ItemKind::Fn(f) if !f.eii_impls.is_empty()) => + ItemKind::Fn(f) if f.eii_impl.is_some()) => { rustc_parse::fake_token_stream_for_item( &self.cx.sess.psess, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 165f06d2fde8b..78a15eeb923a5 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1076,7 +1076,7 @@ pub enum AttributeKind { EiiDeclaration(EiiDecl), /// Implementation detail of `#[eii]` - EiiImpls(ThinVec), + EiiImpl(Box), /// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute). ExportName { diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index dded70ccd08ef..a5a1fc2482b4e 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -40,7 +40,7 @@ impl AttributeKind { Doc(_) => Yes, DocComment { .. } => Yes, EiiDeclaration(_) => Yes, - EiiImpls(..) => No, + EiiImpl(..) => No, ExportName { .. } => Yes, ExportStable => No, Feature(..) => No, diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index 57824a91a680f..d9fc3bbcf08c2 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -301,8 +301,7 @@ fn check_no_generics<'tcx>( // since in that case it looks like a duplicate error: the declaration of the EII already can't contain generics. // So, we check here if at least one of the eii impls has ImplResolution::Macro, which indicates it's // not generated as part of the declaration. - && find_attr!(tcx, external_impl, EiiImpls(impls) if impls.iter().any(|i| matches!(i.resolution, EiiImplResolution::Macro(_))) - ) + && find_attr!(tcx, external_impl, EiiImpl(i) if matches!(i.resolution, EiiImplResolution::Macro(_))) { tcx.dcx().emit_err(EiiWithGenerics { span: tcx.def_span(external_impl), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 35628e54769b4..caf64fd6894f7 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1153,9 +1153,7 @@ fn check_item_fn( fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) { // does the function have an EiiImpl attribute? that contains the defid of a *macro* // that was used to mark the implementation. This is a two step process. - for EiiImpl { resolution, span, .. } in - find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_flat_iter() - { + if let Some(EiiImpl { resolution, span, .. }) = find_attr!(tcx, def_id, EiiImpl(i) => &**i) { let (foreign_item, name) = match resolution { EiiImplResolution::Macro(def_id) => { // we expect this macro to have the `EiiMacroFor` attribute, that points to a function @@ -1166,11 +1164,11 @@ fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) { (foreign_item, tcx.item_name(*def_id)) } else { tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII"); - continue; + return; } } EiiImplResolution::Known(def_id) => (*def_id, tcx.item_name(*def_id)), - EiiImplResolution::Error(_eg) => continue, + EiiImplResolution::Error(_eg) => return, }; let _ = compare_eii_function_types(tcx, def_id, foreign_item, name, *span); @@ -1180,9 +1178,7 @@ fn check_eiis_fn(tcx: TyCtxt<'_>, def_id: LocalDefId) { fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) { // does the function have an EiiImpl attribute? that contains the defid of a *macro* // that was used to mark the implementation. This is a two step process. - for EiiImpl { resolution, span, .. } in - find_attr!(tcx, def_id, EiiImpls(impls) => impls).into_flat_iter() - { + if let Some(EiiImpl { resolution, span, .. }) = find_attr!(tcx, def_id, EiiImpl(i) => &**i) { let (foreign_item, name) = match resolution { EiiImplResolution::Macro(def_id) => { // we expect this macro to have the `EiiMacroFor` attribute, that points to a function @@ -1193,11 +1189,11 @@ fn check_eiis_static<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, ty: Ty<'tcx>) (foreign_item, tcx.item_name(*def_id)) } else { tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII"); - continue; + return; } } EiiImplResolution::Known(def_id) => (*def_id, tcx.item_name(*def_id)), - EiiImplResolution::Error(_eg) => continue, + EiiImplResolution::Error(_eg) => return, }; let _ = compare_eii_statics(tcx, def_id, ty, foreign_item, name, *span); diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 1473b0d108fb3..ebbf63b947a93 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -60,7 +60,6 @@ This API is completely unstable and subject to change. #![feature(gen_blocks)] #![feature(iter_intersperse)] #![feature(never_type)] -#![feature(option_into_flat_iter)] #![feature(slice_partition_dedup)] #![feature(try_blocks)] #![feature(unwrap_infallible)] diff --git a/compiler/rustc_metadata/src/eii.rs b/compiler/rustc_metadata/src/eii.rs index 4328e8de901d8..da6d9e85bc4fa 100644 --- a/compiler/rustc_metadata/src/eii.rs +++ b/compiler/rustc_metadata/src/eii.rs @@ -35,7 +35,12 @@ pub(crate) fn collect<'tcx>(tcx: TyCtxt<'tcx>, LocalCrate: LocalCrate) -> EiiMap // iterate over all items in the current crate for id in tcx.hir_crate_items(()).eiis() { - for i in find_attr!(tcx, id, EiiImpls(e) => e).into_flat_iter() { + // if we find a new declaration, add it to the list without a known implementation + if let Some(decl) = find_attr!(tcx, id, EiiDeclaration(d) => *d) { + eiis.entry(decl.foreign_item).or_insert((decl, Default::default())); + } + + if let Some(i) = find_attr!(tcx, id, EiiImpl(i) => i) { let (foreign_item, decl) = match i.resolution { EiiImplResolution::Macro(macro_defid) => { // find the decl for this one if it wasn't in yet (maybe it's from the local crate? not very useful but not illegal) @@ -63,12 +68,7 @@ pub(crate) fn collect<'tcx>(tcx: TyCtxt<'tcx>, LocalCrate: LocalCrate) -> EiiMap eiis.entry(foreign_item) .or_insert_with(|| (decl, Default::default())) .1 - .insert(id.into(), *i); - } - - // if we find a new declaration, add it to the list without a known implementation - if let Some(decl) = find_attr!(tcx, id, EiiDeclaration(d) => *d) { - eiis.entry(decl.foreign_item).or_insert((decl, Default::default())); + .insert(id.into(), **i); } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 0fa592459167a..1306f1fcfb1ce 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -283,7 +283,7 @@ impl<'a> Parser<'a> { contract, body, define_opaque: None, - eii_impls: ThinVec::new(), + eii_impl: None, })) } else if self.eat_keyword_case(exp!(Extern), case) { if self.eat_keyword_case(exp!(Crate), case) { @@ -1257,7 +1257,7 @@ impl<'a> Parser<'a> { mutability: _, expr, define_opaque, - eii_impls: _, + eii_impl: _, }) => { self.dcx() .emit_err(diagnostics::AssociatedStaticItemNotAllowed { span }); @@ -1523,7 +1523,7 @@ impl<'a> Parser<'a> { expr: body, safety: Safety::Default, define_opaque: None, - eii_impls: ThinVec::default(), + eii_impl: None, })) } _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), @@ -1661,15 +1661,8 @@ impl<'a> Parser<'a> { self.expect_semi()?; - let item = StaticItem { - ident, - ty, - safety, - mutability, - expr, - define_opaque: None, - eii_impls: ThinVec::default(), - }; + let item = + StaticItem { ident, ty, safety, mutability, expr, define_opaque: None, eii_impl: None }; Ok(ItemKind::Static(Box::new(item))) } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 6489167afcdac..d1d82b2ed43e0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -211,7 +211,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_rustc_legacy_const_generics(item, *attr_span, fn_indexes) } AttributeKind::Doc(attr) => self.check_doc_attrs(attr, hir_id, target), - AttributeKind::EiiImpls(impls) => self.check_eii_impl(impls), + AttributeKind::EiiImpl(eii_impl) => self.check_eii_impl(eii_impl), AttributeKind::RustcMustImplementOneOf { attr_span, fn_names } => { self.check_rustc_must_implement_one_of(*attr_span, fn_names, hir_id, target) } @@ -474,51 +474,50 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that each externally implementable item (EII) implementation uses `unsafe` /// exactly when its declaration requires it. - fn check_eii_impl(&self, impls: &[EiiImpl]) { - for EiiImpl { span, inner_span, resolution, impl_unsafe_span, is_default: _ } in impls { - let impl_unsafe = match resolution { - EiiImplResolution::Macro(eii_macro) => find_attr!( - self.tcx, - *eii_macro, - EiiDeclaration(EiiDecl { impl_unsafe, .. }) => *impl_unsafe - ), - EiiImplResolution::Known(foreign_item_did) => self - .tcx - .externally_implementable_items(foreign_item_did.krate) - .get(foreign_item_did) - .map(|(decl, _)| decl.impl_unsafe), - EiiImplResolution::Error(_) => None, - }; - let Some(needs_unsafe) = impl_unsafe else { - continue; - }; + fn check_eii_impl(&self, eii_impl: &EiiImpl) { + let EiiImpl { span, inner_span, resolution, impl_unsafe_span, is_default: _ } = eii_impl; + let impl_unsafe = match resolution { + EiiImplResolution::Macro(eii_macro) => find_attr!( + self.tcx, + *eii_macro, + EiiDeclaration(EiiDecl { impl_unsafe, .. }) => *impl_unsafe + ), + EiiImplResolution::Known(foreign_item_did) => self + .tcx + .externally_implementable_items(foreign_item_did.krate) + .get(foreign_item_did) + .map(|(decl, _)| decl.impl_unsafe), + EiiImplResolution::Error(_) => None, + }; + let Some(needs_unsafe) = impl_unsafe else { + return; + }; - let name = match resolution { - EiiImplResolution::Macro(eii_macro) => self.tcx.item_name(*eii_macro), - EiiImplResolution::Known(def_id) => self.tcx.item_name(*def_id), - EiiImplResolution::Error(_) => unreachable!(), - }; + let name = match resolution { + EiiImplResolution::Macro(eii_macro) => self.tcx.item_name(*eii_macro), + EiiImplResolution::Known(def_id) => self.tcx.item_name(*def_id), + EiiImplResolution::Error(_) => unreachable!(), + }; - match (needs_unsafe, *impl_unsafe_span) { - (true, None) => { - self.dcx().emit_err(diagnostics::EiiImplRequiresUnsafe { - span: *span, - name, - suggestion: diagnostics::EiiImplRequiresUnsafeSuggestion { - left: inner_span.shrink_to_lo(), - right: inner_span.shrink_to_hi(), - }, - }); - } - (false, Some(unsafe_span)) => { - self.dcx().emit_err(diagnostics::EiiImplCannotBeUnsafe { - impl_span: *span, - unsafe_span, - name, - }); - } - _ => {} + match (needs_unsafe, *impl_unsafe_span) { + (true, None) => { + self.dcx().emit_err(diagnostics::EiiImplRequiresUnsafe { + span: *span, + name, + suggestion: diagnostics::EiiImplRequiresUnsafeSuggestion { + left: inner_span.shrink_to_lo(), + right: inner_span.shrink_to_hi(), + }, + }); + } + (false, Some(unsafe_span)) => { + self.dcx().emit_err(diagnostics::EiiImplCannotBeUnsafe { + impl_span: *span, + unsafe_span, + name, + }); } + _ => {} } } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 63bff7a3f4498..97ca994c37540 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -303,7 +303,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { expr: _, safety, define_opaque: _, - eii_impls: _, + eii_impl: _, }) => { let safety = match safety { ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f30e6844c861c..fc723586c1acc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1147,7 +1147,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc debug!("(resolving function) entering function"); if let FnKind::Fn(_, _, f) = fn_kind { - self.resolve_eii(&f.eii_impls); + self.resolve_eii(f.eii_impl.as_deref()); } // Create a value rib for the function. @@ -2940,7 +2940,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ItemKind::Static(ast::StaticItem { - ident, ty, expr, define_opaque, eii_impls, .. + ident, ty, expr, define_opaque, eii_impl, .. }) => { self.with_static_rib(def_kind, |this| { this.with_lifetime_rib(LifetimeRibKind::elided(LifetimeRes::Static), |this| { @@ -2953,7 +2953,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } }); self.resolve_define_opaques(define_opaque); - self.resolve_eii(&eii_impls); + self.resolve_eii(eii_impl.as_deref()); } ItemKind::Const(ast::ConstItem { @@ -5568,8 +5568,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } - fn resolve_eii(&mut self, eii_impls: &[EiiImpl]) { - for EiiImpl { node_id, eii_macro_path, known_eii_macro_resolution, .. } in eii_impls { + fn resolve_eii(&mut self, eii_impl: Option<&EiiImpl>) { + if let Some(EiiImpl { node_id, eii_macro_path, known_eii_macro_resolution, .. }) = eii_impl + { // See docs on the `known_eii_macro_resolution` field: // if we already know the resolution statically, don't bother resolving it. if let Some(target) = known_eii_macro_resolution { 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 3f0b99aa4d780..523e799ef2522 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -332,7 +332,7 @@ fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { expr: le, safety: ls, define_opaque: _, - eii_impls: _, + eii_impl: _, }), Static(box StaticItem { ident: ri, @@ -341,7 +341,7 @@ fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { expr: re, safety: rs, define_opaque: _, - eii_impls: _, + eii_impl: _, }), ) => eq_id(*li, *ri) && lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_deref(), re.as_deref()), ( @@ -381,7 +381,7 @@ fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { contract: lc, body: lb, define_opaque: _, - eii_impls: _, + eii_impl: _, }), Fn(box ast::Fn { defaultness: rd, @@ -391,7 +391,7 @@ fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { contract: rc, body: rb, define_opaque: _, - eii_impls: _, + eii_impl: _, }), ) => { eq_defaultness(*ld, *rd) @@ -539,7 +539,7 @@ fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { expr: le, safety: ls, define_opaque: _, - eii_impls: _, + eii_impl: _, }), Static(box StaticItem { ident: ri, @@ -548,7 +548,7 @@ fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { expr: re, safety: rs, define_opaque: _, - eii_impls: _, + eii_impl: _, }), ) => eq_id(*li, *ri) && eq_ty(lt, rt) && lm == rm && eq_expr_opt(le.as_deref(), re.as_deref()) && ls == rs, ( @@ -560,7 +560,7 @@ fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { contract: lc, body: lb, define_opaque: _, - eii_impls: _, + eii_impl: _, }), Fn(box ast::Fn { defaultness: rd, @@ -570,7 +570,7 @@ fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { contract: rc, body: rb, define_opaque: _, - eii_impls: _, + eii_impl: _, }), ) => { eq_defaultness(*ld, *rd) @@ -649,7 +649,7 @@ fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { contract: lc, body: lb, define_opaque: _, - eii_impls: _, + eii_impl: _, }), Fn(box ast::Fn { defaultness: rd, @@ -659,7 +659,7 @@ fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { contract: rc, body: rb, define_opaque: _, - eii_impls: _, + eii_impl: _, }), ) => { eq_defaultness(*ld, *rd) diff --git a/tests/ui/eii/duplicate/both_decl_and_impl.rs b/tests/ui/eii/duplicate/both_decl_and_impl.rs new file mode 100644 index 0000000000000..a2fc571d3f497 --- /dev/null +++ b/tests/ui/eii/duplicate/both_decl_and_impl.rs @@ -0,0 +1,27 @@ +//@ ignore-backends: gcc +// FIXME(#125418): linking on Windows GNU targets is not yet supported. +//@ ignore-windows-gnu +// Tests that one item can't both define and impl an EII at the same time +#![feature(extern_item_impls)] + +#[eii] +fn a(x: u64); + +#[a] +#[eii] +//~^ ERROR a single item cannot both declare and implement EIIs +fn b(x: u64) {} + +#[eii] +fn c(x: u64); +//~^ ERROR `#[c]` function required, but not found + +#[eii] +#[c] +fn d(x: u64) {} +//~^ ERROR only a small subset of attributes are supported on externally implementable items + +fn main() { + a(42); + b(42); +} diff --git a/tests/ui/eii/duplicate/both_decl_and_impl.stderr b/tests/ui/eii/duplicate/both_decl_and_impl.stderr new file mode 100644 index 0000000000000..1cec485a90cff --- /dev/null +++ b/tests/ui/eii/duplicate/both_decl_and_impl.stderr @@ -0,0 +1,28 @@ +error: a single item cannot both declare and implement EIIs + --> $DIR/both_decl_and_impl.rs:11:1 + | +LL | #[eii] + | ^^^^^^ + +error: only a small subset of attributes are supported on externally implementable items + --> $DIR/both_decl_and_impl.rs:21:1 + | +LL | fn d(x: u64) {} + | ^^^^^^^^^^^^ + | +note: this attribute is not supported + --> $DIR/both_decl_and_impl.rs:20:1 + | +LL | #[c] + | ^^^^ + +error: `#[c]` function required, but not found + --> $DIR/both_decl_and_impl.rs:16:4 + | +LL | fn c(x: u64); + | ^ expected because `#[c]` was declared here in crate `both_decl_and_impl` + | + = help: expected at least one implementation in crate `both_decl_and_impl` or any of its dependencies + +error: aborting due to 3 previous errors + diff --git a/tests/ui/eii/duplicate/multiple_impls.rs b/tests/ui/eii/duplicate/multiple_impls.rs index 80f6147789743..3e541cb16b131 100644 --- a/tests/ui/eii/duplicate/multiple_impls.rs +++ b/tests/ui/eii/duplicate/multiple_impls.rs @@ -1,25 +1,37 @@ -//@ run-pass -//@ check-run-results //@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu -// Tests whether one function could implement two EIIs. +// Tests that one item can't implement two EIIs #![feature(extern_item_impls)] #[eii] fn a(x: u64); +//~^ ERROR `#[a]` function required, but not found #[eii] fn b(x: u64); #[a] #[b] +//~^ ERROR a single item cannot implement multiple EIIs fn implementation(x: u64) { println!("{x:?}") } -// what you would write: +#[eii(c)] +//~^ ERROR `#[c]` static required, but not found +static C: u64; + +#[eii(d)] +static D: u64; + +#[c] +#[d] +//~^ ERROR a single item cannot implement multiple EIIs +static IMPL: u64 = 5; + fn main() { a(42); b(42); + println!("{C} {D} {IMPL}") } diff --git a/tests/ui/eii/duplicate/multiple_impls.run.stdout b/tests/ui/eii/duplicate/multiple_impls.run.stdout deleted file mode 100644 index daaac9e303029..0000000000000 --- a/tests/ui/eii/duplicate/multiple_impls.run.stdout +++ /dev/null @@ -1,2 +0,0 @@ -42 -42 diff --git a/tests/ui/eii/duplicate/multiple_impls.stderr b/tests/ui/eii/duplicate/multiple_impls.stderr new file mode 100644 index 0000000000000..efeec635c859a --- /dev/null +++ b/tests/ui/eii/duplicate/multiple_impls.stderr @@ -0,0 +1,30 @@ +error: a single item cannot implement multiple EIIs + --> $DIR/multiple_impls.rs:15:1 + | +LL | #[b] + | ^^^^ + +error: a single item cannot implement multiple EIIs + --> $DIR/multiple_impls.rs:29:1 + | +LL | #[d] + | ^^^^ + +error: `#[a]` function required, but not found + --> $DIR/multiple_impls.rs:8:4 + | +LL | fn a(x: u64); + | ^ expected because `#[a]` was declared here in crate `multiple_impls` + | + = help: expected at least one implementation in crate `multiple_impls` or any of its dependencies + +error: `#[c]` static required, but not found + --> $DIR/multiple_impls.rs:21:7 + | +LL | #[eii(c)] + | ^ expected because `#[c]` was declared here in crate `multiple_impls` + | + = help: expected at least one implementation in crate `multiple_impls` or any of its dependencies + +error: aborting due to 4 previous errors + diff --git a/tests/ui/eii/static/multiple_impls.rs b/tests/ui/eii/static/multiple_impls.rs deleted file mode 100644 index 1129417b958ca..0000000000000 --- a/tests/ui/eii/static/multiple_impls.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ ignore-backends: gcc -// FIXME(#125418): linking on Windows GNU targets is not yet supported. -//@ ignore-windows-gnu -// Tests whether one function could implement two EIIs. -#![feature(extern_item_impls)] - -#[eii(a)] -static A: u64; - -#[eii(b)] -static B: u64; - -#[a] -#[b] -//~^ ERROR static cannot implement multiple EIIs -static IMPL: u64 = 5; - -fn main() { - println!("{A} {B} {IMPL}") -} diff --git a/tests/ui/eii/static/multiple_impls.run.stdout b/tests/ui/eii/static/multiple_impls.run.stdout deleted file mode 100644 index 58945c2b48291..0000000000000 --- a/tests/ui/eii/static/multiple_impls.run.stdout +++ /dev/null @@ -1 +0,0 @@ -5 5 5 diff --git a/tests/ui/eii/static/multiple_impls.stderr b/tests/ui/eii/static/multiple_impls.stderr deleted file mode 100644 index b31331f2483f1..0000000000000 --- a/tests/ui/eii/static/multiple_impls.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: static cannot implement multiple EIIs - --> $DIR/multiple_impls.rs:14:1 - | -LL | #[b] - | ^^^^ - | - = note: this is not allowed because multiple externally implementable statics that alias may be unintuitive - -error: aborting due to 1 previous error - From 496056fb26fec158af8c045c0aefd813d82b9f9f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 3 Aug 2026 11:33:41 +0300 Subject: [PATCH 48/53] Use `thread::available_parallelism` as the default limit for backend parallelism --- compiler/rustc_interface/src/interface.rs | 6 ++--- compiler/rustc_session/src/config.rs | 29 ++++------------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 2ad6fb6450a16..18f869d24cbfb 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -15,7 +15,7 @@ use rustc_parse::lexer::StripTokens; use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::Recovery; use rustc_query_impl::print_query_stack; -use rustc_session::config::{self, BackendJobs, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; +use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; use rustc_session::parse::ParseSess; use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint}; use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs}; @@ -375,9 +375,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se // Initialize jobserver as early as possible. let early_dcx = EarlyDiagCtxt::new(config.opts.error_format); - if let Some(limit) = - config.opts.jobs.frontend.max(config.opts.jobs.backend.map(BackendJobs::value)) - { + if let Some(limit) = config.opts.jobs.frontend.max(config.opts.jobs.backend) { jobserver::initialize(limit.get(), |err| { let note = "the build environment is likely misconfigured"; early_dcx.early_struct_warn(err).with_note(note).emit() diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 022784b56d4ce..1cfd03288a417 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1649,26 +1649,6 @@ impl PointerAuthOption { } } -#[derive(Clone, Copy)] -pub enum BackendJobs { - /// The number of backend jobs has a static limit. - Limited(NonZero), - /// The number of backend jobs is either unlimited if there's an inherited jobserver, - /// or limited to 32 if there's no inherited jobserver. - /// This variant exists only to preserve the historical behavior. - /// FIXME: Just use `thread::available_parallelism` as the default static limit. - UnlimitedOr32, -} - -impl BackendJobs { - pub fn value(self) -> NonZero { - match self { - BackendJobs::Limited(n) => n, - BackendJobs::UnlimitedOr32 => NonZero::new(32).unwrap(), - } - } -} - #[derive(Clone, Copy)] pub enum LinkerJobs { /// Do not pass anything to the linker, use it's default behavior. @@ -1682,7 +1662,7 @@ pub enum LinkerJobs { #[derive(Clone, Copy)] pub struct Jobs { pub frontend: Option>, - pub backend: Option, + pub backend: Option>, pub linker: LinkerJobs, } @@ -1735,11 +1715,12 @@ fn parse_jobs_all( let backend = parse_jobs_one(early_dcx, opt_name, &jobs_backend, unstable, &mut available); check_upper_limit(backend, opt_name); - backend.map(BackendJobs::Limited) + backend } None => match jobs { - Some(n) => n.map(BackendJobs::Limited), - None => Some(BackendJobs::UnlimitedOr32), + Some(n) => n, + // Use all available parallelism as the default. + None => parse_jobs_one(early_dcx, "", "0", unstable, &mut available), }, }; let linker = match matches.opt_str("jobs-linker") { From 6a91af6422d75abe35e33ebc97afbe9740672677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 3 Aug 2026 11:57:11 +0200 Subject: [PATCH 49/53] Run try builds on EC2 by default --- src/ci/github-actions/jobs.yml | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 1451b633986b9..3823f6c27c70a 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -71,6 +71,10 @@ runners: os: codebuild-ubuntu-22-8c-$github.run_id-$github.run_attempt <<: *base-job + - &job-linux-48c-ec2 + os: ec2-ubuntu26.04-c8a.12xlarge-x64-linux-$github.run_id-$github.run_attempt + <<: *base-job + envs: production: &production @@ -106,7 +110,6 @@ jobs: IMAGE: dist-x86_64-linux CODEGEN_BACKENDS: llvm,cranelift DOCKER_SCRIPT: dist.sh - <<: *job-linux-36c-codebuild # Jobs that run on each push to a pull request (PR). @@ -176,7 +179,7 @@ pr: # These jobs automatically inherit envs.try, to avoid repeating # it in each job definition. try: - - <<: *job-dist-x86_64-linux + - <<: [*job-dist-x86_64-linux, *job-linux-48c-ec2] name: dist-x86_64-linux-quick # Jobs that only run when explicitly invoked in one of the following ways: @@ -189,21 +192,12 @@ optional: env: IMAGE: pr-check-1 <<: *job-linux-4c - - name: dist-x86_64-linux-ec2 - os: ec2-ubuntu26.04-c8a.12xlarge-x64-linux-$github.run_id-$github.run_attempt - free_disk: true - env: - IMAGE: dist-x86_64-linux - CODEGEN_BACKENDS: llvm,cranelift - DOCKER_SCRIPT: dist.sh - - name: dist-x86_64-linux-ec2-quick - os: ec2-ubuntu26.04-c8a.12xlarge-x64-linux-$github.run_id-$github.run_attempt - free_disk: true - env: - IMAGE: dist-x86_64-linux - CODEGEN_BACKENDS: llvm,cranelift - DOCKER_SCRIPT: dist.sh - DIST_TRY_BUILD: 1 + - <<: [*job-dist-x86_64-linux, *job-linux-36c-codebuild] + name: dist-x86_64-linux-quick-codebuild + # We repeat the try job here so that it can be explicitly executed using `@bors try jobs`, to test + # full x64 Linux dist try builds on EC2. + - <<: [*job-dist-x86_64-linux, *job-linux-48c-ec2] + name: dist-x86_64-linux-quick # Main CI jobs that have to be green to merge a commit into the default branch. # @@ -311,7 +305,7 @@ auto: - name: dist-x86_64-illumos <<: *job-linux-4c - - <<: *job-dist-x86_64-linux + - <<: [*job-dist-x86_64-linux, *job-linux-36c-codebuild] - name: dist-x86_64-linux-alt env: From 6daa152ce85185cd34ad4ad29880602e92a43aad Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 3 Aug 2026 14:44:31 +0200 Subject: [PATCH 50/53] bump tracing-tree --- Cargo.lock | 4 ++-- compiler/rustc_log/Cargo.toml | 2 +- compiler/rustc_pattern_analysis/Cargo.toml | 2 +- src/librustdoc/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0addc566d6bdd..76b17e02c2359 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5927,9 +5927,9 @@ dependencies = [ [[package]] name = "tracing-tree" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b56c62d2c80033cb36fae448730a2f2ef99410fe3ecbffc916681a32f6807dbe" +checksum = "ac87aa03b6a4d5a7e4810d1a80c19601dbe0f8a837e9177f23af721c7ba7beec" dependencies = [ "nu-ansi-term", "tracing-core", diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index d407351fd23dc..0e17378ecfc3d 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -8,7 +8,7 @@ edition = "2024" tracing = "0.1.41" tracing-core = "0.1.34" tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi", "json"] } -tracing-tree = "0.3.1" +tracing-tree = "0.4.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index a644c6a7c01a2..57dc75961e24f 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -24,7 +24,7 @@ tracing = "0.1" [dev-dependencies] # tidy-alphabetical-start tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "ansi"] } -tracing-tree = "0.3.0" +tracing-tree = "0.4.1" # tidy-alphabetical-end [features] diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 1fcc29bf92d93..42142b3990ce0 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -26,7 +26,7 @@ stringdex = "=0.0.6" tempfile = "3" threadpool = "1.8.1" tracing = "0.1" -tracing-tree = "0.3.0" +tracing-tree = "0.4.1" unicode-segmentation = "1.9" # tidy-alphabetical-end From 86e039fb554cd6b295fcb86872e85b4c6bd79f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 3 Aug 2026 14:55:11 +0200 Subject: [PATCH 51/53] Allow running both quick and full codebuild Linux x64 dist job --- src/ci/github-actions/jobs.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 3823f6c27c70a..6df2f07aba983 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -192,8 +192,15 @@ optional: env: IMAGE: pr-check-1 <<: *job-linux-4c + - <<: [*job-dist-x86_64-linux, *job-linux-36c-codebuild] + name: dist-x86_64-linux-codebuild - <<: [*job-dist-x86_64-linux, *job-linux-36c-codebuild] name: dist-x86_64-linux-quick-codebuild + env: + IMAGE: dist-x86_64-linux + CODEGEN_BACKENDS: llvm,cranelift + DOCKER_SCRIPT: dist.sh + DIST_TRY_BUILD: 1 # We repeat the try job here so that it can be explicitly executed using `@bors try jobs`, to test # full x64 Linux dist try builds on EC2. - <<: [*job-dist-x86_64-linux, *job-linux-48c-ec2] From 07e1398046f6c7831f70daf2a281bcb7d04e54e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 3 Aug 2026 18:32:07 +0200 Subject: [PATCH 52/53] Fix lookup of object files --- compiler/rustc_codegen_ssa/src/back/link.rs | 11 +++++++---- compiler/rustc_metadata/src/locator.rs | 4 ++-- compiler/rustc_session/src/filesearch.rs | 9 ++++++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8cbf3647f5630..47462ca2cac91 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,7 +1,7 @@ mod raw_dylib; use std::collections::BTreeSet; -use std::ffi::{OsStr, OsString}; +use std::ffi::OsString; use std::fs::{File, OpenOptions, read}; use std::io::{BufReader, BufWriter, Write}; use std::ops::{ControlFlow, Deref}; @@ -2061,9 +2061,12 @@ fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> Pat } } - for (_, path) in sess.target_filesearch().get_file_candidates(name, "", PathKind::Native) { - if path.file_name().map_or(false, |n| n == OsStr::new(name)) && path.exists() { - return path; + // Note: this is O(n^2), it could be expensive-ish if we lookup many object files for many + // search paths + for search_path in sess.target_filesearch().search_paths(PathKind::Native) { + let file_path = search_path.dir.join(name); + if file_path.exists() { + return file_path; } } PathBuf::from(name) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 378f779556a9c..f26b27399b958 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -434,7 +434,7 @@ impl<'a> CrateLocator<'a> { } for (hash, spf_path) in - self.filesearch.get_file_candidates(prefix, suffix, self.path_kind) + self.filesearch.get_library_candidates(prefix, suffix, self.path_kind) { info!("lib candidate: {}", spf_path.display()); @@ -462,7 +462,7 @@ impl<'a> CrateLocator<'a> { } if should_check_staticlibs { - for (_, path) in self.filesearch.get_file_candidates( + for (_, path) in self.filesearch.get_library_candidates( staticlib_prefix, staticlib_suffix, self.path_kind, diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index e1b3dcd94135a..d88fed2f84ab8 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -35,7 +35,11 @@ impl FileSearch { /// Return files from the search dirs of this filesearch that match the given `prefix` and /// `suffix` and have the given `kind`. - pub fn get_file_candidates<'b>( + /// + /// Note that this function only searches files that match lib/staticlib/dlllib prefixes, not + /// all files from the search paths! + /// Access `search_paths` directly if you want to scan all files within them. + pub fn get_library_candidates<'b>( &'b self, prefix: &'b str, suffix: &'b str, @@ -65,6 +69,9 @@ impl FileSearch { target: &Target, use_implicit_sysroot_deps: bool, ) -> Self { + // We keep a list of all found paths that look like libraries in `FileSearch`, to optimize + // lookup in `get_library_candidates`. + // These prefixes should be kept in sync with `CrateLocator::find_library_crate`. let prefixes = ["lib", &target.staticlib_prefix, &target.dll_prefix]; // Load all files from all search paths, filter them by supported prefixes, and sort them, From 6b47c9636e985b6f80a7f1aac3000e6548e25e9e Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 3 Aug 2026 20:31:04 -0500 Subject: [PATCH 53/53] Update the tracking issue for `borrowed_buf_init` This used the same tracking issue as `read_buf`, which is likely to stabilize in the near future without this portion of the API. --- library/core/src/io/borrowed_buf.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs index 4402aa13a39cd..7ca6f6d8a02e8 100644 --- a/library/core/src/io/borrowed_buf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -94,7 +94,7 @@ impl<'data, T> BorrowedBuf<'data, T> { } /// Returns `true` if the buffer is initialized. - #[unstable(feature = "borrowed_buf_init", issue = "78485")] + #[unstable(feature = "borrowed_buf_init", issue = "160476")] #[inline] pub fn is_init(&self) -> bool { self.init @@ -170,7 +170,7 @@ impl<'data, T: Copy> BorrowedBuf<'data, T> { /// # Safety /// /// All the elements of the buffer must be initialized. - #[unstable(feature = "borrowed_buf_init", issue = "78485")] + #[unstable(feature = "borrowed_buf_init", issue = "160476")] #[inline] pub unsafe fn set_init(&mut self) -> &mut Self { self.init = true; @@ -240,7 +240,7 @@ impl<'a, T: Copy> BorrowedCursor<'a, T> { } /// Returns `true` if the buffer is initialized. - #[unstable(feature = "borrowed_buf_init", issue = "78485")] + #[unstable(feature = "borrowed_buf_init", issue = "160476")] #[inline] pub fn is_init(&self) -> bool { self.buf.init @@ -251,7 +251,7 @@ impl<'a, T: Copy> BorrowedCursor<'a, T> { /// # Safety /// /// All the elements of the cursor must be initialized. - #[unstable(feature = "borrowed_buf_init", issue = "78485")] + #[unstable(feature = "borrowed_buf_init", issue = "160476")] #[inline] pub unsafe fn set_init(&mut self) { self.buf.init = true; @@ -280,7 +280,7 @@ impl<'a, T: Copy> BorrowedCursor<'a, T> { /// # Panics /// /// Panics if there are less than `n` elements initialized. - #[unstable(feature = "borrowed_buf_init", issue = "78485")] + #[unstable(feature = "borrowed_buf_init", issue = "160476")] #[inline] pub fn advance_checked(&mut self, n: usize) -> &mut Self { // The subtraction cannot underflow by invariant of this type. @@ -359,7 +359,7 @@ impl<'a, T: Copy> BorrowedCursor<'a, T> { impl<'a> BorrowedCursor<'a, u8> { /// Initializes all bytes in the cursor and returns them. - #[unstable(feature = "borrowed_buf_init", issue = "78485")] + #[unstable(feature = "borrowed_buf_init", issue = "160476")] #[inline] pub fn ensure_init(&mut self) -> &mut [u8] { // SAFETY: always in bounds and we never uninitialize these bytes.