From 99e6a28804eac57faa37134d61a2bb17069996a2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Thu, 30 May 2024 18:32:46 -0400 Subject: [PATCH 001/489] Add f16/f128 handling in a couple places --- compiler/rustc_codegen_llvm/src/abi.rs | 2 ++ compiler/rustc_target/src/abi/call/mod.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index a6a3f0f964611..2e52d3f426a83 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -121,8 +121,10 @@ impl LlvmType for Reg { match self.kind { RegKind::Integer => cx.type_ix(self.size.bits()), RegKind::Float => match self.size.bits() { + 16 => cx.type_f16(), 32 => cx.type_f32(), 64 => cx.type_f64(), + 128 => cx.type_f128(), _ => bug!("unsupported float: {:?}", self), }, RegKind::Vector => cx.type_vector(cx.type_i8(), self.size.bytes()), diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index fc79c9232d1bd..f83d0492004a2 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -236,8 +236,10 @@ impl Reg { _ => panic!("unsupported integer: {self:?}"), }, RegKind::Float => match self.size.bits() { + 16 => dl.f16_align.abi, 32 => dl.f32_align.abi, 64 => dl.f64_align.abi, + 128 => dl.f128_align.abi, _ => panic!("unsupported float: {self:?}"), }, RegKind::Vector => dl.vector_align(self.size).abi, From 32efd239554dd80d7983e160024e7d4cd6db3439 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Mon, 8 Jul 2024 11:40:04 -0700 Subject: [PATCH 002/489] Add target page for riscv64gc-unknown-linux-gnu --- src/doc/rustc/src/platform-support.md | 2 +- .../riscv64gc-unknown-linux-gnu.md | 127 ++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f5cd4bd217a32..0ecaaf5a9aae6 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -97,7 +97,7 @@ target | notes `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17) `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17) -`riscv64gc-unknown-linux-gnu` | RISC-V Linux (kernel 4.20, glibc 2.29) +[`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29) `s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17) `x86_64-unknown-freebsd` | 64-bit FreeBSD `x86_64-unknown-illumos` | illumos diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md new file mode 100644 index 0000000000000..21d547f5aaba7 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md @@ -0,0 +1,127 @@ +# `riscv64gc-unknown-linux-gnu` + +**Tier: 2 (with Host Tools)** + +RISC-V targets using the *RV64I* base instruction set with the *G* collection of extensions, as well as the *C* extension. + + +## Target maintainers + +- TODO + + +## Requirements + +This target requires: + +* Linux Kernel version 4.20 or later +* glibc 2.17 or later + + +## Building the target + +These targets are distributed through `rustup`, and otherwise require no +special configuration. + +If you need to build your own Rust for some reason though, the targets can be +enabled in `config.toml`. For example: + +```toml +[build] +target = ["riscv64gc-unknown-linux-gnu"] +``` + + +## Building Rust programs + + +On a RISC-V host, the `riscv64gc-unknown-linux-gnu` target should be automatically +installed and used by default. + +On a non-RISC-V host, add the target: + +```bash +rustup target add riscv64gc-unknown-linux-gnu +``` + +Then cross compile crates with: + +```bash +cargo build --target riscv64gc-unknown-linux-gnu +``` + + +## Testing + +There are no special requirements for testing and running the targets. +For testing cross builds on the host, please refer to the "Cross-compilation +toolchains and C code" +section below. + + +## Cross-compilation toolchains and C code + +A RISC-V toolchain can be obtained for Windows/Mac/Linux from the +[`riscv-gnu-toolchain`](https://github.com/riscv-collab/riscv-gnu-toolchain) +repostory. Binaries are available via +[embecosm](https://www.embecosm.com/resources/tool-chain-downloads/#riscv-linux), +and may also be available from your OS's package manager. + +On Ubuntu, a RISC-V toolchain can be installed with: + +```bash +apt install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu libc6-dev-riscv64-cross +``` + +Depending on your system, you may need to configure the target to use the GNU +GCC linker. To use it, add the following to your `.cargo/config.toml`: + +```toml +[target.riscv64gc-unknown-linux-gnu] +linker = "riscv64-linux-gnu-gcc" +``` + +If your `riscv64-linux-gnu-*` toolchain is not in your `PATH` you may need to +configure additional settings: + +```toml +[target.riscv64gc-unknown-linux-gnu] +# Adjust the paths to point at your toolchain +cc = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-gcc" +cxx = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-g++" +ar = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-ar" +ranlib = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-ranlib" +linker = "/TOOLCHAIN_PATH/bin/riscv64-linux-gnu-gcc" +``` + +To test cross compiled binaries on a non-RISCV-V host, you can use +[`qemu`](https://www.qemu.org/docs/master/system/target-riscv.html). +On Ubuntu, a RISC-V emulator can be obtained with: + +```bash +apt install qemu-system-riscv64 +``` + +Then, in `.cargo/config.toml` set the `runner`: + +```toml +[target.riscv64gc-unknown-linux-gnu] +runner = "qemu-riscv64-static -L /usr/riscv64-linux-gnu -cpu rv64" +``` + +On Mac and Linux, it's also possible to use +[`lima`](https://github.com/lima-vm/lima) to emulate RISC-V in a similar way to +how WSL2 works on Windows: + +```bash +limactl start template://riscv +limactl shell riscv +``` + +Using [Docker (with BuildKit)](https://docs.docker.com/build/buildkit/) the +[`riscv64/ubuntu`](https://hub.docker.com/r/riscv64/ubuntu) image can be used +to buiild or run `riscv64gc-unknown-linux-gnu` binaries. + +```bash +docker run --platform linux/riscv64 -ti --rm --mount "type=bind,src=$(pwd),dst=/checkout" riscv64/ubuntu bash +``` From 22364f86aeba440066db931132ecee8292b709fd Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Tue, 9 Jul 2024 14:24:05 +0200 Subject: [PATCH 003/489] This pattern using lazy protected Reserved IM prevents spurious writes --- .../tree_borrows/reservedim_spurious_write.rs | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs new file mode 100644 index 0000000000000..1f52537f9a295 --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -0,0 +1,109 @@ +// Illustrating a problematic interaction between Reserved, interior mutability, +// and protectors, that makes spurious writes fail in the previous model of Tree Borrows. +// As for all similar tests, we disable preemption so that the error message is deterministic. +//@compile-flags: -Zmiri-tree-borrows -Zmiri-preemption-rate=0 + +use std::cell::Cell; +use std::sync::{Arc, Barrier}; +use std::thread; + +// Here is the problematic interleaving: +// - thread 1: retag and activate `x` (protected) +// - thread 2: create but do not retag (lazy) `y` as Reserved with interior mutability +// - thread 1: spurious write through `x` would go here +// - thread 2: function exit (noop due to lazyness) +// - thread 1: function exit (no permanent effect on `y` because it is now Reserved IM unprotected) +// - thread 2: write through `y` +// In the source code nothing happens to `y` + +// `Send`able raw pointer wrapper. +#[derive(Copy, Clone)] +struct SendPtr(*mut u8); +unsafe impl Send for SendPtr {} + +type IdxBarrier = (usize, Arc); + +// Barriers to enforce the interleaving. +// This macro expects `synchronized!(thread, msg)` where `thread` is a `IdxBarrier`, +// and `msg` is the message to be displayed when the thread reaches this point in the execution. +macro_rules! synchronized { + ($thread:expr, $msg:expr) => {{ + let (thread_id, barrier) = &$thread; + eprintln!("Thread {} executing: {}", thread_id, $msg); + barrier.wait(); + }}; +} + +fn main() { + eprintln!("Without spurious write"); + example(false); + + eprintln!("\nIf this text is visible then the model forbids spurious writes.\n"); + + eprintln!("With spurious write"); + example(true); + + eprintln!("\nIf this text is visible then the model fails to detect a noalias violation.\n"); +} + +fn example(spurious: bool) { + // For this example it is important that we have at least two bytes + // because lazyness is involved. + let mut data = [0u8; 2]; + let ptr = SendPtr(std::ptr::addr_of_mut!(data[0])); + let barrier = Arc::new(Barrier::new(2)); + let bx = Arc::clone(&barrier); + let by = Arc::clone(&barrier); + + // Retag and activate `x`, wait until the other thread creates a lazy permission. + // Then do a spurious write. Finally exit the function after the other thread. + let thread_1 = thread::spawn(move || { + let b = (1, bx); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + fn inner(x: &mut u8, b: IdxBarrier, spurious: bool) { + *x = 42; // activate immediately + synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); + // A spurious write should be valid here because `x` is + // `Active` and protected. + if spurious { + synchronized!(b, "spurious write x (executed)"); + *x = 64; + } else { + synchronized!(b, "spurious write x (skipped)"); + } + synchronized!(b, "ret y"); + synchronized!(b, "ret x"); + } + inner(unsafe { &mut *ptr.0 }, b.clone(), spurious); + synchronized!(b, "write y"); + synchronized!(b, "end"); + }); + + // Create a lazy Reserved with interior mutability. + // Wait for the other thread's spurious write then observe the side effects + // of that write. + let thread_2 = thread::spawn(move || { + let b = (2, by); + synchronized!(b, "start"); + let ptr = ptr; + synchronized!(b, "retag x (&mut, protect)"); + synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); + fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { + synchronized!(b, "spurious write x"); + synchronized!(b, "ret y"); + y as *mut Cell as *mut u8 + } + // Currently `ptr` points to `data[0]`. We retag it for `data[1]` + // then use it for `data[0]` where its initialization has been deferred. + let y = inner(unsafe { &mut *(ptr.0 as *mut Cell).wrapping_add(1) }, b.clone()); + synchronized!(b, "ret x"); + synchronized!(b, "write y"); + unsafe { *y.wrapping_sub(1) = 13 } + synchronized!(b, "end"); + }); + + thread_1.join().unwrap(); + thread_2.join().unwrap(); +} From 2de6e7f3a680a8000f83f2b62252d18a1bb06966 Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Tue, 9 Jul 2024 14:36:46 +0200 Subject: [PATCH 004/489] Implement fix for reservedim_spurious_write: ignore IM on protected --- .../src/borrow_tracker/tree_borrows/mod.rs | 10 ++++- .../src/borrow_tracker/tree_borrows/perms.rs | 5 +++ .../reserved/cell-protected-write.stderr | 6 +-- .../tree_borrows/reservedim_spurious_write.rs | 2 +- .../reservedim_spurious_write.stderr | 41 +++++++++++++++++++ .../tests/pass/tree_borrows/reserved.stderr | 2 +- 6 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 86074384084d5..4d9595b352f28 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -141,8 +141,14 @@ impl<'tcx> NewPermission { ) -> Option { let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.param_env()); let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.param_env()); + let is_protected = kind == RetagKind::FnEntry; + // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, + // interior mutability and protectors interact poorly. + // To eliminate the case of Protected Reserved IM we override interior mutability + // in the case of a protected reference. let initial_state = match mutability { - Mutability::Mut if ty_is_unpin => Permission::new_reserved(ty_is_freeze), + Mutability::Mut if ty_is_unpin => + Permission::new_reserved(ty_is_freeze || is_protected), Mutability::Not if ty_is_freeze => Permission::new_frozen(), // Raw pointers never enter this function so they are not handled. // However raw pointers are not the only pointers that take the parent @@ -151,7 +157,7 @@ impl<'tcx> NewPermission { _ => return None, }; - let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector); + let protector = is_protected.then_some(ProtectorKind::StrongProtector); Some(Self { zero_size: false, initial_state, protector }) } diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 7aa9c3e862bcc..9c19ae76a2d01 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -22,6 +22,11 @@ enum PermissionPriv { /// - foreign-read then child-write is UB due to `conflicted`, /// - child-write then foreign-read is UB since child-write will activate and then /// foreign-read disables a protected `Active`, which is UB. + /// + /// Note: since the discovery of `tests/fail/tree_borrows/reservedim_spurious_write.rs`, + /// `ty_is_freeze` does not strictly mean that the type has no interior mutability, + /// it could be an interior mutable type that lost its interior mutability privileges + /// when retagged with a protector. Reserved { ty_is_freeze: bool, conflicted: bool }, /// represents: a unique pointer; /// allows: child reads, child writes; diff --git a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr index 7d000ba55e60b..ce9a5b7f15865 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reserved/cell-protected-write.stderr @@ -5,7 +5,7 @@ Warning: this tree is indicative only. Some tags may have been hidden. | RsM | └─┬── | RsM | ├─┬── | RsM | │ └─┬── -| RsM | │ └──── Strongly protected +| Rs | │ └──── Strongly protected | RsM | └──── ────────────────────────────────────────────────── error: Undefined Behavior: write access through (y, callee:y, caller:y) at ALLOC[0x0] is forbidden @@ -16,14 +16,14 @@ LL | *y = 1; | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag (y, callee:y, caller:y) is foreign to the protected tag (callee:x) (i.e., it is not a child) - = help: this foreign write access would cause the protected tag (callee:x) (currently Reserved (interior mutable)) to become Disabled + = help: this foreign write access would cause the protected tag (callee:x) (currently Reserved) to become Disabled = help: protected tags must never be Disabled help: the accessed tag was created here --> $DIR/cell-protected-write.rs:LL:CC | LL | let y = (&mut *n).get(); | ^^^^^^^^^ -help: the protected tag was created here, in the initial state Reserved (interior mutable) +help: the protected tag was created here, in the initial state Reserved --> $DIR/cell-protected-write.rs:LL:CC | LL | unsafe fn write_second(x: &mut UnsafeCell, y: *mut u8) { diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 1f52537f9a295..5e7cb5e34cc2b 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -100,7 +100,7 @@ fn example(spurious: bool) { let y = inner(unsafe { &mut *(ptr.0 as *mut Cell).wrapping_add(1) }, b.clone()); synchronized!(b, "ret x"); synchronized!(b, "write y"); - unsafe { *y.wrapping_sub(1) = 13 } + unsafe { *y.wrapping_sub(1) = 13 } //~ERROR: /write access through .* is forbidden/ synchronized!(b, "end"); }); diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr new file mode 100644 index 0000000000000..9be6c157c0cbb --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr @@ -0,0 +1,41 @@ +Without spurious write +Thread 1 executing: start +Thread 2 executing: start +Thread 2 executing: retag x (&mut, protect) +Thread 1 executing: retag x (&mut, protect) +Thread 1 executing: [lazy] retag y (&mut, protect, IM) +Thread 2 executing: [lazy] retag y (&mut, protect, IM) +Thread 2 executing: spurious write x +Thread 1 executing: spurious write x (skipped) +Thread 1 executing: ret y +Thread 2 executing: ret y +Thread 2 executing: ret x +Thread 1 executing: ret x +Thread 1 executing: write y +Thread 2 executing: write y +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | unsafe { *y.wrapping_sub(1) = 13 } + | ^^^^^^^^^^^^^^^^^^^^^^^ write access through at ALLOC[0x0] is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag has state Disabled which forbids this child write access +help: the accessed tag was created here, in the initial state Reserved + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { + | ^ +help: the accessed tag later transitioned to Disabled due to a protector release (acting as a foreign write access) on every location previously accessed by this tag + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | } + | ^ + = help: this transition corresponds to a loss of read and write permissions + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/reservedim_spurious_write.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr index 0d0d52c717fed..d149a4065f92b 100644 --- a/src/tools/miri/tests/pass/tree_borrows/reserved.stderr +++ b/src/tools/miri/tests/pass/tree_borrows/reserved.stderr @@ -6,7 +6,7 @@ Warning: this tree is indicative only. Some tags may have been hidden. | RsM | └─┬── | RsM | ├─┬── | RsM | │ └─┬── -| RsCM| │ └──── +| RsC | │ └──── | RsM | └──── ────────────────────────────────────────────────── [interior mut] Foreign Read: Re* -> Re* From 22996ad073870c5ac7753ba1acbaba784adc534d Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Tue, 9 Jul 2024 19:42:12 +0200 Subject: [PATCH 005/489] Apply suggestions - split test into two revisions - clarify comments --- .../src/borrow_tracker/tree_borrows/mod.rs | 3 +- .../tree_borrows/reservedim_spurious_write.rs | 26 +++++------- .../reservedim_spurious_write.with.stderr | 40 +++++++++++++++++++ ... reservedim_spurious_write.without.stderr} | 1 - 4 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr rename src/tools/miri/tests/fail/tree_borrows/{reservedim_spurious_write.stderr => reservedim_spurious_write.without.stderr} (98%) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 4d9595b352f28..123d4b407fb4c 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -145,7 +145,8 @@ impl<'tcx> NewPermission { // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, // interior mutability and protectors interact poorly. // To eliminate the case of Protected Reserved IM we override interior mutability - // in the case of a protected reference. + // in the case of a protected reference: protected references are always considered + // "freeze". let initial_state = match mutability { Mutability::Mut if ty_is_unpin => Permission::new_reserved(ty_is_freeze || is_protected), diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 5e7cb5e34cc2b..611f64dce5e50 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -2,6 +2,12 @@ // and protectors, that makes spurious writes fail in the previous model of Tree Borrows. // As for all similar tests, we disable preemption so that the error message is deterministic. //@compile-flags: -Zmiri-tree-borrows -Zmiri-preemption-rate=0 +// +// One revision without spurious read (default source code) and one with spurious read. +// Both are expected to be UB. Both revisions are expected to have the *same* error +// because we are aligning the behavior of `without` to that of `with` so that the +// spurious write is effectively a noop in the long term. +//@revisions: without with use std::cell::Cell; use std::sync::{Arc, Barrier}; @@ -9,7 +15,7 @@ use std::thread; // Here is the problematic interleaving: // - thread 1: retag and activate `x` (protected) -// - thread 2: create but do not retag (lazy) `y` as Reserved with interior mutability +// - thread 2: retag but do not initialize (lazy) `y` as Reserved with interior mutability // - thread 1: spurious write through `x` would go here // - thread 2: function exit (noop due to lazyness) // - thread 1: function exit (no permanent effect on `y` because it is now Reserved IM unprotected) @@ -35,18 +41,6 @@ macro_rules! synchronized { } fn main() { - eprintln!("Without spurious write"); - example(false); - - eprintln!("\nIf this text is visible then the model forbids spurious writes.\n"); - - eprintln!("With spurious write"); - example(true); - - eprintln!("\nIf this text is visible then the model fails to detect a noalias violation.\n"); -} - -fn example(spurious: bool) { // For this example it is important that we have at least two bytes // because lazyness is involved. let mut data = [0u8; 2]; @@ -62,12 +56,12 @@ fn example(spurious: bool) { synchronized!(b, "start"); let ptr = ptr; synchronized!(b, "retag x (&mut, protect)"); - fn inner(x: &mut u8, b: IdxBarrier, spurious: bool) { + fn inner(x: &mut u8, b: IdxBarrier) { *x = 42; // activate immediately synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); // A spurious write should be valid here because `x` is // `Active` and protected. - if spurious { + if cfg!(with) { synchronized!(b, "spurious write x (executed)"); *x = 64; } else { @@ -76,7 +70,7 @@ fn example(spurious: bool) { synchronized!(b, "ret y"); synchronized!(b, "ret x"); } - inner(unsafe { &mut *ptr.0 }, b.clone(), spurious); + inner(unsafe { &mut *ptr.0 }, b.clone()); synchronized!(b, "write y"); synchronized!(b, "end"); }); diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr new file mode 100644 index 0000000000000..5ac9c912ba9ee --- /dev/null +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr @@ -0,0 +1,40 @@ +Thread 1 executing: start +Thread 2 executing: start +Thread 2 executing: retag x (&mut, protect) +Thread 1 executing: retag x (&mut, protect) +Thread 1 executing: [lazy] retag y (&mut, protect, IM) +Thread 2 executing: [lazy] retag y (&mut, protect, IM) +Thread 2 executing: spurious write x +Thread 1 executing: spurious write x (executed) +Thread 1 executing: ret y +Thread 2 executing: ret y +Thread 2 executing: ret x +Thread 1 executing: ret x +Thread 1 executing: write y +Thread 2 executing: write y +error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | unsafe { *y.wrapping_sub(1) = 13 } + | ^^^^^^^^^^^^^^^^^^^^^^^ write access through at ALLOC[0x0] is forbidden + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: the accessed tag has state Disabled which forbids this child write access +help: the accessed tag was created here, in the initial state Reserved + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { + | ^ +help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x1] + --> $DIR/reservedim_spurious_write.rs:LL:CC + | +LL | *x = 64; + | ^^^^^^^ + = help: this transition corresponds to a loss of read and write permissions + = note: BACKTRACE (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/reservedim_spurious_write.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr similarity index 98% rename from src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr rename to src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr index 9be6c157c0cbb..97c71fdedefb3 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr @@ -1,4 +1,3 @@ -Without spurious write Thread 1 executing: start Thread 2 executing: start Thread 2 executing: retag x (&mut, protect) From 68aed4a5cebf846d88716489e4ea66074d669c5b Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Wed, 10 Jul 2024 14:32:02 +0200 Subject: [PATCH 006/489] Second byte is not involved in the example; use a Cell<()> instead --- .../tree_borrows/reservedim_spurious_write.rs | 23 +++++++++++-------- .../reservedim_spurious_write.with.stderr | 6 ++--- .../reservedim_spurious_write.without.stderr | 6 ++--- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 611f64dce5e50..6ae79be6cc7e8 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -41,10 +41,10 @@ macro_rules! synchronized { } fn main() { - // For this example it is important that we have at least two bytes - // because lazyness is involved. - let mut data = [0u8; 2]; - let ptr = SendPtr(std::ptr::addr_of_mut!(data[0])); + // The conflict occurs one one single location but the example involves + // lazily initialized permissions. + let mut data = 0u8; + let ptr = SendPtr(std::ptr::addr_of_mut!(data)); let barrier = Arc::new(Barrier::new(2)); let bx = Arc::clone(&barrier); let by = Arc::clone(&barrier); @@ -84,17 +84,20 @@ fn main() { let ptr = ptr; synchronized!(b, "retag x (&mut, protect)"); synchronized!(b, "[lazy] retag y (&mut, protect, IM)"); - fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { + fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 { synchronized!(b, "spurious write x"); synchronized!(b, "ret y"); - y as *mut Cell as *mut u8 + // `y` is not retagged for any bytes, so the pointer we return + // has its permission lazily initialized. + y as *mut Cell<()> as *mut u8 } - // Currently `ptr` points to `data[0]`. We retag it for `data[1]` - // then use it for `data[0]` where its initialization has been deferred. - let y = inner(unsafe { &mut *(ptr.0 as *mut Cell).wrapping_add(1) }, b.clone()); + // Currently `ptr` points to `data`. + // We do a zero-sized retag so that its permission is lazy. + let y_zst = unsafe { &mut *(ptr.0 as *mut Cell<()>) }; + let y = inner(y_zst, b.clone()); synchronized!(b, "ret x"); synchronized!(b, "write y"); - unsafe { *y.wrapping_sub(1) = 13 } //~ERROR: /write access through .* is forbidden/ + unsafe { *y = 13 } //~ERROR: /write access through .* is forbidden/ synchronized!(b, "end"); }); diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr index 5ac9c912ba9ee..0e4517e90105c 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.with.stderr @@ -15,15 +15,15 @@ Thread 2 executing: write y error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden --> $DIR/reservedim_spurious_write.rs:LL:CC | -LL | unsafe { *y.wrapping_sub(1) = 13 } - | ^^^^^^^^^^^^^^^^^^^^^^^ write access through at ALLOC[0x0] is forbidden +LL | unsafe { *y = 13 } + | ^^^^^^^ write access through at ALLOC[0x0] is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag has state Disabled which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/reservedim_spurious_write.rs:LL:CC | -LL | fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { +LL | fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 { | ^ help: the accessed tag later transitioned to Disabled due to a foreign write access at offsets [0x0..0x1] --> $DIR/reservedim_spurious_write.rs:LL:CC diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr index 97c71fdedefb3..cbeef90243bfb 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.without.stderr @@ -15,15 +15,15 @@ Thread 2 executing: write y error: Undefined Behavior: write access through at ALLOC[0x0] is forbidden --> $DIR/reservedim_spurious_write.rs:LL:CC | -LL | unsafe { *y.wrapping_sub(1) = 13 } - | ^^^^^^^^^^^^^^^^^^^^^^^ write access through at ALLOC[0x0] is forbidden +LL | unsafe { *y = 13 } + | ^^^^^^^ write access through at ALLOC[0x0] is forbidden | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental = help: the accessed tag has state Disabled which forbids this child write access help: the accessed tag was created here, in the initial state Reserved --> $DIR/reservedim_spurious_write.rs:LL:CC | -LL | fn inner(y: &mut Cell, b: IdxBarrier) -> *mut u8 { +LL | fn inner(y: &mut Cell<()>, b: IdxBarrier) -> *mut u8 { | ^ help: the accessed tag later transitioned to Disabled due to a protector release (acting as a foreign write access) on every location previously accessed by this tag --> $DIR/reservedim_spurious_write.rs:LL:CC From fe0bd76a8bdb80f4460dd59612076cf91370f7a1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 10 Jul 2024 16:03:20 +0200 Subject: [PATCH 007/489] elaborate unknowable goals if a trait is unknowable, but its super trait is definitely not implemented, then the trait itself is definitely also not implemented. --- .../src/solve/assembly/mod.rs | 12 +++++++ compiler/rustc_type_ir/src/inherent.rs | 1 + .../normalize-for-errors.next.stderr | 1 + tests/ui/coherence/normalize-for-errors.rs | 1 + .../super-trait-knowable-1.current.stderr | 13 ++++++++ .../super-traits/super-trait-knowable-1.rs | 19 +++++++++++ .../super-traits/super-trait-knowable-2.rs | 33 +++++++++++++++++++ .../super-trait-knowable-3.current.stderr | 13 ++++++++ .../super-traits/super-trait-knowable-3.rs | 22 +++++++++++++ ...8728.stderr => issue-48728.current.stderr} | 2 +- tests/ui/issues/issue-48728.rs | 7 +++- 11 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-1.rs create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-2.rs create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr create mode 100644 tests/ui/coherence/super-traits/super-trait-knowable-3.rs rename tests/ui/issues/{issue-48728.stderr => issue-48728.current.stderr} (95%) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 01dde9ca587ca..4e1a3558a9c1e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -699,6 +699,18 @@ where if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? { Err(NoSolution) } else { + // While the trait bound itself may be unknowable, we may be able to + // prove that a super trait is not implemented. For this, we recursively + // prove the super trait bounds of the current goal. + // + // We skip the goal itself as that one would cycle. + let predicate: I::Predicate = trait_ref.upcast(cx); + ecx.add_goals( + GoalSource::Misc, + elaborate::elaborate(cx, [predicate]) + .skip(1) + .map(|predicate| goal.with(cx, predicate)), + ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } }, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index de86a8536f7af..2b6ccc8e430b5 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -433,6 +433,7 @@ pub trait Predicate>: + UpcastFrom> + UpcastFrom> + IntoKind>> + + Elaboratable { fn as_clause(self) -> Option; diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr index 6c56a9177414b..634a10b7a14c3 100644 --- a/tests/ui/coherence/normalize-for-errors.next.stderr +++ b/tests/ui/coherence/normalize-for-errors.next.stderr @@ -7,6 +7,7 @@ LL | LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` | + = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs index 2288118676ab3..4188389a3ad5b 100644 --- a/tests/ui/coherence/normalize-for-errors.rs +++ b/tests/ui/coherence/normalize-for-errors.rs @@ -18,5 +18,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} //~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, //~| NOTE conflicting implementation for `(Box<(MyType,)>, //~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions +//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr new file mode 100644 index 0000000000000..fb01cf158d980 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.current.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` + --> $DIR/super-trait-knowable-1.rs:16:1 + | +LL | impl> Overlap for U {} + | ----------------------------------- first implementation here +LL | impl Overlap for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: downstream crates may implement trait `Sub<_>` for type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-1.rs b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs new file mode 100644 index 0000000000000..80df8c19ee51f --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-1.rs @@ -0,0 +1,19 @@ +// Added in #124532. While `(): Super` is knowable, `(): Sub` is not. +// +// We therefore elaborate super trait bounds in the implicit negative +// overlap check. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +trait Super {} +trait Sub: Super {} + +trait Overlap {} +impl> Overlap for U {} +impl Overlap for () {} +//[current]~^ ERROR conflicting implementations + +fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-2.rs b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs new file mode 100644 index 0000000000000..d1f2e8d1c1a15 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-2.rs @@ -0,0 +1,33 @@ +// A regression test for pyella-0.1.5 which broke when +// enabling the new solver in coherence. +// +// `Tensor: TensorValue` is knowable while `Tensor: TensorOp` +// may be implemented downstream. We previously didn't check the +// super trait bound in coherence, causing these impls to overlap. +// +// However, we did fail to normalize ` {} +pub trait TensorOp: TensorValue {} + +pub struct Tensor; +impl TensorCompare for Tensor {} +impl TensorCompare for T1 +where + T1: TensorOp, + T1::Unmasked: Sized, +{} + + +fn main() {} diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr new file mode 100644 index 0000000000000..542edb8b7f674 --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.current.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Overlap<_>` for type `()` + --> $DIR/super-trait-knowable-3.rs:19:1 + | +LL | impl>> Overlap for U {} + | ---------------------------------------- first implementation here +LL | impl Overlap for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: downstream crates may implement trait `Sub<_>` for type `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/super-traits/super-trait-knowable-3.rs b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs new file mode 100644 index 0000000000000..295d7ac48d8cc --- /dev/null +++ b/tests/ui/coherence/super-traits/super-trait-knowable-3.rs @@ -0,0 +1,22 @@ +// Unlike in `super-trait-knowable-1.rs`, the knowable +// super trait bound is in a nested goal so this would not +// compile if we were to only elaborate root goals. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +trait Super {} +trait Sub: Super {} + +struct W(T); +trait Bound {} +impl, U> Bound> for T {} + +trait Overlap {} +impl>> Overlap for U {} +impl Overlap for () {} +//[current]~^ ERROR conflicting implementations of trait `Overlap<_>` for type `()` + +fn main() {} diff --git a/tests/ui/issues/issue-48728.stderr b/tests/ui/issues/issue-48728.current.stderr similarity index 95% rename from tests/ui/issues/issue-48728.stderr rename to tests/ui/issues/issue-48728.current.stderr index 6b4247f1d7965..2a1b4ff781854 100644 --- a/tests/ui/issues/issue-48728.stderr +++ b/tests/ui/issues/issue-48728.current.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Clone` for type `Node<[_]>` - --> $DIR/issue-48728.rs:4:10 + --> $DIR/issue-48728.rs:9:10 | LL | #[derive(Clone)] | ^^^^^ conflicting implementation for `Node<[_]>` diff --git a/tests/ui/issues/issue-48728.rs b/tests/ui/issues/issue-48728.rs index cbdc10bd2e1ea..7ef05f4277b27 100644 --- a/tests/ui/issues/issue-48728.rs +++ b/tests/ui/issues/issue-48728.rs @@ -1,7 +1,12 @@ // Regression test for #48728, an ICE that occurred computing // coherence "help" information. -#[derive(Clone)] //~ ERROR conflicting implementations of trait `Clone` +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +#[derive(Clone)] //[current]~ ERROR conflicting implementations of trait `Clone` struct Node(Box); impl Clone for Node<[T]> { From 0d49862998b3695297dffba21c80b35fb73e245d Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 13:05:03 -0500 Subject: [PATCH 008/489] Clarify/add `must_use` messages for more `into_raw*` functions of `alloc` types. --- library/alloc/src/boxed.rs | 2 ++ library/alloc/src/rc.rs | 2 ++ library/alloc/src/string.rs | 2 +- library/alloc/src/vec/mod.rs | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 65bcb241e4aec..21fd8d24af3d7 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1097,6 +1097,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Self) -> *mut T { @@ -1150,6 +1151,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 3745ecb48c18e..af3ace96d9c29 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1372,6 +1372,7 @@ impl Rc { /// let x = unsafe { Rc::from_raw_in(ptr, alloc) }; /// assert_eq!(&*x, "hello"); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = mem::ManuallyDrop::new(this); @@ -3100,6 +3101,7 @@ impl Weak { /// /// [`from_raw_in`]: Weak::from_raw_in /// [`as_ptr`]: Weak::as_ptr + #[must_use = "losing the pointer will leak memory"] #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub fn into_raw_with_allocator(self) -> (*const T, A) { diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 36078da7c35a6..ede2a42d12fe5 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -903,7 +903,7 @@ impl String { /// let rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) }; /// assert_eq!(rebuilt, "hello"); /// ``` - #[must_use = "`self` will be dropped if the result is not used"] + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts(self) -> (*mut u8, usize, usize) { self.vec.into_raw_parts() diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6e9b017ad75cf..b01ccb3848341 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -879,6 +879,7 @@ impl Vec { /// }; /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts(self) -> (*mut T, usize, usize) { let mut me = ManuallyDrop::new(self); @@ -922,6 +923,7 @@ impl Vec { /// }; /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` + #[must_use = "losing the pointer will leak memory"] #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts_with_alloc(self) -> (*mut T, usize, usize, A) { From 6d477d3a9de714d877a9eda48b0eda3e12e301be Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 13:08:24 -0500 Subject: [PATCH 009/489] Add `must_use` to IntoRawFd/IntoRawSocket/IntoRawHandle's methods. --- library/std/src/os/fd/raw.rs | 1 + library/std/src/os/solid/io.rs | 1 + library/std/src/os/windows/io/raw.rs | 2 ++ 3 files changed, 4 insertions(+) diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index ef896ea95c9c9..9d6fcaa3634d8 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -138,6 +138,7 @@ pub trait IntoRawFd { /// let raw_fd: RawFd = f.into_raw_fd(); /// # Ok::<(), io::Error>(()) /// ``` + #[must_use = "losing the raw file descriptor may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_fd(self) -> RawFd; } diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index 19b4fe22093c3..13d8419830df1 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -347,6 +347,7 @@ pub trait IntoRawFd { /// This function **transfers ownership** of the underlying file descriptor /// to the caller. Callers are then the unique owners of the file descriptor /// and must close the descriptor once it's no longer needed. + #[must_use = "losing the raw file descriptor may leak resources"] fn into_raw_fd(self) -> RawFd; } diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index 770583a9ce3e0..e76650be742a6 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -89,6 +89,7 @@ pub trait IntoRawHandle { /// However, transferring ownership is not strictly required. Use a /// `Into::into` implementation for an API which strictly /// transfers ownership. + #[must_use = "losing the raw handle may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_handle(self) -> RawHandle; } @@ -230,6 +231,7 @@ pub trait IntoRawSocket { /// However, transferring ownership is not strictly required. Use a /// `Into::into` implementation for an API which strictly /// transfers ownership. + #[must_use = "losing the raw socket may leak resources"] #[stable(feature = "into_raw_os", since = "1.4.0")] fn into_raw_socket(self) -> RawSocket; } From 84d84daf1735d8996cdaf3aea487051215cffdf3 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 10 Jul 2024 21:03:25 -0500 Subject: [PATCH 010/489] Explicitly ignore `into_raw_handle()` using `let _ =` in sys/pal/windows. --- library/std/src/sys/pal/windows/process.rs | 2 +- library/std/src/sys/pal/windows/stdio.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/pal/windows/process.rs index c62764696b86b..6b3b79149ce21 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/pal/windows/process.rs @@ -571,7 +571,7 @@ impl Stdio { Ok(io) => unsafe { let io = Handle::from_raw_handle(io); let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS); - io.into_raw_handle(); + let _ = io.into_raw_handle(); // Don't close the handle ret }, // If no stdio handle is available, then propagate the null value. diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs index 10aeeac07ea2e..88b3996466fff 100644 --- a/library/std/src/sys/pal/windows/stdio.rs +++ b/library/std/src/sys/pal/windows/stdio.rs @@ -101,7 +101,7 @@ fn write( unsafe { let handle = Handle::from_raw_handle(handle); let ret = handle.write(data); - handle.into_raw_handle(); // Don't close the handle + let _ = handle.into_raw_handle(); // Don't close the handle return ret; } } @@ -250,7 +250,7 @@ impl io::Read for Stdin { unsafe { let handle = Handle::from_raw_handle(handle); let ret = handle.read(buf); - handle.into_raw_handle(); // Don't close the handle + let _ = handle.into_raw_handle(); // Don't close the handle return ret; } } From 78f6386b623c64160fa3475605c7ebfb065f62bf Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Fri, 12 Jul 2024 10:51:32 +0200 Subject: [PATCH 011/489] Clarify comment in tests/fail/tree_borrows/reservedim_spurious_write.rs Co-authored-by: Ralf Jung --- .../tests/fail/tree_borrows/reservedim_spurious_write.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs index 6ae79be6cc7e8..73f227fee2fcb 100644 --- a/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs +++ b/src/tools/miri/tests/fail/tree_borrows/reservedim_spurious_write.rs @@ -41,8 +41,9 @@ macro_rules! synchronized { } fn main() { - // The conflict occurs one one single location but the example involves - // lazily initialized permissions. + // The conflict occurs on one single location but the example involves + // lazily initialized permissions. We will use `&mut Cell<()>` references + // to `data` to achieve this. let mut data = 0u8; let ptr = SendPtr(std::ptr::addr_of_mut!(data)); let barrier = Arc::new(Barrier::new(2)); From 1bafedbfe97e7b9d527a1eb6434f4b1fb4db2dd5 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 12 Jul 2024 12:26:23 +0200 Subject: [PATCH 012/489] Implement rough symbol interning infra --- src/tools/rust-analyzer/.typos.toml | 2 + src/tools/rust-analyzer/Cargo.lock | 7 + .../rust-analyzer/crates/intern/Cargo.toml | 3 +- .../rust-analyzer/crates/intern/src/lib.rs | 3 + .../rust-analyzer/crates/intern/src/symbol.rs | 293 ++++++++++++++++++ .../crates/intern/src/symbol/symbols.rs | 236 ++++++++++++++ 6 files changed, 543 insertions(+), 1 deletion(-) create mode 100644 src/tools/rust-analyzer/crates/intern/src/symbol.rs create mode 100644 src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs diff --git a/src/tools/rust-analyzer/.typos.toml b/src/tools/rust-analyzer/.typos.toml index c2e8b265218fb..e7e764ce03517 100644 --- a/src/tools/rust-analyzer/.typos.toml +++ b/src/tools/rust-analyzer/.typos.toml @@ -14,6 +14,8 @@ extend-ignore-re = [ "\\w*\\.{3,4}\\w*", '"flate2"', "raison d'être", + "inout", + "optin" ] [default.extend-words] diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index e9ebe26f42c2c..b165697724e05 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -835,6 +835,7 @@ dependencies = [ "dashmap", "hashbrown", "rustc-hash", + "sptr", "triomphe", ] @@ -1885,6 +1886,12 @@ dependencies = [ "vfs", ] +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + [[package]] name = "stable_deref_trait" version = "1.2.0" diff --git a/src/tools/rust-analyzer/crates/intern/Cargo.toml b/src/tools/rust-analyzer/crates/intern/Cargo.toml index 67b4164ce1fe0..c08ecb5c307b1 100644 --- a/src/tools/rust-analyzer/crates/intern/Cargo.toml +++ b/src/tools/rust-analyzer/crates/intern/Cargo.toml @@ -18,6 +18,7 @@ dashmap.workspace = true hashbrown.workspace = true rustc-hash.workspace = true triomphe.workspace = true +sptr = "0.3.2" [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/intern/src/lib.rs b/src/tools/rust-analyzer/crates/intern/src/lib.rs index 40d18b1cf8677..868d03caff557 100644 --- a/src/tools/rust-analyzer/crates/intern/src/lib.rs +++ b/src/tools/rust-analyzer/crates/intern/src/lib.rs @@ -20,6 +20,9 @@ type Guard = dashmap::RwLockWriteGuard< HashMap, SharedValue<()>, BuildHasherDefault>, >; +mod symbol; +pub use self::symbol::{symbols, Symbol}; + pub struct Interned { arc: Arc, } diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs new file mode 100644 index 0000000000000..a1cffd0662f8e --- /dev/null +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -0,0 +1,293 @@ +//! Attempt at flexible symbol interning, allowing to intern and free strings at runtime while also +//! supporting + +use std::{ + borrow::Borrow, + fmt, + hash::{BuildHasherDefault, Hash, Hasher}, + mem, + ptr::NonNull, + sync::OnceLock, +}; + +use dashmap::{DashMap, SharedValue}; +use hashbrown::{hash_map::RawEntryMut, HashMap}; +use rustc_hash::FxHasher; +use sptr::Strict; +use triomphe::Arc; + +pub mod symbols; + +// some asserts for layout compatibility +const _: () = assert!(std::mem::size_of::>() == std::mem::size_of::<&str>()); +const _: () = assert!(std::mem::align_of::>() == std::mem::align_of::<&str>()); + +const _: () = assert!(std::mem::size_of::>>() == std::mem::size_of::<&&str>()); +const _: () = assert!(std::mem::align_of::>>() == std::mem::align_of::<&&str>()); + +/// A pointer that points to a pointer to a `str`, it may be backed as a `&'static &'static str` or +/// `Arc>` but its size is that of a thin pointer. The active variant is encoded as a tag +/// in the LSB of the alignment niche. +#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] +struct TaggedArcPtr { + packed: NonNull<*const str>, +} + +unsafe impl Send for TaggedArcPtr {} +unsafe impl Sync for TaggedArcPtr {} + +impl TaggedArcPtr { + const BOOL_BITS: usize = true as usize; + + const fn non_arc(r: &&str) -> Self { + Self { + // SAFETY: The pointer is non-null as it is derived from a reference + // Ideally we would call out to `pack_arc` but for a `false` tag, unfortunately the + // packing stuff requires reading out the pointer to an integer which is not supported + // in const contexts, so here we make use of the fact that for the non-arc version the + // tag is false (0) and thus does not need touching the actual pointer value.ext) + packed: unsafe { + NonNull::new_unchecked((r as *const &str).cast::<*const str>().cast_mut()) + }, + } + } + + fn arc(arc: Arc>) -> Self { + Self { + packed: Self::pack_arc( + // Safety: `Arc::into_raw` always returns a non null pointer + unsafe { NonNull::new_unchecked(Arc::into_raw(arc).cast_mut().cast()) }, + ), + } + } + + /// Retrieves the tag. + #[inline] + pub(crate) fn try_as_arc_owned(self) -> Option>> { + // Unpack the tag from the alignment niche + let tag = Strict::addr(self.packed.as_ptr()) & Self::BOOL_BITS; + if tag != 0 { + // Safety: We checked that the tag is non-zero -> true, so we are pointing to the data offset of an `Arc` + Some(unsafe { Arc::from_raw(self.pointer().as_ptr().cast::>()) }) + } else { + None + } + } + + #[inline] + const fn pack_arc(ptr: NonNull<*const str>) -> NonNull<*const str> { + let packed_tag = true as usize; + + // can't use this strict provenance stuff here due to trait methods not being const + // unsafe { + // // Safety: The pointer is derived from a non-null + // NonNull::new_unchecked(Strict::map_addr(ptr.as_ptr(), |addr| { + // // Safety: + // // - The pointer is `NonNull` => it's address is `NonZero` + // // - `P::BITS` least significant bits are always zero (`Pointer` contract) + // // - `T::BITS <= P::BITS` (from `Self::ASSERTION`) + // // + // // Thus `addr >> T::BITS` is guaranteed to be non-zero. + // // + // // `{non_zero} | packed_tag` can't make the value zero. + + // (addr >> Self::BOOL_BITS) | packed_tag + // })) + // } + // so what follows is roughly what the above looks like but inlined + + let self_addr = unsafe { core::mem::transmute::<*const _, usize>(ptr.as_ptr()) }; + let addr = self_addr | packed_tag; + let dest_addr = addr as isize; + let offset = dest_addr.wrapping_sub(self_addr as isize); + + // SAFETY: The resulting pointer is guaranteed to be NonNull as we only modify the niche bytes + unsafe { NonNull::new_unchecked(ptr.as_ptr().cast::().wrapping_offset(offset).cast()) } + } + + #[inline] + pub(crate) fn pointer(self) -> NonNull<*const str> { + // SAFETY: The resulting pointer is guaranteed to be NonNull as we only modify the niche bytes + unsafe { + NonNull::new_unchecked(Strict::map_addr(self.packed.as_ptr(), |addr| { + addr & !Self::BOOL_BITS + })) + } + } + + #[inline] + pub(crate) fn as_str(&self) -> &str { + // SAFETY: We always point to a pointer to a str no matter what variant is active + unsafe { *self.pointer().as_ptr().cast::<&str>() } + } +} + +#[derive(PartialEq, Eq, Hash, Clone, Debug)] +pub struct Symbol { + repr: TaggedArcPtr, +} +const _: () = assert!(std::mem::size_of::() == std::mem::size_of::>()); +const _: () = assert!(std::mem::align_of::() == std::mem::align_of::>()); + +static MAP: OnceLock>> = OnceLock::new(); + +impl Symbol { + pub fn intern(s: &str) -> Self { + let (mut shard, hash) = Self::select_shard(s); + // Atomically, + // - check if `obj` is already in the map + // - if so, copy out its entry, conditionally bumping the backing Arc and return it + // - if not, put it into a box and then into an Arc, insert it, bump the ref-count and return the copy + // This needs to be atomic (locking the shard) to avoid races with other thread, which could + // insert the same object between us looking it up and inserting it. + match shard.raw_entry_mut().from_key_hashed_nocheck(hash, s) { + RawEntryMut::Occupied(occ) => Self { repr: increase_arc_refcount(occ.key().0) }, + RawEntryMut::Vacant(vac) => Self { + repr: increase_arc_refcount( + vac.insert_hashed_nocheck( + hash, + SymbolProxy(TaggedArcPtr::arc(Arc::new(Box::::from(s)))), + SharedValue::new(()), + ) + .0 + .0, + ), + }, + } + } + + pub fn as_str(&self) -> &str { + self.repr.as_str() + } + + #[inline] + fn select_shard( + s: &str, + ) -> ( + dashmap::RwLockWriteGuard< + 'static, + HashMap, BuildHasherDefault>, + >, + u64, + ) { + let storage = MAP.get_or_init(symbols::prefill); + let hash = { + let mut hasher = std::hash::BuildHasher::build_hasher(storage.hasher()); + s.hash(&mut hasher); + hasher.finish() + }; + let shard_idx = storage.determine_shard(hash as usize); + let shard = &storage.shards()[shard_idx]; + (shard.write(), hash) + } + + #[cold] + fn drop_slow(arc: &Arc>) { + let (mut shard, hash) = Self::select_shard(arc); + + if Arc::count(arc) != 2 { + // Another thread has interned another copy + return; + } + + match shard.raw_entry_mut().from_key_hashed_nocheck::(hash, arc.as_ref()) { + RawEntryMut::Occupied(occ) => occ.remove_entry(), + RawEntryMut::Vacant(_) => unreachable!(), + } + .0 + .0 + .try_as_arc_owned() + .unwrap(); + + // Shrink the backing storage if the shard is less than 50% occupied. + if shard.len() * 2 < shard.capacity() { + shard.shrink_to_fit(); + } + } +} + +impl Drop for Symbol { + #[inline] + fn drop(&mut self) { + let Some(arc) = self.repr.try_as_arc_owned() else { + return; + }; + // When the last `Ref` is dropped, remove the object from the global map. + if Arc::count(&arc) == 2 { + // Only `self` and the global map point to the object. + + Self::drop_slow(&arc); + } + // decrement the ref count + drop(arc); + } +} + +fn increase_arc_refcount(repr: TaggedArcPtr) -> TaggedArcPtr { + let Some(arc) = repr.try_as_arc_owned() else { + return repr; + }; + // increase the ref count + mem::forget(arc.clone()); + mem::forget(arc); + repr +} + +impl fmt::Display for Symbol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_str().fmt(f) + } +} + +// only exists so we can use `from_key_hashed_nocheck` with a &str +#[derive(Debug, PartialEq, Eq)] +struct SymbolProxy(TaggedArcPtr); + +impl Hash for SymbolProxy { + fn hash(&self, state: &mut H) { + self.0.as_str().hash(state); + } +} + +impl Borrow for SymbolProxy { + fn borrow(&self) -> &str { + self.0.as_str() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn smoke_test() { + Symbol::intern("isize"); + let base_len = MAP.get().unwrap().len(); + let hello = Symbol::intern("hello"); + let world = Symbol::intern("world"); + let bang = Symbol::intern("!"); + let q = Symbol::intern("?"); + assert_eq!(MAP.get().unwrap().len(), base_len + 4); + let bang2 = Symbol::intern("!"); + assert_eq!(MAP.get().unwrap().len(), base_len + 4); + drop(bang2); + assert_eq!(MAP.get().unwrap().len(), base_len + 4); + drop(q); + assert_eq!(MAP.get().unwrap().len(), base_len + 3); + let default = Symbol::intern("default"); + assert_eq!(MAP.get().unwrap().len(), base_len + 3); + assert_eq!( + "hello default world!", + format!("{} {} {}{}", hello.as_str(), default.as_str(), world.as_str(), bang.as_str()) + ); + drop(default); + assert_eq!( + "hello world!", + format!("{} {}{}", hello.as_str(), world.as_str(), bang.as_str()) + ); + drop(hello); + drop(world); + drop(bang); + assert_eq!(MAP.get().unwrap().len(), base_len); + } +} diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs new file mode 100644 index 0000000000000..d2ca4401b66e9 --- /dev/null +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -0,0 +1,236 @@ +#![allow(non_upper_case_globals)] + +use std::hash::{BuildHasherDefault, Hash as _, Hasher as _}; + +use dashmap::{DashMap, SharedValue}; +use rustc_hash::FxHasher; + +use crate::{ + symbol::{SymbolProxy, TaggedArcPtr}, + Symbol, +}; +macro_rules! define_symbols { + ($($name:ident),* $(,)?) => { + $( + pub const $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) }; + )* + + + pub(super) fn prefill() -> DashMap> { + let mut dashmap_ = >>::with_hasher(BuildHasherDefault::default()); + + let hash_thing_ = |hasher_: &BuildHasherDefault, it_: &SymbolProxy| { + let mut hasher_ = std::hash::BuildHasher::build_hasher(hasher_); + it_.hash(&mut hasher_); + hasher_.finish() + }; + { + $( + + let proxy_ = SymbolProxy($name.repr); + let hash_ = hash_thing_(dashmap_.hasher(), &proxy_); + let shard_idx_ = dashmap_.determine_shard(hash_ as usize); + dashmap_.shards_mut()[shard_idx_].get_mut().raw_entry_mut().from_hash(hash_, |k| k == &proxy_).insert(proxy_, SharedValue::new(())); + )* + } + dashmap_ + } + }; +} +define_symbols! { + add_assign, + add, + alloc, + as_str, + asm, + assert, + bench, + bitand_assign, + bitand, + bitor_assign, + bitor, + bitxor_assign, + bitxor, + bool, + Box, + boxed, + branch, + call_mut, + call_once, + call, + Center, + cfg_accessible, + cfg_attr, + cfg_eval, + cfg, + char, + Clone, + column, + compile_error, + concat_bytes, + concat_idents, + concat, + const_format_args, + Copy, + core_panic, + core, + crate_type, + Debug, + default, + Default, + deref_mut, + deref, + derive_const, + derive, + div_assign, + div, + doc, + drop, + env, + eq, + Eq, + f128, + f16, + f32, + f64, + feature, + file, + filter_map, + fmt, + fn_mut, + fn_once, + format_args_nl, + format_args, + format, + from_usize, + future_trait, + future, + Future, + ge, + global_allocator, + global_asm, + gt, + Hash, + i128, + i16, + i32, + i64, + i8, + Implied, + include_bytes, + include_str, + include, + index_mut, + index, + Index, + into_future, + IntoFuture, + IntoIter, + IntoIterator, + is_empty, + Is, + isize, + Item, + iter_mut, + iter, + Iterator, + le, + Left, + len, + line, + llvm_asm, + log_syntax, + lt, + macro_rules, + module_path, + mul_assign, + mul, + ne, + neg, + Neg, + new_binary, + new_debug, + new_display, + new_lower_exp, + new_lower_hex, + new_octal, + new_pointer, + new_upper_exp, + new_upper_hex, + new_v1_formatted, + new, + next, + no_core, + no_std, + none, + None, + not, + Not, + Ok, + ops, + option_env, + option, + Option, + Ord, + Output, + owned_box, + panic_2015, + panic_2021, + Param, + partial_ord, + PartialEq, + PartialOrd, + pieces, + poll, + prelude, + quote, + r#fn, + Range, + RangeFrom, + RangeFull, + RangeInclusive, + RangeTo, + RangeToInclusive, + recursion_limit, + register_attr, + register_tool, + rem_assign, + rem, + result, + Result, + Right, + rust_2015, + rust_2018, + rust_2021, + rust_2024, + shl_assign, + shl, + shr_assign, + shr, + std_panic, + std, + str, + string, + String, + stringify, + sub_assign, + sub, + Target, + test_case, + test, + trace_macros, + Try, + u128, + u16, + u32, + u64, + u8, + Unknown, + unreachable_2015, + unreachable_2021, + unreachable, + unsafe_cell, + usize, + v1, + va_list +} From e805055b0ea7595fd7400b7583fa0b6ff11264bf Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 12 Jul 2024 14:11:28 +0200 Subject: [PATCH 013/489] Add missing docs --- src/tools/rust-analyzer/crates/intern/src/symbol.rs | 2 +- src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index a1cffd0662f8e..290657a3d3627 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -39,7 +39,7 @@ unsafe impl Sync for TaggedArcPtr {} impl TaggedArcPtr { const BOOL_BITS: usize = true as usize; - const fn non_arc(r: &&str) -> Self { + const fn non_arc(r: &'static &'static str) -> Self { Self { // SAFETY: The pointer is non-null as it is derived from a reference // Ideally we would call out to `pack_arc` but for a `false` tag, unfortunately the diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index d2ca4401b66e9..a1cf6e0941466 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -1,3 +1,4 @@ +//! Module defining all known symbols required by the rest of rust-analyzer. #![allow(non_upper_case_globals)] use std::hash::{BuildHasherDefault, Hash as _, Hasher as _}; From 602da3fadd919c41378b4b1b694ae1c391ace6d8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 12 Jul 2024 15:57:54 +0200 Subject: [PATCH 014/489] Use Symbol in Name --- .../rust-analyzer/crates/hir-def/src/attr.rs | 9 +- .../crates/hir-def/src/body/lower.rs | 114 ++--- .../crates/hir-def/src/builtin_type.rs | 85 ++-- .../rust-analyzer/crates/hir-def/src/data.rs | 4 +- .../rust-analyzer/crates/hir-def/src/db.rs | 8 +- .../crates/hir-def/src/expander.rs | 6 + .../crates/hir-def/src/find_path.rs | 25 +- .../crates/hir-def/src/hir/format_args.rs | 6 +- .../crates/hir-def/src/item_tree/lower.rs | 11 +- .../crates/hir-def/src/lang_item.rs | 13 +- .../rust-analyzer/crates/hir-def/src/lib.rs | 2 +- .../crates/hir-def/src/nameres/collector.rs | 90 ++-- .../crates/hir-def/src/path/lower.rs | 10 +- .../crates/hir-def/src/resolver.rs | 25 +- .../crates/hir-expand/src/attrs.rs | 91 ++-- .../hir-expand/src/builtin_attr_macro.rs | 3 +- .../hir-expand/src/builtin_derive_macro.rs | 3 +- .../crates/hir-expand/src/builtin_fn_macro.rs | 15 +- .../rust-analyzer/crates/hir-expand/src/db.rs | 9 + .../crates/hir-expand/src/declarative.rs | 7 +- .../crates/hir-expand/src/mod_path.rs | 30 +- .../crates/hir-expand/src/name.rs | 391 ++++-------------- .../crates/hir-expand/src/quote.rs | 2 + .../crates/hir-ty/src/autoderef.rs | 6 +- .../crates/hir-ty/src/chalk_db.rs | 9 +- .../hir-ty/src/diagnostics/decl_check.rs | 2 +- .../crates/hir-ty/src/diagnostics/expr.rs | 4 +- .../crates/hir-ty/src/display.rs | 5 +- .../rust-analyzer/crates/hir-ty/src/infer.rs | 5 +- .../crates/hir-ty/src/infer/closure.rs | 13 +- .../crates/hir-ty/src/infer/expr.rs | 15 +- .../crates/hir-ty/src/infer/mutability.rs | 15 +- .../crates/hir-ty/src/infer/path.rs | 3 +- .../crates/hir-ty/src/infer/unify.rs | 6 +- .../crates/hir-ty/src/lang_items.rs | 54 +-- .../rust-analyzer/crates/hir-ty/src/lib.rs | 7 +- .../crates/hir-ty/src/mir/eval.rs | 37 +- .../crates/hir-ty/src/mir/eval/shim.rs | 23 +- .../crates/hir-ty/src/mir/lower.rs | 6 +- .../crates/hir-ty/src/mir/lower/as_place.rs | 13 +- .../rust-analyzer/crates/hir-ty/src/traits.rs | 9 +- .../rust-analyzer/crates/hir/src/attrs.rs | 3 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 15 +- .../crates/hir/src/source_analyzer.rs | 35 +- .../rust-analyzer/crates/hir/src/symbols.rs | 2 +- .../ide-assists/src/handlers/bool_to_enum.rs | 2 +- .../src/handlers/convert_bool_then.rs | 4 +- .../handlers/convert_iter_for_each_to_for.rs | 8 +- .../handlers/destructure_struct_binding.rs | 4 +- .../handlers/generate_is_empty_from_len.rs | 6 +- .../ide-assists/src/handlers/inline_call.rs | 7 +- .../src/handlers/replace_method_eager_lazy.rs | 4 +- .../crates/ide-assists/src/utils.rs | 4 +- .../crates/ide-completion/src/completions.rs | 4 +- .../src/completions/attribute/macro_use.rs | 2 +- .../ide-completion/src/completions/dot.rs | 9 +- .../ide-completion/src/completions/expr.rs | 11 +- .../src/completions/lifetime.rs | 4 +- .../ide-completion/src/completions/use_.rs | 5 +- .../ide-completion/src/context/analysis.rs | 6 +- .../crates/ide-completion/src/render.rs | 6 +- .../ide-completion/src/render/function.rs | 10 +- .../rust-analyzer/crates/ide-db/src/defs.rs | 2 +- .../ide-db/src/imports/import_assets.rs | 6 +- .../crates/ide-db/src/path_transform.rs | 2 +- .../src/handlers/missing_fields.rs | 4 +- .../src/handlers/unresolved_field.rs | 2 +- .../crates/ide/src/goto_definition.rs | 2 +- .../crates/ide/src/inlay_hints.rs | 4 +- .../ide/src/inlay_hints/generic_param.rs | 2 +- .../crates/ide/src/test_explorer.rs | 11 +- .../crates/ide/src/view_memory_layout.rs | 15 +- .../rust-analyzer/crates/intern/src/lib.rs | 2 +- .../rust-analyzer/crates/intern/src/symbol.rs | 2 +- .../crates/intern/src/symbol/symbols.rs | 121 +++++- 75 files changed, 756 insertions(+), 761 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 184dab8367c16..a1ffb8c0a7596 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -9,6 +9,7 @@ use hir_expand::{ attrs::{collect_attrs, Attr, AttrId, RawAttrs}, HirFileId, InFile, }; +use intern::sym; use la_arena::{ArenaMap, Idx, RawIdx}; use mbe::DelimiterKind; use syntax::{ @@ -199,8 +200,8 @@ impl Attrs { .segments() .iter() .rev() - .zip(["core", "prelude", "v1", "test"].iter().rev()) - .all(|it| it.0.as_str() == Some(it.1)) + .zip([sym::core, sym::prelude, sym::v1, sym::test].iter().rev()) + .all(|it| it.0 == it.1) }) } @@ -568,6 +569,10 @@ impl<'attr> AttrQuery<'attr> { self.attrs().find_map(|attr| attr.string_value()) } + pub fn string_value_with_span(self) -> Option<(&'attr str, span::Span)> { + self.attrs().find_map(|attr| attr.string_value_with_span()) + } + pub fn string_value_unescape(self) -> Option> { self.attrs().find_map(|attr| attr.string_value_unescape()) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index be7068c807a5f..83ba8f41931e2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -5,10 +5,10 @@ use std::mem; use base_db::CrateId; use hir_expand::{ - name::{name, AsName, Name}, + name::{AsName, Name}, ExpandError, InFile, }; -use intern::Interned; +use intern::{sym, Interned}; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::AstIdMap; @@ -187,8 +187,10 @@ impl ExprCollector<'_> { { let is_mutable = self_param.mut_token().is_some() && self_param.amp_token().is_none(); - let binding_id: la_arena::Idx = - self.alloc_binding(name![self], BindingAnnotation::new(is_mutable, false)); + let binding_id: la_arena::Idx = self.alloc_binding( + Name::new_symbol_root(sym::self_), + BindingAnnotation::new(is_mutable, false), + ); self.body.self_param = Some(binding_id); self.source_map.self_param = Some(self.expander.in_file(AstPtr::new(&self_param))); } @@ -1588,18 +1590,22 @@ impl ExprCollector<'_> { }); let mut mappings = vec![]; let fmt = match template.and_then(|it| self.expand_macros_to_string(it)) { - Some((s, is_direct_literal)) => format_args::parse( - &s, - fmt_snippet, - args, - is_direct_literal, - |name| self.alloc_expr_desugared(Expr::Path(Path::from(name))), - |name, span| { - if let Some(span) = span { - mappings.push((span, name)) - } - }, - ), + Some((s, is_direct_literal)) => { + let call_ctx = self.expander.syntax_context(); + format_args::parse( + &s, + fmt_snippet, + args, + is_direct_literal, + |name| self.alloc_expr_desugared(Expr::Path(Path::from(name))), + |name, span| { + if let Some(span) = span { + mappings.push((span, name)) + } + }, + call_ctx, + ) + } None => FormatArgs { template: Default::default(), arguments: args.finish(), @@ -1723,14 +1729,18 @@ impl ExprCollector<'_> { // unsafe { ::core::fmt::UnsafeArg::new() } // ) - let Some(new_v1_formatted) = - LangItem::FormatArguments.ty_rel_path(self.db, self.krate, name![new_v1_formatted]) - else { + let Some(new_v1_formatted) = LangItem::FormatArguments.ty_rel_path( + self.db, + self.krate, + Name::new_symbol_root(sym::new_v1_formatted), + ) else { return self.missing_expr(); }; - let Some(unsafe_arg_new) = - LangItem::FormatUnsafeArg.ty_rel_path(self.db, self.krate, name![new]) - else { + let Some(unsafe_arg_new) = LangItem::FormatUnsafeArg.ty_rel_path( + self.db, + self.krate, + Name::new_symbol_root(sym::new), + ) else { return self.missing_expr(); }; let new_v1_formatted = self.alloc_expr_desugared(Expr::Path(new_v1_formatted)); @@ -1812,10 +1822,10 @@ impl ExprCollector<'_> { self.db, self.krate, match alignment { - Some(FormatAlignment::Left) => name![Left], - Some(FormatAlignment::Right) => name![Right], - Some(FormatAlignment::Center) => name![Center], - None => name![Unknown], + Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left), + Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right), + Some(FormatAlignment::Center) => Name::new_symbol_root(sym::Center), + None => Name::new_symbol_root(sym::Unknown), }, ); match align { @@ -1838,8 +1848,11 @@ impl ExprCollector<'_> { let width = self.make_count(width, argmap); let format_placeholder_new = { - let format_placeholder_new = - LangItem::FormatPlaceholder.ty_rel_path(self.db, self.krate, name![new]); + let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path( + self.db, + self.krate, + Name::new_symbol_root(sym::new), + ); match format_placeholder_new { Some(path) => self.alloc_expr_desugared(Expr::Path(path)), None => self.missing_expr(), @@ -1883,11 +1896,14 @@ impl ExprCollector<'_> { *n as u128, Some(BuiltinUint::Usize), ))); - let count_is = - match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Is]) { - Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)), - None => self.missing_expr(), - }; + let count_is = match LangItem::FormatCount.ty_rel_path( + self.db, + self.krate, + Name::new_symbol_root(sym::Is), + ) { + Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)), + None => self.missing_expr(), + }; self.alloc_expr_desugared(Expr::Call { callee: count_is, args: Box::new([args]), @@ -1905,7 +1921,7 @@ impl ExprCollector<'_> { let count_param = match LangItem::FormatCount.ty_rel_path( self.db, self.krate, - name![Param], + Name::new_symbol_root(sym::Param), ) { Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)), None => self.missing_expr(), @@ -1921,7 +1937,11 @@ impl ExprCollector<'_> { self.missing_expr() } } - None => match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Implied]) { + None => match LangItem::FormatCount.ty_rel_path( + self.db, + self.krate, + Name::new_symbol_root(sym::Implied), + ) { Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)), None => self.missing_expr(), }, @@ -1942,18 +1962,18 @@ impl ExprCollector<'_> { let new_fn = match LangItem::FormatArgument.ty_rel_path( self.db, self.krate, - match ty { - Format(Display) => name![new_display], - Format(Debug) => name![new_debug], - Format(LowerExp) => name![new_lower_exp], - Format(UpperExp) => name![new_upper_exp], - Format(Octal) => name![new_octal], - Format(Pointer) => name![new_pointer], - Format(Binary) => name![new_binary], - Format(LowerHex) => name![new_lower_hex], - Format(UpperHex) => name![new_upper_hex], - Usize => name![from_usize], - }, + Name::new_symbol_root(match ty { + Format(Display) => sym::new_display, + Format(Debug) => sym::new_debug, + Format(LowerExp) => sym::new_lower_exp, + Format(UpperExp) => sym::new_upper_exp, + Format(Octal) => sym::new_octal, + Format(Pointer) => sym::new_pointer, + Format(Binary) => sym::new_binary, + Format(LowerHex) => sym::new_lower_hex, + Format(UpperHex) => sym::new_upper_hex, + Usize => sym::from_usize, + }), ) { Some(new_fn) => self.alloc_expr_desugared(Expr::Path(new_fn)), None => self.missing_expr(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs b/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs index f9e55559dab43..2243f514fe102 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs @@ -5,7 +5,8 @@ use std::fmt; -use hir_expand::name::{name, AsName, Name}; +use hir_expand::name::{AsName, Name}; +use intern::sym; /// Different signed int types. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum BuiltinInt { @@ -49,28 +50,28 @@ pub enum BuiltinType { impl BuiltinType { #[rustfmt::skip] pub const ALL: &'static [(Name, BuiltinType)] = &[ - (name![char], BuiltinType::Char), - (name![bool], BuiltinType::Bool), - (name![str], BuiltinType::Str), - - (name![isize], BuiltinType::Int(BuiltinInt::Isize)), - (name![i8], BuiltinType::Int(BuiltinInt::I8)), - (name![i16], BuiltinType::Int(BuiltinInt::I16)), - (name![i32], BuiltinType::Int(BuiltinInt::I32)), - (name![i64], BuiltinType::Int(BuiltinInt::I64)), - (name![i128], BuiltinType::Int(BuiltinInt::I128)), - - (name![usize], BuiltinType::Uint(BuiltinUint::Usize)), - (name![u8], BuiltinType::Uint(BuiltinUint::U8)), - (name![u16], BuiltinType::Uint(BuiltinUint::U16)), - (name![u32], BuiltinType::Uint(BuiltinUint::U32)), - (name![u64], BuiltinType::Uint(BuiltinUint::U64)), - (name![u128], BuiltinType::Uint(BuiltinUint::U128)), - - (name![f16], BuiltinType::Float(BuiltinFloat::F16)), - (name![f32], BuiltinType::Float(BuiltinFloat::F32)), - (name![f64], BuiltinType::Float(BuiltinFloat::F64)), - (name![f128], BuiltinType::Float(BuiltinFloat::F128)), + (Name::new_symbol_root(sym::char), BuiltinType::Char), + (Name::new_symbol_root(sym::bool), BuiltinType::Bool), + (Name::new_symbol_root(sym::str), BuiltinType::Str), + + (Name::new_symbol_root(sym::isize), BuiltinType::Int(BuiltinInt::Isize)), + (Name::new_symbol_root(sym::i8), BuiltinType::Int(BuiltinInt::I8)), + (Name::new_symbol_root(sym::i16), BuiltinType::Int(BuiltinInt::I16)), + (Name::new_symbol_root(sym::i32), BuiltinType::Int(BuiltinInt::I32)), + (Name::new_symbol_root(sym::i64), BuiltinType::Int(BuiltinInt::I64)), + (Name::new_symbol_root(sym::i128), BuiltinType::Int(BuiltinInt::I128)), + + (Name::new_symbol_root(sym::usize), BuiltinType::Uint(BuiltinUint::Usize)), + (Name::new_symbol_root(sym::u8), BuiltinType::Uint(BuiltinUint::U8)), + (Name::new_symbol_root(sym::u16), BuiltinType::Uint(BuiltinUint::U16)), + (Name::new_symbol_root(sym::u32), BuiltinType::Uint(BuiltinUint::U32)), + (Name::new_symbol_root(sym::u64), BuiltinType::Uint(BuiltinUint::U64)), + (Name::new_symbol_root(sym::u128), BuiltinType::Uint(BuiltinUint::U128)), + + (Name::new_symbol_root(sym::f16), BuiltinType::Float(BuiltinFloat::F16)), + (Name::new_symbol_root(sym::f32), BuiltinType::Float(BuiltinFloat::F32)), + (Name::new_symbol_root(sym::f64), BuiltinType::Float(BuiltinFloat::F64)), + (Name::new_symbol_root(sym::f128), BuiltinType::Float(BuiltinFloat::F128)), ]; pub fn by_name(name: &Name) -> Option { @@ -81,30 +82,30 @@ impl BuiltinType { impl AsName for BuiltinType { fn as_name(&self) -> Name { match self { - BuiltinType::Char => name![char], - BuiltinType::Bool => name![bool], - BuiltinType::Str => name![str], + BuiltinType::Char => Name::new_symbol_root(sym::char), + BuiltinType::Bool => Name::new_symbol_root(sym::bool), + BuiltinType::Str => Name::new_symbol_root(sym::str), BuiltinType::Int(it) => match it { - BuiltinInt::Isize => name![isize], - BuiltinInt::I8 => name![i8], - BuiltinInt::I16 => name![i16], - BuiltinInt::I32 => name![i32], - BuiltinInt::I64 => name![i64], - BuiltinInt::I128 => name![i128], + BuiltinInt::Isize => Name::new_symbol_root(sym::isize), + BuiltinInt::I8 => Name::new_symbol_root(sym::i8), + BuiltinInt::I16 => Name::new_symbol_root(sym::i16), + BuiltinInt::I32 => Name::new_symbol_root(sym::i32), + BuiltinInt::I64 => Name::new_symbol_root(sym::i64), + BuiltinInt::I128 => Name::new_symbol_root(sym::i128), }, BuiltinType::Uint(it) => match it { - BuiltinUint::Usize => name![usize], - BuiltinUint::U8 => name![u8], - BuiltinUint::U16 => name![u16], - BuiltinUint::U32 => name![u32], - BuiltinUint::U64 => name![u64], - BuiltinUint::U128 => name![u128], + BuiltinUint::Usize => Name::new_symbol_root(sym::usize), + BuiltinUint::U8 => Name::new_symbol_root(sym::u8), + BuiltinUint::U16 => Name::new_symbol_root(sym::u16), + BuiltinUint::U32 => Name::new_symbol_root(sym::u32), + BuiltinUint::U64 => Name::new_symbol_root(sym::u64), + BuiltinUint::U128 => Name::new_symbol_root(sym::u128), }, BuiltinType::Float(it) => match it { - BuiltinFloat::F16 => name![f16], - BuiltinFloat::F32 => name![f32], - BuiltinFloat::F64 => name![f64], - BuiltinFloat::F128 => name![f128], + BuiltinFloat::F16 => Name::new_symbol_root(sym::f16), + BuiltinFloat::F32 => Name::new_symbol_root(sym::f32), + BuiltinFloat::F64 => Name::new_symbol_root(sym::f64), + BuiltinFloat::F128 => Name::new_symbol_root(sym::f128), }, } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index 55043fdc4b054..f60a433c4dafe 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -6,7 +6,7 @@ use base_db::CrateId; use hir_expand::{ name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, }; -use intern::Interned; +use intern::{sym, Interned}; use smallvec::SmallVec; use syntax::{ast, Parse}; use triomphe::Arc; @@ -485,7 +485,7 @@ impl ExternCrateDeclData { let name = extern_crate.name.clone(); let krate = loc.container.krate(); - let crate_id = if name == hir_expand::name![self] { + let crate_id = if name == sym::self_ { Some(krate) } else { db.crate_def_map(krate) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 0eb9e7d30b251..0a14904f0bceb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -2,7 +2,7 @@ use base_db::{salsa, CrateId, FileId, SourceDatabase, Upcast}; use either::Either; use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId}; -use intern::Interned; +use intern::{sym, Interned}; use la_arena::ArenaMap; use span::MacroCallId; use syntax::{ast, AstPtr}; @@ -261,9 +261,9 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool { let item_tree = db.file_item_tree(file.into()); let attrs = item_tree.raw_attrs(AttrOwner::TopLevel); for attr in &**attrs { - match attr.path().as_ident().and_then(|id| id.as_text()) { - Some(ident) if ident == "no_std" => return true, - Some(ident) if ident == "cfg_attr" => {} + match attr.path().as_ident() { + Some(ident) if *ident == sym::no_std => return true, + Some(ident) if *ident == sym::cfg_attr => {} _ => continue, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs index dbf8e6b225c2a..d1640ad7e5b7b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs @@ -10,6 +10,7 @@ use hir_expand::{ InFile, MacroCallId, }; use limit::Limit; +use span::SyntaxContextId; use syntax::{ast, Parse}; use triomphe::Arc; @@ -52,6 +53,11 @@ impl Expander { self.module.krate } + pub fn syntax_context(&self) -> SyntaxContextId { + // FIXME: + SyntaxContextId::ROOT + } + pub fn enter_expand( &mut self, db: &dyn DefDatabase, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index 9a3c0495414ca..e32add93c5526 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -3,9 +3,10 @@ use std::{cell::Cell, cmp::Ordering, iter}; use hir_expand::{ - name::{known, AsName, Name}, + name::{AsName, Name}, Lookup, }; +use intern::{sym, Symbol}; use rustc_hash::FxHashSet; use crate::{ @@ -414,13 +415,13 @@ fn select_best_path( (Unstable, Stable) => return new_path, _ => {} } - const STD_CRATES: [Name; 3] = [known::std, known::core, known::alloc]; + const STD_CRATES: [Symbol; 3] = [sym::std, sym::core, sym::alloc]; let choose = |new: (ModPath, _), old: (ModPath, _)| { let (new_path, _) = &new; let (old_path, _) = &old; - let new_has_prelude = new_path.segments().iter().any(|seg| seg == &known::prelude); - let old_has_prelude = old_path.segments().iter().any(|seg| seg == &known::prelude); + let new_has_prelude = new_path.segments().iter().any(|seg| *seg == sym::prelude); + let old_has_prelude = old_path.segments().iter().any(|seg| *seg == sym::prelude); match (new_has_prelude, old_has_prelude, cfg.prefer_prelude) { (true, false, true) | (false, true, false) => new, (true, false, false) | (false, true, true) => old, @@ -441,18 +442,20 @@ fn select_best_path( }; match (old_path.0.segments().first(), new_path.0.segments().first()) { - (Some(old), Some(new)) if STD_CRATES.contains(old) && STD_CRATES.contains(new) => { + (Some(old), Some(new)) + if STD_CRATES.contains(old.symbol()) && STD_CRATES.contains(new.symbol()) => + { let rank = match cfg.prefer_no_std { false => |name: &Name| match name { - name if name == &known::core => 0, - name if name == &known::alloc => 1, - name if name == &known::std => 2, + name if *name == sym::core => 0, + name if *name == sym::alloc => 1, + name if *name == sym::std => 2, _ => unreachable!(), }, true => |name: &Name| match name { - name if name == &known::core => 2, - name if name == &known::alloc => 1, - name if name == &known::std => 0, + name if *name == sym::core => 2, + name if *name == sym::alloc => 1, + name if *name == sym::std => 0, _ => unreachable!(), }, }; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index de0fa982c86a2..d6dd5df37366a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -3,10 +3,11 @@ use std::mem; use hir_expand::name::Name; use rustc_parse_format as parse; +use span::SyntaxContextId; use stdx::TupleExt; use syntax::{ ast::{self, IsString}, - SmolStr, TextRange, TextSize, + TextRange, TextSize, }; use crate::hir::ExprId; @@ -174,6 +175,7 @@ pub(crate) fn parse( is_direct_literal: bool, mut synth: impl FnMut(Name) -> ExprId, mut record_usage: impl FnMut(Name, Option), + call_ctx: SyntaxContextId, ) -> FormatArgs { let Ok(text) = s.value() else { return FormatArgs { @@ -248,7 +250,7 @@ pub(crate) fn parse( } } ArgRef::Name(name, span) => { - let name = Name::new_text_dont_use(SmolStr::new(name)); + let name = Name::new(name, call_ctx); if let Some((index, _)) = args.by_name(&name) { record_usage(name, span); // Name found in `args`, so we resolve it to its index. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 199b8daa37efe..496686b4f943c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -2,7 +2,8 @@ use std::collections::hash_map::Entry; -use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId}; +use hir_expand::{mod_path::path, name::AsName, span_map::SpanMapRef, HirFileId}; +use intern::sym; use la_arena::Arena; use rustc_hash::FxHashMap; use span::{AstIdMap, SyntaxContextId}; @@ -323,7 +324,7 @@ impl<'a> Ctx<'a> { let self_type = match self_param.ty() { Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), None => { - let self_type = TypeRef::Path(name![Self].into()); + let self_type = TypeRef::Path(Name::new_symbol_root(sym::Self_).into()); match self_param.kind() { ast::SelfParamKind::Owned => self_type, ast::SelfParamKind::Ref => TypeRef::Reference( @@ -669,7 +670,7 @@ impl<'a> Ctx<'a> { // Traits and trait aliases get the Self type as an implicit first type parameter. generics.type_or_consts.alloc( TypeParamData { - name: Some(name![Self]), + name: Some(Name::new_symbol_root(sym::Self_)), default: None, provenance: TypeParamProvenance::TraitSelf, } @@ -680,7 +681,7 @@ impl<'a> Ctx<'a> { generics.fill_bounds( &self.body_ctx, bounds, - Either::Left(TypeRef::Path(name![Self].into())), + Either::Left(TypeRef::Path(Name::new_symbol_root(sym::Self_).into())), ); } @@ -745,7 +746,7 @@ fn desugar_future_path(orig: TypeRef) -> Path { let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments().len() - 1).collect(); let binding = AssociatedTypeBinding { - name: name![Output], + name: Name::new_symbol_root(sym::Output), args: None, type_ref: Some(orig), bounds: Box::default(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 6d7836d5ae899..4d17650285f40 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -3,6 +3,7 @@ //! This attribute to tell the compiler about semi built-in std library //! features, such as Fn family of traits. use hir_expand::name::Name; +use intern::{sym, Symbol}; use rustc_hash::FxHashMap; use syntax::SmolStr; use triomphe::Arc; @@ -267,6 +268,14 @@ macro_rules! language_item_table { _ => None, } } + + /// Opposite of [`LangItem::name`] + pub fn from_symbol(sym: Symbol) -> Option { + match sym { + $(sym if sym == $module::$name => Some(LangItem::$variant), )* + _ => None, + } + } } } } @@ -274,7 +283,7 @@ macro_rules! language_item_table { impl LangItem { /// Opposite of [`LangItem::name`] pub fn from_name(name: &hir_expand::name::Name) -> Option { - Self::from_str(name.as_str()?) + Self::from_str(name.as_str()) } pub fn path(&self, db: &dyn DefDatabase, start_crate: CrateId) -> Option { @@ -360,7 +369,7 @@ language_item_table! { DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None; Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None; - Fn, kw::fn, fn_trait, Target::Trait, GenericRequirement::Exact(1); + Fn, sym::fn_, fn_trait, Target::Trait, GenericRequirement::Exact(1); FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index fc026a14d442f..a33e681cb5a76 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -862,7 +862,7 @@ impl GeneralConstId { .const_data(const_id) .name .as_ref() - .and_then(|it| it.as_str()) + .map(|it| it.as_str()) .unwrap_or("_") .to_owned(), GeneralConstId::ConstBlockId(id) => format!("{{anonymous const {id:?}}}"), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index b5045efb62157..30d4a79a808d9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -13,11 +13,11 @@ use hir_expand::{ builtin_attr_macro::find_builtin_attr, builtin_derive_macro::find_builtin_derive, builtin_fn_macro::find_builtin_macro, - name::{name, AsName, Name}, + name::{AsName, Name}, proc_macro::CustomProcMacroExpander, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, }; -use intern::Interned; +use intern::{sym, Interned}; use itertools::{izip, Itertools}; use la_arena::Idx; use limit::Limit; @@ -76,25 +76,28 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI let proc_macros = if krate.is_proc_macro { match db.proc_macros().get(&def_map.krate) { - Some(Ok(proc_macros)) => Ok(proc_macros - .iter() - .enumerate() - .map(|(idx, it)| { - let name = Name::new_text_dont_use(it.name.clone()); - ( - name, - if !db.expand_proc_attr_macros() { - CustomProcMacroExpander::dummy() - } else if it.disabled { - CustomProcMacroExpander::disabled() - } else { - CustomProcMacroExpander::new(hir_expand::proc_macro::ProcMacroId::new( - idx as u32, - )) - }, - ) - }) - .collect()), + Some(Ok(proc_macros)) => Ok({ + let ctx = db.syntax_context(tree_id.file_id()); + proc_macros + .iter() + .enumerate() + .map(|(idx, it)| { + let name = Name::new(&it.name, ctx); + ( + name, + if !db.expand_proc_attr_macros() { + CustomProcMacroExpander::dummy() + } else if it.disabled { + CustomProcMacroExpander::disabled() + } else { + CustomProcMacroExpander::new( + hir_expand::proc_macro::ProcMacroId::new(idx as u32), + ) + }, + ) + }) + .collect() + }), Some(Err(e)) => Err(e.clone().into_boxed_str()), None => Err("No proc-macros present for crate".to_owned().into_boxed_str()), } @@ -291,24 +294,24 @@ impl DefCollector<'_> { let Some(attr_name) = attr.path.as_ident() else { continue }; match () { - () if *attr_name == hir_expand::name![recursion_limit] => { + () if *attr_name == sym::recursion_limit => { if let Some(limit) = attr.string_value() { if let Ok(limit) = limit.parse() { crate_data.recursion_limit = Some(limit); } } } - () if *attr_name == hir_expand::name![crate_type] => { + () if *attr_name == sym::crate_type => { if let Some("proc-macro") = attr.string_value() { self.is_proc_macro = true; } } - () if *attr_name == hir_expand::name![no_core] => crate_data.no_core = true, - () if *attr_name == hir_expand::name![no_std] => crate_data.no_std = true, - () if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") => { + () if *attr_name == sym::no_core => crate_data.no_core = true, + () if *attr_name == sym::no_std => crate_data.no_std = true, + () if *attr_name == sym::rustc_coherence_is_core => { crate_data.rustc_coherence_is_core = true; } - () if *attr_name == hir_expand::name![feature] => { + () if *attr_name == sym::feature => { let features = attr .parse_path_comma_token_tree(self.db.upcast()) .into_iter() @@ -319,13 +322,13 @@ impl DefCollector<'_> { }); crate_data.unstable_features.extend(features); } - () if *attr_name == hir_expand::name![register_attr] => { + () if *attr_name == sym::register_attr => { if let Some(ident) = attr.single_ident_value() { crate_data.registered_attrs.push(ident.text.clone()); cov_mark::hit!(register_attr); } } - () if *attr_name == hir_expand::name![register_tool] => { + () if *attr_name == sym::register_tool => { if let Some(ident) = attr.single_ident_value() { crate_data.registered_tools.push(ident.text.clone()); cov_mark::hit!(register_tool); @@ -535,27 +538,30 @@ impl DefCollector<'_> { } let krate = if self.def_map.data.no_std { - name![core] - } else if self.def_map.extern_prelude().any(|(name, _)| *name == name![std]) { - name![std] + Name::new_symbol_root(sym::core) + } else if self.def_map.extern_prelude().any(|(name, _)| *name == sym::std) { + Name::new_symbol_root(sym::std) } else { // If `std` does not exist for some reason, fall back to core. This mostly helps // keep r-a's own tests minimal. - name![core] + Name::new_symbol_root(sym::core) }; let edition = match self.def_map.data.edition { - Edition::Edition2015 => name![rust_2015], - Edition::Edition2018 => name![rust_2018], - Edition::Edition2021 => name![rust_2021], - Edition::Edition2024 => name![rust_2024], + Edition::Edition2015 => Name::new_symbol_root(sym::rust_2015), + Edition::Edition2018 => Name::new_symbol_root(sym::rust_2018), + Edition::Edition2021 => Name::new_symbol_root(sym::rust_2021), + Edition::Edition2024 => Name::new_symbol_root(sym::rust_2024), }; let path_kind = match self.def_map.data.edition { Edition::Edition2015 => PathKind::Plain, _ => PathKind::Abs, }; - let path = ModPath::from_segments(path_kind, [krate, name![prelude], edition]); + let path = ModPath::from_segments( + path_kind, + [krate, Name::new_symbol_root(sym::prelude), edition], + ); let (per_ns, _) = self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None); @@ -838,7 +844,7 @@ impl DefCollector<'_> { } fn resolve_extern_crate(&self, name: &Name) -> Option { - if *name == name![self] { + if *name == sym::self_ { cov_mark::hit!(extern_crate_self_as); Some(self.def_map.crate_root()) } else { @@ -2136,9 +2142,9 @@ impl ModCollector<'_, '_> { let expander = if attrs.by_key("rustc_builtin_macro").exists() { // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name. let name; - let name = match attrs.by_key("rustc_builtin_macro").string_value() { - Some(it) => { - name = Name::new_text_dont_use(it.into()); + let name = match attrs.by_key("rustc_builtin_macro").string_value_with_span() { + Some((it, span)) => { + name = Name::new(it, span.ctx); &name } None => { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs index cee9e055459f5..22397df961066 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs @@ -6,9 +6,9 @@ use crate::{lower::LowerCtx, type_ref::ConstRef}; use hir_expand::{ mod_path::resolve_crate_root, - name::{name, AsName}, + name::{AsName, Name}, }; -use intern::Interned; +use intern::{sym, Interned}; use syntax::ast::{self, AstNode, HasGenericArgs, HasTypeBounds}; use crate::{ @@ -60,7 +60,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option { - segments.push(name![Self]); + segments.push(Name::new_symbol_root(sym::Self_)); } ast::PathSegmentKind::Type { type_ref, trait_ref } => { assert!(path.qualifier().is_none()); // this can only occur at the first segment @@ -268,7 +268,7 @@ fn lower_generic_args_from_fn_path( let bindings = if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty()); Box::new([AssociatedTypeBinding { - name: name![Output], + name: Name::new_symbol_root(sym::Output), args: None, type_ref: Some(type_ref), bounds: Box::default(), @@ -277,7 +277,7 @@ fn lower_generic_args_from_fn_path( // -> () let type_ref = TypeRef::Tuple(Vec::new()); Box::new([AssociatedTypeBinding { - name: name![Output], + name: Name::new_symbol_root(sym::Output), args: None, type_ref: Some(type_ref), bounds: Box::default(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index e5c1f93bbde65..4931418546603 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -2,11 +2,8 @@ use std::{fmt, iter, mem}; use base_db::CrateId; -use hir_expand::{ - name::{name, Name}, - MacroDefId, -}; -use intern::Interned; +use hir_expand::{name::Name, MacroDefId}; +use intern::{sym, Interned}; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; use triomphe::Arc; @@ -197,12 +194,12 @@ impl Resolver { } } &Scope::ImplDefScope(impl_) => { - if first_name == &name![Self] { + if *first_name == sym::Self_ { return Some((TypeNs::SelfType(impl_), remaining_idx(), None)); } } &Scope::AdtScope(adt) => { - if first_name == &name![Self] { + if *first_name == sym::Self_ { return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None)); } } @@ -294,7 +291,7 @@ impl Resolver { } }; let n_segments = path.segments().len(); - let tmp = name![self]; + let tmp = Name::new_symbol_root(sym::Self_); let first_name = if path.is_self() { &tmp } else { path.segments().first()? }; let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); if skip_to_mod { @@ -325,7 +322,7 @@ impl Resolver { } } &Scope::ImplDefScope(impl_) => { - if first_name == &name![Self] { + if *first_name == sym::Self_ { return Some(ResolveValueResult::ValueNs( ValueNs::ImplSelf(impl_), None, @@ -352,7 +349,7 @@ impl Resolver { } } &Scope::ImplDefScope(impl_) => { - if first_name == &name![Self] { + if *first_name == sym::Self_ { return Some(ResolveValueResult::Partial( TypeNs::SelfType(impl_), 1, @@ -361,7 +358,7 @@ impl Resolver { } } Scope::AdtScope(adt) => { - if first_name == &name![Self] { + if *first_name == sym::Self_ { let ty = TypeNs::AdtSelfType(*adt); return Some(ResolveValueResult::Partial(ty, 1, None)); } @@ -425,7 +422,7 @@ impl Resolver { } pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option { - if lifetime.name == name::known::STATIC_LIFETIME { + if lifetime.name == sym::tick_static { return Some(LifetimeNs::Static); } @@ -781,10 +778,10 @@ impl Scope { } } Scope::ImplDefScope(i) => { - acc.add(&name![Self], ScopeDef::ImplSelfType(*i)); + acc.add(&Name::new_symbol_root(sym::Self_), ScopeDef::ImplSelfType(*i)); } Scope::AdtScope(i) => { - acc.add(&name![Self], ScopeDef::AdtSelfType(*i)); + acc.add(&Name::new_symbol_root(sym::Self_), ScopeDef::AdtSelfType(*i)); } Scope::ExprScope(scope) => { if let Some((label, name)) = scope.expr_scopes.label(scope.scope_id) { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index db0feb055e198..6afa7a40f123f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -4,7 +4,7 @@ use std::{borrow::Cow, fmt, ops}; use base_db::CrateId; use cfg::CfgExpr; use either::Either; -use intern::Interned; +use intern::{sym, Interned}; use mbe::{syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode, Punct}; use smallvec::{smallvec, SmallVec}; use span::{Span, SyntaxContextId}; @@ -12,6 +12,7 @@ use syntax::unescape; use syntax::{ast, format_smolstr, match_ast, AstNode, AstToken, SmolStr, SyntaxNode}; use triomphe::ThinArc; +use crate::name::Name; use crate::{ db::ExpandDatabase, mod_path::ModPath, @@ -58,7 +59,7 @@ impl RawAttrs { text: SmolStr::new(format_smolstr!("\"{}\"", Self::escape_chars(doc))), span, }))), - path: Interned::new(ModPath::from(crate::name!(doc))), + path: Interned::new(ModPath::from(Name::new_symbol(sym::doc, span.ctx))), ctxt: span.ctx, } }), @@ -115,47 +116,47 @@ impl RawAttrs { pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs { let has_cfg_attrs = self .iter() - .any(|attr| attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr])); + .any(|attr| attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr)); if !has_cfg_attrs { return self; } let crate_graph = db.crate_graph(); - let new_attrs = - self.iter() - .flat_map(|attr| -> SmallVec<[_; 1]> { - let is_cfg_attr = - attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]); - if !is_cfg_attr { - return smallvec![attr.clone()]; - } + let new_attrs = self + .iter() + .flat_map(|attr| -> SmallVec<[_; 1]> { + let is_cfg_attr = attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr); + if !is_cfg_attr { + return smallvec![attr.clone()]; + } - let subtree = match attr.token_tree_value() { - Some(it) => it, - _ => return smallvec![attr.clone()], - }; - - let (cfg, parts) = match parse_cfg_attr_input(subtree) { - Some(it) => it, - None => return smallvec![attr.clone()], - }; - let index = attr.id; - let attrs = parts.enumerate().take(1 << AttrId::CFG_ATTR_BITS).filter_map( - |(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)), - ); - - let cfg_options = &crate_graph[krate].cfg_options; - let cfg = Subtree { delimiter: subtree.delimiter, token_trees: Box::from(cfg) }; - let cfg = CfgExpr::parse(&cfg); - if cfg_options.check(&cfg) == Some(false) { - smallvec![] - } else { - cov_mark::hit!(cfg_attr_active); - - attrs.collect() - } - }) - .collect::>(); + let subtree = match attr.token_tree_value() { + Some(it) => it, + _ => return smallvec![attr.clone()], + }; + + let (cfg, parts) = match parse_cfg_attr_input(subtree) { + Some(it) => it, + None => return smallvec![attr.clone()], + }; + let index = attr.id; + let attrs = parts + .enumerate() + .take(1 << AttrId::CFG_ATTR_BITS) + .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); + + let cfg_options = &crate_graph[krate].cfg_options; + let cfg = Subtree { delimiter: subtree.delimiter, token_trees: Box::from(cfg) }; + let cfg = CfgExpr::parse(&cfg); + if cfg_options.check(&cfg) == Some(false) { + smallvec![] + } else { + cov_mark::hit!(cfg_attr_active); + + attrs.collect() + } + }) + .collect::>(); let entries = if new_attrs.is_empty() { None } else { @@ -316,6 +317,20 @@ impl Attr { } } + /// #[path = "string"] + pub fn string_value_with_span(&self) -> Option<(&str, span::Span)> { + match self.input.as_deref()? { + AttrInput::Literal(it) => match it.text.strip_prefix('r') { + Some(it) => it.trim_matches('#'), + None => it.text.as_str(), + } + .strip_prefix('"')? + .strip_suffix('"') + .zip(Some(it.span)), + _ => None, + } + } + pub fn string_value_unescape(&self) -> Option> { match self.input.as_deref()? { AttrInput::Literal(it) => match it.text.strip_prefix('r') { @@ -369,7 +384,7 @@ impl Attr { } pub fn cfg(&self) -> Option { - if *self.path.as_ident()? == crate::name![cfg] { + if *self.path.as_ident()? == sym::cfg { self.token_tree_value().map(CfgExpr::parse) } else { None diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs index 2e115f479327e..b9afc666f7528 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs @@ -1,4 +1,5 @@ //! Builtin attributes. +use intern::sym; use span::{MacroCallId, Span}; use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind}; @@ -19,7 +20,7 @@ macro_rules! register_builtin { fn find_by_name(name: &name::Name) -> Option { match name { - $( id if id == &name::name![$name] => Some(BuiltinAttrExpander::$variant), )* + $( id if id == &sym::$name => Some(BuiltinAttrExpander::$variant), )* _ => None, } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs index c7cdc5e92200f..269e9f308c2f6 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs @@ -1,5 +1,6 @@ //! Builtin derives. +use intern::sym; use itertools::izip; use mbe::DocCommentDesugarMode; use rustc_hash::FxHashSet; @@ -36,7 +37,7 @@ macro_rules! register_builtin { fn find_by_name(name: &name::Name) -> Option { match name { - $( id if id == &name::name![$trait] => Some(BuiltinDeriveExpander::$trait), )* + $( id if id == &sym::$trait => Some(BuiltinDeriveExpander::$trait), )* _ => None, } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index 02fd431e4e7ec..e5de5975a2d8b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -3,6 +3,7 @@ use base_db::{AnchoredPath, FileId}; use cfg::CfgExpr; use either::Either; +use intern::sym; use itertools::Itertools; use mbe::{parse_exprs_with_sep, parse_to_token_tree}; use span::{Edition, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; @@ -11,8 +12,7 @@ use syntax::ast::{self, AstToken}; use crate::{ db::ExpandDatabase, hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt}, - name::{self, known}, - quote, + name, quote, quote::dollar_crate, tt::{self, DelimSpan}, ExpandError, ExpandResult, HirFileIdExt, MacroCallId, MacroFileIdExt, @@ -48,8 +48,8 @@ macro_rules! register_builtin { fn find_by_name(ident: &name::Name) -> Option> { match ident { - $( id if id == &name::name![$name] => Some(Either::Left(BuiltinFnLikeExpander::$kind)), )* - $( id if id == &name::name![$e_name] => Some(Either::Right(EagerExpander::$e_kind)), )* + $( id if id == &sym::$name => Some(Either::Left(BuiltinFnLikeExpander::$kind)), )* + $( id if id == &sym::$e_name => Some(Either::Right(EagerExpander::$e_kind)), )* _ => return None, } } @@ -367,8 +367,7 @@ fn panic_expand( let dollar_crate = dollar_crate(span); let call_site_span = span_with_call_site_ctxt(db, span, id); - let mac = - if use_panic_2021(db, call_site_span) { known::panic_2021 } else { known::panic_2015 }; + let mac = if use_panic_2021(db, call_site_span) { sym::panic_2021 } else { sym::panic_2015 }; // Expand to a macro call `$crate::panic::panic_{edition}` let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!); @@ -397,9 +396,9 @@ fn unreachable_expand( let call_site_span = span_with_call_site_ctxt(db, span, id); let mac = if use_panic_2021(db, call_site_span) { - known::unreachable_2021 + sym::unreachable_2021 } else { - known::unreachable_2015 + sym::unreachable_2015 }; // Expand to a macro call `$crate::panic::panic_{edition}` diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index ad25a1168c4d5..e1fb3953f4d2b 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -133,6 +133,15 @@ pub trait ExpandDatabase: SourceDatabase { &self, macro_call: MacroCallId, ) -> Option>>>; + #[salsa::transparent] + fn syntax_context(&self, file: HirFileId) -> SyntaxContextId; +} + +fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId) -> SyntaxContextId { + match file.repr() { + HirFileIdRepr::FileId(_) => SyntaxContextId::ROOT, + HirFileIdRepr::MacroFile(m) => db.macro_arg(m.macro_call_id).2.ctx, + } } /// This expands the given macro call, but with different arguments. This is diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index 29408902f16f8..b920d2127abe8 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -2,6 +2,7 @@ use std::sync::OnceLock; use base_db::{CrateId, VersionReq}; +use intern::sym; use mbe::DocCommentDesugarMode; use span::{Edition, MacroCallId, Span, SyntaxContextId}; use stdx::TupleExt; @@ -111,8 +112,10 @@ impl DeclarativeMacroExpander { match &*attrs .iter() .find(|it| { - it.path.as_ident().and_then(|it| it.as_str()) - == Some("rustc_macro_transparency") + it.path + .as_ident() + .map(|it| *it == sym::rustc_macro_transparency) + .unwrap_or(false) })? .token_tree_value()? .token_trees diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 12fdf88a2a873..7ff8b797fa4a6 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -8,10 +8,11 @@ use std::{ use crate::{ db::ExpandDatabase, hygiene::{marks_rev, SyntaxContextExt, Transparency}, - name::{known, AsName, Name}, + name::{AsName, Name}, tt, }; use base_db::CrateId; +use intern::sym; use smallvec::SmallVec; use span::SyntaxContextId; use syntax::{ast, AstNode}; @@ -106,10 +107,7 @@ impl ModPath { PathKind::Abs => 0, PathKind::DollarCrate(_) => "$crate".len(), }; - self.segments() - .iter() - .map(|segment| segment.as_str().map_or(0, str::len)) - .fold(base, core::ops::Add::add) + self.segments().iter().map(|segment| segment.as_str().len()).fold(base, core::ops::Add::add) } pub fn is_ident(&self) -> bool { @@ -122,8 +120,7 @@ impl ModPath { #[allow(non_snake_case)] pub fn is_Self(&self) -> bool { - self.kind == PathKind::Plain - && matches!(&*self.segments, [name] if *name == known::SELF_TYPE) + self.kind == PathKind::Plain && matches!(&*self.segments, [name] if *name == sym::Self_) } /// If this path is a single identifier, like `foo`, return its name. @@ -265,9 +262,10 @@ fn convert_path( res } } - ast::PathSegmentKind::SelfTypeKw => { - ModPath::from_segments(PathKind::Plain, Some(known::SELF_TYPE)) - } + ast::PathSegmentKind::SelfTypeKw => ModPath::from_segments( + PathKind::Plain, + Some(Name::new_symbol(sym::Self_, SyntaxContextId::ROOT)), + ), ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()), ast::PathSegmentKind::SelfKw => handle_super_kw(0)?, ast::PathSegmentKind::SuperKw => handle_super_kw(1)?, @@ -323,9 +321,9 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option PathKind::SELF, tt::Leaf::Ident(tt::Ident { text, .. }) if text == "super" => { let mut deg = 1; - while let Some(tt::Leaf::Ident(tt::Ident { text, .. })) = leaves.next() { + while let Some(tt::Leaf::Ident(tt::Ident { text, span, .. })) = leaves.next() { if text != "super" { - segments.push(Name::new_text_dont_use(text.clone())); + segments.push(Name::new(text, span.ctx)); break; } deg += 1; @@ -334,13 +332,13 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option PathKind::Crate, tt::Leaf::Ident(ident) => { - segments.push(Name::new_text_dont_use(ident.text.clone())); + segments.push(Name::new(&ident.text, ident.span.ctx)); PathKind::Plain } _ => return None, }; segments.extend(leaves.filter_map(|leaf| match leaf { - ::tt::Leaf::Ident(ident) => Some(Name::new_text_dont_use(ident.text.clone())), + ::tt::Leaf::Ident(ident) => Some(Name::new(&ident.text, ident.span.ctx)), _ => None, })); Some(ModPath { kind, segments }) @@ -385,6 +383,8 @@ macro_rules! __known_path { (core::ops::RangeInclusive) => {}; (core::future::Future) => {}; (core::future::IntoFuture) => {}; + (core::fmt::Debug) => {}; + (std::fmt::format) => {}; (core::ops::Try) => {}; ($path:path) => { compile_error!("Please register your known path in the path module") @@ -396,7 +396,7 @@ macro_rules! __path { ($start:ident $(:: $seg:ident)*) => ({ $crate::__known_path!($start $(:: $seg)*); $crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Abs, vec![ - $crate::mod_path::__name![$start], $($crate::mod_path::__name![$seg],)* + $crate::name::Name::new_symbol_root(intern::sym::$start), $($crate::name::Name::new_symbol_root(intern::sym::$seg),)* ]) }); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index fe754bc82494a..da0adbef16342 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -2,6 +2,8 @@ use std::fmt; +use intern::{sym::MISSING_NAME, Symbol}; +use span::SyntaxContextId; use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; /// `Name` is a wrapper around string, which is used in hir for both references @@ -11,32 +13,49 @@ use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; /// Note that `Name` holds and prints escaped name i.e. prefixed with "r#" when it /// is a raw identifier. Use [`unescaped()`][Name::unescaped] when you need the /// name without "r#". -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct Name(Repr); +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Name { + symbol: Symbol, + ctx: (), +} -/// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier. -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct UnescapedName<'a>(&'a Name); +impl Ord for Name { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.symbol.as_str().cmp(other.symbol.as_str()) + } +} -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -enum Repr { - Text(SmolStr), - TupleField(usize), +impl PartialOrd for Name { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } } +impl PartialEq for Name { + fn eq(&self, sym: &Symbol) -> bool { + self.symbol == *sym + } +} + +impl PartialEq for Symbol { + fn eq(&self, name: &Name) -> bool { + *self == name.symbol + } +} + +/// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UnescapedName<'a>(&'a Name); + impl UnescapedName<'_> { /// Returns the textual representation of this name as a [`SmolStr`]. Prefer using this over /// [`ToString::to_string`] if possible as this conversion is cheaper in the general case. pub fn to_smol_str(&self) -> SmolStr { - match &self.0 .0 { - Repr::Text(it) => { - if let Some(stripped) = it.strip_prefix("r#") { - SmolStr::new(stripped) - } else { - it.clone() - } - } - Repr::TupleField(it) => SmolStr::new(it.to_string()), + let it = self.0.symbol.as_str(); + if let Some(stripped) = it.strip_prefix("r#") { + SmolStr::new(stripped) + } else { + it.into() } } @@ -50,27 +69,26 @@ impl Name { /// Note: this is private to make creating name from random string hard. /// Hopefully, this should allow us to integrate hygiene cleaner in the /// future, and to switch to interned representation of names. - const fn new_text(text: SmolStr) -> Name { - Name(Repr::Text(text)) + fn new_text(text: &str) -> Name { + Name { symbol: Symbol::intern(text), ctx: () } } - // FIXME: See above, unfortunately some places really need this right now - #[doc(hidden)] - pub const fn new_text_dont_use(text: SmolStr) -> Name { - Name(Repr::Text(text)) + pub fn new(text: &str, ctx: SyntaxContextId) -> Name { + _ = ctx; + Name { symbol: Symbol::intern(text), ctx: () } } pub fn new_tuple_field(idx: usize) -> Name { - Name(Repr::TupleField(idx)) + Name { symbol: Symbol::intern(&idx.to_string()), ctx: () } } pub fn new_lifetime(lt: &ast::Lifetime) -> Name { - Self::new_text(lt.text().into()) + Name { symbol: Symbol::intern(lt.text().as_str()), ctx: () } } /// Shortcut to create a name from a string literal. - const fn new_static(text: &'static str) -> Name { - Name::new_text(SmolStr::new_static(text)) + fn new_ref(text: &str) -> Name { + Name { symbol: Symbol::intern(text), ctx: () } } /// Resolve a name from the text of token. @@ -78,14 +96,14 @@ impl Name { match raw_text.strip_prefix("r#") { // When `raw_text` starts with "r#" but the name does not coincide with any // keyword, we never need the prefix so we strip it. - Some(text) if !is_raw_identifier(text) => Name::new_text(SmolStr::new(text)), + Some(text) if !is_raw_identifier(text) => Name::new_ref(text), // Keywords (in the current edition) *can* be used as a name in earlier editions of // Rust, e.g. "try" in Rust 2015. Even in such cases, we keep track of them in their // escaped form. None if is_raw_identifier(raw_text) => { - Name::new_text(format_smolstr!("r#{}", raw_text)) + Name::new_text(&format_smolstr!("r#{}", raw_text)) } - _ => Name::new_text(raw_text.into()), + _ => Name::new_text(raw_text), } } @@ -99,7 +117,7 @@ impl Name { /// name is equal only to itself. It's not clear how to implement this in /// salsa though, so we punt on that bit for a moment. pub const fn missing() -> Name { - Name::new_static("[missing name]") + Name { symbol: MISSING_NAME, ctx: () } } /// Returns true if this is a fake name for things missing in the source code. See @@ -115,41 +133,25 @@ impl Name { /// creating desugared locals and labels. The caller is responsible for picking an index /// that is stable across re-executions pub fn generate_new_name(idx: usize) -> Name { - Name::new_text(format_smolstr!("{idx}")) + Name::new_text(&format_smolstr!("{idx}")) } /// Returns the tuple index this name represents if it is a tuple field. pub fn as_tuple_index(&self) -> Option { - match self.0 { - Repr::TupleField(idx) => Some(idx), - _ => None, - } + self.symbol.as_str().parse().ok() } /// Returns the text this name represents if it isn't a tuple field. - pub fn as_text(&self) -> Option { - match &self.0 { - Repr::Text(it) => Some(it.clone()), - _ => None, - } - } - - /// Returns the text this name represents if it isn't a tuple field. - pub fn as_str(&self) -> Option<&str> { - match &self.0 { - Repr::Text(it) => Some(it), - _ => None, - } + pub fn as_str(&self) -> &str { + self.symbol.as_str() } + // FIXME: Remove this /// Returns the textual representation of this name as a [`SmolStr`]. /// Prefer using this over [`ToString::to_string`] if possible as this conversion is cheaper in /// the general case. pub fn to_smol_str(&self) -> SmolStr { - match &self.0 { - Repr::Text(it) => it.clone(), - Repr::TupleField(it) => SmolStr::new(it.to_string()), - } + self.symbol.as_str().into() } pub fn unescaped(&self) -> UnescapedName<'_> { @@ -157,16 +159,27 @@ impl Name { } pub fn is_escaped(&self) -> bool { - match &self.0 { - Repr::Text(it) => it.starts_with("r#"), - Repr::TupleField(_) => false, - } + self.symbol.as_str().starts_with("r#") } pub fn display<'a>(&'a self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a { _ = db; Display { name: self } } + + pub fn symbol(&self) -> &Symbol { + &self.symbol + } + + pub const fn new_symbol(doc: Symbol, ctx: SyntaxContextId) -> Self { + _ = ctx; + Self { symbol: doc, ctx: () } + } + + // FIXME: This needs to go once we have hygiene + pub const fn new_symbol_root(doc: Symbol) -> Self { + Self { symbol: doc, ctx: () } + } } struct Display<'a> { @@ -175,10 +188,7 @@ struct Display<'a> { impl fmt::Display for Display<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.name.0 { - Repr::Text(text) => fmt::Display::fmt(&text, f), - Repr::TupleField(idx) => fmt::Display::fmt(&idx, f), - } + fmt::Display::fmt(self.name.symbol.as_str(), f) } } @@ -188,13 +198,9 @@ struct UnescapedDisplay<'a> { impl fmt::Display for UnescapedDisplay<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.name.0 .0 { - Repr::Text(text) => { - let text = text.strip_prefix("r#").unwrap_or(text); - fmt::Display::fmt(&text, f) - } - Repr::TupleField(idx) => fmt::Display::fmt(&idx, f), - } + let symbol = &self.name.0.symbol.as_str(); + let text = symbol.strip_prefix("r#").unwrap_or(symbol); + fmt::Display::fmt(&text, f) } } @@ -246,251 +252,6 @@ impl AsName for ast::FieldKind { impl AsName for base_db::Dependency { fn as_name(&self) -> Name { - Name::new_text(SmolStr::new(&*self.name)) + Name::new_text(&self.name) } } - -pub mod known { - macro_rules! known_names { - ($($ident:ident),* $(,)?) => { - $( - #[allow(bad_style)] - pub const $ident: super::Name = - super::Name::new_static(stringify!($ident)); - )* - }; - } - - known_names!( - // Primitives - isize, - i8, - i16, - i32, - i64, - i128, - usize, - u8, - u16, - u32, - u64, - u128, - f16, - f32, - f64, - f128, - bool, - char, - str, - // Special names - macro_rules, - doc, - cfg, - cfg_attr, - register_attr, - register_tool, - // Components of known path (value or mod name) - std, - core, - alloc, - iter, - ops, - fmt, - future, - result, - string, - boxed, - option, - prelude, - rust_2015, - rust_2018, - rust_2021, - rust_2024, - v1, - new_display, - new_debug, - new_lower_exp, - new_upper_exp, - new_octal, - new_pointer, - new_binary, - new_lower_hex, - new_upper_hex, - from_usize, - panic_2015, - panic_2021, - unreachable_2015, - unreachable_2021, - // Components of known path (type name) - Iterator, - IntoIterator, - Item, - IntoIter, - Try, - Ok, - Future, - IntoFuture, - Result, - Option, - Output, - Target, - Box, - RangeFrom, - RangeFull, - RangeInclusive, - RangeToInclusive, - RangeTo, - Range, - String, - Neg, - Not, - None, - Index, - Left, - Right, - Center, - Unknown, - Is, - Param, - Implied, - // Components of known path (function name) - filter_map, - next, - iter_mut, - len, - is_empty, - as_str, - new, - new_v1_formatted, - none, - // Builtin macros - asm, - assert, - column, - compile_error, - concat_idents, - concat_bytes, - concat, - const_format_args, - core_panic, - env, - file, - format, - format_args_nl, - format_args, - global_asm, - include_bytes, - include_str, - include, - line, - llvm_asm, - log_syntax, - module_path, - option_env, - quote, - std_panic, - stringify, - trace_macros, - unreachable, - // Builtin derives - Copy, - Clone, - Default, - Debug, - Hash, - Ord, - PartialOrd, - Eq, - PartialEq, - // Builtin attributes - bench, - cfg_accessible, - cfg_eval, - crate_type, - derive, - derive_const, - global_allocator, - no_core, - no_std, - test, - test_case, - recursion_limit, - feature, - // known methods of lang items - call_once, - call_mut, - call, - eq, - ne, - ge, - gt, - le, - lt, - // known fields of lang items - pieces, - // lang items - add_assign, - add, - bitand_assign, - bitand, - bitor_assign, - bitor, - bitxor_assign, - bitxor, - branch, - deref_mut, - deref, - div_assign, - div, - drop, - fn_mut, - fn_once, - future_trait, - index, - index_mut, - into_future, - mul_assign, - mul, - neg, - not, - owned_box, - partial_ord, - poll, - r#fn, - rem_assign, - rem, - shl_assign, - shl, - shr_assign, - shr, - sub_assign, - sub, - unsafe_cell, - va_list - ); - - // self/Self cannot be used as an identifier - pub const SELF_PARAM: super::Name = super::Name::new_static("self"); - pub const SELF_TYPE: super::Name = super::Name::new_static("Self"); - - pub const STATIC_LIFETIME: super::Name = super::Name::new_static("'static"); - pub const DOLLAR_CRATE: super::Name = super::Name::new_static("$crate"); - - #[macro_export] - macro_rules! name { - (self) => { - $crate::name::known::SELF_PARAM - }; - (Self) => { - $crate::name::known::SELF_TYPE - }; - ('static) => { - $crate::name::known::STATIC_LIFETIME - }; - ($ident:ident) => { - $crate::name::known::$ident - }; - } -} - -pub use crate::name; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs index 8f1e32321e147..f4fc3b7b3e2da 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs @@ -1,6 +1,7 @@ //! A simplified version of quote-crate like quasi quote macro #![allow(clippy::crate_in_macro_def)] +use intern::Symbol; use span::Span; use syntax::format_smolstr; @@ -219,6 +220,7 @@ impl_to_to_tokentrees! { span: &str => self { crate::tt::Literal{text: format_smolstr!("\"{}\"", self.escape_default()), span}}; span: String => self { crate::tt::Literal{text: format_smolstr!("\"{}\"", self.escape_default()), span}}; span: Name => self { crate::tt::Ident{text: self.to_smol_str(), span}}; + span: Symbol => self { crate::tt::Ident{text: self.as_str().into(), span}}; } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs index b706cef0b3a28..736379a3d8730 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs @@ -5,7 +5,8 @@ use chalk_ir::cast::Cast; use hir_def::lang_item::LangItem; -use hir_expand::name::name; +use hir_expand::name::Name; +use intern::sym; use limit::Limit; use triomphe::Arc; @@ -151,7 +152,8 @@ pub(crate) fn deref_by_trait( let deref_trait = db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?; - let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; + let target = + db.trait_data(deref_trait).associated_type_by_name(&Name::new_symbol_root(sym::Target))?; let projection = { let b = TyBuilder::subst_for_def(db, deref_trait, None); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 3ac8cbaaf8b70..868827b2b6603 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -3,6 +3,8 @@ use core::ops; use std::{iter, ops::ControlFlow, sync::Arc}; +use hir_expand::name::Name; +use intern::sym; use tracing::debug; use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds}; @@ -16,7 +18,6 @@ use hir_def::{ AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup, TypeAliasId, VariantId, }; -use hir_expand::name::name; use crate::{ db::{HirDatabase, InternedCoroutine}, @@ -293,8 +294,10 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { .lang_item(self.krate, LangItem::Future) .and_then(|item| item.as_trait()) .and_then(|trait_| { - let alias = - self.db.trait_data(trait_).associated_type_by_name(&name![Output])?; + let alias = self + .db + .trait_data(trait_) + .associated_type_by_name(&Name::new_symbol_root(sym::Output))?; Some((trait_, alias)) }) { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 15ecf9aafcfc9..1df801f3a4fd5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -247,7 +247,7 @@ impl<'a> DeclValidator<'a> { // Check the module name. let Some(module_name) = module_id.name(self.db.upcast()) else { return }; let Some(module_name_replacement) = - module_name.as_str().and_then(to_lower_snake_case).map(|new_name| Replacement { + to_lower_snake_case(module_name.as_str()).map(|new_name| Replacement { current_name: module_name, suggested_text: new_name, expected_case: CaseType::LowerSnakeCase, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index c28ab2e98afb1..048bdd2c38bce 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -8,7 +8,7 @@ use either::Either; use hir_def::lang_item::LangItem; use hir_def::{resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule}; use hir_def::{ItemContainerId, Lookup}; -use hir_expand::name; +use intern::sym; use itertools::Itertools; use rustc_hash::FxHashSet; use rustc_pattern_analysis::constructor::Constructor; @@ -423,7 +423,7 @@ impl FilterMapNextChecker { ItemContainerId::TraitId(iterator_trait_id) => { let iterator_trait_items = &db.trait_data(iterator_trait_id).items; iterator_trait_items.iter().find_map(|(name, it)| match it { - &AssocItemId::FunctionId(id) if *name == name![filter_map] => Some(id), + &AssocItemId::FunctionId(id) if *name == sym::filter_map => Some(id), _ => None, }) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index a9a5d829f5f91..2a644de1fbecc 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -25,7 +25,7 @@ use hir_def::{ ModuleId, TraitId, }; use hir_expand::name::Name; -use intern::{Internable, Interned}; +use intern::{sym, Internable, Interned}; use itertools::Itertools; use la_arena::ArenaMap; use rustc_apfloat::{ @@ -1171,7 +1171,8 @@ impl HirDisplay for Ty { .lang_item(body.module(db.upcast()).krate(), LangItem::Future) .and_then(LangItemTarget::as_trait); let output = future_trait.and_then(|t| { - db.trait_data(t).associated_type_by_name(&hir_expand::name!(Output)) + db.trait_data(t) + .associated_type_by_name(&Name::new_symbol_root(sym::Output)) }); write!(f, "impl ")?; if let Some(t) = future_trait { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 66ee02d74d9a0..928a3f5e493c7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -46,8 +46,9 @@ use hir_def::{ AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId, }; -use hir_expand::name::{name, Name}; +use hir_expand::name::Name; use indexmap::IndexSet; +use intern::sym; use la_arena::{ArenaMap, Entry}; use once_cell::unsync::OnceCell; use rustc_hash::{FxHashMap, FxHashSet}; @@ -1424,7 +1425,7 @@ impl<'a> InferenceContext<'a> { } fn resolve_output_on(&self, trait_: TraitId) -> Option { - self.db.trait_data(trait_).associated_type_by_name(&name![Output]) + self.db.trait_data(trait_).associated_type_by_name(&Name::new_symbol_root(sym::Output)) } fn resolve_lang_trait(&self, lang: LangItem) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index b7c7b6654536a..f54081a276c8d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -15,7 +15,8 @@ use hir_def::{ resolver::{resolver_for_expr, ResolveValueResult, ValueNs}, DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId, }; -use hir_expand::name; +use hir_expand::name::Name; +use intern::sym; use rustc_hash::FxHashMap; use smallvec::SmallVec; use stdx::never; @@ -268,9 +269,7 @@ impl CapturedItem { } let variant_data = f.parent.variant_data(db.upcast()); let field = match &*variant_data { - VariantData::Record(fields) => { - fields[f.local_id].name.as_str().unwrap_or("[missing field]").to_owned() - } + VariantData::Record(fields) => fields[f.local_id].name.as_str().to_owned(), VariantData::Tuple(fields) => fields .iter() .position(|it| it.0 == f.local_id) @@ -621,8 +620,10 @@ impl InferenceContext<'_> { if let Some(deref_trait) = self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait()) { - if let Some(deref_fn) = - self.db.trait_data(deref_trait).method_by_name(&name![deref_mut]) + if let Some(deref_fn) = self + .db + .trait_data(deref_trait) + .method_by_name(&Name::new_symbol_root(sym::deref_mut)) { break 'b deref_fn == f; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 7a0f7872a649d..a0c3f48642e3b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -15,7 +15,8 @@ use hir_def::{ path::{GenericArgs, Path}, BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId, }; -use hir_expand::name::{name, Name}; +use hir_expand::name::Name; +use intern::sym; use stdx::always; use syntax::ast::RangeOp; @@ -646,8 +647,10 @@ impl InferenceContext<'_> { match op { UnaryOp::Deref => { if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) { - if let Some(deref_fn) = - self.db.trait_data(deref_trait).method_by_name(&name![deref]) + if let Some(deref_fn) = self + .db + .trait_data(deref_trait) + .method_by_name(&Name::new_symbol_root(sym::deref)) { // FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that // the mutability is not wrong, and will be fixed in `self.infer_mut`). @@ -785,8 +788,10 @@ impl InferenceContext<'_> { // mutability will be fixed up in `InferenceContext::infer_mut`; adj.push(Adjustment::borrow(Mutability::Not, self_ty.clone())); self.write_expr_adj(*base, adj); - if let Some(func) = - self.db.trait_data(index_trait).method_by_name(&name!(index)) + if let Some(func) = self + .db + .trait_data(index_trait) + .method_by_name(&Name::new_symbol_root(sym::index)) { let substs = TyBuilder::subst_for_def(self.db, index_trait, None) .push(self_ty.clone()) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index 00e5eac229fb6..ca8996fb89e77 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -6,7 +6,8 @@ use hir_def::{ hir::{Array, BinaryOp, BindingAnnotation, Expr, ExprId, PatId, Statement, UnaryOp}, lang_item::LangItem, }; -use hir_expand::name; +use hir_expand::name::Name; +use intern::sym; use crate::{lower::lower_to_chalk_mutability, Adjust, Adjustment, AutoBorrow, OverloadedDeref}; @@ -108,8 +109,10 @@ impl InferenceContext<'_> { .lang_item(self.table.trait_env.krate, LangItem::IndexMut) .and_then(|l| l.as_trait()) { - if let Some(index_fn) = - self.db.trait_data(index_trait).method_by_name(&name![index_mut]) + if let Some(index_fn) = self + .db + .trait_data(index_trait) + .method_by_name(&Name::new_symbol_root(sym::index_mut)) { *f = index_fn; let base_adjustments = self @@ -139,8 +142,10 @@ impl InferenceContext<'_> { .lang_item(self.table.trait_env.krate, LangItem::DerefMut) .and_then(|l| l.as_trait()) { - if let Some(deref_fn) = - self.db.trait_data(deref_trait).method_by_name(&name![deref_mut]) + if let Some(deref_fn) = self + .db + .trait_data(deref_trait) + .method_by_name(&Name::new_symbol_root(sym::deref_mut)) { *f = deref_fn; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 490ecfd7fa3c3..67a0ec60f19d6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -7,6 +7,7 @@ use hir_def::{ AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup, }; use hir_expand::name::Name; +use intern::sym; use stdx::never; use crate::{ @@ -227,7 +228,7 @@ impl InferenceContext<'_> { Path::LangItem(..) => ( PathSegment { name: { - _d = hir_expand::name::known::Unknown; + _d = Name::new_symbol_root(sym::Unknown); &_d }, args_and_bindings: None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index ed4d55d203773..800b06afbd0b2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -9,7 +9,8 @@ use chalk_ir::{ use chalk_solve::infer::ParameterEnaVariableExt; use either::Either; use ena::unify::UnifyKey; -use hir_expand::name; +use hir_expand::name::Name; +use intern::sym; use rustc_hash::FxHashMap; use smallvec::SmallVec; use triomphe::Arc; @@ -781,7 +782,8 @@ impl<'a> InferenceTable<'a> { let krate = self.trait_env.krate; let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; let trait_data = self.db.trait_data(fn_once_trait); - let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?; + let output_assoc_type = + trait_data.associated_type_by_name(&Name::new_symbol_root(sym::Output))?; let mut arg_tys = Vec::with_capacity(num_args); let arg_ty = TyBuilder::tuple(num_args) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs index 85ed46b96321a..69ff03eb49ece 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs @@ -2,6 +2,7 @@ use hir_def::{data::adt::StructFlags, lang_item::LangItem, AdtId}; use hir_expand::name::Name; +use intern::sym; use crate::db::HirDatabase; @@ -16,48 +17,47 @@ pub fn is_unsafe_cell(db: &dyn HirDatabase, adt: AdtId) -> bool { } pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, LangItem)> { - use hir_expand::name; use syntax::ast::{ArithOp, BinaryOp, CmpOp, Ordering}; Some(match op { BinaryOp::LogicOp(_) => return None, BinaryOp::ArithOp(aop) => match aop { - ArithOp::Add => (name![add], LangItem::Add), - ArithOp::Mul => (name![mul], LangItem::Mul), - ArithOp::Sub => (name![sub], LangItem::Sub), - ArithOp::Div => (name![div], LangItem::Div), - ArithOp::Rem => (name![rem], LangItem::Rem), - ArithOp::Shl => (name![shl], LangItem::Shl), - ArithOp::Shr => (name![shr], LangItem::Shr), - ArithOp::BitXor => (name![bitxor], LangItem::BitXor), - ArithOp::BitOr => (name![bitor], LangItem::BitOr), - ArithOp::BitAnd => (name![bitand], LangItem::BitAnd), + ArithOp::Add => (Name::new_symbol_root(sym::add), LangItem::Add), + ArithOp::Mul => (Name::new_symbol_root(sym::mul), LangItem::Mul), + ArithOp::Sub => (Name::new_symbol_root(sym::sub), LangItem::Sub), + ArithOp::Div => (Name::new_symbol_root(sym::div), LangItem::Div), + ArithOp::Rem => (Name::new_symbol_root(sym::rem), LangItem::Rem), + ArithOp::Shl => (Name::new_symbol_root(sym::shl), LangItem::Shl), + ArithOp::Shr => (Name::new_symbol_root(sym::shr), LangItem::Shr), + ArithOp::BitXor => (Name::new_symbol_root(sym::bitxor), LangItem::BitXor), + ArithOp::BitOr => (Name::new_symbol_root(sym::bitor), LangItem::BitOr), + ArithOp::BitAnd => (Name::new_symbol_root(sym::bitand), LangItem::BitAnd), }, BinaryOp::Assignment { op: Some(aop) } => match aop { - ArithOp::Add => (name![add_assign], LangItem::AddAssign), - ArithOp::Mul => (name![mul_assign], LangItem::MulAssign), - ArithOp::Sub => (name![sub_assign], LangItem::SubAssign), - ArithOp::Div => (name![div_assign], LangItem::DivAssign), - ArithOp::Rem => (name![rem_assign], LangItem::RemAssign), - ArithOp::Shl => (name![shl_assign], LangItem::ShlAssign), - ArithOp::Shr => (name![shr_assign], LangItem::ShrAssign), - ArithOp::BitXor => (name![bitxor_assign], LangItem::BitXorAssign), - ArithOp::BitOr => (name![bitor_assign], LangItem::BitOrAssign), - ArithOp::BitAnd => (name![bitand_assign], LangItem::BitAndAssign), + ArithOp::Add => (Name::new_symbol_root(sym::add_assign), LangItem::AddAssign), + ArithOp::Mul => (Name::new_symbol_root(sym::mul_assign), LangItem::MulAssign), + ArithOp::Sub => (Name::new_symbol_root(sym::sub_assign), LangItem::SubAssign), + ArithOp::Div => (Name::new_symbol_root(sym::div_assign), LangItem::DivAssign), + ArithOp::Rem => (Name::new_symbol_root(sym::rem_assign), LangItem::RemAssign), + ArithOp::Shl => (Name::new_symbol_root(sym::shl_assign), LangItem::ShlAssign), + ArithOp::Shr => (Name::new_symbol_root(sym::shr_assign), LangItem::ShrAssign), + ArithOp::BitXor => (Name::new_symbol_root(sym::bitxor_assign), LangItem::BitXorAssign), + ArithOp::BitOr => (Name::new_symbol_root(sym::bitor_assign), LangItem::BitOrAssign), + ArithOp::BitAnd => (Name::new_symbol_root(sym::bitand_assign), LangItem::BitAndAssign), }, BinaryOp::CmpOp(cop) => match cop { - CmpOp::Eq { negated: false } => (name![eq], LangItem::PartialEq), - CmpOp::Eq { negated: true } => (name![ne], LangItem::PartialEq), + CmpOp::Eq { negated: false } => (Name::new_symbol_root(sym::eq), LangItem::PartialEq), + CmpOp::Eq { negated: true } => (Name::new_symbol_root(sym::ne), LangItem::PartialEq), CmpOp::Ord { ordering: Ordering::Less, strict: false } => { - (name![le], LangItem::PartialOrd) + (Name::new_symbol_root(sym::le), LangItem::PartialOrd) } CmpOp::Ord { ordering: Ordering::Less, strict: true } => { - (name![lt], LangItem::PartialOrd) + (Name::new_symbol_root(sym::lt), LangItem::PartialOrd) } CmpOp::Ord { ordering: Ordering::Greater, strict: false } => { - (name![ge], LangItem::PartialOrd) + (Name::new_symbol_root(sym::ge), LangItem::PartialOrd) } CmpOp::Ord { ordering: Ordering::Greater, strict: true } => { - (name![gt], LangItem::PartialOrd) + (Name::new_symbol_root(sym::gt), LangItem::PartialOrd) } }, BinaryOp::Assignment { op: None } => return None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index bd650869bb386..60447ac582030 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -61,7 +61,8 @@ use chalk_ir::{ }; use either::Either; use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId}; -use hir_expand::name; +use hir_expand::name::Name; +use intern::sym; use la_arena::{Arena, Idx}; use mir::{MirEvalError, VTableMap}; use rustc_hash::{FxHashMap, FxHashSet}; @@ -894,7 +895,9 @@ pub fn callable_sig_from_fn_trait( ) -> Option<(FnTrait, CallableSig)> { let krate = trait_env.krate; let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; - let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; + let output_assoc_type = db + .trait_data(fn_once_trait) + .associated_type_by_name(&Name::new_symbol_root(sym::Output))?; let mut table = InferenceTable::new(db, trait_env.clone()); let b = TyBuilder::trait_ref(db, fn_once_trait); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 2d9c221b732b0..982080c5ff5fe 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -14,8 +14,8 @@ use hir_def::{ AdtId, ConstId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, StaticId, VariantId, }; -use hir_expand::{mod_path::ModPath, HirFileIdExt, InFile}; -use intern::Interned; +use hir_expand::{mod_path::path, name::Name, HirFileIdExt, InFile}; +use intern::{sym, Interned}; use la_arena::ArenaMap; use rustc_abi::TargetDataLayout; use rustc_apfloat::{ @@ -35,7 +35,7 @@ use crate::{ layout::{Layout, LayoutError, RustcEnumVariantIdx}, mapping::from_chalk, method_resolution::{is_dyn_method, lookup_impl_const}, - name, static_lifetime, + static_lifetime, traits::FnTrait, utils::{detect_variant_from_bytes, ClosureSubst}, CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstScalar, FnDefId, Interner, MemoryMap, @@ -631,15 +631,19 @@ impl Evaluator<'_> { cached_fn_trait_func: db .lang_item(crate_id, LangItem::Fn) .and_then(|x| x.as_trait()) - .and_then(|x| db.trait_data(x).method_by_name(&name![call])), + .and_then(|x| db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call))), cached_fn_mut_trait_func: db .lang_item(crate_id, LangItem::FnMut) .and_then(|x| x.as_trait()) - .and_then(|x| db.trait_data(x).method_by_name(&name![call_mut])), + .and_then(|x| { + db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_mut)) + }), cached_fn_once_trait_func: db .lang_item(crate_id, LangItem::FnOnce) .and_then(|x| x.as_trait()) - .and_then(|x| db.trait_data(x).method_by_name(&name![call_once])), + .and_then(|x| { + db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_once)) + }), }) } @@ -2633,10 +2637,7 @@ impl Evaluator<'_> { let static_data = self.db.static_data(st); let result = if !static_data.is_extern { let konst = self.db.const_eval_static(st).map_err(|e| { - MirEvalError::ConstEvalError( - static_data.name.as_str().unwrap_or("_").to_owned(), - Box::new(e), - ) + MirEvalError::ConstEvalError(static_data.name.as_str().to_owned(), Box::new(e)) })?; self.allocate_const_in_heap(locals, &konst)? } else { @@ -2693,7 +2694,7 @@ impl Evaluator<'_> { ) -> Result<()> { let Some(drop_fn) = (|| { let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?; - self.db.trait_data(drop_trait).method_by_name(&name![drop]) + self.db.trait_data(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop)) })() else { // in some tests we don't have drop trait in minicore, and // we can ignore drop in them. @@ -2797,14 +2798,13 @@ pub fn render_const_using_debug_impl( let resolver = owner.resolver(db.upcast()); let Some(TypeNs::TraitId(debug_trait)) = resolver.resolve_path_in_type_ns_fully( db.upcast(), - &hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments( - hir_expand::mod_path::PathKind::Abs, - [name![core], name![fmt], name![Debug]], - )), + &hir_def::path::Path::from_known_path_with_no_generic(path![core::fmt::Debug]), ) else { not_supported!("core::fmt::Debug not found"); }; - let Some(debug_fmt_fn) = db.trait_data(debug_trait).method_by_name(&name![fmt]) else { + let Some(debug_fmt_fn) = + db.trait_data(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt)) + else { not_supported!("core::fmt::Debug::fmt not found"); }; // a1 = &[""] @@ -2829,10 +2829,7 @@ pub fn render_const_using_debug_impl( evaluator.write_memory(a3.offset(5 * evaluator.ptr_size()), &[1])?; let Some(ValueNs::FunctionId(format_fn)) = resolver.resolve_path_in_value_ns_fully( db.upcast(), - &hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments( - hir_expand::mod_path::PathKind::Abs, - [name![std], name![fmt], name![format]], - )), + &hir_def::path::Path::from_known_path_with_no_generic(path![std::fmt::format]), ) else { not_supported!("std::fmt::format not found"); }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index ce22e9d2c2cb8..67e102b1ed183 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -8,12 +8,14 @@ use hir_def::{ builtin_type::{BuiltinInt, BuiltinUint}, resolver::HasResolver, }; +use hir_expand::name::Name; +use intern::sym; use crate::{ error_lifetime, mir::eval::{ - name, pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, - HirDisplay, Interned, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, + pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay, + Interned, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Substitution, Ty, TyBuilder, TyExt, }, @@ -64,7 +66,7 @@ impl Evaluator<'_> { }; if is_intrinsic { self.exec_intrinsic( - function_data.name.as_text().unwrap_or_default().as_str(), + function_data.name.as_str(), args, generic_args, destination, @@ -86,7 +88,7 @@ impl Evaluator<'_> { }; if is_platform_intrinsic { self.exec_platform_intrinsic( - function_data.name.as_text().unwrap_or_default().as_str(), + function_data.name.as_str(), args, generic_args, destination, @@ -104,7 +106,7 @@ impl Evaluator<'_> { }; if is_extern_c { self.exec_extern_c( - function_data.name.as_text().unwrap_or_default().as_str(), + function_data.name.as_str(), args, generic_args, destination, @@ -117,7 +119,7 @@ impl Evaluator<'_> { .attrs .iter() .filter_map(|it| it.path().as_ident()) - .filter_map(|it| it.as_str()) + .map(|it| it.as_str()) .find(|it| { [ "rustc_allocator", @@ -1274,10 +1276,11 @@ impl Evaluator<'_> { args.push(IntervalAndTy::new(addr, field, self, locals)?); } if let Some(target) = self.db.lang_item(self.crate_id, LangItem::FnOnce) { - if let Some(def) = target - .as_trait() - .and_then(|it| self.db.trait_data(it).method_by_name(&name![call_once])) - { + if let Some(def) = target.as_trait().and_then(|it| { + self.db + .trait_data(it) + .method_by_name(&Name::new_symbol_root(sym::call_once)) + }) { self.exec_fn_trait( def, &args, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 1a0a1b780a16e..1b8c772d80e32 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -1113,9 +1113,9 @@ impl<'ctx> MirLowerCtx<'ctx> { .iter() .map(|it| { let o = match it.1.name.as_str() { - Some("start") => lp.take(), - Some("end") => rp.take(), - Some("exhausted") => { + "start" => lp.take(), + "end" => rp.take(), + "exhausted" => { Some(Operand::from_bytes(Box::new([0]), TyBuilder::bool())) } _ => None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs index 4ad00909e4127..5e8a2dfb735f6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs @@ -4,7 +4,7 @@ use crate::mir::MutBorrowKind; use super::*; use hir_def::FunctionId; -use hir_expand::name; +use intern::sym; macro_rules! not_supported { ($it: expr) => { @@ -192,7 +192,7 @@ impl MirLowerCtx<'_> { if let Some(deref_fn) = self .db .trait_data(deref_trait) - .method_by_name(&name![deref_mut]) + .method_by_name(&Name::new_symbol_root(sym::deref_mut)) { break 'b deref_fn == f; } @@ -324,12 +324,17 @@ impl MirLowerCtx<'_> { mutability: bool, ) -> Result> { let (chalk_mut, trait_lang_item, trait_method_name, borrow_kind) = if !mutability { - (Mutability::Not, LangItem::Deref, name![deref], BorrowKind::Shared) + ( + Mutability::Not, + LangItem::Deref, + Name::new_symbol_root(sym::deref), + BorrowKind::Shared, + ) } else { ( Mutability::Mut, LangItem::DerefMut, - name![deref_mut], + Name::new_symbol_root(sym::deref_mut), BorrowKind::Mut { kind: MutBorrowKind::Default }, ) }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index 4283a94657b9f..ce9ffa284c904 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -12,7 +12,8 @@ use hir_def::{ lang_item::{LangItem, LangItemTarget}, BlockId, TraitId, }; -use hir_expand::name::{name, Name}; +use hir_expand::name::Name; +use intern::sym; use stdx::panic_context; use triomphe::Arc; @@ -256,9 +257,9 @@ impl FnTrait { pub fn method_name(self) -> Name { match self { - FnTrait::FnOnce => name!(call_once), - FnTrait::FnMut => name!(call_mut), - FnTrait::Fn => name!(call), + FnTrait::FnOnce => Name::new_symbol_root(sym::call_once), + FnTrait::FnMut => Name::new_symbol_root(sym::call_mut), + FnTrait::Fn => Name::new_symbol_root(sym::call), } } diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index 7b3ff7b06458b..af60c233e5519 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -12,6 +12,7 @@ use hir_def::{ }; use hir_expand::{mod_path::PathKind, name::Name}; use hir_ty::{db::HirDatabase, method_resolution}; +use span::SyntaxContextId; use crate::{ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, @@ -328,7 +329,7 @@ fn doc_modpath_from_str(link: &str) -> Option { let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { Ok(idx) => Name::new_tuple_field(idx), Err(_) => { - Name::new_text_dont_use(segment.split_once('<').map_or(segment, |it| it.0).into()) + Name::new(segment.split_once('<').map_or(segment, |it| it.0), SyntaxContextId::ROOT) } }); Some(ModPath::from_segments(kind, parts)) diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 016f3418517f9..f90656c75f590 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -58,7 +58,7 @@ use hir_def::{ TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{ - attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult, + attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult, }; use hir_ty::{ all_super_traits, autoderef, check_orphan_rules, @@ -131,7 +131,7 @@ pub use { change::ChangeWithProcMacros, hygiene::{marks_rev, SyntaxContextExt}, inert_attr_macro::AttributeTemplate, - name::{known, Name}, + name::Name, proc_macro::ProcMacros, tt, ExpandResult, HirFileId, HirFileIdExt, InFile, InMacroFile, InRealFile, MacroFileId, MacroFileIdExt, @@ -145,6 +145,7 @@ pub use { }, // FIXME: Properly encapsulate mir hir_ty::{mir, Interner as ChalkTyInterner}, + intern::{sym, Symbol}, }; // These are negative re-exports: pub using these names is forbidden, they @@ -1826,7 +1827,7 @@ impl DefWithBody { continue; } let mut need_mut = &mol[local]; - if body[binding_id].name.as_str() == Some("self") + if body[binding_id].name == sym::self_ && need_mut == &mir::MutabilityReason::Unused { need_mut = &mir::MutabilityReason::Not; @@ -1836,7 +1837,7 @@ impl DefWithBody { match (need_mut, is_mut) { (mir::MutabilityReason::Unused, _) => { - let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_')); + let should_ignore = body[binding_id].name.as_str().starts_with('_'); if !should_ignore { acc.push(UnusedVariable { local }.into()) } @@ -1866,7 +1867,7 @@ impl DefWithBody { } (mir::MutabilityReason::Not, true) => { if !infer.mutated_bindings_in_closure.contains(&binding_id) { - let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_')); + let should_ignore = body[binding_id].name.as_str().starts_with('_'); if !should_ignore { acc.push(UnusedMut { local }.into()) } @@ -2588,7 +2589,7 @@ pub struct StaticLifetime; impl StaticLifetime { pub fn name(self) -> Name { - known::STATIC_LIFETIME + Name::new_symbol_root(sym::tick_static) } } @@ -3248,7 +3249,7 @@ impl Local { } pub fn is_self(self, db: &dyn HirDatabase) -> bool { - self.name(db) == name![self] + self.name(db) == sym::self_ } pub fn is_mut(self, db: &dyn HirDatabase) -> bool { diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 81c57f6caeb63..45401702e9f00 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -25,11 +25,8 @@ use hir_def::{ }; use hir_expand::{ mod_path::path, + name::{AsName, Name}, HirFileId, InFile, InMacroFile, MacroFileId, MacroFileIdExt, - { - name, - name::{AsName, Name}, - }, }; use hir_ty::{ diagnostics::{ @@ -40,6 +37,7 @@ use hir_ty::{ method_resolution, Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, TyLoweringContext, }; +use intern::sym; use itertools::Itertools; use smallvec::SmallVec; use syntax::{ @@ -368,7 +366,7 @@ impl SourceAnalyzer { let items = into_future_trait.items(db); let into_future_type = items.into_iter().find_map(|item| match item { AssocItem::TypeAlias(alias) - if alias.name(db) == hir_expand::name![IntoFuture] => + if alias.name(db) == Name::new_symbol_root(sym::IntoFuture) => { Some(alias) } @@ -398,14 +396,17 @@ impl SourceAnalyzer { // Since deref kind is inferenced and stored in `InferenceResult.method_resolution`, // use that result to find out which one it is. let (deref_trait, deref) = - self.lang_trait_fn(db, LangItem::Deref, &name![deref])?; + self.lang_trait_fn(db, LangItem::Deref, &Name::new_symbol_root(sym::deref))?; self.infer .as_ref() .and_then(|infer| { let expr = self.expr_id(db, &prefix_expr.clone().into())?; let (func, _) = infer.method_resolution(expr)?; - let (deref_mut_trait, deref_mut) = - self.lang_trait_fn(db, LangItem::DerefMut, &name![deref_mut])?; + let (deref_mut_trait, deref_mut) = self.lang_trait_fn( + db, + LangItem::DerefMut, + &Name::new_symbol_root(sym::deref_mut), + )?; if func == deref_mut { Some((deref_mut_trait, deref_mut)) } else { @@ -414,8 +415,12 @@ impl SourceAnalyzer { }) .unwrap_or((deref_trait, deref)) } - ast::UnaryOp::Not => self.lang_trait_fn(db, LangItem::Not, &name![not])?, - ast::UnaryOp::Neg => self.lang_trait_fn(db, LangItem::Neg, &name![neg])?, + ast::UnaryOp::Not => { + self.lang_trait_fn(db, LangItem::Not, &Name::new_symbol_root(sym::not))? + } + ast::UnaryOp::Neg => { + self.lang_trait_fn(db, LangItem::Neg, &Name::new_symbol_root(sym::neg))? + } }; let ty = self.ty_of_expr(db, &prefix_expr.expr()?)?; @@ -435,15 +440,19 @@ impl SourceAnalyzer { let base_ty = self.ty_of_expr(db, &index_expr.base()?)?; let index_ty = self.ty_of_expr(db, &index_expr.index()?)?; - let (index_trait, index_fn) = self.lang_trait_fn(db, LangItem::Index, &name![index])?; + let (index_trait, index_fn) = + self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index))?; let (op_trait, op_fn) = self .infer .as_ref() .and_then(|infer| { let expr = self.expr_id(db, &index_expr.clone().into())?; let (func, _) = infer.method_resolution(expr)?; - let (index_mut_trait, index_mut_fn) = - self.lang_trait_fn(db, LangItem::IndexMut, &name![index_mut])?; + let (index_mut_trait, index_mut_fn) = self.lang_trait_fn( + db, + LangItem::IndexMut, + &Name::new_symbol_root(sym::index_mut), + )?; if func == index_mut_fn { Some((index_mut_trait, index_mut_fn)) } else { diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index 02905ca2ce44d..a6e69d7992b23 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -239,7 +239,7 @@ impl<'a> SymbolCollector<'a> { fn collect_from_trait(&mut self, trait_id: TraitId) { let trait_data = self.db.trait_data(trait_id); - self.with_container_name(trait_data.name.as_text(), |s| { + self.with_container_name(Some(trait_data.name.as_str().into()), |s| { for &(_, assoc_item_id) in &trait_data.items { s.push_assoc_item(assoc_item_id); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs index ab25e0167bfe7..c1fcb8e44db84 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -470,7 +470,7 @@ fn add_enum_def( .module() .scope(ctx.db(), Some(*target_module)) .iter() - .any(|(name, _)| name.as_str() == Some("Bool")) + .any(|(name, _)| name.as_str() == "Bool") { return None; } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs index 61b7b41217760..27e39f6f8ab26 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs @@ -1,4 +1,4 @@ -use hir::{known, AsAssocItem, Semantics}; +use hir::{sym, AsAssocItem, Semantics}; use ide_db::{ famous_defs::FamousDefs, syntax_helpers::node_ext::{ @@ -223,7 +223,7 @@ fn option_variants( let fam = FamousDefs(sema, sema.scope(expr)?.krate()); let option_variants = fam.core_option_Option()?.variants(sema.db); match &*option_variants { - &[variant0, variant1] => Some(if variant0.name(sema.db) == known::None { + &[variant0, variant1] => Some(if variant0.name(sema.db) == sym::None { (variant0, variant1) } else { (variant1, variant0) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs index db96c8fe40aa5..d85147e84b20c 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs @@ -1,4 +1,4 @@ -use hir::known; +use hir::{sym, Name}; use ide_db::famous_defs::FamousDefs; use stdx::format_to; use syntax::{ @@ -149,7 +149,11 @@ fn is_ref_and_impls_iter_method( ast::Expr::RefExpr(r) => r, _ => return None, }; - let wanted_method = if ref_expr.mut_token().is_some() { known::iter_mut } else { known::iter }; + let wanted_method = Name::new_symbol_root(if ref_expr.mut_token().is_some() { + sym::iter_mut + } else { + sym::iter + }); let expr_behind_ref = ref_expr.expr()?; let ty = sema.type_of_expr(&expr_behind_ref)?.adjusted(); let scope = sema.scope(iterable.syntax())?; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs index 666e1a1496e03..62bb6dff21e52 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs @@ -169,8 +169,8 @@ fn get_names_in_scope( let mut names = FxHashSet::default(); scope.process_all_names(&mut |name, scope| { - if let (Some(name), hir::ScopeDef::Local(_)) = (name.as_text(), scope) { - names.insert(name); + if let hir::ScopeDef::Local(_) = scope { + names.insert(name.as_str().into()); } }); Some(names) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs index 4d369e705e88e..05210e66ac24d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs @@ -1,4 +1,4 @@ -use hir::{known, HasSource, Name}; +use hir::{sym, HasSource, Name}; use syntax::{ ast::{self, HasName}, AstNode, @@ -54,13 +54,13 @@ pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext< } let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?; - let len_fn = get_impl_method(ctx, &impl_, &known::len)?; + let len_fn = get_impl_method(ctx, &impl_, &Name::new_symbol_root(sym::len))?; if !len_fn.ret_type(ctx.sema.db).is_usize() { cov_mark::hit!(len_fn_different_return_type); return None; } - if get_impl_method(ctx, &impl_, &known::is_empty).is_some() { + if get_impl_method(ctx, &impl_, &Name::new_symbol_root(sym::is_empty)).is_some() { cov_mark::hit!(is_empty_already_implemented); return None; } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index 8c9fe23bb0bdd..137b8d13171fe 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -2,7 +2,7 @@ use std::collections::BTreeSet; use ast::make; use either::Either; -use hir::{db::HirDatabase, PathResolution, Semantics, TypeInfo}; +use hir::{db::HirDatabase, sym, PathResolution, Semantics, TypeInfo}; use ide_db::{ base_db::{FileId, FileRange}, defs::Definition, @@ -430,10 +430,7 @@ fn inline( let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty); - let is_self = param - .name(sema.db) - .and_then(|name| name.as_text()) - .is_some_and(|name| name == "self"); + let is_self = param.name(sema.db).is_some_and(|name| name == sym::self_); if is_self { let mut this_pat = make::ident_pat(false, false, make::name("this")); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs index 37ea5123a71e6..12d025f07594e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_method_eager_lazy.rs @@ -47,7 +47,7 @@ pub(crate) fn replace_with_lazy_method(acc: &mut Assists, ctx: &AssistContext<'_ None, None, |func| { - let valid = func.name(ctx.sema.db).as_str() == Some(&*method_name_lazy) + let valid = func.name(ctx.sema.db).as_str() == &*method_name_lazy && func.num_params(ctx.sema.db) == n_params && { let params = func.params_without_self(ctx.sema.db); @@ -133,7 +133,7 @@ pub(crate) fn replace_with_eager_method(acc: &mut Assists, ctx: &AssistContext<' None, None, |func| { - let valid = func.name(ctx.sema.db).as_str() == Some(method_name_eager) + let valid = func.name(ctx.sema.db).as_str() == method_name_eager && func.num_params(ctx.sema.db) == n_params; valid.then_some(func) }, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index ba6ef1921ac63..c67693ea2bb89 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -88,8 +88,8 @@ pub fn has_test_related_attribute(attrs: &hir::AttrsWithOwner) -> bool { let path = attr.path(); (|| { Some( - path.segments().first()?.as_text()?.starts_with("test") - || path.segments().last()?.as_text()?.ends_with("test"), + path.segments().first()?.as_str().starts_with("test") + || path.segments().last()?.as_str().ends_with("test"), ) })() .unwrap_or_default() diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index 995a4443edff5..4a8ea171805e2 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -24,7 +24,7 @@ pub(crate) mod vis; use std::iter; -use hir::{known, HasAttrs, ImportPathConfig, ScopeDef, Variant}; +use hir::{sym, HasAttrs, ImportPathConfig, Name, ScopeDef, Variant}; use ide_db::{imports::import_assets::LocatedImport, RootDatabase, SymbolKind}; use syntax::{ast, SmolStr}; @@ -618,7 +618,7 @@ fn enum_variants_with_paths( let mut process_variant = |variant: Variant| { let self_path = hir::ModPath::from_segments( hir::PathKind::Plain, - iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))), + iter::once(Name::new_symbol_root(sym::Self_)).chain(iter::once(variant.name(ctx.db))), ); cb(acc, ctx, variant, self_path); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/macro_use.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/macro_use.rs index f45f9cba258de..7e3a62405a78c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/macro_use.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/macro_use.rs @@ -18,7 +18,7 @@ pub(super) fn complete_macro_use( for mod_def in krate.root_module().declarations(ctx.db) { if let ModuleDef::Macro(mac) = mod_def { let mac_name = mac.name(ctx.db); - let Some(mac_name) = mac_name.as_str() else { continue }; + let mac_name = mac_name.as_str(); let existing_import = existing_imports .iter() diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index a4f092cc498ef..d3290db4ef82b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -1,5 +1,6 @@ //! Completes references after dot (fields and method calls). +use hir::{sym, Name}; use ide_db::FxHashSet; use syntax::SmolStr; @@ -90,12 +91,14 @@ pub(crate) fn complete_undotted_self( in_breakable: expr_ctx.in_breakable, }, }, - Some(hir::known::SELF_PARAM), + Some(Name::new_symbol_root(sym::self_)), field, &ty, ) }, - |acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty), + |acc, field, ty| { + acc.add_tuple_field(ctx, Some(Name::new_symbol_root(sym::self_)), field, &ty) + }, true, false, ); @@ -112,7 +115,7 @@ pub(crate) fn complete_undotted_self( }, }, func, - Some(hir::known::SELF_PARAM), + Some(Name::new_symbol_root(sym::self_)), None, ) }); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 01f9368aa4ebf..72b36922da0bd 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -1,6 +1,6 @@ //! Completion of names from the current scope in expression position. -use hir::{ImportPathConfig, ScopeDef}; +use hir::{sym, ImportPathConfig, Name, ScopeDef}; use syntax::ast; use crate::{ @@ -190,7 +190,7 @@ pub(crate) fn complete_expr_path( path_ctx, strukt, None, - Some(hir::known::SELF_TYPE), + Some(Name::new_symbol_root(sym::Self_)), ); } } @@ -210,7 +210,12 @@ pub(crate) fn complete_expr_path( acc.add_union_literal(ctx, un, path, None); if complete_self { - acc.add_union_literal(ctx, un, None, Some(hir::known::SELF_TYPE)); + acc.add_union_literal( + ctx, + un, + None, + Some(Name::new_symbol_root(sym::Self_)), + ); } } hir::Adt::Enum(e) => { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs index 2c6cbf6146a95..541ccf2d198e3 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs @@ -7,7 +7,7 @@ //! there is no value in lifting these out into the outline module test since they will either not //! show up for normal completions, or they won't show completions other than lifetimes depending //! on the fixture input. -use hir::{known, ScopeDef}; +use hir::{sym, Name, ScopeDef}; use syntax::{ast, TokenText}; use crate::{ @@ -47,7 +47,7 @@ pub(crate) fn complete_lifetime( } }); if param_lifetime.is_none() { - acc.add_lifetime(ctx, known::STATIC_LIFETIME); + acc.add_lifetime(ctx, Name::new_symbol_root(sym::tick_static)); } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs index 27e9d1d6cfe0c..5fe6cd0e90743 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs @@ -55,9 +55,8 @@ pub(crate) fn complete_use_path( if !ctx.check_stability(def.attrs(ctx.db).as_deref()) { continue; } - let is_name_already_imported = name - .as_text() - .map_or(false, |text| already_imported_names.contains(text.as_str())); + let is_name_already_imported = + already_imported_names.contains(name.as_str()); let add_resolution = match def { ScopeDef::Unknown if unknown_is_current(&name) => { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index a14fe24fa75d7..1e972b9b4ce06 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -823,13 +823,13 @@ fn classify_name_ref( for item in trait_.items_with_supertraits(sema.db) { match item { hir::AssocItem::TypeAlias(assoc_ty) => { - if assoc_ty.name(sema.db).as_str()? == arg_name { + if assoc_ty.name(sema.db).as_str() == arg_name { override_location = Some(TypeLocation::AssocTypeEq); return None; } }, hir::AssocItem::Const(const_) => { - if const_.name(sema.db)?.as_str()? == arg_name { + if const_.name(sema.db)?.as_str() == arg_name { override_location = Some(TypeLocation::AssocConstEq); return None; } @@ -867,7 +867,7 @@ fn classify_name_ref( let trait_items = trait_.items_with_supertraits(sema.db); let assoc_ty = trait_items.iter().find_map(|item| match item { hir::AssocItem::TypeAlias(assoc_ty) => { - (assoc_ty.name(sema.db).as_str()? == arg_name) + (assoc_ty.name(sema.db).as_str() == arg_name) .then_some(assoc_ty) }, _ => None, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index fe9e2e5268a99..15c20f11863b6 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -280,8 +280,7 @@ pub(crate) fn render_expr( let mut snippet_formatter = |ty: &hir::Type| { let arg_name = ty .as_adt() - .and_then(|adt| adt.name(ctx.db).as_text()) - .map(|s| stdx::to_lower_snake_case(s.as_str())) + .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str())) .unwrap_or_else(|| String::from("_")); let res = format!("${{{i}:{arg_name}}}"); i += 1; @@ -290,8 +289,7 @@ pub(crate) fn render_expr( let mut label_formatter = |ty: &hir::Type| { ty.as_adt() - .and_then(|adt| adt.name(ctx.db).as_text()) - .map(|s| stdx::to_lower_snake_case(s.as_str())) + .map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str())) .unwrap_or_else(|| String::from("...")) }; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index 48c9d624f63ac..c15e91c404839 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -188,7 +188,7 @@ fn compute_return_type_match( CompletionRelevanceReturnType::Constructor } else if ret_type .as_adt() - .and_then(|adt| adt.name(db).as_str().map(|name| name.ends_with("Builder"))) + .map(|adt| adt.name(db).as_str().ends_with("Builder")) .unwrap_or(false) { // fn([..]) -> [..]Builder @@ -227,11 +227,7 @@ pub(super) fn add_call_parens<'b>( None => { let name = match param.ty().as_adt() { None => "_".to_owned(), - Some(adt) => adt - .name(ctx.db) - .as_text() - .map(|s| to_lower_snake_case(s.as_str())) - .unwrap_or_else(|| "_".to_owned()), + Some(adt) => to_lower_snake_case(adt.name(ctx.db).as_str()), }; f(&format_args!("${{{}:{name}}}", index + offset)) } @@ -264,7 +260,7 @@ pub(super) fn add_call_parens<'b>( fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'static str { if let Some(derefed_ty) = ty.remove_ref() { for (name, local) in ctx.locals.iter() { - if name.as_text().as_deref() == Some(arg) { + if name.as_str() == arg { return if local.ty(ctx.db) == derefed_ty { if ty.is_mutable_reference() { "&mut " diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index a75a708d95692..dbb2adcd301f5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -144,7 +144,7 @@ impl Definition { Definition::Local(it) => it.name(db), Definition::GenericParam(it) => it.name(db), Definition::Label(it) => it.name(db), - Definition::BuiltinLifetime(StaticLifetime) => hir::known::STATIC_LIFETIME, + Definition::BuiltinLifetime(it) => it.name(), Definition::BuiltinAttr(_) => return None, // FIXME Definition::ToolModule(_) => return None, // FIXME Definition::DeriveHelper(it) => it.name(db), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 088717a66e590..4814394de6b29 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -389,16 +389,16 @@ fn import_for_item( let mut import_path_candidate_segments = import_path_candidate.segments().iter().rev(); let predicate = |it: EitherOrBoth<&SmolStr, &Name>| match it { // segments match, check next one - EitherOrBoth::Both(a, b) if b.as_str() == Some(&**a) => None, + EitherOrBoth::Both(a, b) if b.as_str() == &**a => None, // segments mismatch / qualifier is longer than the path, bail out EitherOrBoth::Both(..) | EitherOrBoth::Left(_) => Some(false), // all segments match and we have exhausted the qualifier, proceed EitherOrBoth::Right(_) => Some(true), }; if item_as_assoc.is_none() { - let item_name = item_name(db, original_item)?.as_text()?; + let item_name = item_name(db, original_item)?; let last_segment = import_path_candidate_segments.next()?; - if last_segment.as_str() != Some(&*item_name) { + if *last_segment != item_name { return None; } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs index e21d54ccd0e5b..84a388a460b82 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs @@ -472,7 +472,7 @@ fn find_trait_for_assoc_item( }); for name in names { - if assoc_item_name.as_str() == name.as_text()?.as_str() { + if assoc_item_name.as_str() == name.as_str() { // It is fine to return the first match because in case of // multiple possibilities, the exact trait must be disambiguated // in the definition of trait being implemented, so this search diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index 6a809cb0cefa8..4cdb279a21ca6 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -1,7 +1,7 @@ use either::Either; use hir::{ db::{ExpandDatabase, HirDatabase}, - known, AssocItem, HirDisplay, HirFileIdExt, ImportPathConfig, InFile, Type, + sym, AssocItem, HirDisplay, HirFileIdExt, ImportPathConfig, InFile, Type, }; use ide_db::{ assists::Assist, famous_defs::FamousDefs, imports::import_assets::item_for_path_search, @@ -210,7 +210,7 @@ fn get_default_constructor( let has_new_func = ty .iterate_assoc_items(ctx.sema.db, krate, |assoc_item| { if let AssocItem::Function(func) = assoc_item { - if func.name(ctx.sema.db) == known::new + if func.name(ctx.sema.db) == sym::new && func.assoc_fn_params(ctx.sema.db).is_empty() { return Some(()); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 41357b59622bf..46c373d8df081 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -76,7 +76,7 @@ fn field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option Some(alias), + hir::AssocItem::TypeAlias(alias) if alias.name(db) == sym::Item => Some(alias), _ => None, })?; if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs index 51855eeae232e..b60a80a8ac6b5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs @@ -46,7 +46,7 @@ pub(crate) fn hints( } let name = param.name(sema.db); - let param_name = name.as_str()?; + let param_name = name.as_str(); let should_hide = { let argument = get_string_representation(&arg)?; diff --git a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs index 99e2430860794..b27dc60ffafc7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs +++ b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs @@ -66,8 +66,11 @@ fn discover_tests_in_module( let mut r = vec![]; for c in module.children(db) { - let module_name = - c.name(db).as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]").to_owned(); + let module_name = c + .name(db) + .as_ref() + .map(|n| n.as_str().to_owned()) + .unwrap_or_else(|| "[mod without name]".to_owned()); let module_id = format!("{prefix_id}::{module_name}"); let module_children = discover_tests_in_module(db, c, module_id.clone(), only_in_this_file); if !module_children.is_empty() { @@ -94,7 +97,7 @@ fn discover_tests_in_module( continue; } let nav = f.try_to_nav(db).map(|r| r.call_site); - let fn_name = f.name(db).as_str().unwrap_or("[function without name]").to_owned(); + let fn_name = f.name(db).as_str().to_owned(); r.push(TestItem { id: format!("{prefix_id}::{fn_name}"), kind: TestItemKind::Function, @@ -153,7 +156,7 @@ fn find_module_id_and_test_parents( let parent = Some(id.clone()); id += "::"; let module_name = &module.name(sema.db); - let module_name = module_name.as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]"); + let module_name = module_name.as_ref().map(|n| n.as_str()).unwrap_or("[mod without name]"); id += module_name; let nav = NavigationTarget::from_module_to_decl(sema.db, module).call_site; r.push(TestItem { diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs index 826447d058dff..ad99c2162cd62 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs @@ -64,11 +64,7 @@ enum FieldOrTupleIdx { impl FieldOrTupleIdx { fn name(&self, db: &RootDatabase) -> String { match *self { - FieldOrTupleIdx::Field(f) => f - .name(db) - .as_str() - .map(|s| s.to_owned()) - .unwrap_or_else(|| format!(".{}", f.name(db).as_tuple_index().unwrap())), + FieldOrTupleIdx::Field(f) => f.name(db).as_str().to_owned(), FieldOrTupleIdx::TupleIdx(i) => format!(".{i}"), } } @@ -189,14 +185,7 @@ pub(crate) fn view_memory_layout( | Definition::SelfType(_) => "[ROOT]".to_owned(), // def is an item - def => def - .name(db) - .map(|n| { - n.as_str() - .map(|s| s.to_owned()) - .unwrap_or_else(|| format!(".{}", n.as_tuple_index().unwrap())) - }) - .unwrap_or("[ROOT]".to_owned()), + def => def.name(db).map(|n| n.as_str().to_owned()).unwrap_or("[ROOT]".to_owned()), }; let typename = ty.display(db).to_string(); diff --git a/src/tools/rust-analyzer/crates/intern/src/lib.rs b/src/tools/rust-analyzer/crates/intern/src/lib.rs index 868d03caff557..58327419f6314 100644 --- a/src/tools/rust-analyzer/crates/intern/src/lib.rs +++ b/src/tools/rust-analyzer/crates/intern/src/lib.rs @@ -21,7 +21,7 @@ type Guard = dashmap::RwLockWriteGuard< >; mod symbol; -pub use self::symbol::{symbols, Symbol}; +pub use self::symbol::{symbols as sym, Symbol}; pub struct Interned { arc: Arc, diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 290657a3d3627..1517f516fc15d 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -1,5 +1,5 @@ //! Attempt at flexible symbol interning, allowing to intern and free strings at runtime while also -//! supporting +//! supporting compile time declaration of symbols that will never be freed. use std::{ borrow::Borrow, diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index a1cf6e0941466..04bf4dff50c3e 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -11,10 +11,13 @@ use crate::{ Symbol, }; macro_rules! define_symbols { - ($($name:ident),* $(,)?) => { + (@WITH_NAME: $($alias:ident = $value:literal),* $(,)? @PLAIN: $($name:ident),* $(,)?) => { $( pub const $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) }; )* + $( + pub const $alias: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&$value) }; + )* pub(super) fn prefill() -> DashMap> { @@ -33,12 +36,45 @@ macro_rules! define_symbols { let shard_idx_ = dashmap_.determine_shard(hash_ as usize); dashmap_.shards_mut()[shard_idx_].get_mut().raw_entry_mut().from_hash(hash_, |k| k == &proxy_).insert(proxy_, SharedValue::new(())); )* + $( + + let proxy_ = SymbolProxy($alias.repr); + let hash_ = hash_thing_(dashmap_.hasher(), &proxy_); + let shard_idx_ = dashmap_.determine_shard(hash_ as usize); + dashmap_.shards_mut()[shard_idx_].get_mut().raw_entry_mut().from_hash(hash_, |k| k == &proxy_).insert(proxy_, SharedValue::new(())); + )* } dashmap_ } }; } define_symbols! { + @WITH_NAME: + + self_ = "self", + Self_ = "Self", + tick_static = "'static", + dollar_crate = "$crate", + MISSING_NAME = "[missing name]", + INTEGER_0 = "0", + INTEGER_1 = "1", + INTEGER_2 = "2", + INTEGER_3 = "3", + INTEGER_4 = "4", + INTEGER_5 = "5", + INTEGER_6 = "6", + INTEGER_7 = "7", + INTEGER_8 = "8", + INTEGER_9 = "9", + INTEGER_10 = "10", + INTEGER_11 = "11", + INTEGER_12 = "12", + INTEGER_13 = "13", + INTEGER_14 = "14", + INTEGER_15 = "15", + fn_ = "fn", + + @PLAIN: add_assign, add, alloc, @@ -52,10 +88,88 @@ define_symbols! { bitor, bitxor_assign, bitxor, + transmute_opts, + transmute_trait, + coerce_unsized, + dispatch_from_dyn,destruct, bool, + panic, + begin_panic, + panic_nounwind, + panic_fmt, + panic_misaligned_pointer_dereference, + panic_display, + const_panic_fmt, + panic_bounds_check, + panic_info, + panic_location, + panic_impl, + panic_cannot_unwind, + sized, + unsize, + format_alignment, + start, + format_argument, + format_arguments, + format_count, + format_placeholder, + format_unsafe_arg, + exchange_malloc, + box_free, + drop_in_place, + alloc_layout, + eh_personality, + eh_catch_typeinfo, + phantom_data, + manually_drop, + maybe_uninit, + align_offset, + termination, + tuple_trait, + slice_len_fn, + from_residual, + from_output, + from_yeet, + pointer_like, + const_param_ty, + Poll, + Ready, + Pending, + ResumeTy, + get_context, + Context, + Some, + Err, + Continue, + Break, + into_iter, + new_unchecked, + range_inclusive_new, + CStr, + fn_ptr_trait, + freeze, + coroutine_state, + c_void, + coroutine, + unpin, + pin, + fn_ptr_addr, + structural_teq, + fn_once_output, + copy, + clone, + sync, + discriminant_kind, Box, + structural_peq, boxed, branch, + discriminant_type, + pointee_trait, + metadata_type, + dyn_metadata, + deref_target, + receiver, call_mut, call_once, call, @@ -168,6 +282,7 @@ define_symbols! { not, Not, Ok, + opaque, ops, option_env, option, @@ -204,6 +319,9 @@ define_symbols! { rust_2018, rust_2021, rust_2024, + rustc_coherence_is_core, + rustc_macro_transparency, + semitransparent, shl_assign, shl, shr_assign, @@ -220,6 +338,7 @@ define_symbols! { test_case, test, trace_macros, + transparent, Try, u128, u16, From 292b9de2beaa5d9ccb0ef2beac1da2968f9f1b55 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 12 Jul 2024 17:11:12 +0200 Subject: [PATCH 015/489] Fix cloning Symbols not increasing their ref count --- .../rust-analyzer/crates/intern/src/symbol.rs | 90 +++++++++++++------ .../crates/intern/src/symbol/symbols.rs | 1 + 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 1517f516fc15d..9f7a788d006c8 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -5,7 +5,7 @@ use std::{ borrow::Borrow, fmt, hash::{BuildHasherDefault, Hash, Hasher}, - mem, + mem::{self, ManuallyDrop}, ptr::NonNull, sync::OnceLock, }; @@ -25,6 +25,15 @@ const _: () = assert!(std::mem::align_of::>() == std::mem::align_of::<& const _: () = assert!(std::mem::size_of::>>() == std::mem::size_of::<&&str>()); const _: () = assert!(std::mem::align_of::>>() == std::mem::align_of::<&&str>()); +const _: () = + assert!(std::mem::size_of::<*const *const str>() == std::mem::size_of::()); +const _: () = + assert!(std::mem::align_of::<*const *const str>() == std::mem::align_of::()); + +const _: () = assert!(std::mem::size_of::>>() == std::mem::size_of::()); +const _: () = + assert!(std::mem::align_of::>>() == std::mem::align_of::()); + /// A pointer that points to a pointer to a `str`, it may be backed as a `&'static &'static str` or /// `Arc>` but its size is that of a thin pointer. The active variant is encoded as a tag /// in the LSB of the alignment niche. @@ -40,19 +49,24 @@ impl TaggedArcPtr { const BOOL_BITS: usize = true as usize; const fn non_arc(r: &'static &'static str) -> Self { - Self { - // SAFETY: The pointer is non-null as it is derived from a reference - // Ideally we would call out to `pack_arc` but for a `false` tag, unfortunately the - // packing stuff requires reading out the pointer to an integer which is not supported - // in const contexts, so here we make use of the fact that for the non-arc version the - // tag is false (0) and thus does not need touching the actual pointer value.ext) - packed: unsafe { - NonNull::new_unchecked((r as *const &str).cast::<*const str>().cast_mut()) - }, - } + assert!( + mem::align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS + ); + // SAFETY: The pointer is non-null as it is derived from a reference + // Ideally we would call out to `pack_arc` but for a `false` tag, unfortunately the + // packing stuff requires reading out the pointer to an integer which is not supported + // in const contexts, so here we make use of the fact that for the non-arc version the + // tag is false (0) and thus does not need touching the actual pointer value.ext) + + let packed = + unsafe { NonNull::new_unchecked((r as *const &str).cast::<*const str>().cast_mut()) }; + Self { packed } } fn arc(arc: Arc>) -> Self { + assert!( + mem::align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS + ); Self { packed: Self::pack_arc( // Safety: `Arc::into_raw` always returns a non null pointer @@ -63,12 +77,14 @@ impl TaggedArcPtr { /// Retrieves the tag. #[inline] - pub(crate) fn try_as_arc_owned(self) -> Option>> { + pub(crate) fn try_as_arc_owned(self) -> Option>>> { // Unpack the tag from the alignment niche let tag = Strict::addr(self.packed.as_ptr()) & Self::BOOL_BITS; if tag != 0 { // Safety: We checked that the tag is non-zero -> true, so we are pointing to the data offset of an `Arc` - Some(unsafe { Arc::from_raw(self.pointer().as_ptr().cast::>()) }) + Some(ManuallyDrop::new(unsafe { + Arc::from_raw(self.pointer().as_ptr().cast::>()) + })) } else { None } @@ -122,10 +138,11 @@ impl TaggedArcPtr { } } -#[derive(PartialEq, Eq, Hash, Clone, Debug)] +#[derive(PartialEq, Eq, Hash, Debug)] pub struct Symbol { repr: TaggedArcPtr, } + const _: () = assert!(std::mem::size_of::() == std::mem::size_of::>()); const _: () = assert!(std::mem::align_of::() == std::mem::align_of::>()); @@ -185,19 +202,27 @@ impl Symbol { fn drop_slow(arc: &Arc>) { let (mut shard, hash) = Self::select_shard(arc); - if Arc::count(arc) != 2 { - // Another thread has interned another copy - return; + match Arc::count(arc) { + 0 => unreachable!(), + 1 => unreachable!(), + 2 => (), + _ => { + // Another thread has interned another copy + return; + } } - match shard.raw_entry_mut().from_key_hashed_nocheck::(hash, arc.as_ref()) { - RawEntryMut::Occupied(occ) => occ.remove_entry(), - RawEntryMut::Vacant(_) => unreachable!(), - } - .0 - .0 - .try_as_arc_owned() - .unwrap(); + ManuallyDrop::into_inner( + match shard.raw_entry_mut().from_key_hashed_nocheck::(hash, arc.as_ref()) { + RawEntryMut::Occupied(occ) => occ.remove_entry(), + RawEntryMut::Vacant(_) => unreachable!(), + } + .0 + .0 + .try_as_arc_owned() + .unwrap(), + ); + debug_assert_eq!(Arc::count(&arc), 1); // Shrink the backing storage if the shard is less than 50% occupied. if shard.len() * 2 < shard.capacity() { @@ -219,7 +244,13 @@ impl Drop for Symbol { Self::drop_slow(&arc); } // decrement the ref count - drop(arc); + ManuallyDrop::into_inner(arc); + } +} + +impl Clone for Symbol { + fn clone(&self) -> Self { + Self { repr: increase_arc_refcount(self.repr) } } } @@ -228,8 +259,7 @@ fn increase_arc_refcount(repr: TaggedArcPtr) -> TaggedArcPtr { return repr; }; // increase the ref count - mem::forget(arc.clone()); - mem::forget(arc); + mem::forget(Arc::clone(&arc)); repr } @@ -265,6 +295,7 @@ mod tests { let base_len = MAP.get().unwrap().len(); let hello = Symbol::intern("hello"); let world = Symbol::intern("world"); + let more_worlds = world.clone(); let bang = Symbol::intern("!"); let q = Symbol::intern("?"); assert_eq!(MAP.get().unwrap().len(), base_len + 4); @@ -275,6 +306,7 @@ mod tests { drop(q); assert_eq!(MAP.get().unwrap().len(), base_len + 3); let default = Symbol::intern("default"); + let many_worlds = world.clone(); assert_eq!(MAP.get().unwrap().len(), base_len + 3); assert_eq!( "hello default world!", @@ -285,6 +317,8 @@ mod tests { "hello world!", format!("{} {}{}", hello.as_str(), world.as_str(), bang.as_str()) ); + drop(many_worlds); + drop(more_worlds); drop(hello); drop(world); drop(bang); diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 04bf4dff50c3e..af1af0536c2e5 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -10,6 +10,7 @@ use crate::{ symbol::{SymbolProxy, TaggedArcPtr}, Symbol, }; + macro_rules! define_symbols { (@WITH_NAME: $($alias:ident = $value:literal),* $(,)? @PLAIN: $($name:ident),* $(,)?) => { $( From 5a292c954195678125a20aa219c2d2b3b718c56f Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sat, 13 Jul 2024 07:09:17 +0900 Subject: [PATCH 016/489] Allow macro expansions into `RestPat` in tuple args work as ellipsis like plain `RestPat` --- .../crates/hir-def/src/body/lower.rs | 44 ++++++++++-- .../src/handlers/mismatched_arg_count.rs | 69 +++++++++++++++++++ 2 files changed, 108 insertions(+), 5 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index be7068c807a5f..08490470eb142 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -4,6 +4,7 @@ use std::mem; use base_db::CrateId; +use either::Either; use hir_expand::{ name::{name, AsName, Name}, ExpandError, InFile, @@ -1432,14 +1433,12 @@ impl ExprCollector<'_> { has_leading_comma: bool, binding_list: &mut BindingList, ) -> (Box<[PatId]>, Option) { + let args: Vec<_> = args.map(|p| self.collect_pat_possibly_rest(p, binding_list)).collect(); // Find the location of the `..`, if there is one. Note that we do not // consider the possibility of there being multiple `..` here. - let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_))); + let ellipsis = args.iter().position(|p| p.is_right()); // We want to skip the `..` pattern here, since we account for it above. - let mut args: Vec<_> = args - .filter(|p| !matches!(p, ast::Pat::RestPat(_))) - .map(|p| self.collect_pat(p, binding_list)) - .collect(); + let mut args: Vec<_> = args.into_iter().filter_map(Either::left).collect(); // if there is a leading comma, the user is most likely to type out a leading pattern // so we insert a missing pattern at the beginning for IDE features if has_leading_comma { @@ -1449,6 +1448,41 @@ impl ExprCollector<'_> { (args.into_boxed_slice(), ellipsis) } + // `collect_pat` rejects `ast::Pat::RestPat`, but it should be handled in some cases that + // it is the macro expansion result of an arg sub-pattern in a slice or tuple pattern. + fn collect_pat_possibly_rest( + &mut self, + pat: ast::Pat, + binding_list: &mut BindingList, + ) -> Either { + match &pat { + ast::Pat::RestPat(_) => Either::Right(()), + ast::Pat::MacroPat(mac) => match mac.macro_call() { + Some(call) => { + let macro_ptr = AstPtr::new(&call); + let src = self.expander.in_file(AstPtr::new(&pat)); + let pat = + self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| { + if let Some(expanded_pat) = expanded_pat { + this.collect_pat_possibly_rest(expanded_pat, binding_list) + } else { + Either::Left(this.missing_pat()) + } + }); + if let Some(pat) = pat.left() { + self.source_map.pat_map.insert(src, pat); + } + pat + } + None => { + let ptr = AstPtr::new(&pat); + Either::Left(self.alloc_pat(Pat::Missing, ptr)) + } + }, + _ => Either::Left(self.collect_pat(pat, binding_list)), + } + } + // endregion: patterns /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 41c762c85b2cd..4242422663796 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -256,6 +256,75 @@ impl Foo { ); } + #[test] + fn rest_pat_in_macro_expansion() { + check_diagnostics( + r#" +// issue #17292 +#![allow(dead_code)] + +macro_rules! replace_with_2_dots { + ( $( $input:tt )* ) => { + .. + }; +} + +macro_rules! enum_str { + ( + $( + $variant:ident ( + $( $tfield:ty ),* + ) + ) + , + * + ) => { + enum Foo { + $( + $variant ( $( $tfield ),* ), + )* + } + + impl Foo { + fn variant_name_as_str(&self) -> &str { + match self { + $( + Self::$variant ( replace_with_2_dots!( $( $tfield ),* ) ) + => "", + )* + } + } + } + }; +} + +enum_str! { + TupleVariant1(i32), + TupleVariant2(), + TupleVariant3(i8,u8,i128) +} +"#, + ); + + check_diagnostics( + r#" +#![allow(dead_code)] +macro_rules! two_dots1 { + () => { .. }; +} + +macro_rules! two_dots2 { + () => { two_dots1!() }; +} + +fn test() { + let (_, _, two_dots1!()) = ((), 42); + let (_, two_dots2!(), _) = (1, true, 2, false, (), (), 3); +} +"#, + ); + } + #[test] fn varargs() { check_diagnostics( From 377a0a7696bbd33c38ac418e8c75428a147eb688 Mon Sep 17 00:00:00 2001 From: bors Date: Thu, 11 Jul 2024 08:55:34 +0000 Subject: [PATCH 017/489] Trigger VSCode to rename after extract variable assist is applied When the user applies the "Extract Variable" assist, the cursor is positioned at the newly inserted variable. This commit adds a command to the assist that triggers the rename action in VSCode. This way, the user can quickly rename the variable after applying the assist. Fixes part of: #17579 --- .../crates/ide-assists/src/assist_context.rs | 6 +++--- .../src/handlers/extract_variable.rs | 3 +++ .../crates/ide-assists/src/tests.rs | 20 +++++++++++-------- .../crates/ide-db/src/assists.rs | 11 +++++++++- .../crates/ide-db/src/source_change.rs | 15 ++++++++++---- .../trait_impl_redundant_assoc_item.rs | 2 +- .../src/handlers/typed_hole.rs | 2 +- .../src/handlers/unresolved_field.rs | 8 ++++---- .../src/handlers/unresolved_method.rs | 4 ++-- .../src/handlers/unused_variables.rs | 2 +- .../crates/ide-diagnostics/src/lib.rs | 2 +- src/tools/rust-analyzer/crates/ide/src/ssr.rs | 10 +++++----- .../crates/rust-analyzer/src/config.rs | 2 ++ .../crates/rust-analyzer/src/lsp/to_proto.rs | 18 +++++++++++++++-- .../rust-analyzer/editors/code/src/client.ts | 1 + .../editors/code/src/commands.ts | 6 ++++++ .../rust-analyzer/editors/code/src/main.ts | 1 + 17 files changed, 80 insertions(+), 33 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs index 8c7670e0cb71a..c459cdb735af0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs @@ -185,11 +185,11 @@ impl Assists { return None; } - let mut trigger_signature_help = false; + let mut command = None; let source_change = if self.resolve.should_resolve(&id) { let mut builder = SourceChangeBuilder::new(self.file); f(&mut builder); - trigger_signature_help = builder.trigger_signature_help; + command = builder.command.take(); Some(builder.finish()) } else { None @@ -197,7 +197,7 @@ impl Assists { let label = Label::new(label); let group = group.cloned(); - self.buf.push(Assist { id, label, group, target, source_change, trigger_signature_help }); + self.buf.push(Assist { id, label, group, target, source_change, command }); Some(()) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 36d3122651207..af21a839727a0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -135,6 +135,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op } } } + edit.rename(); } Anchor::Replace(stmt) => { cov_mark::hit!(test_extract_var_expr_stmt); @@ -149,6 +150,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op } } } + edit.rename(); } Anchor::WrapInBlock(to_wrap) => { let indent_to = to_wrap.indent_level(); @@ -192,6 +194,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op } } } + edit.rename(); // fixup indentation of block block.indent(indent_to); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index 2dcfda334b806..29dac4c550002 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -454,7 +454,7 @@ pub fn test_some_range(a: int) -> bool { group: None, target: 59..60, source_change: None, - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&extract_into_variable_assist); @@ -470,7 +470,7 @@ pub fn test_some_range(a: int) -> bool { group: None, target: 59..60, source_change: None, - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&extract_into_function_assist); @@ -500,7 +500,7 @@ pub fn test_some_range(a: int) -> bool { group: None, target: 59..60, source_change: None, - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&extract_into_variable_assist); @@ -516,7 +516,7 @@ pub fn test_some_range(a: int) -> bool { group: None, target: 59..60, source_change: None, - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&extract_into_function_assist); @@ -587,7 +587,9 @@ pub fn test_some_range(a: int) -> bool { is_snippet: true, }, ), - trigger_signature_help: false, + command: Some( + Rename, + ), } "#]] .assert_debug_eq(&extract_into_variable_assist); @@ -603,7 +605,7 @@ pub fn test_some_range(a: int) -> bool { group: None, target: 59..60, source_change: None, - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&extract_into_function_assist); @@ -666,7 +668,9 @@ pub fn test_some_range(a: int) -> bool { is_snippet: true, }, ), - trigger_signature_help: false, + command: Some( + Rename, + ), } "#]] .assert_debug_eq(&extract_into_variable_assist); @@ -715,7 +719,7 @@ pub fn test_some_range(a: int) -> bool { is_snippet: true, }, ), - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&extract_into_function_assist); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs index 7a7328f312d20..0ddbde49abc4f 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs @@ -29,7 +29,16 @@ pub struct Assist { /// cumbersome, especially if you want to embed an assist into another data /// structure, such as a diagnostic. pub source_change: Option, - pub trigger_signature_help: bool, + /// The command to execute after the assist is applied. + pub command: Option, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Command { + /// Show the parameter hints popup. + TriggerSignatureHelp, + /// Rename the just inserted item. + Rename, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs index 7ef7b7ae1d0f8..fba377417e30a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs @@ -5,7 +5,7 @@ use std::{collections::hash_map::Entry, iter, mem}; -use crate::SnippetCap; +use crate::{assists::Command, SnippetCap}; use base_db::{AnchoredPathBuf, FileId}; use itertools::Itertools; use nohash_hasher::IntMap; @@ -194,7 +194,7 @@ pub struct SourceChangeBuilder { pub edit: TextEditBuilder, pub file_id: FileId, pub source_change: SourceChange, - pub trigger_signature_help: bool, + pub command: Option, /// Maps the original, immutable `SyntaxNode` to a `clone_for_update` twin. pub mutated_tree: Option, @@ -236,7 +236,7 @@ impl SourceChangeBuilder { edit: TextEdit::builder(), file_id, source_change: SourceChange::default(), - trigger_signature_help: false, + command: None, mutated_tree: None, snippet_builder: None, } @@ -304,8 +304,15 @@ impl SourceChangeBuilder { let file_system_edit = FileSystemEdit::MoveFile { src, dst }; self.source_change.push_file_system_edit(file_system_edit); } + + /// Triggers the parameter hint popup after the assist is applied pub fn trigger_signature_help(&mut self) { - self.trigger_signature_help = true; + self.command = Some(Command::TriggerSignatureHelp); + } + + /// Renames the item at the cursor position after the assist is applied + pub fn rename(&mut self) { + self.command = Some(Command::Rename); } /// Adds a tabstop snippet to place the cursor before `node` diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs index a470ce72fc3e0..8c50960684dac 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs @@ -98,7 +98,7 @@ fn quickfix_for_redundant_assoc_item( group: None, target: range, source_change: Some(source_change_builder.finish()), - trigger_signature_help: false, + command: None, }]) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs index 4f04267adb1ea..3fa38ed9eeeec 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -82,7 +82,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option original_range.file_id, TextEdit::replace(original_range.range, code), )), - trigger_signature_help: false, + command: None, }) .collect(); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 41357b59622bf..66733223e2734 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -130,7 +130,7 @@ fn add_variant_to_union( group: None, target: error_range.range, source_change: Some(src_change_builder.finish()), - trigger_signature_help: false, + command: None, }) } @@ -173,7 +173,7 @@ fn add_field_to_struct_fix( group: None, target: error_range.range, source_change: Some(src_change_builder.finish()), - trigger_signature_help: false, + command: None, }) } None => { @@ -204,7 +204,7 @@ fn add_field_to_struct_fix( group: None, target: error_range.range, source_change: Some(src_change_builder.finish()), - trigger_signature_help: false, + command: None, }) } Some(FieldList::TupleFieldList(_tuple)) => { @@ -266,7 +266,7 @@ fn method_fix( file_id, TextEdit::insert(range.end(), "()".to_owned()), )), - trigger_signature_help: false, + command: None, }) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 42211cdbe5d46..46722f43d4fbb 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -108,7 +108,7 @@ fn field_fix( (file_id, TextEdit::insert(range.start(), "(".to_owned())), (file_id, TextEdit::insert(range.end(), ")".to_owned())), ])), - trigger_signature_help: false, + command: None, }) } @@ -191,7 +191,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) - file_id, TextEdit::replace(range, assoc_func_call_expr_string), )), - trigger_signature_help: false, + command: None, }) } else { None diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs index fdd4e862cafcd..f3ce306885733 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs @@ -73,7 +73,7 @@ fn fixes( diagnostic_range.file_id, TextEdit::replace(name_range, format!("_{}", var_name.display(db))), )), - trigger_signature_help: false, + command: None, }]) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 6d1226d65c5cf..d30ee1a1b966f 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -613,7 +613,7 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist { group: None, target, source_change: None, - trigger_signature_help: false, + command: None, } } diff --git a/src/tools/rust-analyzer/crates/ide/src/ssr.rs b/src/tools/rust-analyzer/crates/ide/src/ssr.rs index b49fe391bf258..6133c33c71a15 100644 --- a/src/tools/rust-analyzer/crates/ide/src/ssr.rs +++ b/src/tools/rust-analyzer/crates/ide/src/ssr.rs @@ -45,7 +45,7 @@ pub(crate) fn ssr_assists( group: Some(GroupLabel("Apply SSR".into())), target: comment_range, source_change, - trigger_signature_help: false, + command: None, }; ssr_assists.push(assist); @@ -143,7 +143,7 @@ mod tests { is_snippet: false, }, ), - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&apply_in_file_assist); @@ -196,7 +196,7 @@ mod tests { is_snippet: false, }, ), - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&apply_in_workspace_assist); @@ -236,7 +236,7 @@ mod tests { ), target: 10..21, source_change: None, - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&apply_in_file_assist); @@ -256,7 +256,7 @@ mod tests { ), target: 10..21, source_change: None, - trigger_signature_help: false, + command: None, } "#]] .assert_debug_eq(&apply_in_workspace_assist); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 3594cdda2e962..990ef77642c1b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -1135,6 +1135,7 @@ pub struct ClientCommandsConfig { pub show_reference: bool, pub goto_location: bool, pub trigger_parameter_hints: bool, + pub rename: bool, } #[derive(Debug)] @@ -1901,6 +1902,7 @@ impl Config { show_reference: get("rust-analyzer.showReferences"), goto_location: get("rust-analyzer.gotoLocation"), trigger_parameter_hints: get("editor.action.triggerParameterHints"), + rename: get("editor.action.rename"), } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index de394d3d11879..b0003fa89e3f2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -13,7 +13,7 @@ use ide::{ NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp, SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize, }; -use ide_db::{rust_doc::format_docs, FxHasher}; +use ide_db::{assists, rust_doc::format_docs, FxHasher}; use itertools::Itertools; use paths::{Utf8Component, Utf8Prefix}; use semver::VersionReq; @@ -1336,8 +1336,14 @@ pub(crate) fn code_action( command: None, }; - if assist.trigger_signature_help && snap.config.client_commands().trigger_parameter_hints { + if assist.command == Some(assists::Command::TriggerSignatureHelp) + && snap.config.client_commands().trigger_parameter_hints + { res.command = Some(command::trigger_parameter_hints()); + } else if assist.command == Some(assists::Command::Rename) + && snap.config.client_commands().rename + { + res.command = Some(command::rename()); } match (assist.source_change, resolve_data) { @@ -1715,6 +1721,14 @@ pub(crate) mod command { arguments: None, } } + + pub(crate) fn rename() -> lsp_types::Command { + lsp_types::Command { + title: "rename".into(), + command: "rust-analyzer.rename".into(), + arguments: None, + } + } } pub(crate) fn implementation_title(count: usize) -> String { diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts index 542233e7b9187..1599f4b13aea9 100644 --- a/src/tools/rust-analyzer/editors/code/src/client.ts +++ b/src/tools/rust-analyzer/editors/code/src/client.ts @@ -348,6 +348,7 @@ class ExperimentalFeatures implements lc.StaticFeature { "rust-analyzer.showReferences", "rust-analyzer.gotoLocation", "editor.action.triggerParameterHints", + "editor.action.rename", ], }, ...capabilities.experimental, diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts index 2b0b300106228..72ca2923dda1a 100644 --- a/src/tools/rust-analyzer/editors/code/src/commands.ts +++ b/src/tools/rust-analyzer/editors/code/src/commands.ts @@ -118,6 +118,12 @@ export function triggerParameterHints(_: CtxInit): Cmd { }; } +export function rename(_: CtxInit): Cmd { + return async () => { + await vscode.commands.executeCommand("editor.action.rename"); + }; +} + export function openLogs(ctx: CtxInit): Cmd { return async () => { if (ctx.client.outputChannel) { diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts index c96f2ae869e0c..a23f3656e3bff 100644 --- a/src/tools/rust-analyzer/editors/code/src/main.ts +++ b/src/tools/rust-analyzer/editors/code/src/main.ts @@ -190,6 +190,7 @@ function createCommands(): Record { runSingle: { enabled: commands.runSingle }, showReferences: { enabled: commands.showReferences }, triggerParameterHints: { enabled: commands.triggerParameterHints }, + rename: { enabled: commands.rename }, openLogs: { enabled: commands.openLogs }, revealDependency: { enabled: commands.revealDependency }, }; From 6351a2064261a8e1ec57d7dc8e1b1a1e6bf4e3fe Mon Sep 17 00:00:00 2001 From: Campbell Date: Sat, 13 Jul 2024 21:54:22 +1200 Subject: [PATCH 018/489] feat: Add incorrect case diagnostics for enum variant fields and all variables --- .../hir-ty/src/diagnostics/decl_check.rs | 93 +++++++++++-- .../src/handlers/incorrect_case.rs | 128 +++++++++++++++--- .../src/handlers/missing_match_arms.rs | 4 +- 3 files changed, 194 insertions(+), 31 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index 15ecf9aafcfc9..1e6cb85d3b0ca 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -17,8 +17,8 @@ use std::fmt; use hir_def::{ data::adt::VariantData, db::DefDatabase, hir::Pat, src::HasSource, AdtId, AttrDefId, ConstId, - EnumId, FunctionId, ItemContainerId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, - TraitId, TypeAliasId, + EnumId, EnumVariantId, FunctionId, ItemContainerId, Lookup, ModuleDefId, ModuleId, StaticId, + StructId, TraitId, TypeAliasId, }; use hir_expand::{ name::{AsName, Name}, @@ -353,17 +353,16 @@ impl<'a> DeclValidator<'a> { continue; }; - let is_param = ast::Param::can_cast(parent.kind()); - // We have to check that it's either `let var = ...` or `var @ Variant(_)` statement, - // because e.g. match arms are patterns as well. - // In other words, we check that it's a named variable binding. - let is_binding = ast::LetStmt::can_cast(parent.kind()) - || (ast::MatchArm::can_cast(parent.kind()) && ident_pat.at_token().is_some()); - if !(is_param || is_binding) { - // This pattern is not an actual variable declaration, e.g. `Some(val) => {..}` match arm. + let is_shorthand = ast::RecordPatField::cast(parent.clone()) + .map(|parent| parent.name_ref().is_none()) + .unwrap_or_default(); + if is_shorthand { + // We don't check shorthand field patterns, such as 'field' in `Thing { field }`, + // since the shorthand isn't the declaration. continue; } + let is_param = ast::Param::can_cast(parent.kind()); let ident_type = if is_param { IdentType::Parameter } else { IdentType::Variable }; self.create_incorrect_case_diagnostic_for_ast_node( @@ -489,6 +488,11 @@ impl<'a> DeclValidator<'a> { /// Check incorrect names for enum variants. fn validate_enum_variants(&mut self, enum_id: EnumId) { let data = self.db.enum_data(enum_id); + + for (variant_id, _) in data.variants.iter() { + self.validate_enum_variant_fields(*variant_id); + } + let mut enum_variants_replacements = data .variants .iter() @@ -551,6 +555,75 @@ impl<'a> DeclValidator<'a> { } } + /// Check incorrect names for fields of enum variant. + fn validate_enum_variant_fields(&mut self, variant_id: EnumVariantId) { + let variant_data = self.db.enum_variant_data(variant_id); + let VariantData::Record(fields) = variant_data.variant_data.as_ref() else { + return; + }; + let mut variant_field_replacements = fields + .iter() + .filter_map(|(_, field)| { + to_lower_snake_case(&field.name.to_smol_str()).map(|new_name| Replacement { + current_name: field.name.clone(), + suggested_text: new_name, + expected_case: CaseType::LowerSnakeCase, + }) + }) + .peekable(); + + // XXX: only look at sources if we do have incorrect names + if variant_field_replacements.peek().is_none() { + return; + } + + let variant_loc = variant_id.lookup(self.db.upcast()); + let variant_src = variant_loc.source(self.db.upcast()); + + let Some(ast::FieldList::RecordFieldList(variant_fields_list)) = + variant_src.value.field_list() + else { + always!( + variant_field_replacements.peek().is_none(), + "Replacements ({:?}) were generated for an enum variant \ + which had no fields list: {:?}", + variant_field_replacements.collect::>(), + variant_src + ); + return; + }; + let mut variant_variants_iter = variant_fields_list.fields(); + for field_replacement in variant_field_replacements { + // We assume that parameters in replacement are in the same order as in the + // actual params list, but just some of them (ones that named correctly) are skipped. + let field = loop { + if let Some(field) = variant_variants_iter.next() { + let Some(field_name) = field.name() else { + continue; + }; + if field_name.as_name() == field_replacement.current_name { + break field; + } + } else { + never!( + "Replacement ({:?}) was generated for an enum variant field \ + which was not found: {:?}", + field_replacement, + variant_src + ); + return; + } + }; + + self.create_incorrect_case_diagnostic_for_ast_node( + field_replacement, + variant_src.file_id, + &field, + IdentType::Field, + ); + } + } + fn validate_const(&mut self, const_id: ConstId) { let container = const_id.lookup(self.db.upcast()).container; if self.is_trait_impl_container(container) { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs index a0fad7c850c6b..18a95f0963ddb 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -332,6 +332,7 @@ impl someStruct { check_diagnostics( r#" enum Option { Some, None } +use Option::{Some, None}; #[allow(unused)] fn main() { @@ -344,24 +345,6 @@ fn main() { ); } - #[test] - fn non_let_bind() { - check_diagnostics( - r#" -enum Option { Some, None } - -#[allow(unused)] -fn main() { - match Option::None { - SOME_VAR @ None => (), - // ^^^^^^^^ 💡 warn: Variable `SOME_VAR` should have snake_case name, e.g. `some_var` - Some => (), - } -} -"#, - ); - } - #[test] fn allow_attributes_crate_attr() { check_diagnostics( @@ -427,7 +410,12 @@ fn qualify() { #[test] // Issue #8809. fn parenthesized_parameter() { - check_diagnostics(r#"fn f((O): _) { _ = O; }"#) + check_diagnostics( + r#" +fn f((_O): u8) {} + // ^^ 💡 warn: Variable `_O` should have snake_case name, e.g. `_o` +"#, + ) } #[test] @@ -766,4 +754,106 @@ mod Foo; "#, ) } + + #[test] + fn test_field_shorthand() { + check_diagnostics( + r#" +struct Foo { _nonSnake: u8 } + // ^^^^^^^^^ 💡 warn: Field `_nonSnake` should have snake_case name, e.g. `_non_snake` +fn func(Foo { _nonSnake }: Foo) {} +"#, + ); + } + + #[test] + fn test_match() { + check_diagnostics( + r#" +enum Foo { Variant { nonSnake1: u8 } } + // ^^^^^^^^^ 💡 warn: Field `nonSnake1` should have snake_case name, e.g. `non_snake1` +fn func() { + match (Foo::Variant { nonSnake1: 1 }) { + Foo::Variant { nonSnake1: _nonSnake2 } => {}, + // ^^^^^^^^^^ 💡 warn: Variable `_nonSnake2` should have snake_case name, e.g. `_non_snake2` + } +} +"#, + ); + + check_diagnostics( + r#" +struct Foo(u8); + +fn func() { + match Foo(1) { + Foo(_nonSnake) => {}, + // ^^^^^^^^^ 💡 warn: Variable `_nonSnake` should have snake_case name, e.g. `_non_snake` + } +} +"#, + ); + + check_diagnostics( + r#" +fn main() { + match 1 { + _Bad1 @ _Bad2 => {} + // ^^^^^ 💡 warn: Variable `_Bad1` should have snake_case name, e.g. `_bad1` + // ^^^^^ 💡 warn: Variable `_Bad2` should have snake_case name, e.g. `_bad2` + } +} +"#, + ); + check_diagnostics( + r#" +fn main() { + match 1 { _Bad1 => () } + // ^^^^^ 💡 warn: Variable `_Bad1` should have snake_case name, e.g. `_bad1` +} +"#, + ); + + check_diagnostics( + r#" +enum Foo { V1, V2 } +use Foo::V1; + +fn main() { + match V1 { + _Bad1 @ V1 => {}, + // ^^^^^ 💡 warn: Variable `_Bad1` should have snake_case name, e.g. `_bad1` + Foo::V2 => {} + } +} +"#, + ); + } + + #[test] + fn test_for_loop() { + check_diagnostics( + r#" +//- minicore: iterators +fn func() { + for _nonSnake in [] {} + // ^^^^^^^^^ 💡 warn: Variable `_nonSnake` should have snake_case name, e.g. `_non_snake` +} +"#, + ); + + check_fix( + r#" +//- minicore: iterators +fn func() { + for nonSnake$0 in [] { nonSnake; } +} +"#, + r#" +fn func() { + for non_snake in [] { non_snake; } +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs index 6d0119fb57c6b..97296278c3a3a 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs @@ -608,8 +608,8 @@ fn main() { // `Never` is deliberately not defined so that it's an uninferred type. // We ignore these to avoid triggering bugs in the analysis. match Option::::None { - None => (), - Some(never) => match never {}, + Option::None => (), + Option::Some(never) => match never {}, } match Option::::None { Option::Some(_never) => {}, From fd81880c9108c4b98839d55fe29884a625f05f02 Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Fri, 12 Jul 2024 15:58:59 +0200 Subject: [PATCH 019/489] Leave a trace of the current suboptimal status of foreign_write --- src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs index 9c19ae76a2d01..8e23257b6c006 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs @@ -146,6 +146,12 @@ mod transition { /// non-protected interior mutable `Reserved` which stay the same. fn foreign_write(state: PermissionPriv, protected: bool) -> Option { Some(match state { + // FIXME: since the fix related to reservedim_spurious_write, it is now possible + // to express these transitions of the state machine without an explicit dependency + // on `protected`: because `ty_is_freeze: false` implies `!protected` then + // the line handling `Reserved { .. } if protected` could be deleted. + // This will however require optimizations to the exhaustive tests because + // fewer initial conditions are valid. Reserved { .. } if protected => Disabled, res @ Reserved { ty_is_freeze: false, .. } => res, _ => Disabled, From e03998bb639e8e22dd12d870d2fa059f9cb671e0 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Sat, 13 Jul 2024 19:33:35 -0700 Subject: [PATCH 020/489] Address feedback from @DropDemBits - move `edit.rename()` to the end of the function - use a match statement to set `res.command` --- .../src/handlers/extract_variable.rs | 4 +--- .../crates/rust-analyzer/src/config.rs | 2 +- .../crates/rust-analyzer/src/lsp/to_proto.rs | 17 ++++++++--------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index af21a839727a0..cb34f8d81a33f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -135,7 +135,6 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op } } } - edit.rename(); } Anchor::Replace(stmt) => { cov_mark::hit!(test_extract_var_expr_stmt); @@ -150,7 +149,6 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op } } } - edit.rename(); } Anchor::WrapInBlock(to_wrap) => { let indent_to = to_wrap.indent_level(); @@ -194,12 +192,12 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op } } } - edit.rename(); // fixup indentation of block block.indent(indent_to); } } + edit.rename(); }, ) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 990ef77642c1b..91cde4dc0adbb 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -1128,7 +1128,7 @@ pub struct WorkspaceSymbolConfig { /// How many items are returned at most. pub search_limit: usize, } - +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ClientCommandsConfig { pub run_single: bool, pub debug_single: bool, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index b0003fa89e3f2..323926e435c9f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -1336,15 +1336,14 @@ pub(crate) fn code_action( command: None, }; - if assist.command == Some(assists::Command::TriggerSignatureHelp) - && snap.config.client_commands().trigger_parameter_hints - { - res.command = Some(command::trigger_parameter_hints()); - } else if assist.command == Some(assists::Command::Rename) - && snap.config.client_commands().rename - { - res.command = Some(command::rename()); - } + let commands = snap.config.client_commands(); + res.command = match assist.command { + Some(assists::Command::TriggerSignatureHelp) if commands.trigger_parameter_hints => { + Some(command::trigger_parameter_hints()) + } + Some(assists::Command::Rename) if commands.rename => Some(command::rename()), + _ => None, + }; match (assist.source_change, resolve_data) { (Some(it), _) => res.edit = Some(snippet_workspace_edit(snap, it)?), From b32fc1fcf6734ccbd0dab2a65b2d8969e7a178b7 Mon Sep 17 00:00:00 2001 From: Anita Hammer <166057949+anitahammer@users.noreply.github.com> Date: Sun, 14 Jul 2024 11:26:41 +0100 Subject: [PATCH 021/489] Update manual.adoc --- src/tools/rust-analyzer/docs/user/manual.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc index e1c1c54ec4185..a177720908748 100644 --- a/src/tools/rust-analyzer/docs/user/manual.adoc +++ b/src/tools/rust-analyzer/docs/user/manual.adoc @@ -623,7 +623,7 @@ https://github.com/rust-lang/rust-analyzer/tree/master/docs/dev[dev docs]! **Source:** https://github.com/rust-lang/rust-analyzer/blob/master/crates/rust-analyzer/src/config.rs[config.rs] -The <<_installation,Installation>> section contains details on configuration for some of the editors. +The <> section contains details on configuration for some of the editors. In general `rust-analyzer` is configured via LSP messages, which means that it's up to the editor to decide on the exact format and location of configuration files. Some clients, such as <> or <> provide `rust-analyzer` specific configuration UIs. Others may require you to know a bit more about the interaction with `rust-analyzer`. From 26fb6a8738f9f991078ad6eb59ee2a9f4f88c649 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 14 Jul 2024 12:19:19 +0200 Subject: [PATCH 022/489] Use statics + clone instead of const until const can access statics --- .../rust-analyzer/crates/hir-def/src/attr.rs | 10 +- .../crates/hir-def/src/body/lower.rs | 42 ++--- .../crates/hir-def/src/builtin_type.rs | 92 +++++----- .../rust-analyzer/crates/hir-def/src/data.rs | 2 +- .../rust-analyzer/crates/hir-def/src/db.rs | 4 +- .../crates/hir-def/src/find_path.rs | 20 +-- .../crates/hir-def/src/item_scope.rs | 2 +- .../crates/hir-def/src/item_tree/lower.rs | 9 +- .../crates/hir-def/src/lang_item.rs | 18 +- .../crates/hir-def/src/nameres/collector.rs | 36 ++-- .../crates/hir-def/src/path/lower.rs | 6 +- .../crates/hir-def/src/resolver.rs | 18 +- .../crates/hir-expand/src/attrs.rs | 77 +++++---- .../crates/hir-expand/src/builtin_fn_macro.rs | 12 +- .../crates/hir-expand/src/declarative.rs | 2 +- .../crates/hir-expand/src/inert_attr_macro.rs | 4 +- .../crates/hir-expand/src/mod_path.rs | 7 +- .../crates/hir-expand/src/name.rs | 17 +- .../crates/hir-ty/src/autoderef.rs | 5 +- .../crates/hir-ty/src/chalk_db.rs | 21 ++- .../crates/hir-ty/src/diagnostics/expr.rs | 4 +- .../crates/hir-ty/src/display.rs | 5 +- .../rust-analyzer/crates/hir-ty/src/infer.rs | 4 +- .../crates/hir-ty/src/infer/closure.rs | 2 +- .../crates/hir-ty/src/infer/expr.rs | 4 +- .../crates/hir-ty/src/infer/mutability.rs | 4 +- .../crates/hir-ty/src/infer/path.rs | 2 +- .../crates/hir-ty/src/infer/unify.rs | 2 +- .../crates/hir-ty/src/lang_items.rs | 62 ++++--- .../rust-analyzer/crates/hir-ty/src/lib.rs | 2 +- .../crates/hir-ty/src/mir/eval.rs | 12 +- .../crates/hir-ty/src/mir/eval/shim.rs | 4 +- .../crates/hir-ty/src/mir/lower/as_place.rs | 12 +- .../rust-analyzer/crates/hir-ty/src/traits.rs | 6 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 6 +- .../crates/hir/src/source_analyzer.rs | 19 ++- .../src/handlers/convert_bool_then.rs | 2 +- .../handlers/convert_iter_for_each_to_for.rs | 4 +- .../handlers/generate_is_empty_from_len.rs | 4 +- .../ide-assists/src/handlers/inline_call.rs | 2 +- .../crates/ide-completion/src/completions.rs | 3 +- .../ide-completion/src/completions/dot.rs | 6 +- .../ide-completion/src/completions/expr.rs | 4 +- .../src/completions/lifetime.rs | 2 +- .../src/handlers/missing_fields.rs | 2 +- .../crates/ide/src/inlay_hints.rs | 2 +- .../ide/src/syntax_highlighting/highlight.rs | 13 +- .../rust-analyzer/crates/intern/src/symbol.rs | 6 +- .../crates/intern/src/symbol/symbols.rs | 159 +++++++++--------- 49 files changed, 395 insertions(+), 368 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index a1ffb8c0a7596..aacfb07319819 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -9,7 +9,7 @@ use hir_expand::{ attrs::{collect_attrs, Attr, AttrId, RawAttrs}, HirFileId, InFile, }; -use intern::sym; +use intern::{sym, Symbol}; use la_arena::{ArenaMap, Idx, RawIdx}; use mbe::DelimiterKind; use syntax::{ @@ -153,7 +153,7 @@ impl Attrs { } pub fn lang_item(&self) -> Option { - self.by_key("lang").string_value().and_then(LangItem::from_str) + self.by_key("lang").string_value().and_then(|it| LangItem::from_symbol(&Symbol::intern(it))) } pub fn has_doc_hidden(&self) -> bool { @@ -200,7 +200,11 @@ impl Attrs { .segments() .iter() .rev() - .zip([sym::core, sym::prelude, sym::v1, sym::test].iter().rev()) + .zip( + [sym::core.clone(), sym::prelude.clone(), sym::v1.clone(), sym::test.clone()] + .iter() + .rev(), + ) .all(|it| it.0 == it.1) }) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index 83ba8f41931e2..b96745022a21a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -188,7 +188,7 @@ impl ExprCollector<'_> { let is_mutable = self_param.mut_token().is_some() && self_param.amp_token().is_none(); let binding_id: la_arena::Idx = self.alloc_binding( - Name::new_symbol_root(sym::self_), + Name::new_symbol_root(sym::self_.clone()), BindingAnnotation::new(is_mutable, false), ); self.body.self_param = Some(binding_id); @@ -1732,14 +1732,14 @@ impl ExprCollector<'_> { let Some(new_v1_formatted) = LangItem::FormatArguments.ty_rel_path( self.db, self.krate, - Name::new_symbol_root(sym::new_v1_formatted), + Name::new_symbol_root(sym::new_v1_formatted.clone()), ) else { return self.missing_expr(); }; let Some(unsafe_arg_new) = LangItem::FormatUnsafeArg.ty_rel_path( self.db, self.krate, - Name::new_symbol_root(sym::new), + Name::new_symbol_root(sym::new.clone()), ) else { return self.missing_expr(); }; @@ -1822,10 +1822,10 @@ impl ExprCollector<'_> { self.db, self.krate, match alignment { - Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left), - Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right), - Some(FormatAlignment::Center) => Name::new_symbol_root(sym::Center), - None => Name::new_symbol_root(sym::Unknown), + Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left.clone()), + Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right.clone()), + Some(FormatAlignment::Center) => Name::new_symbol_root(sym::Center.clone()), + None => Name::new_symbol_root(sym::Unknown.clone()), }, ); match align { @@ -1851,7 +1851,7 @@ impl ExprCollector<'_> { let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path( self.db, self.krate, - Name::new_symbol_root(sym::new), + Name::new_symbol_root(sym::new.clone()), ); match format_placeholder_new { Some(path) => self.alloc_expr_desugared(Expr::Path(path)), @@ -1899,7 +1899,7 @@ impl ExprCollector<'_> { let count_is = match LangItem::FormatCount.ty_rel_path( self.db, self.krate, - Name::new_symbol_root(sym::Is), + Name::new_symbol_root(sym::Is.clone()), ) { Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)), None => self.missing_expr(), @@ -1921,7 +1921,7 @@ impl ExprCollector<'_> { let count_param = match LangItem::FormatCount.ty_rel_path( self.db, self.krate, - Name::new_symbol_root(sym::Param), + Name::new_symbol_root(sym::Param.clone()), ) { Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)), None => self.missing_expr(), @@ -1940,7 +1940,7 @@ impl ExprCollector<'_> { None => match LangItem::FormatCount.ty_rel_path( self.db, self.krate, - Name::new_symbol_root(sym::Implied), + Name::new_symbol_root(sym::Implied.clone()), ) { Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)), None => self.missing_expr(), @@ -1963,16 +1963,16 @@ impl ExprCollector<'_> { self.db, self.krate, Name::new_symbol_root(match ty { - Format(Display) => sym::new_display, - Format(Debug) => sym::new_debug, - Format(LowerExp) => sym::new_lower_exp, - Format(UpperExp) => sym::new_upper_exp, - Format(Octal) => sym::new_octal, - Format(Pointer) => sym::new_pointer, - Format(Binary) => sym::new_binary, - Format(LowerHex) => sym::new_lower_hex, - Format(UpperHex) => sym::new_upper_hex, - Usize => sym::from_usize, + Format(Display) => sym::new_display.clone(), + Format(Debug) => sym::new_debug.clone(), + Format(LowerExp) => sym::new_lower_exp.clone(), + Format(UpperExp) => sym::new_upper_exp.clone(), + Format(Octal) => sym::new_octal.clone(), + Format(Pointer) => sym::new_pointer.clone(), + Format(Binary) => sym::new_binary.clone(), + Format(LowerHex) => sym::new_lower_hex.clone(), + Format(UpperHex) => sym::new_upper_hex.clone(), + Usize => sym::from_usize.clone(), }), ) { Some(new_fn) => self.alloc_expr_desugared(Expr::Path(new_fn)), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs b/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs index 2243f514fe102..6dc1c4546e804 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs @@ -49,63 +49,67 @@ pub enum BuiltinType { impl BuiltinType { #[rustfmt::skip] - pub const ALL: &'static [(Name, BuiltinType)] = &[ - (Name::new_symbol_root(sym::char), BuiltinType::Char), - (Name::new_symbol_root(sym::bool), BuiltinType::Bool), - (Name::new_symbol_root(sym::str), BuiltinType::Str), - - (Name::new_symbol_root(sym::isize), BuiltinType::Int(BuiltinInt::Isize)), - (Name::new_symbol_root(sym::i8), BuiltinType::Int(BuiltinInt::I8)), - (Name::new_symbol_root(sym::i16), BuiltinType::Int(BuiltinInt::I16)), - (Name::new_symbol_root(sym::i32), BuiltinType::Int(BuiltinInt::I32)), - (Name::new_symbol_root(sym::i64), BuiltinType::Int(BuiltinInt::I64)), - (Name::new_symbol_root(sym::i128), BuiltinType::Int(BuiltinInt::I128)), - - (Name::new_symbol_root(sym::usize), BuiltinType::Uint(BuiltinUint::Usize)), - (Name::new_symbol_root(sym::u8), BuiltinType::Uint(BuiltinUint::U8)), - (Name::new_symbol_root(sym::u16), BuiltinType::Uint(BuiltinUint::U16)), - (Name::new_symbol_root(sym::u32), BuiltinType::Uint(BuiltinUint::U32)), - (Name::new_symbol_root(sym::u64), BuiltinType::Uint(BuiltinUint::U64)), - (Name::new_symbol_root(sym::u128), BuiltinType::Uint(BuiltinUint::U128)), - - (Name::new_symbol_root(sym::f16), BuiltinType::Float(BuiltinFloat::F16)), - (Name::new_symbol_root(sym::f32), BuiltinType::Float(BuiltinFloat::F32)), - (Name::new_symbol_root(sym::f64), BuiltinType::Float(BuiltinFloat::F64)), - (Name::new_symbol_root(sym::f128), BuiltinType::Float(BuiltinFloat::F128)), - ]; + pub fn all_builtin_types() -> [(Name, BuiltinType); 19] { + [ + (Name::new_symbol_root(sym::char.clone()), BuiltinType::Char), + (Name::new_symbol_root(sym::bool.clone()), BuiltinType::Bool), + (Name::new_symbol_root(sym::str.clone()), BuiltinType::Str), + + (Name::new_symbol_root(sym::isize.clone()), BuiltinType::Int(BuiltinInt::Isize)), + (Name::new_symbol_root(sym::i8.clone()), BuiltinType::Int(BuiltinInt::I8)), + (Name::new_symbol_root(sym::i16.clone()), BuiltinType::Int(BuiltinInt::I16)), + (Name::new_symbol_root(sym::i32.clone()), BuiltinType::Int(BuiltinInt::I32)), + (Name::new_symbol_root(sym::i64.clone()), BuiltinType::Int(BuiltinInt::I64)), + (Name::new_symbol_root(sym::i128.clone()), BuiltinType::Int(BuiltinInt::I128)), + + (Name::new_symbol_root(sym::usize.clone()), BuiltinType::Uint(BuiltinUint::Usize)), + (Name::new_symbol_root(sym::u8.clone()), BuiltinType::Uint(BuiltinUint::U8)), + (Name::new_symbol_root(sym::u16.clone()), BuiltinType::Uint(BuiltinUint::U16)), + (Name::new_symbol_root(sym::u32.clone()), BuiltinType::Uint(BuiltinUint::U32)), + (Name::new_symbol_root(sym::u64.clone()), BuiltinType::Uint(BuiltinUint::U64)), + (Name::new_symbol_root(sym::u128.clone()), BuiltinType::Uint(BuiltinUint::U128)), + + (Name::new_symbol_root(sym::f16.clone()), BuiltinType::Float(BuiltinFloat::F16)), + (Name::new_symbol_root(sym::f32.clone()), BuiltinType::Float(BuiltinFloat::F32)), + (Name::new_symbol_root(sym::f64.clone()), BuiltinType::Float(BuiltinFloat::F64)), + (Name::new_symbol_root(sym::f128.clone()), BuiltinType::Float(BuiltinFloat::F128)), + ] + } pub fn by_name(name: &Name) -> Option { - Self::ALL.iter().find_map(|(n, ty)| if n == name { Some(*ty) } else { None }) + Self::all_builtin_types() + .iter() + .find_map(|(n, ty)| if n == name { Some(*ty) } else { None }) } } impl AsName for BuiltinType { fn as_name(&self) -> Name { match self { - BuiltinType::Char => Name::new_symbol_root(sym::char), - BuiltinType::Bool => Name::new_symbol_root(sym::bool), - BuiltinType::Str => Name::new_symbol_root(sym::str), + BuiltinType::Char => Name::new_symbol_root(sym::char.clone()), + BuiltinType::Bool => Name::new_symbol_root(sym::bool.clone()), + BuiltinType::Str => Name::new_symbol_root(sym::str.clone()), BuiltinType::Int(it) => match it { - BuiltinInt::Isize => Name::new_symbol_root(sym::isize), - BuiltinInt::I8 => Name::new_symbol_root(sym::i8), - BuiltinInt::I16 => Name::new_symbol_root(sym::i16), - BuiltinInt::I32 => Name::new_symbol_root(sym::i32), - BuiltinInt::I64 => Name::new_symbol_root(sym::i64), - BuiltinInt::I128 => Name::new_symbol_root(sym::i128), + BuiltinInt::Isize => Name::new_symbol_root(sym::isize.clone()), + BuiltinInt::I8 => Name::new_symbol_root(sym::i8.clone()), + BuiltinInt::I16 => Name::new_symbol_root(sym::i16.clone()), + BuiltinInt::I32 => Name::new_symbol_root(sym::i32.clone()), + BuiltinInt::I64 => Name::new_symbol_root(sym::i64.clone()), + BuiltinInt::I128 => Name::new_symbol_root(sym::i128.clone()), }, BuiltinType::Uint(it) => match it { - BuiltinUint::Usize => Name::new_symbol_root(sym::usize), - BuiltinUint::U8 => Name::new_symbol_root(sym::u8), - BuiltinUint::U16 => Name::new_symbol_root(sym::u16), - BuiltinUint::U32 => Name::new_symbol_root(sym::u32), - BuiltinUint::U64 => Name::new_symbol_root(sym::u64), - BuiltinUint::U128 => Name::new_symbol_root(sym::u128), + BuiltinUint::Usize => Name::new_symbol_root(sym::usize.clone()), + BuiltinUint::U8 => Name::new_symbol_root(sym::u8.clone()), + BuiltinUint::U16 => Name::new_symbol_root(sym::u16.clone()), + BuiltinUint::U32 => Name::new_symbol_root(sym::u32.clone()), + BuiltinUint::U64 => Name::new_symbol_root(sym::u64.clone()), + BuiltinUint::U128 => Name::new_symbol_root(sym::u128.clone()), }, BuiltinType::Float(it) => match it { - BuiltinFloat::F16 => Name::new_symbol_root(sym::f16), - BuiltinFloat::F32 => Name::new_symbol_root(sym::f32), - BuiltinFloat::F64 => Name::new_symbol_root(sym::f64), - BuiltinFloat::F128 => Name::new_symbol_root(sym::f128), + BuiltinFloat::F16 => Name::new_symbol_root(sym::f16.clone()), + BuiltinFloat::F32 => Name::new_symbol_root(sym::f32.clone()), + BuiltinFloat::F64 => Name::new_symbol_root(sym::f64.clone()), + BuiltinFloat::F128 => Name::new_symbol_root(sym::f128.clone()), }, } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index f60a433c4dafe..964a5f04bfd22 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -485,7 +485,7 @@ impl ExternCrateDeclData { let name = extern_crate.name.clone(); let krate = loc.container.krate(); - let crate_id = if name == sym::self_ { + let crate_id = if name == sym::self_.clone() { Some(krate) } else { db.crate_def_map(krate) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 0a14904f0bceb..eac8f0dd74ac8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -262,8 +262,8 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool { let attrs = item_tree.raw_attrs(AttrOwner::TopLevel); for attr in &**attrs { match attr.path().as_ident() { - Some(ident) if *ident == sym::no_std => return true, - Some(ident) if *ident == sym::cfg_attr => {} + Some(ident) if *ident == sym::no_std.clone() => return true, + Some(ident) if *ident == sym::cfg_attr.clone() => {} _ => continue, } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index e32add93c5526..a3a602c2c117b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -415,13 +415,13 @@ fn select_best_path( (Unstable, Stable) => return new_path, _ => {} } - const STD_CRATES: [Symbol; 3] = [sym::std, sym::core, sym::alloc]; + let std_crates: [Symbol; 3] = [sym::std.clone(), sym::core.clone(), sym::alloc.clone()]; let choose = |new: (ModPath, _), old: (ModPath, _)| { let (new_path, _) = &new; let (old_path, _) = &old; - let new_has_prelude = new_path.segments().iter().any(|seg| *seg == sym::prelude); - let old_has_prelude = old_path.segments().iter().any(|seg| *seg == sym::prelude); + let new_has_prelude = new_path.segments().iter().any(|seg| *seg == sym::prelude.clone()); + let old_has_prelude = old_path.segments().iter().any(|seg| *seg == sym::prelude.clone()); match (new_has_prelude, old_has_prelude, cfg.prefer_prelude) { (true, false, true) | (false, true, false) => new, (true, false, false) | (false, true, true) => old, @@ -443,19 +443,19 @@ fn select_best_path( match (old_path.0.segments().first(), new_path.0.segments().first()) { (Some(old), Some(new)) - if STD_CRATES.contains(old.symbol()) && STD_CRATES.contains(new.symbol()) => + if std_crates.contains(old.symbol()) && std_crates.contains(new.symbol()) => { let rank = match cfg.prefer_no_std { false => |name: &Name| match name { - name if *name == sym::core => 0, - name if *name == sym::alloc => 1, - name if *name == sym::std => 2, + name if *name == sym::core.clone() => 0, + name if *name == sym::alloc.clone() => 1, + name if *name == sym::std.clone() => 2, _ => unreachable!(), }, true => |name: &Name| match name { - name if *name == sym::core => 2, - name if *name == sym::alloc => 1, - name if *name == sym::std => 0, + name if *name == sym::core.clone() => 2, + name if *name == sym::alloc.clone() => 1, + name if *name == sym::std.clone() => 0, _ => unreachable!(), }, }; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index d86c0667a0bb7..092c0a1dfdf81 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -119,7 +119,7 @@ struct DeriveMacroInvocation { } pub(crate) static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { - BuiltinType::ALL + BuiltinType::all_builtin_types() .iter() .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None))) .collect() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs index 496686b4f943c..5c80da93048c7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs @@ -324,7 +324,8 @@ impl<'a> Ctx<'a> { let self_type = match self_param.ty() { Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref), None => { - let self_type = TypeRef::Path(Name::new_symbol_root(sym::Self_).into()); + let self_type = + TypeRef::Path(Name::new_symbol_root(sym::Self_.clone()).into()); match self_param.kind() { ast::SelfParamKind::Owned => self_type, ast::SelfParamKind::Ref => TypeRef::Reference( @@ -670,7 +671,7 @@ impl<'a> Ctx<'a> { // Traits and trait aliases get the Self type as an implicit first type parameter. generics.type_or_consts.alloc( TypeParamData { - name: Some(Name::new_symbol_root(sym::Self_)), + name: Some(Name::new_symbol_root(sym::Self_.clone())), default: None, provenance: TypeParamProvenance::TraitSelf, } @@ -681,7 +682,7 @@ impl<'a> Ctx<'a> { generics.fill_bounds( &self.body_ctx, bounds, - Either::Left(TypeRef::Path(Name::new_symbol_root(sym::Self_).into())), + Either::Left(TypeRef::Path(Name::new_symbol_root(sym::Self_.clone()).into())), ); } @@ -746,7 +747,7 @@ fn desugar_future_path(orig: TypeRef) -> Path { let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments().len() - 1).collect(); let binding = AssociatedTypeBinding { - name: Name::new_symbol_root(sym::Output), + name: Name::new_symbol_root(sym::Output.clone()), args: None, type_ref: Some(orig), bounds: Box::default(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 4d17650285f40..07b27659ab3dd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -192,8 +192,7 @@ impl LangItems { } pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option { - let attrs = db.attrs(item); - attrs.by_key("lang").string_value().and_then(LangItem::from_str) + db.attrs(item).lang_item() } pub(crate) fn notable_traits_in_deps( @@ -261,18 +260,9 @@ macro_rules! language_item_table { } /// Opposite of [`LangItem::name`] - #[allow(clippy::should_implement_trait)] - pub fn from_str(name: &str) -> Option { - match name { - $( stringify!($name) => Some(LangItem::$variant), )* - _ => None, - } - } - - /// Opposite of [`LangItem::name`] - pub fn from_symbol(sym: Symbol) -> Option { + pub fn from_symbol(sym: &Symbol) -> Option { match sym { - $(sym if sym == $module::$name => Some(LangItem::$variant), )* + $(sym if *sym == $module::$name => Some(LangItem::$variant), )* _ => None, } } @@ -283,7 +273,7 @@ macro_rules! language_item_table { impl LangItem { /// Opposite of [`LangItem::name`] pub fn from_name(name: &hir_expand::name::Name) -> Option { - Self::from_str(name.as_str()) + Self::from_symbol(name.symbol()) } pub fn path(&self, db: &dyn DefDatabase, start_crate: CrateId) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 30d4a79a808d9..f14679f6c2f14 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -294,24 +294,24 @@ impl DefCollector<'_> { let Some(attr_name) = attr.path.as_ident() else { continue }; match () { - () if *attr_name == sym::recursion_limit => { + () if *attr_name == sym::recursion_limit.clone() => { if let Some(limit) = attr.string_value() { if let Ok(limit) = limit.parse() { crate_data.recursion_limit = Some(limit); } } } - () if *attr_name == sym::crate_type => { + () if *attr_name == sym::crate_type.clone() => { if let Some("proc-macro") = attr.string_value() { self.is_proc_macro = true; } } - () if *attr_name == sym::no_core => crate_data.no_core = true, - () if *attr_name == sym::no_std => crate_data.no_std = true, - () if *attr_name == sym::rustc_coherence_is_core => { + () if *attr_name == sym::no_core.clone() => crate_data.no_core = true, + () if *attr_name == sym::no_std.clone() => crate_data.no_std = true, + () if *attr_name == sym::rustc_coherence_is_core.clone() => { crate_data.rustc_coherence_is_core = true; } - () if *attr_name == sym::feature => { + () if *attr_name == sym::feature.clone() => { let features = attr .parse_path_comma_token_tree(self.db.upcast()) .into_iter() @@ -322,13 +322,13 @@ impl DefCollector<'_> { }); crate_data.unstable_features.extend(features); } - () if *attr_name == sym::register_attr => { + () if *attr_name == sym::register_attr.clone() => { if let Some(ident) = attr.single_ident_value() { crate_data.registered_attrs.push(ident.text.clone()); cov_mark::hit!(register_attr); } } - () if *attr_name == sym::register_tool => { + () if *attr_name == sym::register_tool.clone() => { if let Some(ident) = attr.single_ident_value() { crate_data.registered_tools.push(ident.text.clone()); cov_mark::hit!(register_tool); @@ -538,20 +538,20 @@ impl DefCollector<'_> { } let krate = if self.def_map.data.no_std { - Name::new_symbol_root(sym::core) - } else if self.def_map.extern_prelude().any(|(name, _)| *name == sym::std) { - Name::new_symbol_root(sym::std) + Name::new_symbol_root(sym::core.clone()) + } else if self.def_map.extern_prelude().any(|(name, _)| *name == sym::std.clone()) { + Name::new_symbol_root(sym::std.clone()) } else { // If `std` does not exist for some reason, fall back to core. This mostly helps // keep r-a's own tests minimal. - Name::new_symbol_root(sym::core) + Name::new_symbol_root(sym::core.clone()) }; let edition = match self.def_map.data.edition { - Edition::Edition2015 => Name::new_symbol_root(sym::rust_2015), - Edition::Edition2018 => Name::new_symbol_root(sym::rust_2018), - Edition::Edition2021 => Name::new_symbol_root(sym::rust_2021), - Edition::Edition2024 => Name::new_symbol_root(sym::rust_2024), + Edition::Edition2015 => Name::new_symbol_root(sym::rust_2015.clone()), + Edition::Edition2018 => Name::new_symbol_root(sym::rust_2018.clone()), + Edition::Edition2021 => Name::new_symbol_root(sym::rust_2021.clone()), + Edition::Edition2024 => Name::new_symbol_root(sym::rust_2024.clone()), }; let path_kind = match self.def_map.data.edition { @@ -560,7 +560,7 @@ impl DefCollector<'_> { }; let path = ModPath::from_segments( path_kind, - [krate, Name::new_symbol_root(sym::prelude), edition], + [krate, Name::new_symbol_root(sym::prelude.clone()), edition], ); let (per_ns, _) = @@ -844,7 +844,7 @@ impl DefCollector<'_> { } fn resolve_extern_crate(&self, name: &Name) -> Option { - if *name == sym::self_ { + if *name == sym::self_.clone() { cov_mark::hit!(extern_crate_self_as); Some(self.def_map.crate_root()) } else { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs index 22397df961066..7c39773aa6874 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs @@ -60,7 +60,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option { - segments.push(Name::new_symbol_root(sym::Self_)); + segments.push(Name::new_symbol_root(sym::Self_.clone())); } ast::PathSegmentKind::Type { type_ref, trait_ref } => { assert!(path.qualifier().is_none()); // this can only occur at the first segment @@ -268,7 +268,7 @@ fn lower_generic_args_from_fn_path( let bindings = if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty()); Box::new([AssociatedTypeBinding { - name: Name::new_symbol_root(sym::Output), + name: Name::new_symbol_root(sym::Output.clone()), args: None, type_ref: Some(type_ref), bounds: Box::default(), @@ -277,7 +277,7 @@ fn lower_generic_args_from_fn_path( // -> () let type_ref = TypeRef::Tuple(Vec::new()); Box::new([AssociatedTypeBinding { - name: Name::new_symbol_root(sym::Output), + name: Name::new_symbol_root(sym::Output.clone()), args: None, type_ref: Some(type_ref), bounds: Box::default(), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 4931418546603..c196f00281639 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -194,12 +194,12 @@ impl Resolver { } } &Scope::ImplDefScope(impl_) => { - if *first_name == sym::Self_ { + if *first_name == sym::Self_.clone() { return Some((TypeNs::SelfType(impl_), remaining_idx(), None)); } } &Scope::AdtScope(adt) => { - if *first_name == sym::Self_ { + if *first_name == sym::Self_.clone() { return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None)); } } @@ -291,7 +291,7 @@ impl Resolver { } }; let n_segments = path.segments().len(); - let tmp = Name::new_symbol_root(sym::Self_); + let tmp = Name::new_symbol_root(sym::self_.clone()); let first_name = if path.is_self() { &tmp } else { path.segments().first()? }; let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); if skip_to_mod { @@ -322,7 +322,7 @@ impl Resolver { } } &Scope::ImplDefScope(impl_) => { - if *first_name == sym::Self_ { + if *first_name == sym::Self_.clone() { return Some(ResolveValueResult::ValueNs( ValueNs::ImplSelf(impl_), None, @@ -349,7 +349,7 @@ impl Resolver { } } &Scope::ImplDefScope(impl_) => { - if *first_name == sym::Self_ { + if *first_name == sym::Self_.clone() { return Some(ResolveValueResult::Partial( TypeNs::SelfType(impl_), 1, @@ -358,7 +358,7 @@ impl Resolver { } } Scope::AdtScope(adt) => { - if *first_name == sym::Self_ { + if *first_name == sym::Self_.clone() { let ty = TypeNs::AdtSelfType(*adt); return Some(ResolveValueResult::Partial(ty, 1, None)); } @@ -422,7 +422,7 @@ impl Resolver { } pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option { - if lifetime.name == sym::tick_static { + if lifetime.name == sym::tick_static.clone() { return Some(LifetimeNs::Static); } @@ -778,10 +778,10 @@ impl Scope { } } Scope::ImplDefScope(i) => { - acc.add(&Name::new_symbol_root(sym::Self_), ScopeDef::ImplSelfType(*i)); + acc.add(&Name::new_symbol_root(sym::Self_.clone()), ScopeDef::ImplSelfType(*i)); } Scope::AdtScope(i) => { - acc.add(&Name::new_symbol_root(sym::Self_), ScopeDef::AdtSelfType(*i)); + acc.add(&Name::new_symbol_root(sym::Self_.clone()), ScopeDef::AdtSelfType(*i)); } Scope::ExprScope(scope) => { if let Some((label, name)) = scope.expr_scopes.label(scope.scope_id) { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 6afa7a40f123f..36636a228f147 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -59,7 +59,10 @@ impl RawAttrs { text: SmolStr::new(format_smolstr!("\"{}\"", Self::escape_chars(doc))), span, }))), - path: Interned::new(ModPath::from(Name::new_symbol(sym::doc, span.ctx))), + path: Interned::new(ModPath::from(Name::new_symbol( + sym::doc.clone(), + span.ctx, + ))), ctxt: span.ctx, } }), @@ -116,47 +119,47 @@ impl RawAttrs { pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs { let has_cfg_attrs = self .iter() - .any(|attr| attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr)); + .any(|attr| attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr.clone())); if !has_cfg_attrs { return self; } let crate_graph = db.crate_graph(); - let new_attrs = self - .iter() - .flat_map(|attr| -> SmallVec<[_; 1]> { - let is_cfg_attr = attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr); - if !is_cfg_attr { - return smallvec![attr.clone()]; - } - - let subtree = match attr.token_tree_value() { - Some(it) => it, - _ => return smallvec![attr.clone()], - }; + let new_attrs = + self.iter() + .flat_map(|attr| -> SmallVec<[_; 1]> { + let is_cfg_attr = + attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr.clone()); + if !is_cfg_attr { + return smallvec![attr.clone()]; + } - let (cfg, parts) = match parse_cfg_attr_input(subtree) { - Some(it) => it, - None => return smallvec![attr.clone()], - }; - let index = attr.id; - let attrs = parts - .enumerate() - .take(1 << AttrId::CFG_ATTR_BITS) - .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); - - let cfg_options = &crate_graph[krate].cfg_options; - let cfg = Subtree { delimiter: subtree.delimiter, token_trees: Box::from(cfg) }; - let cfg = CfgExpr::parse(&cfg); - if cfg_options.check(&cfg) == Some(false) { - smallvec![] - } else { - cov_mark::hit!(cfg_attr_active); - - attrs.collect() - } - }) - .collect::>(); + let subtree = match attr.token_tree_value() { + Some(it) => it, + _ => return smallvec![attr.clone()], + }; + + let (cfg, parts) = match parse_cfg_attr_input(subtree) { + Some(it) => it, + None => return smallvec![attr.clone()], + }; + let index = attr.id; + let attrs = parts.enumerate().take(1 << AttrId::CFG_ATTR_BITS).filter_map( + |(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)), + ); + + let cfg_options = &crate_graph[krate].cfg_options; + let cfg = Subtree { delimiter: subtree.delimiter, token_trees: Box::from(cfg) }; + let cfg = CfgExpr::parse(&cfg); + if cfg_options.check(&cfg) == Some(false) { + smallvec![] + } else { + cov_mark::hit!(cfg_attr_active); + + attrs.collect() + } + }) + .collect::>(); let entries = if new_attrs.is_empty() { None } else { @@ -384,7 +387,7 @@ impl Attr { } pub fn cfg(&self) -> Option { - if *self.path.as_ident()? == sym::cfg { + if *self.path.as_ident()? == sym::cfg.clone() { self.token_tree_value().map(CfgExpr::parse) } else { None diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index e5de5975a2d8b..97867dfc66e92 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -367,7 +367,11 @@ fn panic_expand( let dollar_crate = dollar_crate(span); let call_site_span = span_with_call_site_ctxt(db, span, id); - let mac = if use_panic_2021(db, call_site_span) { sym::panic_2021 } else { sym::panic_2015 }; + let mac = if use_panic_2021(db, call_site_span) { + sym::panic_2021.clone() + } else { + sym::panic_2015.clone() + }; // Expand to a macro call `$crate::panic::panic_{edition}` let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!); @@ -396,9 +400,9 @@ fn unreachable_expand( let call_site_span = span_with_call_site_ctxt(db, span, id); let mac = if use_panic_2021(db, call_site_span) { - sym::unreachable_2021 + sym::unreachable_2021.clone() } else { - sym::unreachable_2015 + sym::unreachable_2015.clone() }; // Expand to a macro call `$crate::panic::panic_{edition}` @@ -431,7 +435,7 @@ fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool { // FIXME: Record allow_internal_unstable in the macro def (not been done yet because it // would consume quite a bit extra memory for all call locs...) // if let Some(features) = expn.def.allow_internal_unstable { - // if features.iter().any(|&f| f == sym::edition_panic) { + // if features.iter().any(|&f| f == sym::edition_panic.clone()) { // span = expn.call_site; // continue; // } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index b920d2127abe8..2e7865ed3bf8c 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -114,7 +114,7 @@ impl DeclarativeMacroExpander { .find(|it| { it.path .as_ident() - .map(|it| *it == sym::rustc_macro_transparency) + .map(|it| *it == sym::rustc_macro_transparency.clone()) .unwrap_or(false) })? .token_tree_value()? diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index 7ead7e9390152..0c112554e1f43 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -553,7 +553,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ ), BuiltinAttribute { - // name: sym::rustc_diagnostic_item, + // name: sym::rustc_diagnostic_item.clone(), name: "rustc_diagnostic_item", // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`. // only_local: false, @@ -562,7 +562,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[ // duplicates: ErrorFollowing, // gate: Gated( // Stability::Unstable, - // sym::rustc_attrs, + // sym::rustc_attrs.clone(), // "diagnostic items compiler internal support for linting", // cfg_fn!(rustc_attrs), // ), diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 7ff8b797fa4a6..ed7d551888756 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -120,7 +120,8 @@ impl ModPath { #[allow(non_snake_case)] pub fn is_Self(&self) -> bool { - self.kind == PathKind::Plain && matches!(&*self.segments, [name] if *name == sym::Self_) + self.kind == PathKind::Plain + && matches!(&*self.segments, [name] if *name == sym::Self_.clone()) } /// If this path is a single identifier, like `foo`, return its name. @@ -264,7 +265,7 @@ fn convert_path( } ast::PathSegmentKind::SelfTypeKw => ModPath::from_segments( PathKind::Plain, - Some(Name::new_symbol(sym::Self_, SyntaxContextId::ROOT)), + Some(Name::new_symbol(sym::Self_.clone(), SyntaxContextId::ROOT)), ), ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()), ast::PathSegmentKind::SelfKw => handle_super_kw(0)?, @@ -396,7 +397,7 @@ macro_rules! __path { ($start:ident $(:: $seg:ident)*) => ({ $crate::__known_path!($start $(:: $seg)*); $crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Abs, vec![ - $crate::name::Name::new_symbol_root(intern::sym::$start), $($crate::name::Name::new_symbol_root(intern::sym::$seg),)* + $crate::name::Name::new_symbol_root(intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root(intern::sym::$seg.clone()),)* ]) }); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index da0adbef16342..67e73f7fc284c 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -2,7 +2,7 @@ use std::fmt; -use intern::{sym::MISSING_NAME, Symbol}; +use intern::{sym, Symbol}; use span::SyntaxContextId; use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; @@ -13,12 +13,21 @@ use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; /// Note that `Name` holds and prints escaped name i.e. prefixed with "r#" when it /// is a raw identifier. Use [`unescaped()`][Name::unescaped] when you need the /// name without "r#". -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash)] pub struct Name { symbol: Symbol, ctx: (), } +impl fmt::Debug for Name { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Name") + .field("symbol", &self.symbol.as_str()) + .field("ctx", &self.ctx) + .finish() + } +} + impl Ord for Name { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.symbol.as_str().cmp(other.symbol.as_str()) @@ -116,8 +125,8 @@ impl Name { /// Ideally, we want a `gensym` semantics for missing names -- each missing /// name is equal only to itself. It's not clear how to implement this in /// salsa though, so we punt on that bit for a moment. - pub const fn missing() -> Name { - Name { symbol: MISSING_NAME, ctx: () } + pub fn missing() -> Name { + Name { symbol: sym::MISSING_NAME.clone(), ctx: () } } /// Returns true if this is a fake name for things missing in the source code. See diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs index 736379a3d8730..ecfc1ff99e9ea 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs @@ -152,8 +152,9 @@ pub(crate) fn deref_by_trait( let deref_trait = db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?; - let target = - db.trait_data(deref_trait).associated_type_by_name(&Name::new_symbol_root(sym::Target))?; + let target = db + .trait_data(deref_trait) + .associated_type_by_name(&Name::new_symbol_root(sym::Target.clone()))?; let projection = { let b = TyBuilder::subst_for_def(db, deref_trait, None); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 868827b2b6603..d506e00ca1239 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -289,17 +289,16 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> { chalk_ir::Binders::new(binders, bound) } crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => { - if let Some((future_trait, future_output)) = self - .db - .lang_item(self.krate, LangItem::Future) - .and_then(|item| item.as_trait()) - .and_then(|trait_| { - let alias = self - .db - .trait_data(trait_) - .associated_type_by_name(&Name::new_symbol_root(sym::Output))?; - Some((trait_, alias)) - }) + if let Some((future_trait, future_output)) = + self.db + .lang_item(self.krate, LangItem::Future) + .and_then(|item| item.as_trait()) + .and_then(|trait_| { + let alias = self.db.trait_data(trait_).associated_type_by_name( + &Name::new_symbol_root(sym::Output.clone()), + )?; + Some((trait_, alias)) + }) { // Making up Symbol’s value as variable is void: AsyncBlock: // diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 048bdd2c38bce..e52fae06d7f73 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -423,7 +423,9 @@ impl FilterMapNextChecker { ItemContainerId::TraitId(iterator_trait_id) => { let iterator_trait_items = &db.trait_data(iterator_trait_id).items; iterator_trait_items.iter().find_map(|(name, it)| match it { - &AssocItemId::FunctionId(id) if *name == sym::filter_map => Some(id), + &AssocItemId::FunctionId(id) if *name == sym::filter_map.clone() => { + Some(id) + } _ => None, }) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 2a644de1fbecc..f15f6575b7904 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -1171,8 +1171,9 @@ impl HirDisplay for Ty { .lang_item(body.module(db.upcast()).krate(), LangItem::Future) .and_then(LangItemTarget::as_trait); let output = future_trait.and_then(|t| { - db.trait_data(t) - .associated_type_by_name(&Name::new_symbol_root(sym::Output)) + db.trait_data(t).associated_type_by_name(&Name::new_symbol_root( + sym::Output.clone(), + )) }); write!(f, "impl ")?; if let Some(t) = future_trait { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 928a3f5e493c7..82f4ad01e0189 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1425,7 +1425,9 @@ impl<'a> InferenceContext<'a> { } fn resolve_output_on(&self, trait_: TraitId) -> Option { - self.db.trait_data(trait_).associated_type_by_name(&Name::new_symbol_root(sym::Output)) + self.db + .trait_data(trait_) + .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone())) } fn resolve_lang_trait(&self, lang: LangItem) -> Option { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index f54081a276c8d..417fca5dcd671 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs @@ -623,7 +623,7 @@ impl InferenceContext<'_> { if let Some(deref_fn) = self .db .trait_data(deref_trait) - .method_by_name(&Name::new_symbol_root(sym::deref_mut)) + .method_by_name(&Name::new_symbol_root(sym::deref_mut.clone())) { break 'b deref_fn == f; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index a0c3f48642e3b..7857d207be7cf 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -650,7 +650,7 @@ impl InferenceContext<'_> { if let Some(deref_fn) = self .db .trait_data(deref_trait) - .method_by_name(&Name::new_symbol_root(sym::deref)) + .method_by_name(&Name::new_symbol_root(sym::deref.clone())) { // FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that // the mutability is not wrong, and will be fixed in `self.infer_mut`). @@ -791,7 +791,7 @@ impl InferenceContext<'_> { if let Some(func) = self .db .trait_data(index_trait) - .method_by_name(&Name::new_symbol_root(sym::index)) + .method_by_name(&Name::new_symbol_root(sym::index.clone())) { let substs = TyBuilder::subst_for_def(self.db, index_trait, None) .push(self_ty.clone()) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index ca8996fb89e77..abb702d15002f 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -112,7 +112,7 @@ impl InferenceContext<'_> { if let Some(index_fn) = self .db .trait_data(index_trait) - .method_by_name(&Name::new_symbol_root(sym::index_mut)) + .method_by_name(&Name::new_symbol_root(sym::index_mut.clone())) { *f = index_fn; let base_adjustments = self @@ -145,7 +145,7 @@ impl InferenceContext<'_> { if let Some(deref_fn) = self .db .trait_data(deref_trait) - .method_by_name(&Name::new_symbol_root(sym::deref_mut)) + .method_by_name(&Name::new_symbol_root(sym::deref_mut.clone())) { *f = deref_fn; } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs index 67a0ec60f19d6..0b44bbec70f75 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs @@ -228,7 +228,7 @@ impl InferenceContext<'_> { Path::LangItem(..) => ( PathSegment { name: { - _d = Name::new_symbol_root(sym::Unknown); + _d = Name::new_symbol_root(sym::Unknown.clone()); &_d }, args_and_bindings: None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 800b06afbd0b2..7ee63af1c229e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -783,7 +783,7 @@ impl<'a> InferenceTable<'a> { let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; let trait_data = self.db.trait_data(fn_once_trait); let output_assoc_type = - trait_data.associated_type_by_name(&Name::new_symbol_root(sym::Output))?; + trait_data.associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?; let mut arg_tys = Vec::with_capacity(num_args); let arg_ty = TyBuilder::tuple(num_args) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs index 69ff03eb49ece..f704b59d303e5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs @@ -21,43 +21,53 @@ pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, LangIte Some(match op { BinaryOp::LogicOp(_) => return None, BinaryOp::ArithOp(aop) => match aop { - ArithOp::Add => (Name::new_symbol_root(sym::add), LangItem::Add), - ArithOp::Mul => (Name::new_symbol_root(sym::mul), LangItem::Mul), - ArithOp::Sub => (Name::new_symbol_root(sym::sub), LangItem::Sub), - ArithOp::Div => (Name::new_symbol_root(sym::div), LangItem::Div), - ArithOp::Rem => (Name::new_symbol_root(sym::rem), LangItem::Rem), - ArithOp::Shl => (Name::new_symbol_root(sym::shl), LangItem::Shl), - ArithOp::Shr => (Name::new_symbol_root(sym::shr), LangItem::Shr), - ArithOp::BitXor => (Name::new_symbol_root(sym::bitxor), LangItem::BitXor), - ArithOp::BitOr => (Name::new_symbol_root(sym::bitor), LangItem::BitOr), - ArithOp::BitAnd => (Name::new_symbol_root(sym::bitand), LangItem::BitAnd), + ArithOp::Add => (Name::new_symbol_root(sym::add.clone()), LangItem::Add), + ArithOp::Mul => (Name::new_symbol_root(sym::mul.clone()), LangItem::Mul), + ArithOp::Sub => (Name::new_symbol_root(sym::sub.clone()), LangItem::Sub), + ArithOp::Div => (Name::new_symbol_root(sym::div.clone()), LangItem::Div), + ArithOp::Rem => (Name::new_symbol_root(sym::rem.clone()), LangItem::Rem), + ArithOp::Shl => (Name::new_symbol_root(sym::shl.clone()), LangItem::Shl), + ArithOp::Shr => (Name::new_symbol_root(sym::shr.clone()), LangItem::Shr), + ArithOp::BitXor => (Name::new_symbol_root(sym::bitxor.clone()), LangItem::BitXor), + ArithOp::BitOr => (Name::new_symbol_root(sym::bitor.clone()), LangItem::BitOr), + ArithOp::BitAnd => (Name::new_symbol_root(sym::bitand.clone()), LangItem::BitAnd), }, BinaryOp::Assignment { op: Some(aop) } => match aop { - ArithOp::Add => (Name::new_symbol_root(sym::add_assign), LangItem::AddAssign), - ArithOp::Mul => (Name::new_symbol_root(sym::mul_assign), LangItem::MulAssign), - ArithOp::Sub => (Name::new_symbol_root(sym::sub_assign), LangItem::SubAssign), - ArithOp::Div => (Name::new_symbol_root(sym::div_assign), LangItem::DivAssign), - ArithOp::Rem => (Name::new_symbol_root(sym::rem_assign), LangItem::RemAssign), - ArithOp::Shl => (Name::new_symbol_root(sym::shl_assign), LangItem::ShlAssign), - ArithOp::Shr => (Name::new_symbol_root(sym::shr_assign), LangItem::ShrAssign), - ArithOp::BitXor => (Name::new_symbol_root(sym::bitxor_assign), LangItem::BitXorAssign), - ArithOp::BitOr => (Name::new_symbol_root(sym::bitor_assign), LangItem::BitOrAssign), - ArithOp::BitAnd => (Name::new_symbol_root(sym::bitand_assign), LangItem::BitAndAssign), + ArithOp::Add => (Name::new_symbol_root(sym::add_assign.clone()), LangItem::AddAssign), + ArithOp::Mul => (Name::new_symbol_root(sym::mul_assign.clone()), LangItem::MulAssign), + ArithOp::Sub => (Name::new_symbol_root(sym::sub_assign.clone()), LangItem::SubAssign), + ArithOp::Div => (Name::new_symbol_root(sym::div_assign.clone()), LangItem::DivAssign), + ArithOp::Rem => (Name::new_symbol_root(sym::rem_assign.clone()), LangItem::RemAssign), + ArithOp::Shl => (Name::new_symbol_root(sym::shl_assign.clone()), LangItem::ShlAssign), + ArithOp::Shr => (Name::new_symbol_root(sym::shr_assign.clone()), LangItem::ShrAssign), + ArithOp::BitXor => { + (Name::new_symbol_root(sym::bitxor_assign.clone()), LangItem::BitXorAssign) + } + ArithOp::BitOr => { + (Name::new_symbol_root(sym::bitor_assign.clone()), LangItem::BitOrAssign) + } + ArithOp::BitAnd => { + (Name::new_symbol_root(sym::bitand_assign.clone()), LangItem::BitAndAssign) + } }, BinaryOp::CmpOp(cop) => match cop { - CmpOp::Eq { negated: false } => (Name::new_symbol_root(sym::eq), LangItem::PartialEq), - CmpOp::Eq { negated: true } => (Name::new_symbol_root(sym::ne), LangItem::PartialEq), + CmpOp::Eq { negated: false } => { + (Name::new_symbol_root(sym::eq.clone()), LangItem::PartialEq) + } + CmpOp::Eq { negated: true } => { + (Name::new_symbol_root(sym::ne.clone()), LangItem::PartialEq) + } CmpOp::Ord { ordering: Ordering::Less, strict: false } => { - (Name::new_symbol_root(sym::le), LangItem::PartialOrd) + (Name::new_symbol_root(sym::le.clone()), LangItem::PartialOrd) } CmpOp::Ord { ordering: Ordering::Less, strict: true } => { - (Name::new_symbol_root(sym::lt), LangItem::PartialOrd) + (Name::new_symbol_root(sym::lt.clone()), LangItem::PartialOrd) } CmpOp::Ord { ordering: Ordering::Greater, strict: false } => { - (Name::new_symbol_root(sym::ge), LangItem::PartialOrd) + (Name::new_symbol_root(sym::ge.clone()), LangItem::PartialOrd) } CmpOp::Ord { ordering: Ordering::Greater, strict: true } => { - (Name::new_symbol_root(sym::gt), LangItem::PartialOrd) + (Name::new_symbol_root(sym::gt.clone()), LangItem::PartialOrd) } }, BinaryOp::Assignment { op: None } => return None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 60447ac582030..aabf11f268ff8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -897,7 +897,7 @@ pub fn callable_sig_from_fn_trait( let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; let output_assoc_type = db .trait_data(fn_once_trait) - .associated_type_by_name(&Name::new_symbol_root(sym::Output))?; + .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?; let mut table = InferenceTable::new(db, trait_env.clone()); let b = TyBuilder::trait_ref(db, fn_once_trait); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index 982080c5ff5fe..32b7d6dc1138a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -631,18 +631,20 @@ impl Evaluator<'_> { cached_fn_trait_func: db .lang_item(crate_id, LangItem::Fn) .and_then(|x| x.as_trait()) - .and_then(|x| db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call))), + .and_then(|x| { + db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call.clone())) + }), cached_fn_mut_trait_func: db .lang_item(crate_id, LangItem::FnMut) .and_then(|x| x.as_trait()) .and_then(|x| { - db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_mut)) + db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_mut.clone())) }), cached_fn_once_trait_func: db .lang_item(crate_id, LangItem::FnOnce) .and_then(|x| x.as_trait()) .and_then(|x| { - db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_once)) + db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_once.clone())) }), }) } @@ -2694,7 +2696,7 @@ impl Evaluator<'_> { ) -> Result<()> { let Some(drop_fn) = (|| { let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?; - self.db.trait_data(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop)) + self.db.trait_data(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop.clone())) })() else { // in some tests we don't have drop trait in minicore, and // we can ignore drop in them. @@ -2803,7 +2805,7 @@ pub fn render_const_using_debug_impl( not_supported!("core::fmt::Debug not found"); }; let Some(debug_fmt_fn) = - db.trait_data(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt)) + db.trait_data(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt.clone())) else { not_supported!("core::fmt::Debug::fmt not found"); }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 67e102b1ed183..6818759310613 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -319,7 +319,7 @@ impl Evaluator<'_> { return Some(LangItem::BeginPanic); } - let candidate = attrs.by_key("lang").string_value().and_then(LangItem::from_str)?; + let candidate = attrs.lang_item()?; // We want to execute these functions with special logic // `PanicFmt` is not detected here as it's redirected later. if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) { @@ -1279,7 +1279,7 @@ impl Evaluator<'_> { if let Some(def) = target.as_trait().and_then(|it| { self.db .trait_data(it) - .method_by_name(&Name::new_symbol_root(sym::call_once)) + .method_by_name(&Name::new_symbol_root(sym::call_once.clone())) }) { self.exec_fn_trait( def, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs index 5e8a2dfb735f6..424ee1160c820 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs @@ -189,10 +189,10 @@ impl MirLowerCtx<'_> { if let Some(deref_trait) = self.resolve_lang_item(LangItem::DerefMut)?.as_trait() { - if let Some(deref_fn) = self - .db - .trait_data(deref_trait) - .method_by_name(&Name::new_symbol_root(sym::deref_mut)) + if let Some(deref_fn) = + self.db.trait_data(deref_trait).method_by_name( + &Name::new_symbol_root(sym::deref_mut.clone()), + ) { break 'b deref_fn == f; } @@ -327,14 +327,14 @@ impl MirLowerCtx<'_> { ( Mutability::Not, LangItem::Deref, - Name::new_symbol_root(sym::deref), + Name::new_symbol_root(sym::deref.clone()), BorrowKind::Shared, ) } else { ( Mutability::Mut, LangItem::DerefMut, - Name::new_symbol_root(sym::deref_mut), + Name::new_symbol_root(sym::deref_mut.clone()), BorrowKind::Mut { kind: MutBorrowKind::Default }, ) }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index ce9ffa284c904..c46382a0ea822 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -257,9 +257,9 @@ impl FnTrait { pub fn method_name(self) -> Name { match self { - FnTrait::FnOnce => Name::new_symbol_root(sym::call_once), - FnTrait::FnMut => Name::new_symbol_root(sym::call_mut), - FnTrait::Fn => Name::new_symbol_root(sym::call), + FnTrait::FnOnce => Name::new_symbol_root(sym::call_once.clone()), + FnTrait::FnMut => Name::new_symbol_root(sym::call_mut.clone()), + FnTrait::Fn => Name::new_symbol_root(sym::call.clone()), } } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index f90656c75f590..c868357ff982f 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1827,7 +1827,7 @@ impl DefWithBody { continue; } let mut need_mut = &mol[local]; - if body[binding_id].name == sym::self_ + if body[binding_id].name == sym::self_.clone() && need_mut == &mir::MutabilityReason::Unused { need_mut = &mir::MutabilityReason::Not; @@ -2589,7 +2589,7 @@ pub struct StaticLifetime; impl StaticLifetime { pub fn name(self) -> Name { - Name::new_symbol_root(sym::tick_static) + Name::new_symbol_root(sym::tick_static.clone()) } } @@ -3249,7 +3249,7 @@ impl Local { } pub fn is_self(self, db: &dyn HirDatabase) -> bool { - self.name(db) == sym::self_ + self.name(db) == sym::self_.clone() } pub fn is_mut(self, db: &dyn HirDatabase) -> bool { diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 45401702e9f00..be0116862b9cf 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -366,7 +366,7 @@ impl SourceAnalyzer { let items = into_future_trait.items(db); let into_future_type = items.into_iter().find_map(|item| match item { AssocItem::TypeAlias(alias) - if alias.name(db) == Name::new_symbol_root(sym::IntoFuture) => + if alias.name(db) == Name::new_symbol_root(sym::IntoFuture.clone()) => { Some(alias) } @@ -395,8 +395,11 @@ impl SourceAnalyzer { // This can be either `Deref::deref` or `DerefMut::deref_mut`. // Since deref kind is inferenced and stored in `InferenceResult.method_resolution`, // use that result to find out which one it is. - let (deref_trait, deref) = - self.lang_trait_fn(db, LangItem::Deref, &Name::new_symbol_root(sym::deref))?; + let (deref_trait, deref) = self.lang_trait_fn( + db, + LangItem::Deref, + &Name::new_symbol_root(sym::deref.clone()), + )?; self.infer .as_ref() .and_then(|infer| { @@ -405,7 +408,7 @@ impl SourceAnalyzer { let (deref_mut_trait, deref_mut) = self.lang_trait_fn( db, LangItem::DerefMut, - &Name::new_symbol_root(sym::deref_mut), + &Name::new_symbol_root(sym::deref_mut.clone()), )?; if func == deref_mut { Some((deref_mut_trait, deref_mut)) @@ -416,10 +419,10 @@ impl SourceAnalyzer { .unwrap_or((deref_trait, deref)) } ast::UnaryOp::Not => { - self.lang_trait_fn(db, LangItem::Not, &Name::new_symbol_root(sym::not))? + self.lang_trait_fn(db, LangItem::Not, &Name::new_symbol_root(sym::not.clone()))? } ast::UnaryOp::Neg => { - self.lang_trait_fn(db, LangItem::Neg, &Name::new_symbol_root(sym::neg))? + self.lang_trait_fn(db, LangItem::Neg, &Name::new_symbol_root(sym::neg.clone()))? } }; @@ -441,7 +444,7 @@ impl SourceAnalyzer { let index_ty = self.ty_of_expr(db, &index_expr.index()?)?; let (index_trait, index_fn) = - self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index))?; + self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index.clone()))?; let (op_trait, op_fn) = self .infer .as_ref() @@ -451,7 +454,7 @@ impl SourceAnalyzer { let (index_mut_trait, index_mut_fn) = self.lang_trait_fn( db, LangItem::IndexMut, - &Name::new_symbol_root(sym::index_mut), + &Name::new_symbol_root(sym::index_mut.clone()), )?; if func == index_mut_fn { Some((index_mut_trait, index_mut_fn)) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs index 27e39f6f8ab26..77f9c66b354ee 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs @@ -223,7 +223,7 @@ fn option_variants( let fam = FamousDefs(sema, sema.scope(expr)?.krate()); let option_variants = fam.core_option_Option()?.variants(sema.db); match &*option_variants { - &[variant0, variant1] => Some(if variant0.name(sema.db) == sym::None { + &[variant0, variant1] => Some(if variant0.name(sema.db) == sym::None.clone() { (variant0, variant1) } else { (variant1, variant0) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs index d85147e84b20c..e86ff0dbebc62 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs @@ -150,9 +150,9 @@ fn is_ref_and_impls_iter_method( _ => return None, }; let wanted_method = Name::new_symbol_root(if ref_expr.mut_token().is_some() { - sym::iter_mut + sym::iter_mut.clone() } else { - sym::iter + sym::iter.clone() }); let expr_behind_ref = ref_expr.expr()?; let ty = sema.type_of_expr(&expr_behind_ref)?.adjusted(); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs index 05210e66ac24d..ad422b25c39e0 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_is_empty_from_len.rs @@ -54,13 +54,13 @@ pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext< } let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?; - let len_fn = get_impl_method(ctx, &impl_, &Name::new_symbol_root(sym::len))?; + let len_fn = get_impl_method(ctx, &impl_, &Name::new_symbol_root(sym::len.clone()))?; if !len_fn.ret_type(ctx.sema.db).is_usize() { cov_mark::hit!(len_fn_different_return_type); return None; } - if get_impl_method(ctx, &impl_, &Name::new_symbol_root(sym::is_empty)).is_some() { + if get_impl_method(ctx, &impl_, &Name::new_symbol_root(sym::is_empty.clone())).is_some() { cov_mark::hit!(is_empty_already_implemented); return None; } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs index 137b8d13171fe..d0382499b996a 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs @@ -430,7 +430,7 @@ fn inline( let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty); - let is_self = param.name(sema.db).is_some_and(|name| name == sym::self_); + let is_self = param.name(sema.db).is_some_and(|name| name == sym::self_.clone()); if is_self { let mut this_pat = make::ident_pat(false, false, make::name("this")); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index 4a8ea171805e2..ee27d8611eb80 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -618,7 +618,8 @@ fn enum_variants_with_paths( let mut process_variant = |variant: Variant| { let self_path = hir::ModPath::from_segments( hir::PathKind::Plain, - iter::once(Name::new_symbol_root(sym::Self_)).chain(iter::once(variant.name(ctx.db))), + iter::once(Name::new_symbol_root(sym::Self_.clone())) + .chain(iter::once(variant.name(ctx.db))), ); cb(acc, ctx, variant, self_path); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index d3290db4ef82b..a07daf4c4e49c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -91,13 +91,13 @@ pub(crate) fn complete_undotted_self( in_breakable: expr_ctx.in_breakable, }, }, - Some(Name::new_symbol_root(sym::self_)), + Some(Name::new_symbol_root(sym::self_.clone())), field, &ty, ) }, |acc, field, ty| { - acc.add_tuple_field(ctx, Some(Name::new_symbol_root(sym::self_)), field, &ty) + acc.add_tuple_field(ctx, Some(Name::new_symbol_root(sym::self_.clone())), field, &ty) }, true, false, @@ -115,7 +115,7 @@ pub(crate) fn complete_undotted_self( }, }, func, - Some(Name::new_symbol_root(sym::self_)), + Some(Name::new_symbol_root(sym::self_.clone())), None, ) }); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index 72b36922da0bd..71ff6b5aea37a 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -190,7 +190,7 @@ pub(crate) fn complete_expr_path( path_ctx, strukt, None, - Some(Name::new_symbol_root(sym::Self_)), + Some(Name::new_symbol_root(sym::Self_.clone())), ); } } @@ -214,7 +214,7 @@ pub(crate) fn complete_expr_path( ctx, un, None, - Some(Name::new_symbol_root(sym::Self_)), + Some(Name::new_symbol_root(sym::Self_.clone())), ); } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs index 541ccf2d198e3..f31352f49f9de 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs @@ -47,7 +47,7 @@ pub(crate) fn complete_lifetime( } }); if param_lifetime.is_none() { - acc.add_lifetime(ctx, Name::new_symbol_root(sym::tick_static)); + acc.add_lifetime(ctx, Name::new_symbol_root(sym::tick_static.clone())); } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs index 4cdb279a21ca6..a41bf457a9032 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs @@ -210,7 +210,7 @@ fn get_default_constructor( let has_new_func = ty .iterate_assoc_items(ctx.sema.db, krate, |assoc_item| { if let AssocItem::Function(func) = assoc_item { - if func.name(ctx.sema.db) == sym::new + if func.name(ctx.sema.db) == sym::new.clone() && func.assoc_fn_params(ctx.sema.db).is_empty() { return Some(()); diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index 0692f0d700612..ce1a56e45062b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -633,7 +633,7 @@ fn hint_iterator( if ty.impls_trait(db, iter_trait, &[]) { let assoc_type_item = iter_trait.items(db).into_iter().find_map(|item| match item { - hir::AssocItem::TypeAlias(alias) if alias.name(db) == sym::Item => Some(alias), + hir::AssocItem::TypeAlias(alias) if alias.name(db) == sym::Item.clone() => Some(alias), _ => None, })?; if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index c73b6acb0d073..291073f87735c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -6,6 +6,7 @@ use ide_db::{ defs::{Definition, IdentClass, NameClass, NameRefClass}, FxHashMap, RootDatabase, SymbolKind, }; +use stdx::hash_once; use syntax::{ ast, match_ast, AstNode, AstToken, NodeOrToken, SyntaxKind::{self, *}, @@ -358,17 +359,7 @@ fn highlight_name( } fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 { - fn hash(x: T) -> u64 { - use ide_db::FxHasher; - - use std::hash::Hasher; - - let mut hasher = FxHasher::default(); - x.hash(&mut hasher); - hasher.finish() - } - - hash((name, shadow_count)) + hash_once::((name.as_str(), shadow_count)) } pub(super) fn highlight_def( diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 9f7a788d006c8..9e275713876c0 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -91,7 +91,7 @@ impl TaggedArcPtr { } #[inline] - const fn pack_arc(ptr: NonNull<*const str>) -> NonNull<*const str> { + fn pack_arc(ptr: NonNull<*const str>) -> NonNull<*const str> { let packed_tag = true as usize; // can't use this strict provenance stuff here due to trait methods not being const @@ -112,7 +112,7 @@ impl TaggedArcPtr { // } // so what follows is roughly what the above looks like but inlined - let self_addr = unsafe { core::mem::transmute::<*const _, usize>(ptr.as_ptr()) }; + let self_addr = ptr.as_ptr() as *const *const str as usize; let addr = self_addr | packed_tag; let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr as isize); @@ -222,7 +222,7 @@ impl Symbol { .try_as_arc_owned() .unwrap(), ); - debug_assert_eq!(Arc::count(&arc), 1); + debug_assert_eq!(Arc::count(arc), 1); // Shrink the backing storage if the shard is less than 50% occupied. if shard.len() * 2 < shard.capacity() { diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index af1af0536c2e5..6304155ed76ad 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -14,10 +14,10 @@ use crate::{ macro_rules! define_symbols { (@WITH_NAME: $($alias:ident = $value:literal),* $(,)? @PLAIN: $($name:ident),* $(,)?) => { $( - pub const $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) }; + pub static $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) }; )* $( - pub const $alias: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&$value) }; + pub static $alias: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&$value) }; )* @@ -78,10 +78,13 @@ define_symbols! { @PLAIN: add_assign, add, + align_offset, + alloc_layout, alloc, as_str, asm, assert, + begin_panic, bench, bitand_assign, bitand, @@ -89,88 +92,13 @@ define_symbols! { bitor, bitxor_assign, bitxor, - transmute_opts, - transmute_trait, - coerce_unsized, - dispatch_from_dyn,destruct, bool, - panic, - begin_panic, - panic_nounwind, - panic_fmt, - panic_misaligned_pointer_dereference, - panic_display, - const_panic_fmt, - panic_bounds_check, - panic_info, - panic_location, - panic_impl, - panic_cannot_unwind, - sized, - unsize, - format_alignment, - start, - format_argument, - format_arguments, - format_count, - format_placeholder, - format_unsafe_arg, - exchange_malloc, box_free, - drop_in_place, - alloc_layout, - eh_personality, - eh_catch_typeinfo, - phantom_data, - manually_drop, - maybe_uninit, - align_offset, - termination, - tuple_trait, - slice_len_fn, - from_residual, - from_output, - from_yeet, - pointer_like, - const_param_ty, - Poll, - Ready, - Pending, - ResumeTy, - get_context, - Context, - Some, - Err, - Continue, - Break, - into_iter, - new_unchecked, - range_inclusive_new, - CStr, - fn_ptr_trait, - freeze, - coroutine_state, - c_void, - coroutine, - unpin, - pin, - fn_ptr_addr, - structural_teq, - fn_once_output, - copy, - clone, - sync, - discriminant_kind, Box, - structural_peq, boxed, branch, - discriminant_type, - pointee_trait, - metadata_type, - dyn_metadata, - deref_target, - receiver, + Break, + c_void, call_mut, call_once, call, @@ -180,31 +108,51 @@ define_symbols! { cfg_eval, cfg, char, + clone, Clone, + coerce_unsized, column, compile_error, concat_bytes, concat_idents, concat, const_format_args, + const_panic_fmt, + const_param_ty, + Context, + Continue, + copy, Copy, core_panic, core, + coroutine_state, + coroutine, crate_type, + CStr, Debug, default, Default, deref_mut, + deref_target, deref, derive_const, derive, + discriminant_kind, + discriminant_type, + dispatch_from_dyn,destruct, div_assign, div, doc, + drop_in_place, drop, + dyn_metadata, + eh_catch_typeinfo, + eh_personality, env, eq, Eq, + Err, + exchange_malloc, f128, f16, f32, @@ -214,15 +162,29 @@ define_symbols! { filter_map, fmt, fn_mut, + fn_once_output, fn_once, + fn_ptr_addr, + fn_ptr_trait, + format_alignment, format_args_nl, format_args, + format_argument, + format_arguments, + format_count, + format_placeholder, + format_unsafe_arg, format, + freeze, + from_output, + from_residual, from_usize, + from_yeet, future_trait, future, Future, ge, + get_context, global_allocator, global_asm, gt, @@ -240,6 +202,7 @@ define_symbols! { index, Index, into_future, + into_iter, IntoFuture, IntoIter, IntoIterator, @@ -258,6 +221,9 @@ define_symbols! { log_syntax, lt, macro_rules, + manually_drop, + maybe_uninit, + metadata_type, module_path, mul_assign, mul, @@ -271,6 +237,7 @@ define_symbols! { new_lower_hex, new_octal, new_pointer, + new_unchecked, new_upper_exp, new_upper_hex, new_v1_formatted, @@ -293,21 +260,39 @@ define_symbols! { owned_box, panic_2015, panic_2021, + panic_bounds_check, + panic_cannot_unwind, + panic_display, + panic_fmt, + panic_impl, + panic_info, + panic_location, + panic_misaligned_pointer_dereference, + panic_nounwind, + panic, Param, partial_ord, PartialEq, PartialOrd, + Pending, + phantom_data, pieces, + pin, + pointee_trait, + pointer_like, poll, + Poll, prelude, quote, - r#fn, + range_inclusive_new, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, + Ready, + receiver, recursion_limit, register_attr, register_tool, @@ -315,6 +300,7 @@ define_symbols! { rem, result, Result, + ResumeTy, Right, rust_2015, rust_2018, @@ -327,30 +313,43 @@ define_symbols! { shl, shr_assign, shr, + sized, + slice_len_fn, + Some, + start, std_panic, std, str, string, String, stringify, + structural_peq, + structural_teq, sub_assign, sub, + sync, Target, + termination, test_case, test, trace_macros, + transmute_opts, + transmute_trait, transparent, Try, + tuple_trait, u128, u16, u32, u64, u8, Unknown, + unpin, unreachable_2015, unreachable_2021, unreachable, unsafe_cell, + unsize, usize, v1, va_list From d95b2f3f4bb5839b508b86a751c09cb7e0d59cda Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 15 Jul 2024 11:07:04 +0200 Subject: [PATCH 023/489] Fix stable iteration ordering for `Map` usages --- .../crates/hir-def/src/item_scope.rs | 15 +++++----- .../crates/hir-def/src/nameres.rs | 10 +++---- .../hir-def/src/nameres/tests/macros.rs | 1 + .../crates/hir-def/src/resolver.rs | 9 ++++-- .../ide-assists/src/handlers/auto_import.rs | 28 ++++++++++++++++--- .../src/completions/format_string.rs | 2 +- .../ide-completion/src/render/function.rs | 2 +- .../ide-completion/src/tests/flyimport.rs | 2 +- .../ide-db/src/imports/import_assets.rs | 10 +++---- .../rust-analyzer/crates/intern/src/symbol.rs | 1 + .../crates/intern/src/symbol/symbols.rs | 4 +++ 11 files changed, 55 insertions(+), 29 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 092c0a1dfdf81..86c3e0f041d39 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -1,10 +1,9 @@ //! Describes items defined or visible (ie, imported) in a certain scope. //! This is shared between modules and blocks. -use std::collections::hash_map::Entry; - use base_db::CrateId; use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId}; +use indexmap::map::Entry; use itertools::Itertools; use la_arena::Idx; use once_cell::sync::Lazy; @@ -17,8 +16,8 @@ use crate::{ db::DefDatabase, per_ns::PerNs, visibility::{Visibility, VisibilityExplicitness}, - AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, - ModuleDefId, ModuleId, TraitId, UseId, + AdtId, BuiltinType, ConstId, ExternCrateId, FxIndexMap, HasModule, ImplId, LocalModuleId, + Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId, }; #[derive(Debug, Default)] @@ -67,9 +66,9 @@ pub struct ItemScope { /// Defs visible in this scope. This includes `declarations`, but also /// imports. The imports belong to this module and can be resolved by using them on /// the `use_imports_*` fields. - types: FxHashMap)>, - values: FxHashMap)>, - macros: FxHashMap)>, + types: FxIndexMap)>, + values: FxIndexMap)>, + macros: FxIndexMap)>, unresolved: FxHashSet, /// The defs declared in this scope. Each def has a single scope where it is @@ -118,7 +117,7 @@ struct DeriveMacroInvocation { derive_call_ids: SmallVec<[Option; 1]>, } -pub(crate) static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { +pub(crate) static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { BuiltinType::all_builtin_types() .iter() .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None))) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index 8e7ef48112f04..b0543727c27d0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -323,7 +323,7 @@ pub struct ModuleData { /// /// [`None`] for block modules because they are always its `DefMap`'s root. pub parent: Option, - pub children: FxHashMap, + pub children: FxIndexMap, pub scope: ItemScope, } @@ -593,10 +593,8 @@ impl DefMap { self.data.extern_prelude.iter().map(|(name, &def)| (name, def)) } - pub(crate) fn macro_use_prelude( - &self, - ) -> impl Iterator))> + '_ { - self.macro_use_prelude.iter().map(|(name, &def)| (name, def)) + pub(crate) fn macro_use_prelude(&self) -> &FxHashMap)> { + &self.macro_use_prelude } pub(crate) fn resolve_path( @@ -668,7 +666,7 @@ impl ModuleData { origin, visibility, parent: None, - children: FxHashMap::default(), + children: Default::default(), scope: ItemScope::default(), } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs index d278b75e8158a..14d497b3a11c7 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs @@ -1348,6 +1348,7 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a } .keys() .map(|name| name.display(&db).to_string()) .sorted() + .sorted() .join("\n"); expect![[r#" diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index c196f00281639..f0f2210ec2c51 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -4,6 +4,7 @@ use std::{fmt, iter, mem}; use base_db::CrateId; use hir_expand::{name::Name, MacroDefId}; use intern::{sym, Interned}; +use itertools::Itertools as _; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; use triomphe::Arc; @@ -497,9 +498,11 @@ impl Resolver { res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac))); }) }); - def_map.macro_use_prelude().for_each(|(name, (def, _extern_crate))| { - res.add(name, ScopeDef::ModuleDef(def.into())); - }); + def_map.macro_use_prelude().iter().sorted_by_key(|&(k, _)| k.clone()).for_each( + |(name, &(def, _extern_crate))| { + res.add(name, ScopeDef::ModuleDef(def.into())); + }, + ); def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| { res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into()))); }); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs index f17635972b78c..37c5d7ce7efd7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs @@ -1637,8 +1637,8 @@ mod bar { #[test] fn local_inline_import_has_alias() { - // FIXME - check_assist_not_applicable( + // FIXME wrong import + check_assist( auto_import, r#" struct S(T); @@ -1647,14 +1647,24 @@ use S as IoResult; mod foo { pub fn bar() -> S$0<()> {} } +"#, + r#" +struct S(T); +use S as IoResult; + +mod foo { + use crate::S; + + pub fn bar() -> S<()> {} +} "#, ); } #[test] fn alias_local() { - // FIXME - check_assist_not_applicable( + // FIXME wrong import + check_assist( auto_import, r#" struct S(T); @@ -1663,6 +1673,16 @@ use S as IoResult; mod foo { pub fn bar() -> IoResult$0<()> {} } +"#, + r#" +struct S(T); +use S as IoResult; + +mod foo { + use crate::S; + + pub fn bar() -> IoResult<()> {} +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs index 5512ac2153460..559a9bcba2961 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs @@ -31,7 +31,7 @@ pub(crate) fn format_string( }; let source_range = TextRange::new(brace_offset, cursor); - ctx.locals.iter().for_each(|(name, _)| { + ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()).for_each(|(name, _)| { CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str()) .add_to(acc, ctx.db); }); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index c15e91c404839..cdfe23170176c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -259,7 +259,7 @@ pub(super) fn add_call_parens<'b>( fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'static str { if let Some(derefed_ty) = ty.remove_ref() { - for (name, local) in ctx.locals.iter() { + for (name, local) in ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()) { if name.as_str() == arg { return if local.ty(ctx.db) == derefed_ty { if ty.is_mutable_reference() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 7d9c1ed98ac59..eacec018c72b9 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -767,8 +767,8 @@ fn main() { } "#, expect![[r#" - fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED + fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED "#]], ); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 4814394de6b29..38cb4a162c28c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -15,7 +15,7 @@ use syntax::{ use crate::{ helpers::item_name, items_locator::{self, AssocSearchMode, DEFAULT_QUERY_SEARCH_LIMIT}, - RootDatabase, + FxIndexSet, RootDatabase, }; /// A candidate for import, derived during various IDE activities: @@ -262,7 +262,7 @@ impl ImportAssets { let scope = match sema.scope(&self.candidate_node) { Some(it) => it, - None => return >::default().into_iter(), + None => return >::default().into_iter(), }; let krate = self.module_with_candidate.krate(); @@ -319,7 +319,7 @@ fn path_applicable_imports( path_candidate: &PathImportCandidate, mod_path: impl Fn(ItemInNs) -> Option + Copy, scope_filter: impl Fn(ItemInNs) -> bool + Copy, -) -> FxHashSet { +) -> FxIndexSet { let _p = tracing::info_span!("ImportAssets::path_applicable_imports").entered(); match &path_candidate.qualifier { @@ -500,7 +500,7 @@ fn trait_applicable_items( trait_assoc_item: bool, mod_path: impl Fn(ItemInNs) -> Option, scope_filter: impl Fn(hir::Trait) -> bool, -) -> FxHashSet { +) -> FxIndexSet { let _p = tracing::info_span!("ImportAssets::trait_applicable_items").entered(); let db = sema.db; @@ -566,7 +566,7 @@ fn trait_applicable_items( definitions_exist_in_trait_crate || definitions_exist_in_receiver_crate() }); - let mut located_imports = FxHashSet::default(); + let mut located_imports = FxIndexSet::default(); let mut trait_import_paths = FxHashMap::default(); if trait_assoc_item { diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 9e275713876c0..a3cc5c3d6a3d6 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -37,6 +37,7 @@ const _: () = /// A pointer that points to a pointer to a `str`, it may be backed as a `&'static &'static str` or /// `Arc>` but its size is that of a thin pointer. The active variant is encoded as a tag /// in the LSB of the alignment niche. +// Note, Ideally this would encode a `ThinArc` and `ThinRef`/`ThinConstPtr` instead of the double indirection. #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] struct TaggedArcPtr { packed: NonNull<*const str>, diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 6304155ed76ad..064335471e95a 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -13,6 +13,10 @@ use crate::{ macro_rules! define_symbols { (@WITH_NAME: $($alias:ident = $value:literal),* $(,)? @PLAIN: $($name:ident),* $(,)?) => { + // Ideally we would be emitting `const` here, but then we no longer have stable addresses + // which is what we are relying on for equality! In the future if consts can refer to + // statics we should swap these for `const`s and have the the string literal being pointed + // to be statics to refer to such that their address is stable. $( pub static $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) }; )* From 6af77a624ea72427a6bb53dac89053fc95ee3329 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 7 Jul 2024 17:47:38 +0200 Subject: [PATCH 024/489] Encode ident rawness and literal kind separately in tt::Leaf --- src/tools/rust-analyzer/Cargo.lock | 1 + .../rust-analyzer/crates/hir-def/src/attr.rs | 2 +- .../crates/hir-def/src/hir/format_args.rs | 2 +- .../macro_expansion_tests/builtin_fn_macro.rs | 8 +- .../macro_expansion_tests/mbe/regression.rs | 4 +- .../crates/hir-def/src/nameres/collector.rs | 4 +- .../crates/hir-expand/src/attrs.rs | 44 ++-- .../hir-expand/src/builtin_derive_macro.rs | 3 +- .../crates/hir-expand/src/builtin_fn_macro.rs | 199 +++++++++-------- .../crates/hir-expand/src/fixup.rs | 23 +- .../crates/hir-expand/src/lib.rs | 2 +- .../crates/hir-expand/src/mod_path.rs | 10 +- .../crates/hir-expand/src/name.rs | 11 +- .../crates/hir-expand/src/quote.rs | 31 ++- .../rust-analyzer/crates/hir/src/attrs.rs | 8 +- .../crates/ide-db/src/documentation.rs | 17 +- .../rust-analyzer/crates/ide/src/hover.rs | 2 +- src/tools/rust-analyzer/crates/mbe/Cargo.toml | 1 + .../rust-analyzer/crates/mbe/src/benchmark.rs | 15 +- .../crates/mbe/src/expander/transcriber.rs | 24 ++- src/tools/rust-analyzer/crates/mbe/src/lib.rs | 13 +- .../rust-analyzer/crates/mbe/src/parser.rs | 12 +- .../crates/mbe/src/syntax_bridge.rs | 188 +++++++++++----- .../crates/mbe/src/to_parser_input.rs | 26 +-- .../crates/proc-macro-api/src/msg.rs | 34 ++- .../crates/proc-macro-api/src/msg/flat.rs | 124 +++++++++-- .../proc-macro-test/imp/src/lib.rs | 1 - .../crates/proc-macro-srv/src/server_impl.rs | 75 +++---- .../src/server_impl/rust_analyzer_span.rs | 39 ++-- .../src/server_impl/token_id.rs | 38 ++-- .../crates/proc-macro-srv/src/tests/mod.rs | 104 ++++----- .../crates/salsa/tests/macros.rs | 1 + src/tools/rust-analyzer/crates/tt/src/lib.rs | 202 ++++++++++++++++-- 33 files changed, 858 insertions(+), 410 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index b165697724e05..e43f712a6e230 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1046,6 +1046,7 @@ dependencies = [ "arrayvec", "cov-mark", "parser", + "ra-ap-rustc_lexer", "rustc-hash", "smallvec", "span", diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index aacfb07319819..5bd60c58e9b7e 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -605,7 +605,7 @@ impl<'attr> AttrQuery<'attr> { .nth(2); match name { - Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal{ ref text, ..}))) => Some(text), + Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal{ text, kind: tt::LitKind::Str | tt::LitKind::StrRaw(_) , ..}))) => Some(text), _ => None } }) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index d6dd5df37366a..cf176e86dbd5d 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -250,7 +250,7 @@ pub(crate) fn parse( } } ArgRef::Name(name, span) => { - let name = Name::new(name, call_ctx); + let name = Name::new(name, tt::IdentIsRaw::No, call_ctx); if let Some((index, _)) = args.by_name(&name) { record_usage(name, span); // Name found in `args`, so we resolve it to its index. diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index 9596100b60e13..ab8bb8bd4c6fc 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -460,13 +460,13 @@ fn test_concat_expand() { #[rustc_builtin_macro] macro_rules! concat {} -fn main() { concat!("fo", "o", 0, r#"bar"#, "\n", false, '"', '\0'); } +fn main() { concat!("fo", "o", 0, r#""bar""#, "\n", false, '"', '\0'); } "##, expect![[r##" #[rustc_builtin_macro] macro_rules! concat {} -fn main() { "foo0bar\nfalse\"\u{0}"; } +fn main() { "foo0\"bar\"\nfalse\"\u{0}"; } "##]], ); } @@ -478,13 +478,13 @@ fn test_concat_bytes_expand() { #[rustc_builtin_macro] macro_rules! concat_bytes {} -fn main() { concat_bytes!(b'A', b"BC", [68, b'E', 70]); } +fn main() { concat_bytes!(b'A', b"BC\"", [68, b'E', 70], br#"G""#,b'\0'); } "##, expect![[r#" #[rustc_builtin_macro] macro_rules! concat_bytes {} -fn main() { [b'A', 66, 67, 68, b'E', 70]; } +fn main() { b"ABC\"DEFG\"\x00"; } "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs index 4aad53c3bd71c..252b0bb1b59b8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs @@ -1058,7 +1058,7 @@ macro_rules! concat {} macro_rules! line {} fn main() { - "event 0u32"; + "event 0"; } "##]], @@ -1084,7 +1084,7 @@ fn main() { macro_rules! concat_bytes {} fn main() { - let x = /* error: unexpected token in input */[]; + let x = /* error: unexpected token in input */b""; } "#]], diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index f14679f6c2f14..13abcce78ead4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -82,7 +82,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI .iter() .enumerate() .map(|(idx, it)| { - let name = Name::new(&it.name, ctx); + let name = Name::new(&it.name, tt::IdentIsRaw::No, ctx); ( name, if !db.expand_proc_attr_macros() { @@ -2144,7 +2144,7 @@ impl ModCollector<'_, '_> { let name; let name = match attrs.by_key("rustc_builtin_macro").string_value_with_span() { Some((it, span)) => { - name = Name::new(it, span.ctx); + name = Name::new(it, tt::IdentIsRaw::No, span.ctx); &name } None => { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 36636a228f147..4fce7c1fde13f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -5,11 +5,14 @@ use base_db::CrateId; use cfg::CfgExpr; use either::Either; use intern::{sym, Interned}; -use mbe::{syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode, Punct}; +use mbe::{ + desugar_doc_comment_text, syntax_node_to_token_tree, token_to_literal, DelimiterKind, + DocCommentDesugarMode, Punct, +}; use smallvec::{smallvec, SmallVec}; use span::{Span, SyntaxContextId}; use syntax::unescape; -use syntax::{ast, format_smolstr, match_ast, AstNode, AstToken, SmolStr, SyntaxNode}; +use syntax::{ast, match_ast, AstNode, AstToken, SyntaxNode}; use triomphe::ThinArc; use crate::name::Name; @@ -53,11 +56,15 @@ impl RawAttrs { } Either::Right(comment) => comment.doc_comment().map(|doc| { let span = span_map.span_for_range(comment.syntax().text_range()); + let (text, kind) = + desugar_doc_comment_text(doc, DocCommentDesugarMode::ProcMacro); Attr { id, input: Some(Box::new(AttrInput::Literal(tt::Literal { - text: SmolStr::new(format_smolstr!("\"{}\"", Self::escape_chars(doc))), + text, span, + kind, + suffix: None, }))), path: Interned::new(ModPath::from(Name::new_symbol( sym::doc.clone(), @@ -78,10 +85,6 @@ impl RawAttrs { RawAttrs { entries } } - fn escape_chars(s: &str) -> String { - s.replace('\\', r#"\\"#).replace('"', r#"\""#) - } - pub fn from_attrs_owner( db: &dyn ExpandDatabase, owner: InFile<&dyn ast::HasAttrs>, @@ -238,10 +241,8 @@ impl Attr { })?); let span = span_map.span_for_range(range); let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { - Some(Box::new(AttrInput::Literal(tt::Literal { - text: lit.token().text().into(), - span, - }))) + let token = lit.token(); + Some(Box::new(AttrInput::Literal(token_to_literal(token.text().into(), span)))) } else if let Some(tt) = ast.token_tree() { let tree = syntax_node_to_token_tree( tt.syntax(), @@ -310,12 +311,11 @@ impl Attr { /// #[path = "string"] pub fn string_value(&self) -> Option<&str> { match self.input.as_deref()? { - AttrInput::Literal(it) => match it.text.strip_prefix('r') { - Some(it) => it.trim_matches('#'), - None => it.text.as_str(), - } - .strip_prefix('"')? - .strip_suffix('"'), + AttrInput::Literal(tt::Literal { + text, + kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), + .. + }) => Some(text), _ => None, } } @@ -336,12 +336,10 @@ impl Attr { pub fn string_value_unescape(&self) -> Option> { match self.input.as_deref()? { - AttrInput::Literal(it) => match it.text.strip_prefix('r') { - Some(it) => { - it.trim_matches('#').strip_prefix('"')?.strip_suffix('"').map(Cow::Borrowed) - } - None => it.text.strip_prefix('"')?.strip_suffix('"').and_then(unescape), - }, + AttrInput::Literal(tt::Literal { text, kind: tt::LitKind::StrRaw(_), .. }) => { + Some(Cow::Borrowed(text)) + } + AttrInput::Literal(tt::Literal { text, kind: tt::LitKind::Str, .. }) => unescape(text), _ => None, } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs index 269e9f308c2f6..180d8f05627f4 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs @@ -370,7 +370,8 @@ fn name_to_token( ExpandError::other("missing name") })?; let span = token_map.span_at(name.syntax().text_range().start()); - let name_token = tt::Ident { span, text: name.text().into() }; + + let name_token = tt::Ident::new(name.text().as_ref(), span); Ok(name_token) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index 97867dfc66e92..32befb7a7f7df 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -1,13 +1,14 @@ //! Builtin macro +use ::tt::SmolStr; use base_db::{AnchoredPath, FileId}; use cfg::CfgExpr; use either::Either; use intern::sym; -use itertools::Itertools; use mbe::{parse_exprs_with_sep, parse_to_token_tree}; use span::{Edition, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; -use syntax::ast::{self, AstToken}; +use stdx::format_to; +use syntax::unescape::{unescape_byte, unescape_char, unescape_unicode, Mode}; use crate::{ db::ExpandDatabase, @@ -177,8 +178,10 @@ fn line_expand( ExpandResult::ok(tt::Subtree { delimiter: tt::Delimiter::invisible_spanned(span), token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text: "0u32".into(), + text: "0".into(), span, + kind: tt::LitKind::Integer, + suffix: Some(Box::new("u32".into())), }))]), }) } @@ -444,27 +447,6 @@ fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool { } } -fn unquote_str(lit: &tt::Literal) -> Option<(String, Span)> { - let span = lit.span; - let lit = ast::make::tokens::literal(&lit.to_string()); - let token = ast::String::cast(lit)?; - token.value().ok().map(|it| (it.into_owned(), span)) -} - -fn unquote_char(lit: &tt::Literal) -> Option<(char, Span)> { - let span = lit.span; - let lit = ast::make::tokens::literal(&lit.to_string()); - let token = ast::Char::cast(lit)?; - token.value().ok().zip(Some(span)) -} - -fn unquote_byte_string(lit: &tt::Literal) -> Option<(Vec, Span)> { - let span = lit.span; - let lit = ast::make::tokens::literal(&lit.to_string()); - let token = ast::ByteString::cast(lit)?; - token.value().ok().map(|it| (it.into_owned(), span)) -} - fn compile_error_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, @@ -472,10 +454,16 @@ fn compile_error_expand( span: Span, ) -> ExpandResult { let err = match &*tt.token_trees { - [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => match unquote_str(it) { - Some((unquoted, _)) => ExpandError::other(unquoted.into_boxed_str()), - None => ExpandError::other("`compile_error!` argument must be a string"), - }, + [tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + text, + span: _, + kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), + suffix: _, + }))] => + // FIXME: Use the span here! + { + ExpandError::other(Box::from(&*unescape_str(text))) + } _ => ExpandError::other("`compile_error!` argument must be a string"), }; @@ -507,20 +495,33 @@ fn concat_expand( } } } - match t { tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => { // concat works with string and char literals, so remove any quotes. // It also works with integer, float and boolean literals, so just use the rest // as-is. - if let Some((c, span)) = unquote_char(it) { - text.push(c); - record_span(span); - } else { - let (component, span) = - unquote_str(it).unwrap_or_else(|| (it.text.to_string(), it.span)); - text.push_str(&component); - record_span(span); + match it.kind { + tt::LitKind::Char => { + if let Ok(c) = unescape_char(&it.text) { + text.extend(c.escape_default()); + } + record_span(it.span); + } + tt::LitKind::Integer | tt::LitKind::Float => format_to!(text, "{}", it.text), + tt::LitKind::Str => { + text.push_str(&it.text); + record_span(it.span); + } + tt::LitKind::StrRaw(_) => { + format_to!(text, "{}", it.text.escape_debug()); + record_span(it.span); + } + tt::LitKind::Byte + | tt::LitKind::ByteStr + | tt::LitKind::ByteStrRaw(_) + | tt::LitKind::CStr + | tt::LitKind::CStrRaw(_) + | tt::LitKind::Err(_) => err = Some(ExpandError::other("unexpected literal")), } } // handle boolean literals @@ -544,9 +545,9 @@ fn concat_bytes_expand( _db: &dyn ExpandDatabase, _arg_id: MacroCallId, tt: &tt::Subtree, - call_site: Span, + _: Span, ) -> ExpandResult { - let mut bytes = Vec::new(); + let mut bytes = String::new(); let mut err = None; let mut span: Option = None; let mut record_span = |s: Span| match &mut span { @@ -556,14 +557,21 @@ fn concat_bytes_expand( }; for (i, t) in tt.token_trees.iter().enumerate() { match t { - tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { - let token = ast::make::tokens::literal(&lit.to_string()); - record_span(lit.span); - match token.kind() { - syntax::SyntaxKind::BYTE => bytes.push(token.text().to_owned()), - syntax::SyntaxKind::BYTE_STRING => { - let components = unquote_byte_string(lit).map_or(vec![], |(it, _)| it); - components.into_iter().for_each(|it| bytes.push(it.to_string())); + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { text, span, kind, suffix: _ })) => { + record_span(*span); + match kind { + tt::LitKind::Byte => { + if let Ok(b) = unescape_byte(text) { + bytes.extend( + b.escape_ascii().filter_map(|it| char::from_u32(it as u32)), + ); + } + } + tt::LitKind::ByteStr => { + bytes.push_str(text); + } + tt::LitKind::ByteStrRaw(_) => { + bytes.extend(text.escape_debug()); } _ => { err.get_or_insert(mbe::ExpandError::UnexpectedToken.into()); @@ -584,51 +592,49 @@ fn concat_bytes_expand( } } } - let value = tt::Subtree { - delimiter: tt::Delimiter { - open: call_site, - close: call_site, - kind: tt::DelimiterKind::Bracket, - }, - token_trees: { - Itertools::intersperse_with( - bytes.into_iter().map(|it| { - tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text: it.into(), - span: span.unwrap_or(call_site), - })) - }), - || { - tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { - char: ',', - spacing: tt::Spacing::Alone, - span: call_site, - })) - }, - ) - .collect() + let span = span.unwrap_or(tt.delimiter.open); + ExpandResult { + value: tt::Subtree { + delimiter: tt::Delimiter::invisible_spanned(span), + token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + text: bytes.into(), + span, + kind: tt::LitKind::ByteStr, + suffix: None, + }))] + .into(), }, - }; - ExpandResult { value, err } + err, + } } fn concat_bytes_expand_subtree( tree: &tt::Subtree, - bytes: &mut Vec, + bytes: &mut String, mut record_span: impl FnMut(Span), ) -> Result<(), ExpandError> { for (ti, tt) in tree.token_trees.iter().enumerate() { match tt { - tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => { - let lit = ast::make::tokens::literal(&it.to_string()); - match lit.kind() { - syntax::SyntaxKind::BYTE | syntax::SyntaxKind::INT_NUMBER => { - record_span(it.span); - bytes.push(lit.text().to_owned()) - } - _ => { - return Err(mbe::ExpandError::UnexpectedToken.into()); - } + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + text, + span, + kind: tt::LitKind::Byte, + suffix: _, + })) => { + if let Ok(b) = unescape_byte(text) { + bytes.extend(b.escape_ascii().filter_map(|it| char::from_u32(it as u32))); + } + record_span(*span); + } + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + text, + span, + kind: tt::LitKind::Integer, + suffix: _, + })) => { + record_span(*span); + if let Ok(b) = text.parse::() { + bytes.extend(b.escape_ascii().filter_map(|it| char::from_u32(it as u32))); } } tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (), @@ -660,7 +666,7 @@ fn concat_idents_expand( } } // FIXME merge spans - let ident = tt::Ident { text: ident.into(), span }; + let ident = tt::Ident { text: ident.into(), span, is_raw: tt::IdentIsRaw::No }; ExpandResult { value: quote!(span =>#ident), err } } @@ -683,11 +689,16 @@ fn relative_file( } } -fn parse_string(tt: &tt::Subtree) -> Result<(String, Span), ExpandError> { +fn parse_string(tt: &tt::Subtree) -> Result<(SmolStr, Span), ExpandError> { tt.token_trees .first() .and_then(|tt| match tt { - tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(it), + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + text, + span, + kind: tt::LitKind::Str, + suffix: _, + })) => Some((unescape_str(text), *span)), _ => None, }) .ok_or(mbe::ExpandError::ConversionError.into()) @@ -738,6 +749,8 @@ fn include_bytes_expand( token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { text: r#"b"""#.into(), span, + kind: tt::LitKind::ByteStrRaw(1), + suffix: None, }))]), }; ExpandResult::ok(res) @@ -848,3 +861,17 @@ fn quote_expand( ExpandError::other("quote! is not implemented"), ) } + +fn unescape_str(s: &SmolStr) -> SmolStr { + if s.contains('\\') { + let mut buf = String::with_capacity(s.len()); + unescape_unicode(s, Mode::Str, &mut |_, c| { + if let Ok(c) = c { + buf.push(c) + } + }); + buf.into() + } else { + s.clone() + } +} diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs index 9fdf4aa4f7cc7..2896afed084fd 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs @@ -86,6 +86,7 @@ pub(crate) fn fixup_syntax( anchor: SpanAnchor { ast_id: FIXUP_DUMMY_AST_ID, ..span.anchor }, ctx: span.ctx, }, + is_raw: tt::IdentIsRaw::No, }); append.insert(node.clone().into(), vec![replacement]); preorder.skip_subtree(); @@ -101,6 +102,7 @@ pub(crate) fn fixup_syntax( Leaf::Ident(Ident { text: "__ra_fixup".into(), span: fake_span(node_range), + is_raw: tt::IdentIsRaw::No }), ]); } @@ -137,7 +139,8 @@ pub(crate) fn fixup_syntax( append.insert(if_token.into(), vec![ Leaf::Ident(Ident { text: "__ra_fixup".into(), - span: fake_span(node_range) + span: fake_span(node_range), + is_raw: tt::IdentIsRaw::No }), ]); } @@ -167,7 +170,8 @@ pub(crate) fn fixup_syntax( append.insert(while_token.into(), vec![ Leaf::Ident(Ident { text: "__ra_fixup".into(), - span: fake_span(node_range) + span: fake_span(node_range), + is_raw: tt::IdentIsRaw::No }), ]); } @@ -214,7 +218,8 @@ pub(crate) fn fixup_syntax( append.insert(match_token.into(), vec![ Leaf::Ident(Ident { text: "__ra_fixup".into(), - span: fake_span(node_range) + span: fake_span(node_range), + is_raw: tt::IdentIsRaw::No }), ]); } @@ -248,7 +253,8 @@ pub(crate) fn fixup_syntax( ].map(|text| Leaf::Ident(Ident { text: text.into(), - span: fake_span(node_range) + span: fake_span(node_range), + is_raw: tt::IdentIsRaw::No }), ); @@ -281,7 +287,8 @@ pub(crate) fn fixup_syntax( append.insert(colon.into(), vec![ Leaf::Ident(Ident { text: "__ra_fixup".into(), - span: fake_span(node_range) + span: fake_span(node_range), + is_raw: tt::IdentIsRaw::No }) ]); } @@ -293,7 +300,8 @@ pub(crate) fn fixup_syntax( append.insert(colon.into(), vec![ Leaf::Ident(Ident { text: "__ra_fixup".into(), - span: fake_span(node_range) + span: fake_span(node_range), + is_raw: tt::IdentIsRaw::No }) ]); } @@ -326,7 +334,8 @@ pub(crate) fn fixup_syntax( append.insert(node.into(), vec![ Leaf::Ident(Ident { text: "__ra_fixup".into(), - span: fake_span(node_range) + span: fake_span(node_range), + is_raw: tt::IdentIsRaw::No }) ]); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index e7c34e51e857a..c4921da61004c 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -59,7 +59,7 @@ pub use span::{HirFileId, MacroCallId, MacroFileId}; pub mod tt { pub use span::Span; - pub use tt::{DelimiterKind, Spacing}; + pub use tt::{DelimiterKind, IdentIsRaw, LitKind, Spacing}; pub type Delimiter = ::tt::Delimiter; pub type DelimSpan = ::tt::DelimSpan; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index ed7d551888756..907e939153ba7 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -316,15 +316,15 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option PathKind::Abs, _ => return None, }, - tt::Leaf::Ident(tt::Ident { text, span }) if text == "$crate" => { + tt::Leaf::Ident(tt::Ident { text, span, .. }) if text == "$crate" => { resolve_crate_root(db, span.ctx).map(PathKind::DollarCrate).unwrap_or(PathKind::Crate) } tt::Leaf::Ident(tt::Ident { text, .. }) if text == "self" => PathKind::SELF, tt::Leaf::Ident(tt::Ident { text, .. }) if text == "super" => { let mut deg = 1; - while let Some(tt::Leaf::Ident(tt::Ident { text, span, .. })) = leaves.next() { + while let Some(tt::Leaf::Ident(tt::Ident { text, span, is_raw })) = leaves.next() { if text != "super" { - segments.push(Name::new(text, span.ctx)); + segments.push(Name::new(text, *is_raw, span.ctx)); break; } deg += 1; @@ -333,13 +333,13 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option PathKind::Crate, tt::Leaf::Ident(ident) => { - segments.push(Name::new(&ident.text, ident.span.ctx)); + segments.push(Name::new(&ident.text, ident.is_raw, ident.span.ctx)); PathKind::Plain } _ => return None, }; segments.extend(leaves.filter_map(|leaf| match leaf { - ::tt::Leaf::Ident(ident) => Some(Name::new(&ident.text, ident.span.ctx)), + ::tt::Leaf::Ident(ident) => Some(Name::new(&ident.text, ident.is_raw, ident.span.ctx)), _ => None, })); Some(ModPath { kind, segments }) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 67e73f7fc284c..fce9df6722b47 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -82,9 +82,16 @@ impl Name { Name { symbol: Symbol::intern(text), ctx: () } } - pub fn new(text: &str, ctx: SyntaxContextId) -> Name { + pub fn new(text: &str, raw: tt::IdentIsRaw, ctx: SyntaxContextId) -> Name { _ = ctx; - Name { symbol: Symbol::intern(text), ctx: () } + Name { + symbol: if raw.yes() { + Symbol::intern(&format_smolstr!("{}{text}", raw.as_str())) + } else { + Symbol::intern(text) + }, + ctx: (), + } } pub fn new_tuple_field(idx: usize) -> Name { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs index f4fc3b7b3e2da..f1d28450b31e8 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs @@ -3,12 +3,12 @@ use intern::Symbol; use span::Span; -use syntax::format_smolstr; +use tt::IdentIsRaw; use crate::name::Name; pub(crate) const fn dollar_crate(span: Span) -> tt::Ident { - tt::Ident { text: syntax::SmolStr::new_static("$crate"), span } + tt::Ident { text: syntax::SmolStr::new_static("$crate"), span, is_raw: tt::IdentIsRaw::No } } // A helper macro quote macro @@ -101,6 +101,7 @@ macro_rules! __quote { crate::tt::Leaf::Ident(crate::tt::Ident { text: stringify!($tt).into(), span: $span, + is_raw: tt::IdentIsRaw::No, }).into() }] }; @@ -209,23 +210,30 @@ macro_rules! impl_to_to_tokentrees { } impl_to_to_tokentrees! { - span: u32 => self { crate::tt::Literal{text: self.to_string().into(), span} }; - span: usize => self { crate::tt::Literal{text: self.to_string().into(), span} }; - span: i32 => self { crate::tt::Literal{text: self.to_string().into(), span} }; - span: bool => self { crate::tt::Ident{text: self.to_string().into(), span} }; + span: u32 => self { crate::tt::Literal{text: self.to_string().into(), span, kind: tt::LitKind::Integer, suffix: None } }; + span: usize => self { crate::tt::Literal{text: self.to_string().into(), span, kind: tt::LitKind::Integer, suffix: None } }; + span: i32 => self { crate::tt::Literal{text: self.to_string().into(), span, kind: tt::LitKind::Integer, suffix: None } }; + span: bool => self { crate::tt::Ident{text: self.to_string().into(), span, is_raw: tt::IdentIsRaw::No } }; _span: crate::tt::Leaf => self { self }; _span: crate::tt::Literal => self { self }; _span: crate::tt::Ident => self { self }; _span: crate::tt::Punct => self { self }; - span: &str => self { crate::tt::Literal{text: format_smolstr!("\"{}\"", self.escape_default()), span}}; - span: String => self { crate::tt::Literal{text: format_smolstr!("\"{}\"", self.escape_default()), span}}; - span: Name => self { crate::tt::Ident{text: self.to_smol_str(), span}}; - span: Symbol => self { crate::tt::Ident{text: self.as_str().into(), span}}; + span: &str => self { crate::tt::Literal{text: (*self).into(), span, kind: tt::LitKind::Str, suffix: None }}; + span: String => self { crate::tt::Literal{text: self.into(), span, kind: tt::LitKind::Str, suffix: None }}; + span: Name => self { + let (is_raw, s) = IdentIsRaw::split_from_symbol(self.as_str()); + crate::tt::Ident{text: s.into(), span, is_raw } + }; + span: Symbol => self { + let (is_raw, s) = IdentIsRaw::split_from_symbol(self.as_str()); + crate::tt::Ident{text: s.into(), span, is_raw } + }; } #[cfg(test)] mod tests { use crate::tt; + use ::tt::IdentIsRaw; use base_db::FileId; use expect_test::expect; use span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; @@ -259,7 +267,8 @@ mod tests { } fn mk_ident(name: &str) -> crate::tt::Ident { - crate::tt::Ident { text: name.into(), span: DUMMY } + let (is_raw, s) = IdentIsRaw::split_from_symbol(name); + crate::tt::Ident { text: s.into(), span: DUMMY, is_raw } } #[test] diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index af60c233e5519..02d92620e05b6 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -328,9 +328,11 @@ fn doc_modpath_from_str(link: &str) -> Option { }; let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { Ok(idx) => Name::new_tuple_field(idx), - Err(_) => { - Name::new(segment.split_once('<').map_or(segment, |it| it.0), SyntaxContextId::ROOT) - } + Err(_) => Name::new( + segment.split_once('<').map_or(segment, |it| it.0), + tt::IdentIsRaw::No, + SyntaxContextId::ROOT, + ), }); Some(ModPath::from_segments(kind, parts)) }; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs index 58e77b95c3292..1b9b78f69182a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs @@ -269,12 +269,13 @@ fn get_doc_string_in_attr(it: &ast::Attr) -> Option { } fn doc_indent(attrs: &hir::Attrs) -> usize { - attrs - .by_key("doc") - .attrs() - .filter_map(|attr| attr.string_value()) // no need to use unescape version here - .flat_map(|s| s.lines()) - .filter_map(|line| line.chars().position(|c| !c.is_whitespace())) - .min() - .unwrap_or(0) + let mut min = !0; + for val in attrs.by_key("doc").attrs().filter_map(|attr| attr.string_value_unescape()) { + if let Some(m) = + val.lines().filter_map(|line| line.chars().position(|c| !c.is_whitespace())).min() + { + min = min.min(m); + } + } + min } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 2006baa30a8c3..701374616ad67 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -240,7 +240,7 @@ fn hover_simple( .flatten() .unique_by(|&(def, _, _)| def) .map(|(def, macro_arm, node)| { - hover_for_definition(sema, file_id, def, &node, macro_arm, config) + dbg!(hover_for_definition(sema, file_id, def, &node, macro_arm, config)) }) .reduce(|mut acc: HoverResult, HoverResult { markup, actions }| { acc.actions.extend(actions); diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml index 18444018e1b68..7ce8aadfb3619 100644 --- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml +++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml @@ -17,6 +17,7 @@ rustc-hash.workspace = true smallvec.workspace = true tracing.workspace = true arrayvec.workspace = true +ra-ap-rustc_lexer.workspace = true # local deps syntax.workspace = true diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs index 27dbc84a2b1aa..6a2f1c236869d 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs @@ -226,13 +226,24 @@ fn invocation_fixtures( *seed } fn make_ident(ident: &str) -> tt::TokenTree { - tt::Leaf::Ident(tt::Ident { span: DUMMY, text: SmolStr::new(ident) }).into() + tt::Leaf::Ident(tt::Ident { + span: DUMMY, + text: SmolStr::new(ident), + is_raw: tt::IdentIsRaw::No, + }) + .into() } fn make_punct(char: char) -> tt::TokenTree { tt::Leaf::Punct(tt::Punct { span: DUMMY, char, spacing: tt::Spacing::Alone }).into() } fn make_literal(lit: &str) -> tt::TokenTree { - tt::Leaf::Literal(tt::Literal { span: DUMMY, text: SmolStr::new(lit) }).into() + tt::Leaf::Literal(tt::Literal { + span: DUMMY, + text: SmolStr::new(lit), + kind: tt::LitKind::Str, + suffix: None, + }) + .into() } fn make_subtree( kind: tt::DelimiterKind, diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs index c09cbd1d071ea..e3359865cb276 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs @@ -2,7 +2,7 @@ //! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` use span::Span; -use syntax::SmolStr; +use syntax::{format_smolstr, SmolStr}; use tt::Delimiter; use crate::{ @@ -99,6 +99,7 @@ impl Bindings { Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text: SmolStr::new_static("missing"), span, + is_raw: tt::IdentIsRaw::No, }))) } MetaVarKind::Lifetime => { @@ -113,6 +114,7 @@ impl Bindings { tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text: SmolStr::new_static("missing"), span, + is_raw: tt::IdentIsRaw::No, })), ]), })) @@ -121,6 +123,7 @@ impl Bindings { Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text: SmolStr::new_static("\"missing\""), span, + is_raw: tt::IdentIsRaw::No, }))) } } @@ -236,8 +239,10 @@ fn expand_subtree( ctx.nesting.get(ctx.nesting.len() - 1 - depth).map_or(0, |nest| nest.idx); arena.push( tt::Leaf::Literal(tt::Literal { - text: index.to_string().into(), + text: format_smolstr!("{index}"), span: ctx.call_site, + kind: tt::LitKind::Integer, + suffix: None, }) .into(), ); @@ -249,8 +254,10 @@ fn expand_subtree( }); arena.push( tt::Leaf::Literal(tt::Literal { - text: length.to_string().into(), + text: format_smolstr!("{length}"), span: ctx.call_site, + kind: tt::LitKind::Integer, + suffix: None, }) .into(), ); @@ -314,8 +321,10 @@ fn expand_subtree( }; arena.push( tt::Leaf::Literal(tt::Literal { - text: c.to_string().into(), + text: format_smolstr!("{c}"), span: ctx.call_site, + suffix: None, + kind: tt::LitKind::Integer, }) .into(), ); @@ -363,7 +372,12 @@ fn expand_var( token_trees: Box::new([ tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, span: id }) .into(), - tt::Leaf::from(tt::Ident { text: v.clone(), span: id }).into(), + tt::Leaf::from(tt::Ident { + text: v.clone(), + span: id, + is_raw: tt::IdentIsRaw::No, + }) + .into(), ]), } .into(); diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs index b06c6cee12dbd..8ab9269e9523a 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs @@ -6,6 +6,13 @@ //! The tests for this functionality live in another crate: //! `hir_def::macro_expansion_tests::mbe`. +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_lexer as rustc_lexer; +#[cfg(feature = "in-rust-tree")] +extern crate rustc_lexer; + mod expander; mod parser; mod syntax_bridge; @@ -27,9 +34,9 @@ pub use ::parser::TopEntryPoint; pub use tt::{Delimiter, DelimiterKind, Punct}; pub use crate::syntax_bridge::{ - parse_exprs_with_sep, parse_to_token_tree, parse_to_token_tree_static_span, - syntax_node_to_token_tree, syntax_node_to_token_tree_modified, token_tree_to_syntax_node, - DocCommentDesugarMode, SpanMapper, + desugar_doc_comment_text, parse_exprs_with_sep, parse_to_token_tree, + parse_to_token_tree_static_span, syntax_node_to_token_tree, syntax_node_to_token_tree_modified, + token_to_literal, token_tree_to_syntax_node, DocCommentDesugarMode, SpanMapper, }; pub use crate::syntax_bridge::dummy_test_span_utils::*; diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs index 5c499c06b1525..18af35c1e2900 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs @@ -205,7 +205,11 @@ fn next_op( tt::TokenTree::Leaf(leaf) => match leaf { tt::Leaf::Ident(ident) if ident.text == "crate" => { // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path. - Op::Ident(tt::Ident { text: "$crate".into(), span: ident.span }) + Op::Ident(tt::Ident { + text: "$crate".into(), + span: ident.span, + is_raw: tt::IdentIsRaw::No, + }) } tt::Leaf::Ident(ident) => { let kind = eat_fragment_kind(edition, src, mode)?; @@ -380,9 +384,11 @@ fn parse_metavar_expr(new_meta_vars: bool, src: &mut TtIter<'_, Span>) -> Result fn parse_depth(src: &mut TtIter<'_, Span>) -> Result { if src.len() == 0 { Ok(0) - } else if let tt::Leaf::Literal(lit) = src.expect_literal()? { + } else if let tt::Leaf::Literal(tt::Literal { text, suffix: None, .. }) = + src.expect_literal()? + { // Suffixes are not allowed. - lit.text.parse().map_err(|_| ()) + text.parse().map_err(|_| ()) } else { Err(()) } diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs index 73a04f00d9306..3feddba21061f 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs @@ -4,11 +4,11 @@ use std::fmt; use rustc_hash::{FxHashMap, FxHashSet}; use span::{Edition, SpanAnchor, SpanData, SpanMap}; -use stdx::{never, non_empty_vec::NonEmptyVec}; +use stdx::{format_to, itertools::Itertools, never, non_empty_vec::NonEmptyVec}; use syntax::{ ast::{self, make::tokens::doc_comment}, - AstToken, Parse, PreorderWithTokens, SmolStr, SyntaxElement, SyntaxKind, - SyntaxKind::*, + format_smolstr, AstToken, Parse, PreorderWithTokens, SmolStr, SyntaxElement, + SyntaxKind::{self, *}, SyntaxNode, SyntaxToken, SyntaxTreeBuilder, TextRange, TextSize, WalkEvent, T, }; use tt::{ @@ -317,18 +317,29 @@ where .into() } kind => { - macro_rules! make_leaf { - ($i:ident) => { - tt::$i { span: conv.span_for(abs_range), text: token.to_text(conv) } - .into() + macro_rules! make_ident { + () => { + tt::Ident { + span: conv.span_for(abs_range), + text: token.to_text(conv), + is_raw: tt::IdentIsRaw::No, + } + .into() }; } let leaf: tt::Leaf<_> = match kind { - T![true] | T![false] => make_leaf!(Ident), - IDENT => make_leaf!(Ident), - UNDERSCORE => make_leaf!(Ident), - k if k.is_keyword() => make_leaf!(Ident), - k if k.is_literal() => make_leaf!(Literal), + T![true] | T![false] => make_ident!(), + IDENT => { + let text = token.to_text(conv); + tt::Ident::new(text, conv.span_for(abs_range)).into() + } + UNDERSCORE => make_ident!(), + k if k.is_keyword() => make_ident!(), + k if k.is_literal() => { + let text = token.to_text(conv); + let span = conv.span_for(abs_range); + token_to_literal(text, span).into() + } LIFETIME_IDENT => { let apostrophe = tt::Leaf::from(tt::Punct { char: '\'', @@ -344,6 +355,7 @@ where abs_range.start() + TextSize::of('\''), abs_range.end(), )), + is_raw: tt::IdentIsRaw::No, }); token_trees.push(ident.into()); continue; @@ -388,6 +400,56 @@ where } } +pub fn token_to_literal(text: SmolStr, span: S) -> tt::Literal +where + S: Copy, +{ + use rustc_lexer::LiteralKind; + + let token = rustc_lexer::tokenize(&text).next_tuple(); + let Some((rustc_lexer::Token { + kind: rustc_lexer::TokenKind::Literal { kind, suffix_start }, + .. + },)) = token + else { + return tt::Literal { span, text, kind: tt::LitKind::Err(()), suffix: None }; + }; + + let (kind, start_offset, end_offset) = match kind { + LiteralKind::Int { .. } => (tt::LitKind::Integer, 0, 0), + LiteralKind::Float { .. } => (tt::LitKind::Float, 0, 0), + LiteralKind::Char { terminated } => (tt::LitKind::Char, 1, terminated as usize), + LiteralKind::Byte { terminated } => (tt::LitKind::Byte, 2, terminated as usize), + LiteralKind::Str { terminated } => (tt::LitKind::Str, 1, terminated as usize), + LiteralKind::ByteStr { terminated } => (tt::LitKind::ByteStr, 2, terminated as usize), + LiteralKind::CStr { terminated } => (tt::LitKind::CStr, 2, terminated as usize), + LiteralKind::RawStr { n_hashes } => ( + tt::LitKind::StrRaw(n_hashes.unwrap_or_default()), + 2 + n_hashes.unwrap_or_default() as usize, + 1 + n_hashes.unwrap_or_default() as usize, + ), + LiteralKind::RawByteStr { n_hashes } => ( + tt::LitKind::ByteStrRaw(n_hashes.unwrap_or_default()), + 3 + n_hashes.unwrap_or_default() as usize, + 1 + n_hashes.unwrap_or_default() as usize, + ), + LiteralKind::RawCStr { n_hashes } => ( + tt::LitKind::CStrRaw(n_hashes.unwrap_or_default()), + 3 + n_hashes.unwrap_or_default() as usize, + 1 + n_hashes.unwrap_or_default() as usize, + ), + }; + + let (lit, suffix) = text.split_at(suffix_start as usize); + let lit = &lit[start_offset..lit.len() - end_offset]; + let suffix = match suffix { + "" | "_" => None, + suffix => Some(Box::new(suffix.into())), + }; + + tt::Literal { span, text: lit.into(), kind, suffix } +} + fn is_single_token_op(kind: SyntaxKind) -> bool { matches!( kind, @@ -421,16 +483,10 @@ fn is_single_token_op(kind: SyntaxKind) -> bool { /// That is, strips leading `///` (or `/**`, etc) /// and strips the ending `*/` /// And then quote the string, which is needed to convert to `tt::Literal` -fn doc_comment_text(comment: &ast::Comment, mode: DocCommentDesugarMode) -> SmolStr { - let prefix_len = comment.prefix().len(); - let mut text = &comment.text()[prefix_len..]; - - // Remove ending "*/" - if comment.kind().shape == ast::CommentShape::Block { - text = &text[0..text.len() - 2]; - } - - let text = match mode { +/// +/// Note that proc-macros desugar with string literals where as macro_rules macros desugar with raw string literals. +pub fn desugar_doc_comment_text(text: &str, mode: DocCommentDesugarMode) -> (SmolStr, tt::LitKind) { + match mode { DocCommentDesugarMode::Mbe => { let mut num_of_hashes = 0; let mut count = 0; @@ -444,14 +500,13 @@ fn doc_comment_text(comment: &ast::Comment, mode: DocCommentDesugarMode) -> Smol } // Quote raw string with delimiters - // Note that `tt::Literal` expect an escaped string - format!(r#"r{delim}"{text}"{delim}"#, delim = "#".repeat(num_of_hashes)) + (text.into(), tt::LitKind::StrRaw(num_of_hashes)) } // Quote string with delimiters - // Note that `tt::Literal` expect an escaped string - DocCommentDesugarMode::ProcMacro => format!(r#""{}""#, text.escape_debug()), - }; - text.into() + DocCommentDesugarMode::ProcMacro => { + (format_smolstr!("{}", text.escape_debug()), tt::LitKind::Str) + } + } } fn convert_doc_comment( @@ -463,8 +518,13 @@ fn convert_doc_comment( let comment = ast::Comment::cast(token.clone())?; let doc = comment.kind().doc?; - let mk_ident = - |s: &str| tt::TokenTree::from(tt::Leaf::from(tt::Ident { text: s.into(), span })); + let mk_ident = |s: &str| { + tt::TokenTree::from(tt::Leaf::from(tt::Ident { + text: s.into(), + span, + is_raw: tt::IdentIsRaw::No, + })) + }; let mk_punct = |c: char| { tt::TokenTree::from(tt::Leaf::from(tt::Punct { @@ -475,7 +535,15 @@ fn convert_doc_comment( }; let mk_doc_literal = |comment: &ast::Comment| { - let lit = tt::Literal { text: doc_comment_text(comment, mode), span }; + let prefix_len = comment.prefix().len(); + let mut text = &comment.text()[prefix_len..]; + + // Remove ending "*/" + if comment.kind().shape == ast::CommentShape::Block { + text = &text[0..text.len() - 2]; + } + let (text, kind) = desugar_doc_comment_text(text, mode); + let lit = tt::Literal { text, span, kind, suffix: None }; tt::TokenTree::from(tt::Leaf::from(lit)) }; @@ -902,16 +970,17 @@ fn delim_to_str(d: tt::DelimiterKind, closing: bool) -> Option<&'static str> { impl TtTreeSink<'_, Ctx> where - SpanData: Copy, + SpanData: Copy + fmt::Debug, { /// Parses a float literal as if it was a one to two name ref nodes with a dot inbetween. /// This occurs when a float literal is used as a field access. fn float_split(&mut self, has_pseudo_dot: bool) { let (text, span) = match self.cursor.token_tree() { - Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Literal(lit), _)) => { - (lit.text.as_str(), lit.span) - } - _ => unreachable!(), + Some(tt::buffer::TokenTreeRef::Leaf( + tt::Leaf::Literal(tt::Literal { text, span, kind: tt::LitKind::Float, suffix: _ }), + _, + )) => (text.as_str(), *span), + tt => unreachable!("{tt:?}"), }; // FIXME: Span splitting match text.split_once('.') { @@ -954,7 +1023,7 @@ where } let mut last = self.cursor; - for _ in 0..n_tokens { + 'tokens: for _ in 0..n_tokens { let tmp: u8; if self.cursor.eof() { break; @@ -962,23 +1031,36 @@ where last = self.cursor; let (text, span) = loop { break match self.cursor.token_tree() { - Some(tt::buffer::TokenTreeRef::Leaf(leaf, _)) => { - // Mark the range if needed - let (text, span) = match leaf { - tt::Leaf::Ident(ident) => (ident.text.as_str(), ident.span), - tt::Leaf::Punct(punct) => { - assert!(punct.char.is_ascii()); - tmp = punct.char as u8; - ( - std::str::from_utf8(std::slice::from_ref(&tmp)).unwrap(), - punct.span, - ) + Some(tt::buffer::TokenTreeRef::Leaf(leaf, _)) => match leaf { + tt::Leaf::Ident(ident) => { + if ident.is_raw.yes() { + self.buf.push_str("r#"); + self.text_pos += TextSize::of("r#"); } - tt::Leaf::Literal(lit) => (lit.text.as_str(), lit.span), - }; - self.cursor = self.cursor.bump(); - (text, span) - } + let r = (ident.text.as_str(), ident.span); + self.cursor = self.cursor.bump(); + r + } + tt::Leaf::Punct(punct) => { + assert!(punct.char.is_ascii()); + tmp = punct.char as u8; + let r = ( + std::str::from_utf8(std::slice::from_ref(&tmp)).unwrap(), + punct.span, + ); + self.cursor = self.cursor.bump(); + r + } + tt::Leaf::Literal(lit) => { + let buf_l = self.buf.len(); + format_to!(self.buf, "{lit}"); + debug_assert_ne!(self.buf.len() - buf_l, 0); + self.text_pos += TextSize::new((self.buf.len() - buf_l) as u32); + self.token_map.push(self.text_pos, lit.span); + self.cursor = self.cursor.bump(); + continue 'tokens; + } + }, Some(tt::buffer::TokenTreeRef::Subtree(subtree, _)) => { self.cursor = self.cursor.subtree().unwrap(); match delim_to_str(subtree.delimiter.kind, false) { diff --git a/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs b/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs index 3f70149aa5eae..bf5494d37149b 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs @@ -35,20 +35,21 @@ pub(crate) fn to_parser_input(buffer: &TokenBuffer<'_, S>) Some(tt::buffer::TokenTreeRef::Leaf(leaf, _)) => { match leaf { tt::Leaf::Literal(lit) => { - let is_negated = lit.text.starts_with('-'); - let inner_text = &lit.text[if is_negated { 1 } else { 0 }..]; - - let kind = parser::LexedStr::single_token(inner_text) - .map(|(kind, _error)| kind) - .filter(|kind| { - kind.is_literal() - && (!is_negated || matches!(kind, FLOAT_NUMBER | INT_NUMBER)) - }) - .unwrap_or_else(|| panic!("Fail to convert given literal {:#?}", &lit)); - + let kind = match lit.kind { + tt::LitKind::Byte => SyntaxKind::BYTE, + tt::LitKind::Char => SyntaxKind::CHAR, + tt::LitKind::Integer => SyntaxKind::INT_NUMBER, + tt::LitKind::Float => SyntaxKind::FLOAT_NUMBER, + tt::LitKind::Str | tt::LitKind::StrRaw(_) => SyntaxKind::STRING, + tt::LitKind::ByteStr | tt::LitKind::ByteStrRaw(_) => { + SyntaxKind::BYTE_STRING + } + tt::LitKind::CStr | tt::LitKind::CStrRaw(_) => SyntaxKind::C_STRING, + tt::LitKind::Err(_) => SyntaxKind::ERROR, + }; res.push(kind); - if kind == FLOAT_NUMBER && !inner_text.ends_with('.') { + if kind == FLOAT_NUMBER && !lit.text.ends_with('.') { // Tag the token as joint if it is float with a fractional part // we use this jointness to inform the parser about what token split // event to emit when we encounter a float literal in a field access @@ -58,6 +59,7 @@ pub(crate) fn to_parser_input(buffer: &TokenBuffer<'_, S>) tt::Leaf::Ident(ident) => match ident.text.as_ref() { "_" => res.push(T![_]), i if i.starts_with('\'') => res.push(LIFETIME_IDENT), + _ if ident.is_raw.yes() => res.push(IDENT), _ => match SyntaxKind::from_keyword(&ident.text) { Some(kind) => res.push(kind), None => { diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs index fa3ba9bbfcd73..b5f3d0c3aacd5 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs @@ -19,8 +19,10 @@ pub const VERSION_CHECK_VERSION: u32 = 1; pub const ENCODE_CLOSE_SPAN_VERSION: u32 = 2; pub const HAS_GLOBAL_SPANS: u32 = 3; pub const RUST_ANALYZER_SPAN_SUPPORT: u32 = 4; +/// Whether literals encode their kind as an additional u32 field and idents their rawness as a u32 field +pub const EXTENDED_LEAF_DATA: u32 = 5; -pub const CURRENT_API_VERSION: u32 = RUST_ANALYZER_SPAN_SUPPORT; +pub const CURRENT_API_VERSION: u32 = EXTENDED_LEAF_DATA; #[derive(Debug, Serialize, Deserialize)] pub enum Request { @@ -178,6 +180,7 @@ mod tests { anchor, ctx: SyntaxContextId::ROOT, }, + is_raw: tt::IdentIsRaw::No, } .into(), ), @@ -185,26 +188,28 @@ mod tests { Ident { text: "Foo".into(), span: Span { - range: TextRange::at(TextSize::new(5), TextSize::of("Foo")), + range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")), anchor, ctx: SyntaxContextId::ROOT, }, + is_raw: tt::IdentIsRaw::Yes, } .into(), ), TokenTree::Leaf(Leaf::Literal(Literal { - text: "Foo".into(), - + text: "\"Foo\"".into(), span: Span { - range: TextRange::at(TextSize::new(8), TextSize::of("Foo")), + range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")), anchor, ctx: SyntaxContextId::ROOT, }, + kind: tt::LitKind::Str, + suffix: None, })), TokenTree::Leaf(Leaf::Punct(Punct { char: '@', span: Span { - range: TextRange::at(TextSize::new(11), TextSize::of('@')), + range: TextRange::at(TextSize::new(13), TextSize::of('@')), anchor, ctx: SyntaxContextId::ROOT, }, @@ -213,18 +218,27 @@ mod tests { TokenTree::Subtree(Subtree { delimiter: Delimiter { open: Span { - range: TextRange::at(TextSize::new(12), TextSize::of('{')), + range: TextRange::at(TextSize::new(14), TextSize::of('{')), anchor, ctx: SyntaxContextId::ROOT, }, close: Span { - range: TextRange::at(TextSize::new(13), TextSize::of('}')), + range: TextRange::at(TextSize::new(19), TextSize::of('}')), anchor, ctx: SyntaxContextId::ROOT, }, kind: DelimiterKind::Brace, }, - token_trees: Box::new([]), + token_trees: Box::new([TokenTree::Leaf(Leaf::Literal(Literal { + text: "0".into(), + span: Span { + range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), + anchor, + ctx: SyntaxContextId::ROOT, + }, + kind: tt::LitKind::Integer, + suffix: Some(Box::new("u32".into())), + }))]), }), ]); @@ -236,7 +250,7 @@ mod tests { ctx: SyntaxContextId::ROOT, }, close: Span { - range: TextRange::empty(TextSize::new(13)), + range: TextRange::empty(TextSize::new(19)), anchor, ctx: SyntaxContextId::ROOT, }, diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs index 11fd7596f2b52..7f5afdb7270fe 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs @@ -43,7 +43,7 @@ use serde::{Deserialize, Serialize}; use span::{ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId}; use text_size::TextRange; -use crate::msg::ENCODE_CLOSE_SPAN_VERSION; +use crate::msg::{ENCODE_CLOSE_SPAN_VERSION, EXTENDED_LEAF_DATA}; pub type SpanDataIndexMap = indexmap::IndexSet>; @@ -108,6 +108,8 @@ struct SubtreeRepr { struct LiteralRepr { id: TokenId, text: u32, + suffix: u32, + kind: u16, } struct PunctRepr { @@ -119,6 +121,7 @@ struct PunctRepr { struct IdentRepr { id: TokenId, text: u32, + is_raw: bool, } impl FlatTree { @@ -147,9 +150,17 @@ impl FlatTree { } else { write_vec(w.subtree, SubtreeRepr::write) }, - literal: write_vec(w.literal, LiteralRepr::write), + literal: if version >= EXTENDED_LEAF_DATA { + write_vec(w.literal, LiteralRepr::write_with_kind) + } else { + write_vec(w.literal, LiteralRepr::write) + }, punct: write_vec(w.punct, PunctRepr::write), - ident: write_vec(w.ident, IdentRepr::write), + ident: if version >= EXTENDED_LEAF_DATA { + write_vec(w.ident, IdentRepr::write_with_rawness) + } else { + write_vec(w.ident, IdentRepr::write) + }, token_tree: w.token_tree, text: w.text, } @@ -176,9 +187,17 @@ impl FlatTree { } else { write_vec(w.subtree, SubtreeRepr::write) }, - literal: write_vec(w.literal, LiteralRepr::write), + literal: if version >= EXTENDED_LEAF_DATA { + write_vec(w.literal, LiteralRepr::write_with_kind) + } else { + write_vec(w.literal, LiteralRepr::write) + }, punct: write_vec(w.punct, PunctRepr::write), - ident: write_vec(w.ident, IdentRepr::write), + ident: if version >= EXTENDED_LEAF_DATA { + write_vec(w.ident, IdentRepr::write_with_rawness) + } else { + write_vec(w.ident, IdentRepr::write) + }, token_tree: w.token_tree, text: w.text, } @@ -195,9 +214,17 @@ impl FlatTree { } else { read_vec(self.subtree, SubtreeRepr::read) }, - literal: read_vec(self.literal, LiteralRepr::read), + literal: if version >= EXTENDED_LEAF_DATA { + read_vec(self.literal, LiteralRepr::read_with_kind) + } else { + read_vec(self.literal, LiteralRepr::read) + }, punct: read_vec(self.punct, PunctRepr::read), - ident: read_vec(self.ident, IdentRepr::read), + ident: if version >= EXTENDED_LEAF_DATA { + read_vec(self.ident, IdentRepr::read_with_rawness) + } else { + read_vec(self.ident, IdentRepr::read) + }, token_tree: self.token_tree, text: self.text, span_data_table, @@ -212,9 +239,17 @@ impl FlatTree { } else { read_vec(self.subtree, SubtreeRepr::read) }, - literal: read_vec(self.literal, LiteralRepr::read), + literal: if version >= EXTENDED_LEAF_DATA { + read_vec(self.literal, LiteralRepr::read_with_kind) + } else { + read_vec(self.literal, LiteralRepr::read) + }, punct: read_vec(self.punct, PunctRepr::read), - ident: read_vec(self.ident, IdentRepr::read), + ident: if version >= EXTENDED_LEAF_DATA { + read_vec(self.ident, IdentRepr::read_with_rawness) + } else { + read_vec(self.ident, IdentRepr::read) + }, token_tree: self.token_tree, text: self.text, span_data_table: &(), @@ -280,14 +315,20 @@ impl LiteralRepr { [self.id.0, self.text] } fn read([id, text]: [u32; 2]) -> LiteralRepr { - LiteralRepr { id: TokenId(id), text } + LiteralRepr { id: TokenId(id), text, kind: 0, suffix: !0 } + } + fn write_with_kind(self) -> [u32; 4] { + [self.id.0, self.text, self.kind as u32, self.suffix] + } + fn read_with_kind([id, text, kind, suffix]: [u32; 4]) -> LiteralRepr { + LiteralRepr { id: TokenId(id), text, kind: kind as u16, suffix } } } impl PunctRepr { fn write(self) -> [u32; 3] { let spacing = match self.spacing { - tt::Spacing::Alone => 0, + tt::Spacing::Alone | tt::Spacing::JointHidden => 0, tt::Spacing::Joint => 1, }; [self.id.0, self.char as u32, spacing] @@ -307,7 +348,13 @@ impl IdentRepr { [self.id.0, self.text] } fn read(data: [u32; 2]) -> IdentRepr { - IdentRepr { id: TokenId(data[0]), text: data[1] } + IdentRepr { id: TokenId(data[0]), text: data[1], is_raw: false } + } + fn write_with_rawness(self) -> [u32; 3] { + [self.id.0, self.text, self.is_raw as u32] + } + fn read_with_rawness([id, text, is_raw]: [u32; 3]) -> IdentRepr { + IdentRepr { id: TokenId(id), text, is_raw: is_raw == 1 } } } @@ -380,7 +427,25 @@ impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> { let idx = self.literal.len() as u32; let text = self.intern(&lit.text); let id = self.token_id_of(lit.span); - self.literal.push(LiteralRepr { id, text }); + let suffix = lit.suffix.as_ref().map(|s| self.intern(s)).unwrap_or(!0); + self.literal.push(LiteralRepr { + id, + text, + kind: u16::from_le_bytes(match lit.kind { + tt::LitKind::Err(_) => [0, 0], + tt::LitKind::Byte => [1, 0], + tt::LitKind::Char => [2, 0], + tt::LitKind::Integer => [3, 0], + tt::LitKind::Float => [4, 0], + tt::LitKind::Str => [5, 0], + tt::LitKind::StrRaw(r) => [6, r], + tt::LitKind::ByteStr => [7, 0], + tt::LitKind::ByteStrRaw(r) => [8, r], + tt::LitKind::CStr => [9, 0], + tt::LitKind::CStrRaw(r) => [10, r], + }), + suffix, + }); idx << 2 | 0b01 } tt::Leaf::Punct(punct) => { @@ -393,7 +458,11 @@ impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> { let idx = self.ident.len() as u32; let text = self.intern(&ident.text); let id = self.token_id_of(ident.span); - self.ident.push(IdentRepr { id, text }); + self.ident.push(IdentRepr { + id, + text, + is_raw: ident.is_raw == tt::IdentIsRaw::Yes, + }); idx << 2 | 0b11 } }, @@ -457,10 +526,32 @@ impl<'span, S: InternableSpan> Reader<'span, S> { // that this unwrap doesn't fire. 0b00 => res[idx].take().unwrap().into(), 0b01 => { + use tt::LitKind::*; let repr = &self.literal[idx]; tt::Leaf::Literal(tt::Literal { text: self.text[repr.text as usize].as_str().into(), span: read_span(repr.id), + kind: match u16::to_le_bytes(repr.kind) { + [0, _] => Err(()), + [1, _] => Byte, + [2, _] => Char, + [3, _] => Integer, + [4, _] => Float, + [5, _] => Str, + [6, r] => StrRaw(r), + [7, _] => ByteStr, + [8, r] => ByteStrRaw(r), + [9, _] => CStr, + [10, r] => CStrRaw(r), + _ => unreachable!(), + }, + suffix: if repr.suffix != !0 { + Some(Box::new( + self.text[repr.suffix as usize].as_str().into(), + )) + } else { + None + }, }) .into() } @@ -478,6 +569,11 @@ impl<'span, S: InternableSpan> Reader<'span, S> { tt::Leaf::Ident(tt::Ident { text: self.text[repr.text as usize].as_str().into(), span: read_span(repr.id), + is_raw: if repr.is_raw { + tt::IdentIsRaw::Yes + } else { + tt::IdentIsRaw::No + }, }) .into() } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs index a1707364f3c21..749a7760592b5 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs @@ -1,6 +1,5 @@ //! Exports a few trivial procedural macros for testing. - #![feature(proc_macro_span, proc_macro_def_site)] #![allow(clippy::all)] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs index e8b340a43d305..68e0f85978e0c 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs @@ -49,58 +49,39 @@ fn spacing_to_internal(spacing: proc_macro::Spacing) -> Spacing { #[allow(unused)] fn spacing_to_external(spacing: Spacing) -> proc_macro::Spacing { match spacing { - Spacing::Alone => proc_macro::Spacing::Alone, + Spacing::Alone | Spacing::JointHidden => proc_macro::Spacing::Alone, Spacing::Joint => proc_macro::Spacing::Joint, } } -/// Invokes the callback with a `&[&str]` consisting of each part of the -/// literal's representation. This is done to allow the `ToString` and -/// `Display` implementations to borrow references to symbol values, and -/// both be optimized to reduce overhead. -fn literal_with_stringify_parts( - literal: &bridge::Literal, - interner: SymbolInternerRef, - f: impl FnOnce(&[&str]) -> R, -) -> R { - /// Returns a string containing exactly `num` '#' characters. - /// Uses a 256-character source string literal which is always safe to - /// index with a `u8` index. - fn get_hashes_str(num: u8) -> &'static str { - const HASHES: &str = "\ - ################################################################\ - ################################################################\ - ################################################################\ - ################################################################\ - "; - const _: () = assert!(HASHES.len() == 256); - &HASHES[..num as usize] +fn literal_kind_to_external(kind: tt::LitKind) -> bridge::LitKind { + match kind { + tt::LitKind::Byte => bridge::LitKind::Byte, + tt::LitKind::Char => bridge::LitKind::Char, + tt::LitKind::Integer => bridge::LitKind::Integer, + tt::LitKind::Float => bridge::LitKind::Float, + tt::LitKind::Str => bridge::LitKind::Str, + tt::LitKind::StrRaw(r) => bridge::LitKind::StrRaw(r), + tt::LitKind::ByteStr => bridge::LitKind::ByteStr, + tt::LitKind::ByteStrRaw(r) => bridge::LitKind::ByteStrRaw(r), + tt::LitKind::CStr => bridge::LitKind::CStr, + tt::LitKind::CStrRaw(r) => bridge::LitKind::CStrRaw(r), + tt::LitKind::Err(_) => bridge::LitKind::ErrWithGuar, } +} - { - let symbol = &*literal.symbol.text(interner); - let suffix = &*literal.suffix.map(|s| s.text(interner)).unwrap_or_default(); - match literal.kind { - bridge::LitKind::Byte => f(&["b'", symbol, "'", suffix]), - bridge::LitKind::Char => f(&["'", symbol, "'", suffix]), - bridge::LitKind::Str => f(&["\"", symbol, "\"", suffix]), - bridge::LitKind::StrRaw(n) => { - let hashes = get_hashes_str(n); - f(&["r", hashes, "\"", symbol, "\"", hashes, suffix]) - } - bridge::LitKind::ByteStr => f(&["b\"", symbol, "\"", suffix]), - bridge::LitKind::ByteStrRaw(n) => { - let hashes = get_hashes_str(n); - f(&["br", hashes, "\"", symbol, "\"", hashes, suffix]) - } - bridge::LitKind::CStr => f(&["c\"", symbol, "\"", suffix]), - bridge::LitKind::CStrRaw(n) => { - let hashes = get_hashes_str(n); - f(&["cr", hashes, "\"", symbol, "\"", hashes, suffix]) - } - bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::ErrWithGuar => { - f(&[symbol, suffix]) - } - } +fn literal_kind_to_internal(kind: bridge::LitKind) -> tt::LitKind { + match kind { + bridge::LitKind::Byte => tt::LitKind::Byte, + bridge::LitKind::Char => tt::LitKind::Char, + bridge::LitKind::Str => tt::LitKind::Str, + bridge::LitKind::StrRaw(r) => tt::LitKind::StrRaw(r), + bridge::LitKind::ByteStr => tt::LitKind::ByteStr, + bridge::LitKind::ByteStrRaw(r) => tt::LitKind::ByteStrRaw(r), + bridge::LitKind::CStr => tt::LitKind::CStr, + bridge::LitKind::CStrRaw(r) => tt::LitKind::CStrRaw(r), + bridge::LitKind::Integer => tt::LitKind::Integer, + bridge::LitKind::Float => tt::LitKind::Float, + bridge::LitKind::ErrWithGuar => tt::LitKind::Err(()), } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index bb174ba1b2243..1a71f39612d3b 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -15,7 +15,7 @@ use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER}; use tt::{TextRange, TextSize}; use crate::server_impl::{ - delim_to_external, delim_to_internal, literal_with_stringify_parts, + delim_to_external, delim_to_internal, literal_kind_to_external, literal_kind_to_internal, token_stream::TokenStreamBuilder, Symbol, SymbolInternerRef, SYMBOL_INTERNER, }; mod tt { @@ -171,20 +171,24 @@ impl server::TokenStream for RaSpanServer { bridge::TokenTree::Ident(ident) => { let text = ident.sym.text(self.interner); - let text = - if ident.is_raw { ::tt::SmolStr::from_iter(["r#", &text]) } else { text }; - let ident: tt::Ident = tt::Ident { text, span: ident.span }; + let ident: tt::Ident = tt::Ident { + text, + span: ident.span, + is_raw: if ident.is_raw { tt::IdentIsRaw::Yes } else { tt::IdentIsRaw::No }, + }; let leaf = tt::Leaf::from(ident); let tree = tt::TokenTree::from(leaf); Self::TokenStream::from_iter(iter::once(tree)) } bridge::TokenTree::Literal(literal) => { - let text = literal_with_stringify_parts(&literal, self.interner, |parts| { - ::tt::SmolStr::from_iter(parts.iter().copied()) - }); + let literal = tt::Literal { + text: literal.symbol.text(self.interner), + suffix: literal.suffix.map(|it| Box::new(it.text(self.interner))), + span: literal.span, + kind: literal_kind_to_internal(literal.kind), + }; - let literal = tt::Literal { text, span: literal.span }; let leaf: tt::Leaf = tt::Leaf::from(literal); let tree = tt::TokenTree::from(leaf); Self::TokenStream::from_iter(iter::once(tree)) @@ -250,23 +254,18 @@ impl server::TokenStream for RaSpanServer { .into_iter() .map(|tree| match tree { tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { - bridge::TokenTree::Ident(match ident.text.strip_prefix("r#") { - Some(text) => bridge::Ident { - sym: Symbol::intern(self.interner, text), - is_raw: true, - span: ident.span, - }, - None => bridge::Ident { - sym: Symbol::intern(self.interner, &ident.text), - is_raw: false, - span: ident.span, - }, + bridge::TokenTree::Ident(bridge::Ident { + sym: Symbol::intern(self.interner, &ident.text), + is_raw: ident.is_raw.yes(), + span: ident.span, }) } tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { bridge::TokenTree::Literal(bridge::Literal { span: lit.span, - ..server::FreeFunctions::literal_from_str(self, &lit.text).unwrap() + kind: literal_kind_to_external(lit.kind), + symbol: Symbol::intern(self.interner, &lit.text), + suffix: lit.suffix.map(|it| Symbol::intern(self.interner, &it)), }) } tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs index 12edacbe39dc6..94d5748b0870f 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs @@ -8,7 +8,7 @@ use std::{ use proc_macro::bridge::{self, server}; use crate::server_impl::{ - delim_to_external, delim_to_internal, literal_with_stringify_parts, + delim_to_external, delim_to_internal, literal_kind_to_external, literal_kind_to_internal, token_stream::TokenStreamBuilder, Symbol, SymbolInternerRef, SYMBOL_INTERNER, }; mod tt { @@ -25,10 +25,8 @@ mod tt { } type Group = tt::Subtree; type TokenTree = tt::TokenTree; -#[allow(unused)] type Punct = tt::Punct; type Spacing = tt::Spacing; -#[allow(unused)] type Literal = tt::Literal; type Span = tt::TokenId; type TokenStream = crate::server_impl::TokenStream; @@ -162,20 +160,23 @@ impl server::TokenStream for TokenIdServer { bridge::TokenTree::Ident(ident) => { let text = ident.sym.text(self.interner); - let text = - if ident.is_raw { ::tt::SmolStr::from_iter(["r#", &text]) } else { text }; - let ident: tt::Ident = tt::Ident { text, span: ident.span }; + let ident: tt::Ident = tt::Ident { + text, + span: ident.span, + is_raw: if ident.is_raw { tt::IdentIsRaw::Yes } else { tt::IdentIsRaw::No }, + }; let leaf = tt::Leaf::from(ident); let tree = TokenTree::from(leaf); Self::TokenStream::from_iter(iter::once(tree)) } bridge::TokenTree::Literal(literal) => { - let text = literal_with_stringify_parts(&literal, self.interner, |parts| { - ::tt::SmolStr::from_iter(parts.iter().copied()) - }); - - let literal = tt::Literal { text, span: literal.span }; + let literal = Literal { + text: literal.symbol.text(self.interner), + suffix: literal.suffix.map(|it| Box::new(it.text(self.interner))), + span: literal.span, + kind: literal_kind_to_internal(literal.kind), + }; let leaf = tt::Leaf::from(literal); let tree = TokenTree::from(leaf); @@ -183,7 +184,7 @@ impl server::TokenStream for TokenIdServer { } bridge::TokenTree::Punct(p) => { - let punct = tt::Punct { + let punct = Punct { char: p.ch as char, spacing: if p.joint { Spacing::Joint } else { Spacing::Alone }, span: p.span, @@ -238,16 +239,17 @@ impl server::TokenStream for TokenIdServer { .map(|tree| match tree { tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { bridge::TokenTree::Ident(bridge::Ident { - sym: Symbol::intern(self.interner, ident.text.trim_start_matches("r#")), - is_raw: ident.text.starts_with("r#"), + sym: Symbol::intern(self.interner, &ident.text), + is_raw: ident.is_raw.yes(), span: ident.span, }) } tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { bridge::TokenTree::Literal(bridge::Literal { span: lit.span, - ..server::FreeFunctions::literal_from_str(self, &lit.text) - .unwrap_or_else(|_| panic!("`{}`", lit.text)) + kind: literal_kind_to_external(lit.kind), + symbol: Symbol::intern(self.interner, &lit.text), + suffix: lit.suffix.map(|it| Symbol::intern(self.interner, &it)), }) } tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => { @@ -383,10 +385,12 @@ mod tests { tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text: "struct".into(), span: tt::TokenId(0), + is_raw: tt::IdentIsRaw::No, })), tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text: "T".into(), span: tt::TokenId(0), + is_raw: tt::IdentIsRaw::No, })), tt::TokenTree::Subtree(tt::Subtree { delimiter: tt::Delimiter { @@ -411,6 +415,7 @@ mod tests { kind: tt::DelimiterKind::Parenthesis, }, token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + is_raw: tt::IdentIsRaw::No, text: "a".into(), span: tt::TokenId(0), }))]), @@ -430,6 +435,7 @@ mod tests { tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text: "_".into(), span: tt::TokenId(0), + is_raw: tt::IdentIsRaw::No, })) ); } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs index 6334282538089..dc6e71163b2f2 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs @@ -21,20 +21,20 @@ fn test_derive_error() { assert_expand( "DeriveError", r#"struct S;"#, - expect![[r##" + expect![[r#" SUBTREE $$ 1 1 IDENT compile_error 1 PUNCH ! [alone] 1 SUBTREE () 1 1 - LITERAL "#[derive(DeriveError)] struct S ;"1 - PUNCH ; [alone] 1"##]], - expect![[r##" + LITERAL Str #[derive(DeriveError)] struct S ; 1 + PUNCH ; [alone] 1"#]], + expect![[r#" SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 IDENT compile_error 42:2@0..100#0 PUNCH ! [alone] 42:2@0..100#0 SUBTREE () 42:2@0..100#0 42:2@0..100#0 - LITERAL "#[derive(DeriveError)] struct S ;"42:2@0..100#0 - PUNCH ; [alone] 42:2@0..100#0"##]], + LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#0 + PUNCH ; [alone] 42:2@0..100#0"#]], ); } @@ -47,18 +47,18 @@ fn test_fn_like_macro_noop() { SUBTREE $$ 1 1 IDENT ident 1 PUNCH , [alone] 1 - LITERAL 01 + LITERAL Integer 0 1 PUNCH , [alone] 1 - LITERAL 11 + LITERAL Integer 1 1 PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 IDENT ident 42:2@0..5#0 PUNCH , [alone] 42:2@5..6#0 - LITERAL 042:2@7..8#0 + LITERAL Integer 0 42:2@7..8#0 PUNCH , [alone] 42:2@8..9#0 - LITERAL 142:2@10..11#0 + LITERAL Integer 1 42:2@10..11#0 PUNCH , [alone] 42:2@11..12#0 SUBTREE [] 42:2@13..14#0 42:2@14..15#0"#]], ); @@ -135,22 +135,22 @@ fn test_fn_like_mk_literals() { r#""#, expect![[r#" SUBTREE $$ 1 1 - LITERAL b"byte_string"1 - LITERAL 'c'1 - LITERAL "string"1 - LITERAL 3.14f641 - LITERAL 3.141 - LITERAL 123i641 - LITERAL 1231"#]], + LITERAL ByteStr byte_string 1 + LITERAL Char c 1 + LITERAL Str string 1 + LITERAL Float 3.14f64 1 + LITERAL Float 3.14 1 + LITERAL Integer 123i64 1 + LITERAL Integer 123 1"#]], expect![[r#" SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - LITERAL b"byte_string"42:2@0..100#0 - LITERAL 'c'42:2@0..100#0 - LITERAL "string"42:2@0..100#0 - LITERAL 3.14f6442:2@0..100#0 - LITERAL 3.1442:2@0..100#0 - LITERAL 123i6442:2@0..100#0 - LITERAL 12342:2@0..100#0"#]], + LITERAL ByteStr byte_string 42:2@0..100#0 + LITERAL Char c 42:2@0..100#0 + LITERAL Str string 42:2@0..100#0 + LITERAL Float 3.14f64 42:2@0..100#0 + LITERAL Float 3.14 42:2@0..100#0 + LITERAL Integer 123i64 42:2@0..100#0 + LITERAL Integer 123 42:2@0..100#0"#]], ); } @@ -175,50 +175,50 @@ fn test_fn_like_macro_clone_literals() { assert_expand( "fn_like_clone_tokens", r###"1u16, 2_u32, -4i64, 3.14f32, "hello bridge", "suffixed"suffix, r##"raw"##, 'a', b'b', c"null""###, - expect![[r###" + expect![[r#" SUBTREE $$ 1 1 - LITERAL 1u161 + LITERAL Integer 1u16 1 PUNCH , [alone] 1 - LITERAL 2_u321 + LITERAL Integer 2_u32 1 PUNCH , [alone] 1 PUNCH - [alone] 1 - LITERAL 4i641 + LITERAL Integer 4i64 1 PUNCH , [alone] 1 - LITERAL 3.14f321 + LITERAL Float 3.14f32 1 PUNCH , [alone] 1 - LITERAL "hello bridge"1 + LITERAL Str hello bridge 1 PUNCH , [alone] 1 - LITERAL "suffixed"suffix1 + LITERAL Str suffixedsuffix 1 PUNCH , [alone] 1 - LITERAL r##"raw"##1 + LITERAL StrRaw(2) raw 1 PUNCH , [alone] 1 - LITERAL 'a'1 + LITERAL Char a 1 PUNCH , [alone] 1 - LITERAL b'b'1 + LITERAL Byte b 1 PUNCH , [alone] 1 - LITERAL c"null"1"###]], - expect![[r###" + LITERAL CStr null 1"#]], + expect![[r#" SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - LITERAL 1u1642:2@0..4#0 + LITERAL Integer 1u16 42:2@0..4#0 PUNCH , [alone] 42:2@4..5#0 - LITERAL 2_u3242:2@6..11#0 + LITERAL Integer 2_u32 42:2@6..11#0 PUNCH , [alone] 42:2@11..12#0 PUNCH - [alone] 42:2@13..14#0 - LITERAL 4i6442:2@14..18#0 + LITERAL Integer 4i64 42:2@14..18#0 PUNCH , [alone] 42:2@18..19#0 - LITERAL 3.14f3242:2@20..27#0 + LITERAL Float 3.14f32 42:2@20..27#0 PUNCH , [alone] 42:2@27..28#0 - LITERAL "hello bridge"42:2@29..43#0 + LITERAL Str hello bridge 42:2@29..43#0 PUNCH , [alone] 42:2@43..44#0 - LITERAL "suffixed"suffix42:2@45..61#0 + LITERAL Str suffixedsuffix 42:2@45..61#0 PUNCH , [alone] 42:2@61..62#0 - LITERAL r##"raw"##42:2@63..73#0 + LITERAL StrRaw(2) raw 42:2@63..73#0 PUNCH , [alone] 42:2@73..74#0 - LITERAL 'a'42:2@75..78#0 + LITERAL Char a 42:2@75..78#0 PUNCH , [alone] 42:2@78..79#0 - LITERAL b'b'42:2@80..84#0 + LITERAL Byte b 42:2@80..84#0 PUNCH , [alone] 42:2@84..85#0 - LITERAL c"null"42:2@86..93#0"###]], + LITERAL CStr null 42:2@86..93#0"#]], ); } @@ -231,20 +231,20 @@ fn test_attr_macro() { "attr_error", r#"mod m {}"#, r#"some arguments"#, - expect![[r##" + expect![[r#" SUBTREE $$ 1 1 IDENT compile_error 1 PUNCH ! [alone] 1 SUBTREE () 1 1 - LITERAL "#[attr_error(some arguments)] mod m {}"1 - PUNCH ; [alone] 1"##]], - expect![[r##" + LITERAL Str #[attr_error(some arguments)] mod m {} 1 + PUNCH ; [alone] 1"#]], + expect![[r#" SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 IDENT compile_error 42:2@0..100#0 PUNCH ! [alone] 42:2@0..100#0 SUBTREE () 42:2@0..100#0 42:2@0..100#0 - LITERAL "#[attr_error(some arguments)] mod m {}"42:2@0..100#0 - PUNCH ; [alone] 42:2@0..100#0"##]], + LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#0 + PUNCH ; [alone] 42:2@0..100#0"#]], ); } diff --git a/src/tools/rust-analyzer/crates/salsa/tests/macros.rs b/src/tools/rust-analyzer/crates/salsa/tests/macros.rs index 3d818e53c8e93..9b07740e7de3d 100644 --- a/src/tools/rust-analyzer/crates/salsa/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/salsa/tests/macros.rs @@ -5,6 +5,7 @@ trait MyDatabase: salsa::Database { } mod another_module { + #[allow(dead_code)] pub(crate) fn another_name(_: &dyn crate::MyDatabase, (): ()) {} } diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs index 369744d0e96c7..24fd0abada5f2 100644 --- a/src/tools/rust-analyzer/crates/tt/src/lib.rs +++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs @@ -12,8 +12,54 @@ use stdx::impl_from; pub use smol_str::SmolStr; pub use text_size::{TextRange, TextSize}; +#[derive(Clone, PartialEq, Debug)] +pub struct Lit { + pub kind: LitKind, + pub symbol: SmolStr, + pub suffix: Option, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum IdentIsRaw { + No, + Yes, +} +impl IdentIsRaw { + pub fn yes(self) -> bool { + matches!(self, IdentIsRaw::Yes) + } + pub fn as_str(self) -> &'static str { + match self { + IdentIsRaw::No => "", + IdentIsRaw::Yes => "r#", + } + } + pub fn split_from_symbol(sym: &str) -> (Self, &str) { + if let Some(sym) = sym.strip_prefix("r#") { + (IdentIsRaw::Yes, sym) + } else { + (IdentIsRaw::No, sym) + } + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub enum LitKind { + Byte, + Char, + Integer, // e.g. `1`, `1u8`, `1f32` + Float, // e.g. `1.`, `1.0`, `1e3f32` + Str, + StrRaw(u8), // raw string delimited by `n` hash symbols + ByteStr, + ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols + CStr, + CStrRaw(u8), + Err(()), +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum TokenTree { +pub enum TokenTree { Leaf(Leaf), Subtree(Subtree), } @@ -103,6 +149,15 @@ pub struct DelimSpan { pub close: S, } +impl DelimSpan { + pub fn from_single(sp: Span) -> Self { + DelimSpan { open: sp, close: sp } + } + + pub fn from_pair(open: Span, close: Span) -> Self { + DelimSpan { open, close } + } +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Delimiter { pub open: S, @@ -134,8 +189,11 @@ pub enum DelimiterKind { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Literal { + // escaped pub text: SmolStr, pub span: S, + pub kind: LitKind, + pub suffix: Option>, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -145,23 +203,85 @@ pub struct Punct { pub span: S, } +/// Indicates whether a token can join with the following token to form a +/// compound token. Used for conversions to `proc_macro::Spacing`. Also used to +/// guide pretty-printing, which is where the `JointHidden` value (which isn't +/// part of `proc_macro::Spacing`) comes in useful. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Spacing { + /// The token cannot join with the following token to form a compound + /// token. + /// + /// In token streams parsed from source code, the compiler will use `Alone` + /// for any token immediately followed by whitespace, a non-doc comment, or + /// EOF. + /// + /// When constructing token streams within the compiler, use this for each + /// token that (a) should be pretty-printed with a space after it, or (b) + /// is the last token in the stream. (In the latter case the choice of + /// spacing doesn't matter because it is never used for the last token. We + /// arbitrarily use `Alone`.) + /// + /// Converts to `proc_macro::Spacing::Alone`, and + /// `proc_macro::Spacing::Alone` converts back to this. Alone, - /// Whether the following token is joint to this one. + + /// The token can join with the following token to form a compound token. + /// + /// In token streams parsed from source code, the compiler will use `Joint` + /// for any token immediately followed by punctuation (as determined by + /// `Token::is_punct`). + /// + /// When constructing token streams within the compiler, use this for each + /// token that (a) should be pretty-printed without a space after it, and + /// (b) is followed by a punctuation token. + /// + /// Converts to `proc_macro::Spacing::Joint`, and + /// `proc_macro::Spacing::Joint` converts back to this. Joint, + + /// The token can join with the following token to form a compound token, + /// but this will not be visible at the proc macro level. (This is what the + /// `Hidden` means; see below.) + /// + /// In token streams parsed from source code, the compiler will use + /// `JointHidden` for any token immediately followed by anything not + /// covered by the `Alone` and `Joint` cases: an identifier, lifetime, + /// literal, delimiter, doc comment. + /// + /// When constructing token streams, use this for each token that (a) + /// should be pretty-printed without a space after it, and (b) is followed + /// by a non-punctuation token. + /// + /// Converts to `proc_macro::Spacing::Alone`, but + /// `proc_macro::Spacing::Alone` converts back to `token::Spacing::Alone`. + /// Because of that, pretty-printing of `TokenStream`s produced by proc + /// macros is unavoidably uglier (with more whitespace between tokens) than + /// pretty-printing of `TokenStream`'s produced by other means (i.e. parsed + /// source code, internally constructed token streams, and token streams + /// produced by declarative macros). + JointHidden, } +/// Identifier or keyword. #[derive(Debug, Clone, PartialEq, Eq, Hash)] -/// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier. pub struct Ident { pub text: SmolStr, pub span: S, + pub is_raw: IdentIsRaw, } impl Ident { - pub fn new(text: impl Into, span: S) -> Self { - Ident { text: text.into(), span } + pub fn new(text: impl Into + AsRef, span: S) -> Self { + let t = text.as_ref(); + // let raw_stripped = IdentIsRaw::split_from_symbol(text.as_ref()); + let raw_stripped = t.strip_prefix("r#"); + let is_raw = if raw_stripped.is_none() { IdentIsRaw::No } else { IdentIsRaw::Yes }; + let text = match raw_stripped { + Some(derawed) => derawed.into(), + None => text.into(), + }; + Ident { text, span, is_raw } } } @@ -207,22 +327,35 @@ fn print_debug_token( match tkn { TokenTree::Leaf(leaf) => match leaf { Leaf::Literal(lit) => { - write!(f, "{}LITERAL {}", align, lit.text)?; - fmt::Debug::fmt(&lit.span, f)?; + write!( + f, + "{}LITERAL {:?} {}{} {:#?}", + align, + lit.kind, + lit.text, + lit.suffix.as_ref().map(|it| &***it).unwrap_or(""), + lit.span + )?; } Leaf::Punct(punct) => { write!( f, - "{}PUNCH {} [{}] ", + "{}PUNCH {} [{}] {:#?}", align, punct.char, if punct.spacing == Spacing::Alone { "alone" } else { "joint" }, + punct.span )?; - fmt::Debug::fmt(&punct.span, f)?; } Leaf::Ident(ident) => { - write!(f, "{}IDENT {} ", align, ident.text)?; - fmt::Debug::fmt(&ident.span, f)?; + write!( + f, + "{}IDENT {}{} {:#?}", + align, + ident.is_raw.as_str(), + ident.text, + ident.span + )?; } }, TokenTree::Subtree(subtree) => { @@ -288,13 +421,52 @@ impl fmt::Display for Leaf { impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.is_raw.as_str(), f)?; fmt::Display::fmt(&self.text, f) } } impl fmt::Display for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.text, f) + match self.kind { + LitKind::Byte => write!(f, "b'{}'", self.text), + LitKind::Char => write!(f, "'{}'", self.text), + LitKind::Integer | LitKind::Float | LitKind::Err(_) => write!(f, "{}", self.text), + LitKind::Str => write!(f, "\"{}\"", self.text), + LitKind::ByteStr => write!(f, "b\"{}\"", self.text), + LitKind::CStr => write!(f, "c\"{}\"", self.text), + LitKind::StrRaw(num_of_hashes) => { + let num_of_hashes = num_of_hashes as usize; + write!( + f, + r#"r{0:# { + let num_of_hashes = num_of_hashes as usize; + write!( + f, + r#"br{0:# { + let num_of_hashes = num_of_hashes as usize; + write!( + f, + r#"cr{0:# Subtree { let s = match it { Leaf::Literal(it) => it.text.to_string(), Leaf::Punct(it) => it.char.to_string(), - Leaf::Ident(it) => it.text.to_string(), + Leaf::Ident(it) => format!("{}{}", it.is_raw.as_str(), it.text), }; match (it, last) { (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => { @@ -369,7 +541,9 @@ impl Subtree { pub fn pretty(tkns: &[TokenTree]) -> String { fn tokentree_to_text(tkn: &TokenTree) -> String { match tkn { - TokenTree::Leaf(Leaf::Ident(ident)) => ident.text.clone().into(), + TokenTree::Leaf(Leaf::Ident(ident)) => { + format!("{}{}", ident.is_raw.as_str(), ident.text) + } TokenTree::Leaf(Leaf::Literal(literal)) => literal.text.clone().into(), TokenTree::Leaf(Leaf::Punct(punct)) => format!("{}", punct.char), TokenTree::Subtree(subtree) => { From ed2b355872161fca4b666cf1c459210c428c57ee Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 15 Jul 2024 12:33:51 +0200 Subject: [PATCH 025/489] Add cargo xtask install proc-macro-server --- src/tools/rust-analyzer/crates/ide/src/hover.rs | 2 +- src/tools/rust-analyzer/xtask/src/flags.rs | 17 ++++++++++++++--- src/tools/rust-analyzer/xtask/src/install.rs | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 701374616ad67..2006baa30a8c3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -240,7 +240,7 @@ fn hover_simple( .flatten() .unique_by(|&(def, _, _)| def) .map(|(def, macro_arm, node)| { - dbg!(hover_for_definition(sema, file_id, def, &node, macro_arm, config)) + hover_for_definition(sema, file_id, def, &node, macro_arm, config) }) .reduce(|mut acc: HoverResult, HoverResult { markup, actions }| { acc.actions.extend(actions); diff --git a/src/tools/rust-analyzer/xtask/src/flags.rs b/src/tools/rust-analyzer/xtask/src/flags.rs index cf4a22d476faf..fd4291de9e1b2 100644 --- a/src/tools/rust-analyzer/xtask/src/flags.rs +++ b/src/tools/rust-analyzer/xtask/src/flags.rs @@ -2,7 +2,7 @@ use std::{fmt, str::FromStr}; -use crate::install::{ClientOpt, ServerOpt}; +use crate::install::{ClientOpt, ProcMacroServerOpt, ServerOpt}; xflags::xflags! { src "./src/flags.rs" @@ -23,6 +23,10 @@ xflags::xflags! { optional --mimalloc /// Use jemalloc allocator for server. optional --jemalloc + + /// Install the proc-macro server. + optional --proc-macro-server + /// build in release with debug info set to 2. optional --dev-rel } @@ -109,6 +113,7 @@ pub struct Install { pub client: bool, pub code_bin: Option, pub server: bool, + pub proc_macro_server: bool, pub mimalloc: bool, pub jemalloc: bool, pub dev_rel: bool, @@ -284,7 +289,7 @@ impl Malloc { impl Install { pub(crate) fn server(&self) -> Option { - if self.client && !self.server { + if !self.server { return None; } let malloc = if self.mimalloc { @@ -296,8 +301,14 @@ impl Install { }; Some(ServerOpt { malloc, dev_rel: self.dev_rel }) } + pub(crate) fn proc_macro_server(&self) -> Option { + if !self.proc_macro_server { + return None; + } + Some(ProcMacroServerOpt { dev_rel: self.dev_rel }) + } pub(crate) fn client(&self) -> Option { - if !self.client && self.server { + if !self.client { return None; } Some(ClientOpt { code_bin: self.code_bin.clone() }) diff --git a/src/tools/rust-analyzer/xtask/src/install.rs b/src/tools/rust-analyzer/xtask/src/install.rs index 72e612f9e1d6b..eb33d6f9be696 100644 --- a/src/tools/rust-analyzer/xtask/src/install.rs +++ b/src/tools/rust-analyzer/xtask/src/install.rs @@ -15,6 +15,9 @@ impl flags::Install { if let Some(server) = self.server() { install_server(sh, server).context("install server")?; } + if let Some(server) = self.proc_macro_server() { + install_proc_macro_server(sh, server).context("install proc-macro server")?; + } if let Some(client) = self.client() { install_client(sh, client).context("install client")?; } @@ -34,6 +37,10 @@ pub(crate) struct ServerOpt { pub(crate) dev_rel: bool, } +pub(crate) struct ProcMacroServerOpt { + pub(crate) dev_rel: bool, +} + fn fix_path_for_mac(sh: &Shell) -> anyhow::Result<()> { let mut vscode_path: Vec = { const COMMON_APP_PATH: &str = @@ -132,3 +139,11 @@ fn install_server(sh: &Shell, opts: ServerOpt) -> anyhow::Result<()> { cmd.run()?; Ok(()) } + +fn install_proc_macro_server(sh: &Shell, opts: ProcMacroServerOpt) -> anyhow::Result<()> { + let profile = if opts.dev_rel { "dev-rel" } else { "release" }; + + let cmd = cmd!(sh, "cargo +nightly install --path crates/proc-macro-srv-cli --profile={profile} --locked --force --features sysroot-abi"); + cmd.run()?; + Ok(()) +} From 39eb8c6bc415ba222dccb22a29d8730092a06ee1 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 15 Jul 2024 12:55:05 +0200 Subject: [PATCH 026/489] Escape fetched env vars in env! expansion --- .../macro_expansion_tests/builtin_fn_macro.rs | 2 +- .../crates/hir-expand/src/builtin_fn_macro.rs | 39 +++++++++++-------- .../crates/hir-ty/src/tests/macros.rs | 2 +- .../rust-analyzer/tests/slow-tests/main.rs | 2 +- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index ab8bb8bd4c6fc..487ab537cdac3 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -154,7 +154,7 @@ fn main() { file!(); } #[rustc_builtin_macro] macro_rules! file {() => {}} -fn main() { ""; } +fn main() { "file"; } "##]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index 32befb7a7f7df..fb12adb87cb34 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -8,7 +8,10 @@ use intern::sym; use mbe::{parse_exprs_with_sep, parse_to_token_tree}; use span::{Edition, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use stdx::format_to; -use syntax::unescape::{unescape_byte, unescape_char, unescape_unicode, Mode}; +use syntax::{ + format_smolstr, + unescape::{unescape_byte, unescape_char, unescape_unicode, Mode}, +}; use crate::{ db::ExpandDatabase, @@ -265,7 +268,7 @@ fn file_expand( ) -> ExpandResult { // FIXME: RA purposefully lacks knowledge of absolute file names // so just return "". - let file_name = ""; + let file_name = "file"; let expanded = quote! {span => #file_name @@ -275,34 +278,36 @@ fn file_expand( } fn format_args_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, + _db: &dyn ExpandDatabase, + _id: MacroCallId, tt: &tt::Subtree, span: Span, ) -> ExpandResult { - format_args_expand_general(db, id, tt, "", span) + let pound = mk_pound(span); + let mut tt = tt.clone(); + tt.delimiter.kind = tt::DelimiterKind::Parenthesis; + ExpandResult::ok(quote! {span => + builtin #pound format_args #tt + }) } fn format_args_nl_expand( - db: &dyn ExpandDatabase, - id: MacroCallId, - tt: &tt::Subtree, - span: Span, -) -> ExpandResult { - format_args_expand_general(db, id, tt, "\\n", span) -} - -fn format_args_expand_general( _db: &dyn ExpandDatabase, _id: MacroCallId, tt: &tt::Subtree, - // FIXME: Make use of this so that mir interpretation works properly - _end_string: &str, span: Span, ) -> ExpandResult { let pound = mk_pound(span); let mut tt = tt.clone(); tt.delimiter.kind = tt::DelimiterKind::Parenthesis; + if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + text, + kind: tt::LitKind::Str, + .. + }))) = tt.token_trees.first_mut() + { + *text = format_smolstr!("{text}\\n"); + } ExpandResult::ok(quote! {span => builtin #pound format_args #tt }) @@ -788,7 +793,7 @@ fn include_str_expand( fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &str) -> Option { let krate = db.lookup_intern_macro_call(arg_id).krate; - db.crate_graph()[krate].env.get(key) + db.crate_graph()[krate].env.get(key).map(|it| it.escape_debug().to_string()) } fn env_expand( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs index a0899cb1d632b..5454a496ba8c1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs @@ -703,7 +703,7 @@ fn infer_builtin_macros_file() { } "#, expect![[r#" - !0..2 '""': &'static str + !0..6 '"file"': &'static str 63..87 '{ ...!(); }': () 73..74 'x': &'static str "#]], diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 56f416a0b6e04..aa17b587e0228 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -970,7 +970,7 @@ version = \"0.0.0\" fn out_dirs_check_impl(root_contains_symlink: bool) { if skip_slow_tests() { - return; + // return; } let mut server = Project::with_fixture( From 311aaa5a792489a1f80cfa0e522e0e60b08788de Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 15 Jul 2024 14:41:35 +0200 Subject: [PATCH 027/489] Fix incorrect encoding of literals in the proc-macro-api on version 4 --- src/tools/rust-analyzer/Cargo.lock | 3 +- .../crates/hir-expand/src/attrs.rs | 7 +- .../crates/hir-expand/src/lib.rs | 2 +- src/tools/rust-analyzer/crates/mbe/Cargo.toml | 3 +- src/tools/rust-analyzer/crates/mbe/src/lib.rs | 9 +- .../crates/mbe/src/syntax_bridge.rs | 53 +------- .../crates/proc-macro-api/Cargo.toml | 2 + .../crates/proc-macro-api/src/msg.rs | 53 ++++---- .../crates/proc-macro-api/src/msg/flat.rs | 118 ++++++++++++------ .../crates/proc-macro-srv/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/tt/Cargo.toml | 4 + src/tools/rust-analyzer/crates/tt/src/lib.rs | 61 ++++++++- 12 files changed, 183 insertions(+), 134 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index e43f712a6e230..500a150b57b84 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1046,7 +1046,6 @@ dependencies = [ "arrayvec", "cov-mark", "parser", - "ra-ap-rustc_lexer", "rustc-hash", "smallvec", "span", @@ -1326,6 +1325,7 @@ dependencies = [ "base-db", "indexmap", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mbe", "paths", "rustc-hash", "serde", @@ -2218,6 +2218,7 @@ name = "tt" version = "0.0.0" dependencies = [ "arrayvec", + "ra-ap-rustc_lexer", "smol_str", "stdx", "text-size", diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 4fce7c1fde13f..49a104fa118e6 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -5,9 +5,10 @@ use base_db::CrateId; use cfg::CfgExpr; use either::Either; use intern::{sym, Interned}; + use mbe::{ - desugar_doc_comment_text, syntax_node_to_token_tree, token_to_literal, DelimiterKind, - DocCommentDesugarMode, Punct, + desugar_doc_comment_text, syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode, + Punct, }; use smallvec::{smallvec, SmallVec}; use span::{Span, SyntaxContextId}; @@ -20,7 +21,7 @@ use crate::{ db::ExpandDatabase, mod_path::ModPath, span_map::SpanMapRef, - tt::{self, Subtree}, + tt::{self, token_to_literal, Subtree}, InFile, }; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index c4921da61004c..3460d1ca3d11f 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -59,7 +59,7 @@ pub use span::{HirFileId, MacroCallId, MacroFileId}; pub mod tt { pub use span::Span; - pub use tt::{DelimiterKind, IdentIsRaw, LitKind, Spacing}; + pub use tt::{token_to_literal, DelimiterKind, IdentIsRaw, LitKind, Spacing}; pub type Delimiter = ::tt::Delimiter; pub type DelimSpan = ::tt::DelimSpan; diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml index 7ce8aadfb3619..1002de2104a0c 100644 --- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml +++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml @@ -17,7 +17,6 @@ rustc-hash.workspace = true smallvec.workspace = true tracing.workspace = true arrayvec.workspace = true -ra-ap-rustc_lexer.workspace = true # local deps syntax.workspace = true @@ -30,7 +29,7 @@ span.workspace = true test-utils.workspace = true [features] -in-rust-tree = ["parser/in-rust-tree", "syntax/in-rust-tree"] +in-rust-tree = ["parser/in-rust-tree", "tt/in-rust-tree", "syntax/in-rust-tree"] [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs index 8ab9269e9523a..44b056a1acf5f 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs @@ -6,13 +6,6 @@ //! The tests for this functionality live in another crate: //! `hir_def::macro_expansion_tests::mbe`. -#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] - -#[cfg(not(feature = "in-rust-tree"))] -extern crate ra_ap_rustc_lexer as rustc_lexer; -#[cfg(feature = "in-rust-tree")] -extern crate rustc_lexer; - mod expander; mod parser; mod syntax_bridge; @@ -36,7 +29,7 @@ pub use tt::{Delimiter, DelimiterKind, Punct}; pub use crate::syntax_bridge::{ desugar_doc_comment_text, parse_exprs_with_sep, parse_to_token_tree, parse_to_token_tree_static_span, syntax_node_to_token_tree, syntax_node_to_token_tree_modified, - token_to_literal, token_tree_to_syntax_node, DocCommentDesugarMode, SpanMapper, + token_tree_to_syntax_node, DocCommentDesugarMode, SpanMapper, }; pub use crate::syntax_bridge::dummy_test_span_utils::*; diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs index 3feddba21061f..4d66464932b88 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs @@ -4,7 +4,7 @@ use std::fmt; use rustc_hash::{FxHashMap, FxHashSet}; use span::{Edition, SpanAnchor, SpanData, SpanMap}; -use stdx::{format_to, itertools::Itertools, never, non_empty_vec::NonEmptyVec}; +use stdx::{format_to, never, non_empty_vec::NonEmptyVec}; use syntax::{ ast::{self, make::tokens::doc_comment}, format_smolstr, AstToken, Parse, PreorderWithTokens, SmolStr, SyntaxElement, @@ -14,6 +14,7 @@ use syntax::{ use tt::{ buffer::{Cursor, TokenBuffer}, iter::TtIter, + token_to_literal, }; use crate::to_parser_input::to_parser_input; @@ -400,56 +401,6 @@ where } } -pub fn token_to_literal(text: SmolStr, span: S) -> tt::Literal -where - S: Copy, -{ - use rustc_lexer::LiteralKind; - - let token = rustc_lexer::tokenize(&text).next_tuple(); - let Some((rustc_lexer::Token { - kind: rustc_lexer::TokenKind::Literal { kind, suffix_start }, - .. - },)) = token - else { - return tt::Literal { span, text, kind: tt::LitKind::Err(()), suffix: None }; - }; - - let (kind, start_offset, end_offset) = match kind { - LiteralKind::Int { .. } => (tt::LitKind::Integer, 0, 0), - LiteralKind::Float { .. } => (tt::LitKind::Float, 0, 0), - LiteralKind::Char { terminated } => (tt::LitKind::Char, 1, terminated as usize), - LiteralKind::Byte { terminated } => (tt::LitKind::Byte, 2, terminated as usize), - LiteralKind::Str { terminated } => (tt::LitKind::Str, 1, terminated as usize), - LiteralKind::ByteStr { terminated } => (tt::LitKind::ByteStr, 2, terminated as usize), - LiteralKind::CStr { terminated } => (tt::LitKind::CStr, 2, terminated as usize), - LiteralKind::RawStr { n_hashes } => ( - tt::LitKind::StrRaw(n_hashes.unwrap_or_default()), - 2 + n_hashes.unwrap_or_default() as usize, - 1 + n_hashes.unwrap_or_default() as usize, - ), - LiteralKind::RawByteStr { n_hashes } => ( - tt::LitKind::ByteStrRaw(n_hashes.unwrap_or_default()), - 3 + n_hashes.unwrap_or_default() as usize, - 1 + n_hashes.unwrap_or_default() as usize, - ), - LiteralKind::RawCStr { n_hashes } => ( - tt::LitKind::CStrRaw(n_hashes.unwrap_or_default()), - 3 + n_hashes.unwrap_or_default() as usize, - 1 + n_hashes.unwrap_or_default() as usize, - ), - }; - - let (lit, suffix) = text.split_at(suffix_start as usize); - let lit = &lit[start_offset..lit.len() - end_offset]; - let suffix = match suffix { - "" | "_" => None, - suffix => Some(Box::new(suffix.into())), - }; - - tt::Literal { span, text: lit.into(), kind, suffix } -} - fn is_single_token_op(kind: SyntaxKind) -> bool { matches!( kind, diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml index 7f633d91ecc8c..889eefa8b5c61 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml @@ -28,6 +28,8 @@ span.workspace = true # InternIds for the syntax context base-db.workspace = true la-arena.workspace = true +# only here to parse via token_to_literal +mbe.workspace = true [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs index b5f3d0c3aacd5..65835048173ab 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs @@ -197,7 +197,7 @@ mod tests { .into(), ), TokenTree::Leaf(Leaf::Literal(Literal { - text: "\"Foo\"".into(), + text: "Foo".into(), span: Span { range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")), anchor, @@ -263,32 +263,35 @@ mod tests { #[test] fn test_proc_macro_rpc_works() { let tt = fixture_token_tree(); - let mut span_data_table = Default::default(); - let task = ExpandMacro { - data: ExpandMacroData { - macro_body: FlatTree::new(&tt, CURRENT_API_VERSION, &mut span_data_table), - macro_name: Default::default(), - attributes: None, - has_global_spans: ExpnGlobals { - serialize: true, - def_site: 0, - call_site: 0, - mixed_site: 0, + for v in RUST_ANALYZER_SPAN_SUPPORT..=CURRENT_API_VERSION { + let mut span_data_table = Default::default(); + let task = ExpandMacro { + data: ExpandMacroData { + macro_body: FlatTree::new(&tt, v, &mut span_data_table), + macro_name: Default::default(), + attributes: None, + has_global_spans: ExpnGlobals { + serialize: true, + def_site: 0, + call_site: 0, + mixed_site: 0, + }, + span_data_table: Vec::new(), }, - span_data_table: Vec::new(), - }, - lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(), - env: Default::default(), - current_dir: Default::default(), - }; + lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(), + env: Default::default(), + current_dir: Default::default(), + }; - let json = serde_json::to_string(&task).unwrap(); - // println!("{}", json); - let back: ExpandMacro = serde_json::from_str(&json).unwrap(); + let json = serde_json::to_string(&task).unwrap(); + // println!("{}", json); + let back: ExpandMacro = serde_json::from_str(&json).unwrap(); - assert_eq!( - tt, - back.data.macro_body.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table) - ); + assert_eq!( + tt, + back.data.macro_body.to_subtree_resolved(v, &span_data_table), + "version: {v}" + ); + } } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs index 7f5afdb7270fe..3d962e99d92c2 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs @@ -141,6 +141,7 @@ impl FlatTree { ident: Vec::new(), token_tree: Vec::new(), text: Vec::new(), + version, }; w.write(subtree); @@ -178,6 +179,7 @@ impl FlatTree { ident: Vec::new(), token_tree: Vec::new(), text: Vec::new(), + version, }; w.write(subtree); @@ -228,6 +230,7 @@ impl FlatTree { token_tree: self.token_tree, text: self.text, span_data_table, + version, } .read() } @@ -253,6 +256,7 @@ impl FlatTree { token_tree: self.token_tree, text: self.text, span_data_table: &(), + version, } .read() } @@ -386,8 +390,9 @@ impl InternableSpan for Span { struct Writer<'a, 'span, S: InternableSpan> { work: VecDeque<(usize, &'a tt::Subtree)>, - string_table: FxHashMap<&'a str, u32>, + string_table: FxHashMap, u32>, span_data_table: &'span mut S::Table, + version: u32, subtree: Vec, literal: Vec, @@ -425,9 +430,15 @@ impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> { tt::TokenTree::Leaf(leaf) => match leaf { tt::Leaf::Literal(lit) => { let idx = self.literal.len() as u32; - let text = self.intern(&lit.text); let id = self.token_id_of(lit.span); - let suffix = lit.suffix.as_ref().map(|s| self.intern(s)).unwrap_or(!0); + let (text, suffix) = if self.version >= EXTENDED_LEAF_DATA { + ( + self.intern(&lit.text), + lit.suffix.as_ref().map(|s| self.intern(s)).unwrap_or(!0), + ) + } else { + (self.intern_owned(format!("{lit}")), !0) + }; self.literal.push(LiteralRepr { id, text, @@ -456,13 +467,15 @@ impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> { } tt::Leaf::Ident(ident) => { let idx = self.ident.len() as u32; - let text = self.intern(&ident.text); let id = self.token_id_of(ident.span); - self.ident.push(IdentRepr { - id, - text, - is_raw: ident.is_raw == tt::IdentIsRaw::Yes, - }); + let text = if self.version >= EXTENDED_LEAF_DATA { + self.intern(&ident.text) + } else if ident.is_raw.yes() { + self.intern_owned(format!("r#{}", ident.text,)) + } else { + self.intern(&ident.text) + }; + self.ident.push(IdentRepr { id, text, is_raw: ident.is_raw.yes() }); idx << 2 | 0b11 } }, @@ -484,15 +497,25 @@ impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> { pub(crate) fn intern(&mut self, text: &'a str) -> u32 { let table = &mut self.text; - *self.string_table.entry(text).or_insert_with(|| { + *self.string_table.entry(text.into()).or_insert_with(|| { let idx = table.len(); table.push(text.to_owned()); idx as u32 }) } + + pub(crate) fn intern_owned(&mut self, text: String) -> u32 { + let table = &mut self.text; + *self.string_table.entry(text.clone().into()).or_insert_with(|| { + let idx = table.len(); + table.push(text); + idx as u32 + }) + } } struct Reader<'span, S: InternableSpan> { + version: u32, subtree: Vec, literal: Vec, punct: Vec, @@ -528,30 +551,36 @@ impl<'span, S: InternableSpan> Reader<'span, S> { 0b01 => { use tt::LitKind::*; let repr = &self.literal[idx]; - tt::Leaf::Literal(tt::Literal { - text: self.text[repr.text as usize].as_str().into(), - span: read_span(repr.id), - kind: match u16::to_le_bytes(repr.kind) { - [0, _] => Err(()), - [1, _] => Byte, - [2, _] => Char, - [3, _] => Integer, - [4, _] => Float, - [5, _] => Str, - [6, r] => StrRaw(r), - [7, _] => ByteStr, - [8, r] => ByteStrRaw(r), - [9, _] => CStr, - [10, r] => CStrRaw(r), - _ => unreachable!(), - }, - suffix: if repr.suffix != !0 { - Some(Box::new( - self.text[repr.suffix as usize].as_str().into(), - )) - } else { - None - }, + let text = self.text[repr.text as usize].as_str(); + let span = read_span(repr.id); + tt::Leaf::Literal(if self.version >= EXTENDED_LEAF_DATA { + tt::Literal { + text: text.into(), + span, + kind: match u16::to_le_bytes(repr.kind) { + [0, _] => Err(()), + [1, _] => Byte, + [2, _] => Char, + [3, _] => Integer, + [4, _] => Float, + [5, _] => Str, + [6, r] => StrRaw(r), + [7, _] => ByteStr, + [8, r] => ByteStrRaw(r), + [9, _] => CStr, + [10, r] => CStrRaw(r), + _ => unreachable!(), + }, + suffix: if repr.suffix != !0 { + Some(Box::new( + self.text[repr.suffix as usize].as_str().into(), + )) + } else { + None + }, + } + } else { + tt::token_to_literal(text.into(), span) }) .into() } @@ -566,14 +595,23 @@ impl<'span, S: InternableSpan> Reader<'span, S> { } 0b11 => { let repr = &self.ident[idx]; + let text = self.text[repr.text as usize].as_str(); + let (is_raw, text) = if self.version >= EXTENDED_LEAF_DATA { + ( + if repr.is_raw { + tt::IdentIsRaw::Yes + } else { + tt::IdentIsRaw::No + }, + text, + ) + } else { + tt::IdentIsRaw::split_from_symbol(text) + }; tt::Leaf::Ident(tt::Ident { - text: self.text[repr.text as usize].as_str().into(), + text: text.into(), span: read_span(repr.id), - is_raw: if repr.is_raw { - tt::IdentIsRaw::Yes - } else { - tt::IdentIsRaw::No - }, + is_raw, }) .into() } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index 735f781c43910..065701c05cc7b 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -34,7 +34,7 @@ proc-macro-test.path = "./proc-macro-test" [features] sysroot-abi = [] -in-rust-tree = ["mbe/in-rust-tree", "sysroot-abi"] +in-rust-tree = ["mbe/in-rust-tree", "tt/in-rust-tree","sysroot-abi"] [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/tt/Cargo.toml b/src/tools/rust-analyzer/crates/tt/Cargo.toml index 1311e2ddf89e9..1900635b995ee 100644 --- a/src/tools/rust-analyzer/crates/tt/Cargo.toml +++ b/src/tools/rust-analyzer/crates/tt/Cargo.toml @@ -17,6 +17,10 @@ smol_str.workspace = true text-size.workspace = true stdx.workspace = true +ra-ap-rustc_lexer.workspace = true + +[features] +in-rust-tree = [] [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs index 24fd0abada5f2..c328b3f8a3cc8 100644 --- a/src/tools/rust-analyzer/crates/tt/src/lib.rs +++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs @@ -2,14 +2,21 @@ //! input and output) of macros. It closely mirrors `proc_macro` crate's //! `TokenTree`. +#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] + +#[cfg(not(feature = "in-rust-tree"))] +extern crate ra_ap_rustc_lexer as rustc_lexer; +#[cfg(feature = "in-rust-tree")] +extern crate rustc_lexer; + pub mod buffer; pub mod iter; use std::fmt; -use stdx::impl_from; +use stdx::{impl_from, itertools::Itertools as _}; -pub use smol_str::SmolStr; +pub use smol_str::{format_smolstr, SmolStr}; pub use text_size::{TextRange, TextSize}; #[derive(Clone, PartialEq, Debug)] @@ -196,6 +203,56 @@ pub struct Literal { pub suffix: Option>, } +pub fn token_to_literal(text: SmolStr, span: S) -> Literal +where + S: Copy, +{ + use rustc_lexer::LiteralKind; + + let token = rustc_lexer::tokenize(&text).next_tuple(); + let Some((rustc_lexer::Token { + kind: rustc_lexer::TokenKind::Literal { kind, suffix_start }, + .. + },)) = token + else { + return Literal { span, text, kind: LitKind::Err(()), suffix: None }; + }; + + let (kind, start_offset, end_offset) = match kind { + LiteralKind::Int { .. } => (LitKind::Integer, 0, 0), + LiteralKind::Float { .. } => (LitKind::Float, 0, 0), + LiteralKind::Char { terminated } => (LitKind::Char, 1, terminated as usize), + LiteralKind::Byte { terminated } => (LitKind::Byte, 2, terminated as usize), + LiteralKind::Str { terminated } => (LitKind::Str, 1, terminated as usize), + LiteralKind::ByteStr { terminated } => (LitKind::ByteStr, 2, terminated as usize), + LiteralKind::CStr { terminated } => (LitKind::CStr, 2, terminated as usize), + LiteralKind::RawStr { n_hashes } => ( + LitKind::StrRaw(n_hashes.unwrap_or_default()), + 2 + n_hashes.unwrap_or_default() as usize, + 1 + n_hashes.unwrap_or_default() as usize, + ), + LiteralKind::RawByteStr { n_hashes } => ( + LitKind::ByteStrRaw(n_hashes.unwrap_or_default()), + 3 + n_hashes.unwrap_or_default() as usize, + 1 + n_hashes.unwrap_or_default() as usize, + ), + LiteralKind::RawCStr { n_hashes } => ( + LitKind::CStrRaw(n_hashes.unwrap_or_default()), + 3 + n_hashes.unwrap_or_default() as usize, + 1 + n_hashes.unwrap_or_default() as usize, + ), + }; + + let (lit, suffix) = text.split_at(suffix_start as usize); + let lit = &lit[start_offset..lit.len() - end_offset]; + let suffix = match suffix { + "" | "_" => None, + suffix => Some(Box::new(suffix.into())), + }; + + Literal { span, text: lit.into(), kind, suffix } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Punct { pub char: char, From 9d9b55cd2b14bce066cef83d9d85ba798a2ba95c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 15 Jul 2024 21:25:03 +0200 Subject: [PATCH 028/489] make invalid_type_param_default lint show up in cargo future-compat reports and remove the feature gate that silenced the lint --- compiler/rustc_feature/src/removed.rs | 3 ++ compiler/rustc_feature/src/unstable.rs | 2 - .../src/collect/generics_of.rs | 2 - compiler/rustc_lint_defs/src/builtin.rs | 2 +- ...ate-default_type_parameter_fallback.stderr | 21 --------- tests/ui/impl-trait/where-allowed.stderr | 22 ++++++++++ tests/ui/issues/issue-26812.rs | 4 +- tests/ui/issues/issue-26812.stderr | 25 ++++++++++- .../lifetimes/unusual-rib-combinations.stderr | 11 +++++ ...ed-type-param-in-fn-with-assoc-type.stderr | 10 +++++ .../default_type_parameter_in_fn_or_impl.rs} | 0 ...efault_type_parameter_in_fn_or_impl.stderr | 43 +++++++++++++++++++ 12 files changed, 115 insertions(+), 30 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr rename tests/ui/{feature-gates/feature-gate-default_type_parameter_fallback.rs => type/default_type_parameter_in_fn_or_impl.rs} (100%) create mode 100644 tests/ui/type/default_type_parameter_in_fn_or_impl.stderr diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index f13aa506c1ec0..a78ae0d6993e2 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -75,6 +75,9 @@ declare_features! ( /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. (removed, custom_derive, "1.32.0", Some(29644), Some("subsumed by `#[proc_macro_derive]`")), + /// Allows default type parameters to influence type inference. + (removed, default_type_parameter_fallback, "CURRENT_RUSTC_VERSION", Some(27336), + Some("never properly implemented; requires significant design work")), /// Allows using `#[doc(keyword = "...")]`. (removed, doc_keyword, "1.28.0", Some(51315), Some("merged into `#![feature(rustdoc_internals)]`")), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 948499fb38fbf..407800ce60d5d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -428,8 +428,6 @@ declare_features! ( (unstable, custom_test_frameworks, "1.30.0", Some(50297)), /// Allows declarative macros 2.0 (`macro`). (unstable, decl_macro, "1.17.0", Some(39412)), - /// Allows default type parameters to influence type inference. - (unstable, default_type_parameter_fallback, "1.3.0", Some(27336)), /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait (unstable, deprecated_safe, "1.61.0", Some(94978)), /// Allows having using `suggestion` in the `#[deprecated]` attribute. diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 22d465c8e62be..398a496a3737f 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -323,8 +323,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { if default.is_some() { match allow_defaults { Defaults::Allowed => {} - Defaults::FutureCompatDisallowed - if tcx.features().default_type_parameter_fallback => {} Defaults::FutureCompatDisallowed => { tcx.node_span_lint( lint::builtin::INVALID_TYPE_PARAM_DEFAULT, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index aa7844f40121b..276a507d3e89b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1241,7 +1241,7 @@ declare_lint! { Deny, "type parameter default erroneously allowed in invalid location", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #36887 ", }; } diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr deleted file mode 100644 index 308de2692930d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8 - | -LL | fn avg(_: T) {} - | ^^^^^ - | - = 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 #36887 - = note: `#[deny(invalid_type_param_default)]` on by default - -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6 - | -LL | impl S {} - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #36887 - -error: aborting due to 2 previous errors - diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index f0d259d01de94..1fb69db98c162 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -433,3 +433,25 @@ error: aborting due to 50 previous errors Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0599, E0658, E0666. For more information about an error, try `rustc --explain E0053`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:239:7 + | +LL | impl T {} + | ^^^^^^^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:246:36 + | +LL | fn in_method_generic_param_default(_: T) {} + | ^^^^^^^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/issues/issue-26812.rs b/tests/ui/issues/issue-26812.rs index 3391ea4b350af..e0723e016b381 100644 --- a/tests/ui/issues/issue-26812.rs +++ b/tests/ui/issues/issue-26812.rs @@ -1,6 +1,6 @@ -#![feature(default_type_parameter_fallback)] - fn avg(_: T) {} //~^ ERROR generic parameters with a default cannot use forward declared identifiers +//~| ERROR defaults for type parameters +//~| WARN previously accepted fn main() {} diff --git a/tests/ui/issues/issue-26812.stderr b/tests/ui/issues/issue-26812.stderr index c2a3d4b83d536..4a18b23fd8b13 100644 --- a/tests/ui/issues/issue-26812.stderr +++ b/tests/ui/issues/issue-26812.stderr @@ -1,9 +1,30 @@ error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/issue-26812.rs:3:10 + --> $DIR/issue-26812.rs:1:10 | LL | fn avg(_: T) {} | ^^^^^^^ defaulted generic parameters cannot be forward declared -error: aborting due to 1 previous error +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-26812.rs:1:8 + | +LL | fn avg(_: T) {} + | ^^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0128`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-26812.rs:1:8 + | +LL | fn avg(_: T) {} + | ^^^^^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 70f06b4be603c..3f97ae6c5bd54 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -68,3 +68,14 @@ error: aborting due to 8 previous errors Some errors have detailed explanations: E0106, E0214, E0308, E0770. For more information about an error, try `rustc --explain E0106`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/unusual-rib-combinations.rs:15:6 + | +LL | fn c() {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr index dc0bea58a70e8..bf8829c09257f 100644 --- a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr +++ b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr @@ -12,3 +12,13 @@ LL | foo::(); error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. +Future incompatibility report: Future breakage diagnostic: +warning: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:3:11 + | +LL | fn foo() -> (T, U) { + | ^^^^^^^ + | + = 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 #36887 + diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs b/tests/ui/type/default_type_parameter_in_fn_or_impl.rs similarity index 100% rename from tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs rename to tests/ui/type/default_type_parameter_in_fn_or_impl.rs diff --git a/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr b/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr new file mode 100644 index 0000000000000..a3205cd3c29ca --- /dev/null +++ b/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr @@ -0,0 +1,43 @@ +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8 + | +LL | fn avg(_: T) {} + | ^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6 + | +LL | impl S {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + +error: aborting due to 2 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8 + | +LL | fn avg(_: T) {} + | ^^^^^ + | + = 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 #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6 + | +LL | impl S {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + From e1e5b8a2b69da18b11147aa8d18e731ee32d9819 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 16 Jul 2024 05:14:32 +0000 Subject: [PATCH 029/489] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e90d3732ca577..2c29af8b9357f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -99b7134389e9766462601a2fc4013840b9d31745 +5c8488605624d67b272953bc21d41db60dbd5654 From 7f8a54bbee4fec4a6885c7554a2864a62bf40638 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 16 Jul 2024 09:59:39 +0200 Subject: [PATCH 030/489] Switch token trees to use Symbols --- src/tools/rust-analyzer/Cargo.lock | 8 +- src/tools/rust-analyzer/crates/cfg/Cargo.toml | 1 + .../rust-analyzer/crates/cfg/src/cfg_expr.rs | 13 +- src/tools/rust-analyzer/crates/cfg/src/lib.rs | 2 +- .../rust-analyzer/crates/hir-def/src/attr.rs | 34 ++--- .../crates/hir-def/src/builtin_type.rs | 27 +++- .../rust-analyzer/crates/hir-def/src/data.rs | 2 +- .../crates/hir-def/src/data/adt.rs | 22 ++-- .../rust-analyzer/crates/hir-def/src/db.rs | 2 +- .../crates/hir-def/src/nameres.rs | 15 +-- .../hir-def/src/nameres/attr_resolution.rs | 12 +- .../crates/hir-def/src/nameres/collector.rs | 10 +- .../crates/hir-def/src/nameres/proc_macro.rs | 3 +- .../crates/hir-expand/src/attrs.rs | 33 ++--- .../hir-expand/src/builtin_derive_macro.rs | 22 ++-- .../crates/hir-expand/src/builtin_fn_macro.rs | 74 +++++------ .../crates/hir-expand/src/cfg_process.rs | 9 +- .../crates/hir-expand/src/declarative.rs | 8 +- .../crates/hir-expand/src/fixup.rs | 31 ++--- .../crates/hir-expand/src/inert_attr_macro.rs | 12 +- .../crates/hir-expand/src/mod_path.rs | 24 ++-- .../crates/hir-expand/src/name.rs | 20 ++- .../crates/hir-expand/src/quote.rs | 46 +++---- .../diagnostics/match_check/pat_analysis.rs | 5 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 32 +++-- .../rust-analyzer/crates/ide-db/src/defs.rs | 10 +- .../rust-analyzer/crates/intern/src/symbol.rs | 26 ++++ .../crates/intern/src/symbol/symbols.rs | 24 ++++ src/tools/rust-analyzer/crates/mbe/Cargo.toml | 1 + .../rust-analyzer/crates/mbe/src/benchmark.rs | 7 +- .../rust-analyzer/crates/mbe/src/expander.rs | 6 +- .../crates/mbe/src/expander/matcher.rs | 48 +++---- .../crates/mbe/src/expander/transcriber.rs | 28 ++--- .../rust-analyzer/crates/mbe/src/parser.rs | 42 +++---- .../crates/mbe/src/syntax_bridge.rs | 28 +++-- .../crates/mbe/src/to_parser_input.rs | 11 +- .../crates/proc-macro-api/Cargo.toml | 3 +- .../crates/proc-macro-api/src/lib.rs | 3 +- .../crates/proc-macro-api/src/msg.rs | 11 +- .../crates/proc-macro-api/src/msg/flat.rs | 21 ++-- .../crates/proc-macro-srv/Cargo.toml | 1 + .../crates/proc-macro-srv/src/lib.rs | 3 +- .../crates/proc-macro-srv/src/server_impl.rs | 4 +- .../src/server_impl/rust_analyzer_span.rs | 118 +++++++++++++++--- .../proc-macro-srv/src/server_impl/symbol.rs | 1 - .../src/server_impl/token_id.rs | 38 +++--- .../crates/test-fixture/Cargo.toml | 3 +- .../crates/test-fixture/src/lib.rs | 5 +- src/tools/rust-analyzer/crates/tt/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/tt/src/iter.rs | 5 +- src/tools/rust-analyzer/crates/tt/src/lib.rs | 76 +++++------ 51 files changed, 593 insertions(+), 399 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 500a150b57b84..241392edb1e5d 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -149,6 +149,7 @@ dependencies = [ "mbe", "oorandom", "rustc-hash", + "smol_str", "syntax", "tt", ] @@ -1045,6 +1046,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "cov-mark", + "intern", "parser", "rustc-hash", "smallvec", @@ -1324,8 +1326,8 @@ version = "0.0.0" dependencies = [ "base-db", "indexmap", + "intern", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "mbe", "paths", "rustc-hash", "serde", @@ -1343,6 +1345,7 @@ version = "0.0.0" dependencies = [ "base-db", "expect-test", + "intern", "libloading", "mbe", "memmap2", @@ -1966,6 +1969,7 @@ dependencies = [ "base-db", "cfg", "hir-expand", + "intern", "rustc-hash", "span", "stdx", @@ -2218,8 +2222,8 @@ name = "tt" version = "0.0.0" dependencies = [ "arrayvec", + "intern", "ra-ap-rustc_lexer", - "smol_str", "stdx", "text-size", ] diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml index 9b3a5026ac800..784e86649d1ab 100644 --- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml +++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml @@ -16,6 +16,7 @@ rustc-hash.workspace = true # locals deps tt.workspace = true +smol_str.workspace = true [dev-dependencies] expect-test = "1.4.1" diff --git a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs index b7dbb7b5fdd79..9c95f0e4e4baa 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs @@ -4,7 +4,7 @@ use std::{fmt, slice::Iter as SliceIter}; -use tt::SmolStr; +use smol_str::SmolStr; /// A simple configuration value passed in from the outside. #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] @@ -66,7 +66,7 @@ impl CfgExpr { fn next_cfg_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option { let name = match it.next() { None => return None, - Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.text.clone(), + Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(), Some(_) => return Some(CfgExpr::Invalid), }; @@ -77,10 +77,9 @@ fn next_cfg_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option Some(tt::TokenTree::Leaf(tt::Leaf::Literal(literal))) => { it.next(); it.next(); - // FIXME: escape? raw string? - let value = - SmolStr::new(literal.text.trim_start_matches('"').trim_end_matches('"')); - CfgAtom::KeyValue { key: name, value }.into() + // FIXME: escape? + let value = literal.symbol.as_str().into(); + CfgAtom::KeyValue { key: name.as_str().into(), value }.into() } _ => return Some(CfgExpr::Invalid), } @@ -96,7 +95,7 @@ fn next_cfg_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option _ => CfgExpr::Invalid, } } - _ => CfgAtom::Flag(name).into(), + _ => CfgAtom::Flag(name.as_str().into()).into(), }; // Eat comma separator diff --git a/src/tools/rust-analyzer/crates/cfg/src/lib.rs b/src/tools/rust-analyzer/crates/cfg/src/lib.rs index 8b30286a0a8a8..5ef7a104dda59 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/lib.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/lib.rs @@ -8,10 +8,10 @@ mod tests; use std::fmt; use rustc_hash::FxHashSet; -use tt::SmolStr; pub use cfg_expr::{CfgAtom, CfgExpr}; pub use dnf::DnfExpr; +use smol_str::SmolStr; /// Configuration options used for conditional compilation on items with `cfg` attributes. /// We have two kind of options in different namespaces: atomic options like `unix`, and diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 5bd60c58e9b7e..1a5ac96aa29bb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -159,14 +159,14 @@ impl Attrs { pub fn has_doc_hidden(&self) -> bool { self.by_key("doc").tt_values().any(|tt| { tt.delimiter.kind == DelimiterKind::Parenthesis && - matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "hidden") + matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::hidden) }) } pub fn has_doc_notable_trait(&self) -> bool { self.by_key("doc").tt_values().any(|tt| { tt.delimiter.kind == DelimiterKind::Parenthesis && - matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "notable_trait") + matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::notable_trait) }) } @@ -267,7 +267,7 @@ impl DocExpr { fn next_doc_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option { let name = match it.next() { None => return None, - Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.text.clone(), + Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(), Some(_) => return Some(DocExpr::Invalid), }; @@ -275,13 +275,16 @@ fn next_doc_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option let ret = match it.as_slice().first() { Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '=' => { match it.as_slice().get(1) { - Some(tt::TokenTree::Leaf(tt::Leaf::Literal(literal))) => { + Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + symbol: text, + kind: tt::LitKind::Str, + .. + }))) => { it.next(); it.next(); // FIXME: escape? raw string? - let value = - SmolStr::new(literal.text.trim_start_matches('"').trim_end_matches('"')); - DocAtom::KeyValue { key: name, value }.into() + let value = SmolStr::new(text.as_str()); + DocAtom::KeyValue { key: name.as_str().into(), value }.into() } _ => return Some(DocExpr::Invalid), } @@ -294,7 +297,7 @@ fn next_doc_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option _ => DocExpr::Invalid, } } - _ => DocAtom::Flag(name).into(), + _ => DocAtom::Flag(name.as_str().into()).into(), }; // Eat comma separator @@ -311,10 +314,11 @@ fn parse_comma_sep(subtree: &tt::Subtree) -> Vec { .token_trees .iter() .filter_map(|tt| match tt { - tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { - // FIXME: escape? raw string? - Some(SmolStr::new(lit.text.trim_start_matches('"').trim_end_matches('"'))) - } + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + kind: tt::LitKind::Str, + symbol: text, + .. + })) => Some(SmolStr::new(text.as_str())), _ => None, }) .collect() @@ -598,14 +602,14 @@ impl<'attr> AttrQuery<'attr> { /// #[doc(html_root_url = "url")] /// ^^^^^^^^^^^^^ key /// ``` - pub fn find_string_value_in_tt(self, key: &'attr str) -> Option<&SmolStr> { + pub fn find_string_value_in_tt(self, key: &'attr str) -> Option<&str> { self.tt_values().find_map(|tt| { let name = tt.token_trees.iter() - .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text, ..} )) if text == key)) + .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if sym.as_str() == key)) .nth(2); match name { - Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal{ text, kind: tt::LitKind::Str | tt::LitKind::StrRaw(_) , ..}))) => Some(text), + Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal{ symbol: text, kind: tt::LitKind::Str | tt::LitKind::StrRaw(_) , ..}))) => Some(text.as_str()), _ => None } }) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs b/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs index 6dc1c4546e804..14b9af84e6ffb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/builtin_type.rs @@ -6,7 +6,7 @@ use std::fmt; use hir_expand::name::{AsName, Name}; -use intern::sym; +use intern::{sym, Symbol}; /// Different signed int types. #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum BuiltinInt { @@ -143,6 +143,18 @@ impl BuiltinInt { }; Some(res) } + pub fn from_suffix_sym(suffix: &Symbol) -> Option { + let res = match suffix { + s if *s == sym::isize => Self::Isize, + s if *s == sym::i8 => Self::I8, + s if *s == sym::i16 => Self::I16, + s if *s == sym::i32 => Self::I32, + s if *s == sym::i64 => Self::I64, + s if *s == sym::i128 => Self::I128, + _ => return None, + }; + Some(res) + } } #[rustfmt::skip] @@ -160,6 +172,19 @@ impl BuiltinUint { }; Some(res) } + pub fn from_suffix_sym(suffix: &Symbol) -> Option { + let res = match suffix { + s if *s == sym::usize => Self::Usize, + s if *s == sym::u8 => Self::U8, + s if *s == sym::u16 => Self::U16, + s if *s == sym::u32 => Self::U32, + s if *s == sym::u64 => Self::U64, + s if *s == sym::u128 => Self::U128, + + _ => return None, + }; + Some(res) + } } #[rustfmt::skip] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index 964a5f04bfd22..e2bb02c0c13ff 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -150,7 +150,7 @@ fn parse_rustc_legacy_const_generics(tt: &crate::tt::Subtree) -> Box<[u32]> { let mut indices = Vec::new(); for args in tt.token_trees.chunks(2) { match &args[0] { - tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => match lit.text.parse() { + tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => match lit.symbol.as_str().parse() { Ok(index) => indices.push(index), Err(_) => break, }, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index 0fe73418e51fc..3942c2a98af78 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -9,7 +9,7 @@ use hir_expand::{ name::{AsName, Name}, HirFileId, InFile, }; -use intern::Interned; +use intern::{sym, Interned}; use la_arena::Arena; use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions}; use syntax::ast::{self, HasName, HasVisibility}; @@ -112,12 +112,12 @@ fn parse_repr_tt(tt: &Subtree) -> Option { let mut tts = tt.token_trees.iter().peekable(); while let Some(tt) = tts.next() { if let TokenTree::Leaf(Leaf::Ident(ident)) = tt { - flags.insert(match &*ident.text { - "packed" => { + flags.insert(match &ident.sym { + s if *s == sym::packed => { let pack = if let Some(TokenTree::Subtree(tt)) = tts.peek() { tts.next(); if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() { - lit.text.parse().unwrap_or_default() + lit.symbol.as_str().parse().unwrap_or_default() } else { 0 } @@ -129,11 +129,11 @@ fn parse_repr_tt(tt: &Subtree) -> Option { Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack }); ReprFlags::empty() } - "align" => { + s if *s == sym::align => { if let Some(TokenTree::Subtree(tt)) = tts.peek() { tts.next(); if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() { - if let Ok(align) = lit.text.parse() { + if let Ok(align) = lit.symbol.as_str().parse() { let align = Align::from_bytes(align).ok(); max_align = max_align.max(align); } @@ -141,13 +141,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option { } ReprFlags::empty() } - "C" => ReprFlags::IS_C, - "transparent" => ReprFlags::IS_TRANSPARENT, - "simd" => ReprFlags::IS_SIMD, + s if *s == sym::C => ReprFlags::IS_C, + s if *s == sym::transparent => ReprFlags::IS_TRANSPARENT, + s if *s == sym::simd => ReprFlags::IS_SIMD, repr => { - if let Some(builtin) = BuiltinInt::from_suffix(repr) + if let Some(builtin) = BuiltinInt::from_suffix_sym(repr) .map(Either::Left) - .or_else(|| BuiltinUint::from_suffix(repr).map(Either::Right)) + .or_else(|| BuiltinUint::from_suffix_sym(repr).map(Either::Right)) { int = Some(match builtin { Either::Left(bi) => match bi { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index eac8f0dd74ac8..1f728a0b38b52 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs @@ -278,7 +278,7 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool { tt.split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',')); for output in segments.skip(1) { match output { - [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "no_std" => { + [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::no_std => { return true } _ => {} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs index b0543727c27d0..6861e0f2f5be5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs @@ -63,6 +63,7 @@ use base_db::{CrateId, FileId}; use hir_expand::{ name::Name, proc_macro::ProcMacroKind, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId, }; +use intern::Symbol; use itertools::Itertools; use la_arena::Arena; use rustc_hash::{FxHashMap, FxHashSet}; @@ -148,11 +149,11 @@ struct DefMapCrateData { proc_macro_loading_error: Option>, /// Custom attributes registered with `#![register_attr]`. - registered_attrs: Vec, + registered_attrs: Vec, /// Custom tool modules registered with `#![register_tool]`. - registered_tools: Vec, + registered_tools: Vec, /// Unstable features of Rust enabled with `#![feature(A, B)]`. - unstable_features: FxHashSet, + unstable_features: FxHashSet, /// #[rustc_coherence_is_core] rustc_coherence_is_core: bool, no_core: bool, @@ -170,7 +171,7 @@ impl DefMapCrateData { fn_proc_macro_mapping: FxHashMap::default(), proc_macro_loading_error: None, registered_attrs: Vec::new(), - registered_tools: PREDEFINED_TOOLS.into(), + registered_tools: PREDEFINED_TOOLS.iter().map(|it| Symbol::intern(it)).collect(), unstable_features: FxHashSet::default(), rustc_coherence_is_core: false, no_core: false, @@ -447,15 +448,15 @@ impl DefMap { self.derive_helpers_in_scope.get(&id.map(|it| it.upcast())).map(Deref::deref) } - pub fn registered_tools(&self) -> &[SmolStr] { + pub fn registered_tools(&self) -> &[Symbol] { &self.data.registered_tools } - pub fn registered_attrs(&self) -> &[SmolStr] { + pub fn registered_attrs(&self) -> &[Symbol] { &self.data.registered_attrs } - pub fn is_unstable_feature_enabled(&self, feature: &str) -> bool { + pub fn is_unstable_feature_enabled(&self, feature: &Symbol) -> bool { self.data.unstable_features.contains(feature) } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs index f842027d642a6..747860fd8e17b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs @@ -7,7 +7,7 @@ use hir_expand::{ MacroCallId, MacroCallKind, MacroDefId, }; use span::SyntaxContextId; -use syntax::{ast, SmolStr}; +use syntax::ast; use triomphe::Arc; use crate::{ @@ -79,20 +79,20 @@ impl DefMap { let segments = path.segments(); if let Some(name) = segments.first() { - let name = name.to_smol_str(); - let pred = |n: &_| *n == name; + let name = name.symbol(); + let pred = |n: &_| *n == *name; - let is_tool = self.data.registered_tools.iter().map(SmolStr::as_str).any(pred); + let is_tool = self.data.registered_tools.iter().any(pred); // FIXME: tool modules can be shadowed by actual modules if is_tool { return true; } if segments.len() == 1 { - if find_builtin_attr_idx(&name).is_some() { + if find_builtin_attr_idx(name).is_some() { return true; } - if self.data.registered_attrs.iter().map(SmolStr::as_str).any(pred) { + if self.data.registered_attrs.iter().any(pred) { return true; } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 13abcce78ead4..a614d99de6c1f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -317,20 +317,20 @@ impl DefCollector<'_> { .into_iter() .flatten() .filter_map(|(feat, _)| match feat.segments() { - [name] => Some(name.to_smol_str()), + [name] => Some(name.symbol().clone()), _ => None, }); crate_data.unstable_features.extend(features); } () if *attr_name == sym::register_attr.clone() => { if let Some(ident) = attr.single_ident_value() { - crate_data.registered_attrs.push(ident.text.clone()); + crate_data.registered_attrs.push(ident.sym.clone()); cov_mark::hit!(register_attr); } } () if *attr_name == sym::register_tool.clone() => { if let Some(ident) = attr.single_ident_value() { - crate_data.registered_tools.push(ident.text.clone()); + crate_data.registered_tools.push(ident.sym.clone()); cov_mark::hit!(register_tool); } } @@ -2129,9 +2129,7 @@ impl ModCollector<'_, '_> { let is_export = export_attr.exists(); let local_inner = if is_export { export_attr.tt_values().flat_map(|it| it.token_trees.iter()).any(|it| match it { - tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { - ident.text.contains("local_inner_macros") - } + tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.sym == sym::local_inner_macros, _ => false, }) } else { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs index 5052708dc9391..4789b1f014579 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs @@ -1,6 +1,7 @@ //! Nameres-specific procedural macro data and helpers. use hir_expand::name::{AsName, Name}; +use intern::sym; use crate::attr::Attrs; use crate::tt::{Leaf, TokenTree}; @@ -67,7 +68,7 @@ pub(crate) fn parse_macro_name_and_helper_attrs(tt: &[TokenTree]) -> Option<(Nam TokenTree::Leaf(Leaf::Punct(comma)), TokenTree::Leaf(Leaf::Ident(attributes)), TokenTree::Subtree(helpers) - ] if comma.char == ',' && attributes.text == "attributes" => + ] if comma.char == ',' && attributes.sym == sym::attributes => { let helpers = helpers .token_trees diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index 49a104fa118e6..8ef7b7049ae7d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -62,7 +62,7 @@ impl RawAttrs { Attr { id, input: Some(Box::new(AttrInput::Literal(tt::Literal { - text, + symbol: text, span, kind, suffix: None, @@ -243,7 +243,7 @@ impl Attr { let span = span_map.span_for_range(range); let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { let token = lit.token(); - Some(Box::new(AttrInput::Literal(token_to_literal(token.text().into(), span)))) + Some(Box::new(AttrInput::Literal(token_to_literal(token.text(), span)))) } else if let Some(tt) = ast.token_tree() { let tree = syntax_node_to_token_tree( tt.syntax(), @@ -260,8 +260,8 @@ impl Attr { fn from_tt(db: &dyn ExpandDatabase, mut tt: &[tt::TokenTree], id: AttrId) -> Option { if matches!(tt, - [tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text, .. })), ..] - if text == "unsafe" + [tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, .. })), ..] + if *sym == sym::unsafe_ ) { match tt.get(1) { Some(tt::TokenTree::Subtree(subtree)) => tt = &subtree.token_trees, @@ -313,10 +313,10 @@ impl Attr { pub fn string_value(&self) -> Option<&str> { match self.input.as_deref()? { AttrInput::Literal(tt::Literal { - text, + symbol: text, kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), .. - }) => Some(text), + }) => Some(text.as_str()), _ => None, } } @@ -324,23 +324,24 @@ impl Attr { /// #[path = "string"] pub fn string_value_with_span(&self) -> Option<(&str, span::Span)> { match self.input.as_deref()? { - AttrInput::Literal(it) => match it.text.strip_prefix('r') { - Some(it) => it.trim_matches('#'), - None => it.text.as_str(), - } - .strip_prefix('"')? - .strip_suffix('"') - .zip(Some(it.span)), + AttrInput::Literal(tt::Literal { + symbol: text, + kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), + span, + suffix: _, + }) => Some((text.as_str(), *span)), _ => None, } } pub fn string_value_unescape(&self) -> Option> { match self.input.as_deref()? { - AttrInput::Literal(tt::Literal { text, kind: tt::LitKind::StrRaw(_), .. }) => { - Some(Cow::Borrowed(text)) + AttrInput::Literal(tt::Literal { + symbol: text, kind: tt::LitKind::StrRaw(_), .. + }) => Some(Cow::Borrowed(text.as_str())), + AttrInput::Literal(tt::Literal { symbol: text, kind: tt::LitKind::Str, .. }) => { + unescape(text.as_str()) } - AttrInput::Literal(tt::Literal { text, kind: tt::LitKind::Str, .. }) => unescape(text), _ => None, } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs index 180d8f05627f4..b2924ae6736c7 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs @@ -82,7 +82,7 @@ enum VariantShape { } fn tuple_field_iterator(span: Span, n: usize) -> impl Iterator { - (0..n).map(move |it| tt::Ident::new(format!("f{it}"), span)) + (0..n).map(move |it| tt::Ident::new(&format!("f{it}"), span)) } impl VariantShape { @@ -693,14 +693,14 @@ fn partial_eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult } [first, rest @ ..] => { let rest = rest.iter().map(|it| { - let t1 = tt::Ident::new(format!("{}_self", it.text), it.span); - let t2 = tt::Ident::new(format!("{}_other", it.text), it.span); + let t1 = tt::Ident::new(&format!("{}_self", it.sym), it.span); + let t2 = tt::Ident::new(&format!("{}_other", it.sym), it.span); let and_and = and_and(span); quote!(span =>#and_and #t1 .eq( #t2 )) }); let first = { - let t1 = tt::Ident::new(format!("{}_self", first.text), first.span); - let t2 = tt::Ident::new(format!("{}_other", first.text), first.span); + let t1 = tt::Ident::new(&format!("{}_self", first.sym), first.span); + let t2 = tt::Ident::new(&format!("{}_other", first.sym), first.span); quote!(span =>#t1 .eq( #t2 )) }; quote!(span =>#first ##rest) @@ -730,7 +730,7 @@ fn self_and_other_patterns( let self_patterns = adt.shape.as_pattern_map( name, |it| { - let t = tt::Ident::new(format!("{}_self", it.text), it.span); + let t = tt::Ident::new(&format!("{}_self", it.sym), it.span); quote!(span =>#t) }, span, @@ -738,7 +738,7 @@ fn self_and_other_patterns( let other_patterns = adt.shape.as_pattern_map( name, |it| { - let t = tt::Ident::new(format!("{}_other", it.text), it.span); + let t = tt::Ident::new(&format!("{}_other", it.sym), it.span); quote!(span =>#t) }, span, @@ -776,8 +776,8 @@ fn ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult { |(pat1, pat2, fields)| { let mut body = quote!(span =>#krate::cmp::Ordering::Equal); for f in fields.into_iter().rev() { - let t1 = tt::Ident::new(format!("{}_self", f.text), f.span); - let t2 = tt::Ident::new(format!("{}_other", f.text), f.span); + let t1 = tt::Ident::new(&format!("{}_self", f.sym), f.span); + let t2 = tt::Ident::new(&format!("{}_other", f.sym), f.span); body = compare(krate, quote!(span =>#t1), quote!(span =>#t2), body, span); } let fat_arrow = fat_arrow(span); @@ -838,8 +838,8 @@ fn partial_ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult let mut body = quote!(span =>#krate::option::Option::Some(#krate::cmp::Ordering::Equal)); for f in fields.into_iter().rev() { - let t1 = tt::Ident::new(format!("{}_self", f.text), f.span); - let t2 = tt::Ident::new(format!("{}_other", f.text), f.span); + let t1 = tt::Ident::new(&format!("{}_self", f.sym), f.span); + let t2 = tt::Ident::new(&format!("{}_other", f.sym), f.span); body = compare(krate, quote!(span =>#t1), quote!(span =>#t2), body, span); } let fat_arrow = fat_arrow(span); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index fb12adb87cb34..4b1a3d697280c 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -1,10 +1,9 @@ //! Builtin macro -use ::tt::SmolStr; use base_db::{AnchoredPath, FileId}; use cfg::CfgExpr; use either::Either; -use intern::sym; +use intern::{sym, Symbol}; use mbe::{parse_exprs_with_sep, parse_to_token_tree}; use span::{Edition, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use stdx::format_to; @@ -181,10 +180,10 @@ fn line_expand( ExpandResult::ok(tt::Subtree { delimiter: tt::Delimiter::invisible_spanned(span), token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text: "0".into(), + symbol: sym::INTEGER_0.clone(), span, kind: tt::LitKind::Integer, - suffix: Some(Box::new("u32".into())), + suffix: Some(sym::u32.clone()), }))]), }) } @@ -301,12 +300,12 @@ fn format_args_nl_expand( let mut tt = tt.clone(); tt.delimiter.kind = tt::DelimiterKind::Parenthesis; if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text, + symbol: text, kind: tt::LitKind::Str, .. }))) = tt.token_trees.first_mut() { - *text = format_smolstr!("{text}\\n"); + *text = Symbol::intern(&format_smolstr!("{}\\n", text.as_str())); } ExpandResult::ok(quote! {span => builtin #pound format_args #tt @@ -460,14 +459,14 @@ fn compile_error_expand( ) -> ExpandResult { let err = match &*tt.token_trees { [tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text, + symbol: text, span: _, kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), suffix: _, }))] => // FIXME: Use the span here! { - ExpandError::other(Box::from(&*unescape_str(text))) + ExpandError::other(Box::from(unescape_str(text).as_str())) } _ => ExpandError::other("`compile_error!` argument must be a string"), }; @@ -507,18 +506,20 @@ fn concat_expand( // as-is. match it.kind { tt::LitKind::Char => { - if let Ok(c) = unescape_char(&it.text) { + if let Ok(c) = unescape_char(it.symbol.as_str()) { text.extend(c.escape_default()); } record_span(it.span); } - tt::LitKind::Integer | tt::LitKind::Float => format_to!(text, "{}", it.text), + tt::LitKind::Integer | tt::LitKind::Float => { + format_to!(text, "{}", it.symbol.as_str()) + } tt::LitKind::Str => { - text.push_str(&it.text); + text.push_str(it.symbol.as_str()); record_span(it.span); } tt::LitKind::StrRaw(_) => { - format_to!(text, "{}", it.text.escape_debug()); + format_to!(text, "{}", it.symbol.as_str().escape_debug()); record_span(it.span); } tt::LitKind::Byte @@ -531,9 +532,9 @@ fn concat_expand( } // handle boolean literals tt::TokenTree::Leaf(tt::Leaf::Ident(id)) - if i % 2 == 0 && (id.text == "true" || id.text == "false") => + if i % 2 == 0 && (id.sym == sym::true_ || id.sym == sym::false_) => { - text.push_str(id.text.as_str()); + text.push_str(id.sym.as_str()); record_span(id.span); } tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), @@ -562,21 +563,21 @@ fn concat_bytes_expand( }; for (i, t) in tt.token_trees.iter().enumerate() { match t { - tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { text, span, kind, suffix: _ })) => { + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { symbol: text, span, kind, suffix: _ })) => { record_span(*span); match kind { tt::LitKind::Byte => { - if let Ok(b) = unescape_byte(text) { + if let Ok(b) = unescape_byte(text.as_str()) { bytes.extend( b.escape_ascii().filter_map(|it| char::from_u32(it as u32)), ); } } tt::LitKind::ByteStr => { - bytes.push_str(text); + bytes.push_str(text.as_str()); } tt::LitKind::ByteStrRaw(_) => { - bytes.extend(text.escape_debug()); + bytes.extend(text.as_str().escape_debug()); } _ => { err.get_or_insert(mbe::ExpandError::UnexpectedToken.into()); @@ -602,7 +603,7 @@ fn concat_bytes_expand( value: tt::Subtree { delimiter: tt::Delimiter::invisible_spanned(span), token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text: bytes.into(), + symbol: Symbol::intern(&bytes), span, kind: tt::LitKind::ByteStr, suffix: None, @@ -621,24 +622,24 @@ fn concat_bytes_expand_subtree( for (ti, tt) in tree.token_trees.iter().enumerate() { match tt { tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text, + symbol: text, span, kind: tt::LitKind::Byte, suffix: _, })) => { - if let Ok(b) = unescape_byte(text) { + if let Ok(b) = unescape_byte(text.as_str()) { bytes.extend(b.escape_ascii().filter_map(|it| char::from_u32(it as u32))); } record_span(*span); } tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text, + symbol: text, span, kind: tt::LitKind::Integer, suffix: _, })) => { record_span(*span); - if let Ok(b) = text.parse::() { + if let Ok(b) = text.as_str().parse::() { bytes.extend(b.escape_ascii().filter_map(|it| char::from_u32(it as u32))); } } @@ -662,7 +663,7 @@ fn concat_idents_expand( for (i, t) in tt.token_trees.iter().enumerate() { match t { tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => { - ident.push_str(id.text.as_str()); + ident.push_str(id.sym.as_str()); } tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), _ => { @@ -671,7 +672,7 @@ fn concat_idents_expand( } } // FIXME merge spans - let ident = tt::Ident { text: ident.into(), span, is_raw: tt::IdentIsRaw::No }; + let ident = tt::Ident { sym: Symbol::intern(&ident), span, is_raw: tt::IdentIsRaw::No }; ExpandResult { value: quote!(span =>#ident), err } } @@ -694,12 +695,12 @@ fn relative_file( } } -fn parse_string(tt: &tt::Subtree) -> Result<(SmolStr, Span), ExpandError> { +fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> { tt.token_trees .first() .and_then(|tt| match tt { tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text, + symbol: text, span, kind: tt::LitKind::Str, suffix: _, @@ -739,7 +740,7 @@ pub fn include_input_to_file_id( arg_id: MacroCallId, arg: &tt::Subtree, ) -> Result { - relative_file(db, arg_id, &parse_string(arg)?.0, false) + relative_file(db, arg_id, parse_string(arg)?.0.as_str(), false) } fn include_bytes_expand( @@ -752,7 +753,7 @@ fn include_bytes_expand( let res = tt::Subtree { delimiter: tt::Delimiter::invisible_spanned(span), token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { - text: r#"b"""#.into(), + symbol: Symbol::empty(), span, kind: tt::LitKind::ByteStrRaw(1), suffix: None, @@ -778,7 +779,7 @@ fn include_str_expand( // it's unusual to `include_str!` a Rust file), but we can return an empty string. // Ideally, we'd be able to offer a precise expansion if the user asks for macro // expansion. - let file_id = match relative_file(db, arg_id, &path, true) { + let file_id = match relative_file(db, arg_id, path.as_str(), true) { Ok(file_id) => file_id, Err(_) => { return ExpandResult::ok(quote!(span =>"")); @@ -791,9 +792,9 @@ fn include_str_expand( ExpandResult::ok(quote!(span =>#text)) } -fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &str) -> Option { +fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &Symbol) -> Option { let krate = db.lookup_intern_macro_call(arg_id).krate; - db.crate_graph()[krate].env.get(key).map(|it| it.escape_debug().to_string()) + db.crate_graph()[krate].env.get(key.as_str()).map(|it| it.escape_debug().to_string()) } fn env_expand( @@ -813,7 +814,7 @@ fn env_expand( let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| { // The only variable rust-analyzer ever sets is `OUT_DIR`, so only diagnose that to avoid // unnecessary diagnostics for eg. `CARGO_PKG_NAME`. - if key == "OUT_DIR" { + if key.as_str() == "OUT_DIR" { err = Some(ExpandError::other(r#"`OUT_DIR` not set, enable "build scripts" to fix"#)); } @@ -867,15 +868,16 @@ fn quote_expand( ) } -fn unescape_str(s: &SmolStr) -> SmolStr { - if s.contains('\\') { +fn unescape_str(s: &Symbol) -> Symbol { + if s.as_str().contains('\\') { + let s = s.as_str(); let mut buf = String::with_capacity(s.len()); unescape_unicode(s, Mode::Str, &mut |_, c| { if let Ok(c) = c { buf.push(c) } }); - buf.into() + Symbol::intern(&buf) } else { s.clone() } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs index 55ae19068f9c6..5f038cfe6871d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs @@ -9,7 +9,6 @@ use syntax::{ AstNode, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, T, }; use tracing::{debug, warn}; -use tt::SmolStr; use crate::{db::ExpandDatabase, proc_macro::ProcMacroKind, MacroCallLoc, MacroDefKind}; @@ -263,7 +262,7 @@ where let name = match iter.next() { None => return None, Some(NodeOrToken::Token(element)) => match element.kind() { - syntax::T![ident] => SmolStr::new(element.text()), + syntax::T![ident] => element.text().to_owned(), _ => return Some(CfgExpr::Invalid), }, Some(_) => return Some(CfgExpr::Invalid), @@ -302,13 +301,13 @@ where if (value_token.kind() == syntax::SyntaxKind::STRING) => { let value = value_token.text(); - let value = SmolStr::new(value.trim_matches('"')); - Some(CfgExpr::Atom(CfgAtom::KeyValue { key: name, value })) + let value = value.trim_matches('"').into(); + Some(CfgExpr::Atom(CfgAtom::KeyValue { key: name.into(), value })) } _ => None, } } - _ => Some(CfgExpr::Atom(CfgAtom::Flag(name))), + _ => Some(CfgExpr::Atom(CfgAtom::Flag(name.into()))), }, }; if let Some(NodeOrToken::Token(element)) = iter.peek() { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index 2e7865ed3bf8c..3d3df83361814 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -120,10 +120,10 @@ impl DeclarativeMacroExpander { .token_tree_value()? .token_trees { - [tt::TokenTree::Leaf(tt::Leaf::Ident(i)), ..] => match &*i.text { - "transparent" => Some(Transparency::Transparent), - "semitransparent" => Some(Transparency::SemiTransparent), - "opaque" => Some(Transparency::Opaque), + [tt::TokenTree::Leaf(tt::Leaf::Ident(i)), ..] => match &i.sym { + s if *s == sym::transparent => Some(Transparency::Transparent), + s if *s == sym::semitransparent => Some(Transparency::SemiTransparent), + s if *s == sym::opaque => Some(Transparency::Opaque), _ => None, }, _ => None, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs index 2896afed084fd..cf51535630f5e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs @@ -1,6 +1,7 @@ //! To make attribute macros work reliably when typing, we need to take care to //! fix up syntax errors in the code we're passing to them. +use intern::sym; use mbe::DocCommentDesugarMode; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::SmallVec; @@ -80,7 +81,7 @@ pub(crate) fn fixup_syntax( original.push(original_tree); let span = span_map.span_for_range(node_range); let replacement = Leaf::Ident(Ident { - text: "__ra_fixup".into(), + sym: sym::__ra_fixup.clone(), span: Span { range: TextRange::new(TextSize::new(idx), FIXUP_DUMMY_RANGE_END), anchor: SpanAnchor { ast_id: FIXUP_DUMMY_AST_ID, ..span.anchor }, @@ -100,7 +101,7 @@ pub(crate) fn fixup_syntax( // incomplete field access: some_expr.| append.insert(node.clone().into(), vec![ Leaf::Ident(Ident { - text: "__ra_fixup".into(), + sym: sym::__ra_fixup.clone(), span: fake_span(node_range), is_raw: tt::IdentIsRaw::No }), @@ -138,7 +139,7 @@ pub(crate) fn fixup_syntax( }; append.insert(if_token.into(), vec![ Leaf::Ident(Ident { - text: "__ra_fixup".into(), + sym: sym::__ra_fixup.clone(), span: fake_span(node_range), is_raw: tt::IdentIsRaw::No }), @@ -169,7 +170,7 @@ pub(crate) fn fixup_syntax( }; append.insert(while_token.into(), vec![ Leaf::Ident(Ident { - text: "__ra_fixup".into(), + sym: sym::__ra_fixup.clone(), span: fake_span(node_range), is_raw: tt::IdentIsRaw::No }), @@ -217,7 +218,7 @@ pub(crate) fn fixup_syntax( }; append.insert(match_token.into(), vec![ Leaf::Ident(Ident { - text: "__ra_fixup".into(), + sym: sym::__ra_fixup.clone(), span: fake_span(node_range), is_raw: tt::IdentIsRaw::No }), @@ -247,12 +248,12 @@ pub(crate) fn fixup_syntax( }; let [pat, in_token, iter] = [ - "_", - "in", - "__ra_fixup" - ].map(|text| + sym::underscore.clone(), + sym::in_.clone(), + sym::__ra_fixup.clone(), + ].map(|sym| Leaf::Ident(Ident { - text: text.into(), + sym, span: fake_span(node_range), is_raw: tt::IdentIsRaw::No }), @@ -286,7 +287,7 @@ pub(crate) fn fixup_syntax( if it.name_ref().is_some() && it.expr().is_none() { append.insert(colon.into(), vec![ Leaf::Ident(Ident { - text: "__ra_fixup".into(), + sym: sym::__ra_fixup.clone(), span: fake_span(node_range), is_raw: tt::IdentIsRaw::No }) @@ -299,7 +300,7 @@ pub(crate) fn fixup_syntax( if it.segment().is_none() { append.insert(colon.into(), vec![ Leaf::Ident(Ident { - text: "__ra_fixup".into(), + sym: sym::__ra_fixup.clone(), span: fake_span(node_range), is_raw: tt::IdentIsRaw::No }) @@ -333,7 +334,7 @@ pub(crate) fn fixup_syntax( if it.body().is_none() { append.insert(node.into(), vec![ Leaf::Ident(Ident { - text: "__ra_fixup".into(), + sym: sym::__ra_fixup.clone(), span: fake_span(node_range), is_raw: tt::IdentIsRaw::No }) @@ -448,9 +449,9 @@ mod tests { // `TokenTree`s, see the last assertion in `check()`. fn check_leaf_eq(a: &tt::Leaf, b: &tt::Leaf) -> bool { match (a, b) { - (tt::Leaf::Literal(a), tt::Leaf::Literal(b)) => a.text == b.text, + (tt::Leaf::Literal(a), tt::Leaf::Literal(b)) => a.symbol == b.symbol, (tt::Leaf::Punct(a), tt::Leaf::Punct(b)) => a.char == b.char, - (tt::Leaf::Ident(a), tt::Leaf::Ident(b)) => a.text == b.text, + (tt::Leaf::Ident(a), tt::Leaf::Ident(b)) => a.sym == b.sym, _ => false, } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs index 0c112554e1f43..ee15b1b5ce9d5 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/inert_attr_macro.rs @@ -10,6 +10,7 @@ use std::sync::OnceLock; +use intern::Symbol; use rustc_hash::FxHashMap; pub struct BuiltinAttribute { @@ -26,11 +27,16 @@ pub struct AttributeTemplate { pub name_value_str: Option<&'static str>, } -pub fn find_builtin_attr_idx(name: &str) -> Option { - static BUILTIN_LOOKUP_TABLE: OnceLock> = OnceLock::new(); +pub fn find_builtin_attr_idx(name: &Symbol) -> Option { + static BUILTIN_LOOKUP_TABLE: OnceLock> = OnceLock::new(); BUILTIN_LOOKUP_TABLE .get_or_init(|| { - INERT_ATTRIBUTES.iter().map(|attr| attr.name).enumerate().map(|(a, b)| (b, a)).collect() + INERT_ATTRIBUTES + .iter() + .map(|attr| attr.name) + .enumerate() + .map(|(a, b)| (Symbol::intern(b), a)) + .collect() }) .get(name) .copied() diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 907e939153ba7..2c26fe414d91e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -316,30 +316,36 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option PathKind::Abs, _ => return None, }, - tt::Leaf::Ident(tt::Ident { text, span, .. }) if text == "$crate" => { + tt::Leaf::Ident(tt::Ident { sym: text, span, .. }) if *text == sym::dollar_crate => { resolve_crate_root(db, span.ctx).map(PathKind::DollarCrate).unwrap_or(PathKind::Crate) } - tt::Leaf::Ident(tt::Ident { text, .. }) if text == "self" => PathKind::SELF, - tt::Leaf::Ident(tt::Ident { text, .. }) if text == "super" => { + tt::Leaf::Ident(tt::Ident { sym: text, .. }) if *text == sym::self_ => PathKind::SELF, + tt::Leaf::Ident(tt::Ident { sym: text, .. }) if *text == sym::super_ => { let mut deg = 1; - while let Some(tt::Leaf::Ident(tt::Ident { text, span, is_raw })) = leaves.next() { - if text != "super" { - segments.push(Name::new(text, *is_raw, span.ctx)); + while let Some(tt::Leaf::Ident(tt::Ident { sym: text, span, is_raw })) = leaves.next() { + if *text != sym::super_ { + segments.push(Name::new_symbol_maybe_raw(text.clone(), *is_raw, span.ctx)); break; } deg += 1; } PathKind::Super(deg) } - tt::Leaf::Ident(tt::Ident { text, .. }) if text == "crate" => PathKind::Crate, + tt::Leaf::Ident(tt::Ident { sym: text, .. }) if *text == sym::crate_ => PathKind::Crate, tt::Leaf::Ident(ident) => { - segments.push(Name::new(&ident.text, ident.is_raw, ident.span.ctx)); + segments.push(Name::new_symbol_maybe_raw( + ident.sym.clone(), + ident.is_raw, + ident.span.ctx, + )); PathKind::Plain } _ => return None, }; segments.extend(leaves.filter_map(|leaf| match leaf { - ::tt::Leaf::Ident(ident) => Some(Name::new(&ident.text, ident.is_raw, ident.span.ctx)), + ::tt::Leaf::Ident(ident) => { + Some(Name::new_symbol_maybe_raw(ident.sym.clone(), ident.is_raw, ident.span.ctx)) + } _ => None, })); Some(ModPath { kind, segments }) diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index fce9df6722b47..64c094bd28759 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -17,6 +17,8 @@ use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr}; pub struct Name { symbol: Symbol, ctx: (), + // FIXME: We should probably encode rawness as a property here instead, once we have hygiene + // in here we've got 4 bytes of padding to fill anyways } impl fmt::Debug for Name { @@ -187,14 +189,22 @@ impl Name { &self.symbol } - pub const fn new_symbol(doc: Symbol, ctx: SyntaxContextId) -> Self { + pub const fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self { _ = ctx; - Self { symbol: doc, ctx: () } + Self { symbol, ctx: () } + } + + pub fn new_symbol_maybe_raw(sym: Symbol, raw: tt::IdentIsRaw, ctx: SyntaxContextId) -> Self { + if raw.no() { + Self { symbol: sym, ctx: () } + } else { + Name::new(sym.as_str(), raw, ctx) + } } // FIXME: This needs to go once we have hygiene - pub const fn new_symbol_root(doc: Symbol) -> Self { - Self { symbol: doc, ctx: () } + pub const fn new_symbol_root(sym: Symbol) -> Self { + Self { symbol: sym, ctx: () } } } @@ -250,7 +260,7 @@ impl AsName for ast::NameOrNameRef { impl AsName for tt::Ident { fn as_name(&self) -> Name { - Name::resolve(&self.text) + Name::resolve(self.sym.as_str()) } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs index f1d28450b31e8..a65d46161e583 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs @@ -1,14 +1,14 @@ //! A simplified version of quote-crate like quasi quote macro #![allow(clippy::crate_in_macro_def)] -use intern::Symbol; +use intern::{sym, Symbol}; use span::Span; use tt::IdentIsRaw; use crate::name::Name; -pub(crate) const fn dollar_crate(span: Span) -> tt::Ident { - tt::Ident { text: syntax::SmolStr::new_static("$crate"), span, is_raw: tt::IdentIsRaw::No } +pub(crate) fn dollar_crate(span: Span) -> tt::Ident { + tt::Ident { sym: sym::dollar_crate.clone(), span, is_raw: tt::IdentIsRaw::No } } // A helper macro quote macro @@ -99,7 +99,7 @@ macro_rules! __quote { ($span:ident $tt:ident ) => { vec![ { crate::tt::Leaf::Ident(crate::tt::Ident { - text: stringify!($tt).into(), + sym: intern::Symbol::intern(stringify!($tt)), span: $span, is_raw: tt::IdentIsRaw::No, }).into() @@ -177,12 +177,6 @@ impl ToTokenTree for crate::tt::TokenTree { } } -impl ToTokenTree for &crate::tt::TokenTree { - fn to_token(self, _: Span) -> crate::tt::TokenTree { - self.clone() - } -} - impl ToTokenTree for crate::tt::Subtree { fn to_token(self, _: Span) -> crate::tt::TokenTree { self.into() @@ -198,35 +192,34 @@ macro_rules! impl_to_to_tokentrees { leaf.into() } } - - impl ToTokenTree for &$ty { - fn to_token($this, $span: Span) -> crate::tt::TokenTree { - let leaf: crate::tt::Leaf = $im.clone().into(); - leaf.into() - } - } )* } } +impl ToTokenTree for &T { + fn to_token(self, span: Span) -> crate::tt::TokenTree { + self.clone().to_token(span) + } +} + impl_to_to_tokentrees! { - span: u32 => self { crate::tt::Literal{text: self.to_string().into(), span, kind: tt::LitKind::Integer, suffix: None } }; - span: usize => self { crate::tt::Literal{text: self.to_string().into(), span, kind: tt::LitKind::Integer, suffix: None } }; - span: i32 => self { crate::tt::Literal{text: self.to_string().into(), span, kind: tt::LitKind::Integer, suffix: None } }; - span: bool => self { crate::tt::Ident{text: self.to_string().into(), span, is_raw: tt::IdentIsRaw::No } }; + span: u32 => self { crate::tt::Literal{symbol: Symbol::integer(self as _), span, kind: tt::LitKind::Integer, suffix: None } }; + span: usize => self { crate::tt::Literal{symbol: Symbol::integer(self as _), span, kind: tt::LitKind::Integer, suffix: None } }; + span: i32 => self { crate::tt::Literal{symbol: Symbol::integer(self as _), span, kind: tt::LitKind::Integer, suffix: None } }; + span: bool => self { crate::tt::Ident{sym: if self { sym::true_.clone() } else { sym::false_.clone() }, span, is_raw: tt::IdentIsRaw::No } }; _span: crate::tt::Leaf => self { self }; _span: crate::tt::Literal => self { self }; _span: crate::tt::Ident => self { self }; _span: crate::tt::Punct => self { self }; - span: &str => self { crate::tt::Literal{text: (*self).into(), span, kind: tt::LitKind::Str, suffix: None }}; - span: String => self { crate::tt::Literal{text: self.into(), span, kind: tt::LitKind::Str, suffix: None }}; + span: &str => self { crate::tt::Literal{symbol: Symbol::intern(self), span, kind: tt::LitKind::Str, suffix: None }}; + span: String => self { crate::tt::Literal{symbol: Symbol::intern(&self), span, kind: tt::LitKind::Str, suffix: None }}; span: Name => self { let (is_raw, s) = IdentIsRaw::split_from_symbol(self.as_str()); - crate::tt::Ident{text: s.into(), span, is_raw } + crate::tt::Ident{sym: Symbol::intern(s), span, is_raw } }; span: Symbol => self { let (is_raw, s) = IdentIsRaw::split_from_symbol(self.as_str()); - crate::tt::Ident{text: s.into(), span, is_raw } + crate::tt::Ident{sym: Symbol::intern(s), span, is_raw } }; } @@ -236,6 +229,7 @@ mod tests { use ::tt::IdentIsRaw; use base_db::FileId; use expect_test::expect; + use intern::Symbol; use span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use syntax::{TextRange, TextSize}; @@ -268,7 +262,7 @@ mod tests { fn mk_ident(name: &str) -> crate::tt::Ident { let (is_raw, s) = IdentIsRaw::split_from_symbol(name); - crate::tt::Ident { text: s.into(), span: DUMMY, is_raw } + crate::tt::Ident { sym: Symbol::intern(s), span: DUMMY, is_raw } } #[test] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs index 01e43a67e434b..1374d0c38b866 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs @@ -3,6 +3,7 @@ use std::fmt; use hir_def::{DefWithBodyId, EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId}; +use intern::sym; use once_cell::unsync::Lazy; use rustc_index::IndexVec; use rustc_pattern_analysis::{ @@ -75,9 +76,9 @@ pub(crate) struct MatchCheckCtx<'db> { impl<'db> MatchCheckCtx<'db> { pub(crate) fn new(module: ModuleId, body: DefWithBodyId, db: &'db dyn HirDatabase) -> Self { let def_map = db.crate_def_map(module.krate()); - let exhaustive_patterns = def_map.is_unstable_feature_enabled("exhaustive_patterns"); + let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns); let min_exhaustive_patterns = - def_map.is_unstable_feature_enabled("min_exhaustive_patterns"); + def_map.is_unstable_feature_enabled(&sym::min_exhaustive_patterns); Self { module, body, db, exhaustive_patterns, min_exhaustive_patterns } } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index c868357ff982f..9f33c50670857 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -3380,23 +3380,27 @@ impl BuiltinAttr { if let builtin @ Some(_) = Self::builtin(name) { return builtin; } - let idx = - db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)? as u32; + let idx = db + .crate_def_map(krate.id) + .registered_attrs() + .iter() + .position(|it| it.as_str() == name)? as u32; Some(BuiltinAttr { krate: Some(krate.id), idx }) } fn builtin(name: &str) -> Option { - hir_expand::inert_attr_macro::find_builtin_attr_idx(name) + hir_expand::inert_attr_macro::find_builtin_attr_idx(&Symbol::intern(name)) .map(|idx| BuiltinAttr { krate: None, idx: idx as u32 }) } - pub fn name(&self, db: &dyn HirDatabase) -> SmolStr { - // FIXME: Return a `Name` here + pub fn name(&self, db: &dyn HirDatabase) -> Name { match self.krate { - Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(), - None => { - SmolStr::new(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name) - } + Some(krate) => Name::new_symbol_root( + db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(), + ), + None => Name::new_symbol_root(Symbol::intern( + hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name, + )), } } @@ -3420,13 +3424,15 @@ impl ToolModule { pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option { let krate = krate.id; let idx = - db.crate_def_map(krate).registered_tools().iter().position(|it| it == name)? as u32; + db.crate_def_map(krate).registered_tools().iter().position(|it| it.as_str() == name)? + as u32; Some(ToolModule { krate, idx }) } - pub fn name(&self, db: &dyn HirDatabase) -> SmolStr { - // FIXME: Return a `Name` here - db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone() + pub fn name(&self, db: &dyn HirDatabase) -> Name { + Name::new_symbol_root( + db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone(), + ) } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index dbb2adcd301f5..a53c156b5da62 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -192,13 +192,13 @@ impl Definition { let AttributeTemplate { word, list, name_value_str } = it.template(db)?; let mut docs = "Valid forms are:".to_owned(); if word { - format_to!(docs, "\n - #\\[{}]", name); + format_to!(docs, "\n - #\\[{}]", name.display(db)); } if let Some(list) = list { - format_to!(docs, "\n - #\\[{}({})]", name, list); + format_to!(docs, "\n - #\\[{}({})]", name.display(db), list); } if let Some(name_value_str) = name_value_str { - format_to!(docs, "\n - #\\[{} = {}]", name, name_value_str); + format_to!(docs, "\n - #\\[{} = {}]", name.display(db), name_value_str); } Some(Documentation::new(docs.replace('*', "\\*"))) } @@ -256,8 +256,8 @@ impl Definition { Definition::GenericParam(it) => it.display(db).to_string(), Definition::Label(it) => it.name(db).display(db).to_string(), Definition::ExternCrateDecl(it) => it.display(db).to_string(), - Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db)), - Definition::ToolModule(it) => it.name(db).to_string(), + Definition::BuiltinAttr(it) => format!("#[{}]", it.name(db).display(db)), + Definition::ToolModule(it) => it.name(db).display(db).to_string(), Definition::DeriveHelper(it) => format!("derive_helper {}", it.name(db).display(db)), } } diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index a3cc5c3d6a3d6..9e3f6d842f315 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -174,6 +174,32 @@ impl Symbol { } } + pub fn integer(i: usize) -> Self { + match i { + 0 => symbols::INTEGER_0.clone(), + 1 => symbols::INTEGER_1.clone(), + 2 => symbols::INTEGER_2.clone(), + 3 => symbols::INTEGER_3.clone(), + 4 => symbols::INTEGER_4.clone(), + 5 => symbols::INTEGER_5.clone(), + 6 => symbols::INTEGER_6.clone(), + 7 => symbols::INTEGER_7.clone(), + 8 => symbols::INTEGER_8.clone(), + 9 => symbols::INTEGER_9.clone(), + 10 => symbols::INTEGER_10.clone(), + 11 => symbols::INTEGER_11.clone(), + 12 => symbols::INTEGER_12.clone(), + 13 => symbols::INTEGER_13.clone(), + 14 => symbols::INTEGER_14.clone(), + 15 => symbols::INTEGER_15.clone(), + i => Symbol::intern(&format!("{i}")), + } + } + + pub fn empty() -> Self { + symbols::__empty.clone() + } + pub fn as_str(&self) -> &str { self.repr.as_str() } diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 064335471e95a..61b9d099e06a3 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -56,6 +56,10 @@ macro_rules! define_symbols { define_symbols! { @WITH_NAME: + __empty = "", + unsafe_ = "unsafe", + in_ = "in", + super_ = "super", self_ = "self", Self_ = "Self", tick_static = "'static", @@ -78,10 +82,18 @@ define_symbols! { INTEGER_14 = "14", INTEGER_15 = "15", fn_ = "fn", + crate_ = "crate", + underscore = "_", + true_ = "true", + false_ = "false", + let_ = "let", + const_ = "const", @PLAIN: + __ra_fixup, add_assign, add, + attributes, align_offset, alloc_layout, alloc, @@ -92,6 +104,9 @@ define_symbols! { bench, bitand_assign, bitand, + notable_trait, + hidden, + local_inner_macros, bitor_assign, bitor, bitxor_assign, @@ -225,9 +240,12 @@ define_symbols! { log_syntax, lt, macro_rules, + ignore, + count, manually_drop, maybe_uninit, metadata_type, + missing, module_path, mul_assign, mul, @@ -349,6 +367,10 @@ define_symbols! { u8, Unknown, unpin, + simd, + C, + align, + packed, unreachable_2015, unreachable_2021, unreachable, @@ -356,5 +378,7 @@ define_symbols! { unsize, usize, v1, + exhaustive_patterns, + min_exhaustive_patterns, va_list } diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml index 1002de2104a0c..57834623e84fa 100644 --- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml +++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml @@ -24,6 +24,7 @@ parser.workspace = true tt.workspace = true stdx.workspace = true span.workspace = true +intern.workspace = true [dev-dependencies] test-utils.workspace = true diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs index 6a2f1c236869d..04e78a0833407 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs @@ -1,10 +1,11 @@ //! This module add real world mbe example for benchmark tests +use intern::Symbol; use rustc_hash::FxHashMap; use span::{Edition, Span}; use syntax::{ ast::{self, HasName}, - AstNode, SmolStr, + AstNode, }; use test_utils::{bench, bench_fixture, skip_slow_tests}; @@ -228,7 +229,7 @@ fn invocation_fixtures( fn make_ident(ident: &str) -> tt::TokenTree { tt::Leaf::Ident(tt::Ident { span: DUMMY, - text: SmolStr::new(ident), + sym: Symbol::intern(ident), is_raw: tt::IdentIsRaw::No, }) .into() @@ -239,7 +240,7 @@ fn invocation_fixtures( fn make_literal(lit: &str) -> tt::TokenTree { tt::Leaf::Literal(tt::Literal { span: DUMMY, - text: SmolStr::new(lit), + symbol: Symbol::intern(lit), kind: tt::LitKind::Str, suffix: None, }) diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs index cfad8bcc0b454..55b89aa848d5d 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander.rs @@ -5,9 +5,9 @@ mod matcher; mod transcriber; +use intern::Symbol; use rustc_hash::FxHashMap; use span::{Edition, Span}; -use syntax::SmolStr; use crate::{parser::MetaVarKind, ExpandError, ExpandResult, MatchedArmIndex}; @@ -110,12 +110,12 @@ pub(crate) fn expand_rules( /// the `Bindings` we should take. We push to the stack when we enter a /// repetition. /// -/// In other words, `Bindings` is a *multi* mapping from `SmolStr` to +/// In other words, `Bindings` is a *multi* mapping from `Symbol` to /// `tt::TokenTree`, where the index to select a particular `TokenTree` among /// many is not a plain `usize`, but a `&[usize]`. #[derive(Debug, Default, Clone, PartialEq, Eq)] struct Bindings { - inner: FxHashMap, + inner: FxHashMap, } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs index b20d5579ca63b..3762d20bab62e 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs @@ -61,9 +61,9 @@ use std::{rc::Rc, sync::Arc}; +use intern::{sym, Symbol}; use smallvec::{smallvec, SmallVec}; use span::{Edition, Span}; -use syntax::SmolStr; use tt::{iter::TtIter, DelimSpan}; use crate::{ @@ -74,12 +74,12 @@ use crate::{ }; impl Bindings { - fn push_optional(&mut self, name: &SmolStr) { - self.inner.insert(name.clone(), Binding::Fragment(Fragment::Empty)); + fn push_optional(&mut self, name: Symbol) { + self.inner.insert(name, Binding::Fragment(Fragment::Empty)); } - fn push_empty(&mut self, name: &SmolStr) { - self.inner.insert(name.clone(), Binding::Empty); + fn push_empty(&mut self, name: Symbol) { + self.inner.insert(name, Binding::Empty); } fn bindings(&self) -> impl Iterator { @@ -127,10 +127,10 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree, edition: #[derive(Debug, Clone)] enum BindingKind { - Empty(SmolStr), - Optional(SmolStr), - Fragment(SmolStr, Fragment), - Missing(SmolStr, MetaVarKind), + Empty(Symbol), + Optional(Symbol), + Fragment(Symbol, Fragment), + Missing(Symbol, MetaVarKind), Nested(usize, usize), } @@ -178,20 +178,20 @@ impl BindingsBuilder { } } - fn push_empty(&mut self, idx: &mut BindingsIdx, var: &SmolStr) { + fn push_empty(&mut self, idx: &mut BindingsIdx, var: &Symbol) { self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Empty(var.clone())))); } - fn push_optional(&mut self, idx: &mut BindingsIdx, var: &SmolStr) { + fn push_optional(&mut self, idx: &mut BindingsIdx, var: &Symbol) { self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone())))); } - fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &SmolStr, fragment: Fragment) { + fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &Symbol, fragment: Fragment) { self.nodes[idx.0] .push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment)))); } - fn push_missing(&mut self, idx: &mut BindingsIdx, var: &SmolStr, kind: MetaVarKind) { + fn push_missing(&mut self, idx: &mut BindingsIdx, var: &Symbol, kind: MetaVarKind) { self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Missing(var.clone(), kind)))); } @@ -219,10 +219,10 @@ impl BindingsBuilder { for cmd in nodes { match cmd { BindingKind::Empty(name) => { - bindings.push_empty(name); + bindings.push_empty(name.clone()); } BindingKind::Optional(name) => { - bindings.push_optional(name); + bindings.push_optional(name.clone()); } BindingKind::Fragment(name, fragment) => { bindings.inner.insert(name.clone(), Binding::Fragment(fragment.clone())); @@ -507,7 +507,7 @@ fn match_loop_inner<'t>( } OpDelimited::Op(Op::Literal(lhs)) => { if let Ok(rhs) = src.clone().expect_leaf() { - if matches!(rhs, tt::Leaf::Literal(it) if it.text == lhs.text) { + if matches!(rhs, tt::Leaf::Literal(it) if it.symbol == lhs.symbol) { item.dot.next(); } else { res.add_err(ExpandError::UnexpectedToken); @@ -521,7 +521,7 @@ fn match_loop_inner<'t>( } OpDelimited::Op(Op::Ident(lhs)) => { if let Ok(rhs) = src.clone().expect_leaf() { - if matches!(rhs, tt::Leaf::Ident(it) if it.text == lhs.text) { + if matches!(rhs, tt::Leaf::Ident(it) if it.sym == lhs.sym) { item.dot.next(); } else { res.add_err(ExpandError::UnexpectedToken); @@ -554,7 +554,7 @@ fn match_loop_inner<'t>( // ident, not a punct. ExpandError::UnexpectedToken } else { - let lhs: SmolStr = lhs.collect(); + let lhs = lhs.collect::(); ExpandError::binding_error(format!("expected punct: `{lhs}`")) } } else { @@ -759,7 +759,9 @@ fn match_meta_var( // [1]: https://github.com/rust-lang/rust/blob/f0c4da499/compiler/rustc_expand/src/mbe/macro_parser.rs#L576 match input.peek_n(0) { Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it))) - if it.text == "_" || it.text == "let" || it.text == "const" => + if it.sym == sym::underscore + || it.sym == sym::let_ + || it.sym == sym::const_ => { return ExpandResult::only_err(ExpandError::NoMatchingRule) } @@ -824,7 +826,7 @@ fn match_meta_var( expect_fragment(input, fragment, edition).map(|it| it.map(Fragment::Tokens)) } -fn collect_vars(collector_fun: &mut impl FnMut(SmolStr), pattern: &MetaTemplate) { +fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate) { for op in pattern.iter() { match op { Op::Var { name, .. } => collector_fun(name.clone()), @@ -908,13 +910,13 @@ fn expect_separator(iter: &mut TtIter<'_, S>, separator: &Separator) -> let mut fork = iter.clone(); let ok = match separator { Separator::Ident(lhs) => match fork.expect_ident_or_underscore() { - Ok(rhs) => rhs.text == lhs.text, + Ok(rhs) => rhs.sym == lhs.sym, Err(_) => false, }, Separator::Literal(lhs) => match fork.expect_literal() { Ok(rhs) => match rhs { - tt::Leaf::Literal(rhs) => rhs.text == lhs.text, - tt::Leaf::Ident(rhs) => rhs.text == lhs.text, + tt::Leaf::Literal(rhs) => rhs.symbol == lhs.symbol, + tt::Leaf::Ident(rhs) => rhs.sym == lhs.symbol, tt::Leaf::Punct(_) => false, }, Err(_) => false, diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs index e3359865cb276..4de7cccd9680e 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs @@ -1,8 +1,8 @@ //! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like //! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` +use intern::{sym, Symbol}; use span::Span; -use syntax::{format_smolstr, SmolStr}; use tt::Delimiter; use crate::{ @@ -12,16 +12,16 @@ use crate::{ }; impl Bindings { - fn get(&self, name: &str) -> Result<&Binding, ExpandError> { + fn get(&self, name: &Symbol) -> Result<&Binding, ExpandError> { match self.inner.get(name) { Some(binding) => Ok(binding), - None => Err(ExpandError::UnresolvedBinding(Box::new(Box::from(name)))), + None => Err(ExpandError::UnresolvedBinding(Box::new(Box::from(name.as_str())))), } } fn get_fragment( &self, - name: &str, + name: &Symbol, mut span: Span, nesting: &mut [NestingState], marker: impl Fn(&mut Span), @@ -97,7 +97,7 @@ impl Bindings { | MetaVarKind::Expr | MetaVarKind::Ident => { Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { - text: SmolStr::new_static("missing"), + sym: sym::missing.clone(), span, is_raw: tt::IdentIsRaw::No, }))) @@ -112,7 +112,7 @@ impl Bindings { spacing: tt::Spacing::Joint, })), tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { - text: SmolStr::new_static("missing"), + sym: sym::missing.clone(), span, is_raw: tt::IdentIsRaw::No, })), @@ -121,7 +121,7 @@ impl Bindings { } MetaVarKind::Literal => { Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { - text: SmolStr::new_static("\"missing\""), + sym: sym::missing.clone(), span, is_raw: tt::IdentIsRaw::No, }))) @@ -239,7 +239,7 @@ fn expand_subtree( ctx.nesting.get(ctx.nesting.len() - 1 - depth).map_or(0, |nest| nest.idx); arena.push( tt::Leaf::Literal(tt::Literal { - text: format_smolstr!("{index}"), + symbol: Symbol::integer(index), span: ctx.call_site, kind: tt::LitKind::Integer, suffix: None, @@ -254,7 +254,7 @@ fn expand_subtree( }); arena.push( tt::Leaf::Literal(tt::Literal { - text: format_smolstr!("{length}"), + symbol: Symbol::integer(length), span: ctx.call_site, kind: tt::LitKind::Integer, suffix: None, @@ -263,7 +263,7 @@ fn expand_subtree( ); } Op::Count { name, depth } => { - let mut binding = match ctx.bindings.get(name.as_str()) { + let mut binding = match ctx.bindings.get(name) { Ok(b) => b, Err(e) => { if err.is_none() { @@ -321,7 +321,7 @@ fn expand_subtree( }; arena.push( tt::Leaf::Literal(tt::Literal { - text: format_smolstr!("{c}"), + symbol: Symbol::integer(c), span: ctx.call_site, suffix: None, kind: tt::LitKind::Integer, @@ -344,12 +344,12 @@ fn expand_subtree( fn expand_var( ctx: &mut ExpandCtx<'_>, - v: &SmolStr, + v: &Symbol, id: Span, marker: impl Fn(&mut Span), ) -> ExpandResult { // We already handle $crate case in mbe parser - debug_assert!(v != "crate"); + debug_assert!(*v != sym::crate_); match ctx.bindings.get_fragment(v, id, &mut ctx.nesting, marker) { Ok(it) => ExpandResult::ok(it), @@ -373,7 +373,7 @@ fn expand_var( tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, span: id }) .into(), tt::Leaf::from(tt::Ident { - text: v.clone(), + sym: v.clone(), span: id, is_raw: tt::IdentIsRaw::No, }) diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs index 18af35c1e2900..74a2c771e2037 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use arrayvec::ArrayVec; +use intern::{sym, Symbol}; use span::{Edition, Span, SyntaxContextId}; -use syntax::SmolStr; use tt::iter::TtIter; use crate::ParseError; @@ -67,12 +67,12 @@ impl MetaTemplate { #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum Op { Var { - name: SmolStr, + name: Symbol, kind: Option, id: Span, }, Ignore { - name: SmolStr, + name: Symbol, id: Span, }, Index { @@ -82,7 +82,7 @@ pub(crate) enum Op { depth: usize, }, Count { - name: SmolStr, + name: Symbol, // FIXME: `usize`` once we drop support for 1.76 depth: Option, }, @@ -138,8 +138,8 @@ impl PartialEq for Separator { use Separator::*; match (self, other) { - (Ident(a), Ident(b)) => a.text == b.text, - (Literal(a), Literal(b)) => a.text == b.text, + (Ident(a), Ident(b)) => a.sym == b.sym, + (Literal(a), Literal(b)) => a.symbol == b.symbol, (Puncts(a), Puncts(b)) if a.len() == b.len() => { let a_iter = a.iter().map(|a| a.char); let b_iter = b.iter().map(|b| b.char); @@ -203,23 +203,23 @@ fn next_op( } }, tt::TokenTree::Leaf(leaf) => match leaf { - tt::Leaf::Ident(ident) if ident.text == "crate" => { + tt::Leaf::Ident(ident) if ident.sym == sym::crate_ => { // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path. Op::Ident(tt::Ident { - text: "$crate".into(), + sym: sym::dollar_crate.clone(), span: ident.span, is_raw: tt::IdentIsRaw::No, }) } tt::Leaf::Ident(ident) => { let kind = eat_fragment_kind(edition, src, mode)?; - let name = ident.text.clone(); + let name = ident.sym.clone(); let id = ident.span; Op::Var { name, kind, id } } tt::Leaf::Literal(lit) if is_boolean_literal(lit) => { let kind = eat_fragment_kind(edition, src, mode)?; - let name = lit.text.clone(); + let name = lit.symbol.clone(); let id = lit.span; Op::Var { name, kind, id } } @@ -277,7 +277,7 @@ fn eat_fragment_kind( let ident = src .expect_ident() .map_err(|()| ParseError::unexpected("missing fragment specifier"))?; - let kind = match ident.text.as_str() { + let kind = match ident.sym.as_str() { "path" => MetaVarKind::Path, "ty" => MetaVarKind::Ty, "pat" => match edition(ident.span.ctx) { @@ -303,7 +303,7 @@ fn eat_fragment_kind( } fn is_boolean_literal(lit: &tt::Literal) -> bool { - matches!(lit.text.as_str(), "true" | "false") + matches!(lit.symbol.as_str(), "true" | "false") } fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option, RepeatKind), ParseError> { @@ -353,23 +353,23 @@ fn parse_metavar_expr(new_meta_vars: bool, src: &mut TtIter<'_, Span>) -> Result let mut args = TtIter::new(args); - let op = match &*func.text { - "ignore" => { + let op = match &func.sym { + s if sym::ignore == *s => { if new_meta_vars { args.expect_dollar()?; } let ident = args.expect_ident()?; - Op::Ignore { name: ident.text.clone(), id: ident.span } + Op::Ignore { name: ident.sym.clone(), id: ident.span } } - "index" => Op::Index { depth: parse_depth(&mut args)? }, - "len" => Op::Len { depth: parse_depth(&mut args)? }, - "count" => { + s if sym::index == *s => Op::Index { depth: parse_depth(&mut args)? }, + s if sym::len == *s => Op::Len { depth: parse_depth(&mut args)? }, + s if sym::count == *s => { if new_meta_vars { args.expect_dollar()?; } let ident = args.expect_ident()?; let depth = if try_eat_comma(&mut args) { Some(parse_depth(&mut args)?) } else { None }; - Op::Count { name: ident.text.clone(), depth } + Op::Count { name: ident.sym.clone(), depth } } _ => return Err(()), }; @@ -384,11 +384,11 @@ fn parse_metavar_expr(new_meta_vars: bool, src: &mut TtIter<'_, Span>) -> Result fn parse_depth(src: &mut TtIter<'_, Span>) -> Result { if src.len() == 0 { Ok(0) - } else if let tt::Leaf::Literal(tt::Literal { text, suffix: None, .. }) = + } else if let tt::Leaf::Literal(tt::Literal { symbol: text, suffix: None, .. }) = src.expect_literal()? { // Suffixes are not allowed. - text.parse().map_err(|_| ()) + text.as_str().parse().map_err(|_| ()) } else { Err(()) } diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs index 4d66464932b88..7ff89631080e4 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs @@ -2,6 +2,7 @@ use std::fmt; +use intern::Symbol; use rustc_hash::{FxHashMap, FxHashSet}; use span::{Edition, SpanAnchor, SpanData, SpanMap}; use stdx::{format_to, never, non_empty_vec::NonEmptyVec}; @@ -322,7 +323,7 @@ where () => { tt::Ident { span: conv.span_for(abs_range), - text: token.to_text(conv), + sym: Symbol::intern(&token.to_text(conv)), is_raw: tt::IdentIsRaw::No, } .into() @@ -332,14 +333,14 @@ where T![true] | T![false] => make_ident!(), IDENT => { let text = token.to_text(conv); - tt::Ident::new(text, conv.span_for(abs_range)).into() + tt::Ident::new(&text, conv.span_for(abs_range)).into() } UNDERSCORE => make_ident!(), k if k.is_keyword() => make_ident!(), k if k.is_literal() => { let text = token.to_text(conv); let span = conv.span_for(abs_range); - token_to_literal(text, span).into() + token_to_literal(&text, span).into() } LIFETIME_IDENT => { let apostrophe = tt::Leaf::from(tt::Punct { @@ -351,7 +352,7 @@ where token_trees.push(apostrophe.into()); let ident = tt::Leaf::from(tt::Ident { - text: SmolStr::new(&token.to_text(conv)[1..]), + sym: Symbol::intern(&token.to_text(conv)[1..]), span: conv.span_for(TextRange::new( abs_range.start() + TextSize::of('\''), abs_range.end(), @@ -436,7 +437,7 @@ fn is_single_token_op(kind: SyntaxKind) -> bool { /// And then quote the string, which is needed to convert to `tt::Literal` /// /// Note that proc-macros desugar with string literals where as macro_rules macros desugar with raw string literals. -pub fn desugar_doc_comment_text(text: &str, mode: DocCommentDesugarMode) -> (SmolStr, tt::LitKind) { +pub fn desugar_doc_comment_text(text: &str, mode: DocCommentDesugarMode) -> (Symbol, tt::LitKind) { match mode { DocCommentDesugarMode::Mbe => { let mut num_of_hashes = 0; @@ -451,11 +452,11 @@ pub fn desugar_doc_comment_text(text: &str, mode: DocCommentDesugarMode) -> (Smo } // Quote raw string with delimiters - (text.into(), tt::LitKind::StrRaw(num_of_hashes)) + (Symbol::intern(text), tt::LitKind::StrRaw(num_of_hashes)) } // Quote string with delimiters DocCommentDesugarMode::ProcMacro => { - (format_smolstr!("{}", text.escape_debug()), tt::LitKind::Str) + (Symbol::intern(&format_smolstr!("{}", text.escape_debug())), tt::LitKind::Str) } } } @@ -471,7 +472,7 @@ fn convert_doc_comment( let mk_ident = |s: &str| { tt::TokenTree::from(tt::Leaf::from(tt::Ident { - text: s.into(), + sym: Symbol::intern(s), span, is_raw: tt::IdentIsRaw::No, })) @@ -494,7 +495,7 @@ fn convert_doc_comment( text = &text[0..text.len() - 2]; } let (text, kind) = desugar_doc_comment_text(text, mode); - let lit = tt::Literal { text, span, kind, suffix: None }; + let lit = tt::Literal { symbol: text, span, kind, suffix: None }; tt::TokenTree::from(tt::Leaf::from(lit)) }; @@ -928,7 +929,12 @@ where fn float_split(&mut self, has_pseudo_dot: bool) { let (text, span) = match self.cursor.token_tree() { Some(tt::buffer::TokenTreeRef::Leaf( - tt::Leaf::Literal(tt::Literal { text, span, kind: tt::LitKind::Float, suffix: _ }), + tt::Leaf::Literal(tt::Literal { + symbol: text, + span, + kind: tt::LitKind::Float, + suffix: _, + }), _, )) => (text.as_str(), *span), tt => unreachable!("{tt:?}"), @@ -988,7 +994,7 @@ where self.buf.push_str("r#"); self.text_pos += TextSize::of("r#"); } - let r = (ident.text.as_str(), ident.span); + let r = (ident.sym.as_str(), ident.span); self.cursor = self.cursor.bump(); r } diff --git a/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs b/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs index bf5494d37149b..7636359805c72 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs @@ -49,23 +49,22 @@ pub(crate) fn to_parser_input(buffer: &TokenBuffer<'_, S>) }; res.push(kind); - if kind == FLOAT_NUMBER && !lit.text.ends_with('.') { + if kind == FLOAT_NUMBER && !lit.symbol.as_str().ends_with('.') { // Tag the token as joint if it is float with a fractional part // we use this jointness to inform the parser about what token split // event to emit when we encounter a float literal in a field access res.was_joint(); } } - tt::Leaf::Ident(ident) => match ident.text.as_ref() { + tt::Leaf::Ident(ident) => match ident.sym.as_str() { "_" => res.push(T![_]), i if i.starts_with('\'') => res.push(LIFETIME_IDENT), _ if ident.is_raw.yes() => res.push(IDENT), - _ => match SyntaxKind::from_keyword(&ident.text) { + text => match SyntaxKind::from_keyword(text) { Some(kind) => res.push(kind), None => { - let contextual_keyword = - SyntaxKind::from_contextual_keyword(&ident.text) - .unwrap_or(SyntaxKind::IDENT); + let contextual_keyword = SyntaxKind::from_contextual_keyword(text) + .unwrap_or(SyntaxKind::IDENT); res.push_ident(contextual_keyword); } }, diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml index 889eefa8b5c61..345fb9f8ae973 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml @@ -28,8 +28,7 @@ span.workspace = true # InternIds for the syntax context base-db.workspace = true la-arena.workspace = true -# only here to parse via token_to_literal -mbe.workspace = true +intern.workspace = true [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index 3a915e668bbff..54c1475b8b1c8 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -13,7 +13,6 @@ use base_db::Env; use paths::{AbsPath, AbsPathBuf}; use span::Span; use std::{fmt, io, sync::Arc}; -use tt::SmolStr; use serde::{Deserialize, Serialize}; @@ -66,7 +65,7 @@ impl MacroDylib { pub struct ProcMacro { process: Arc, dylib_path: Arc, - name: SmolStr, + name: Box, kind: ProcMacroKind, } diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs index 65835048173ab..65f60a7c5bd28 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs @@ -158,6 +158,7 @@ type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) #[cfg(test)] mod tests { use base_db::FileId; + use intern::{sym, Symbol}; use la_arena::RawIdx; use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId}; use text_size::{TextRange, TextSize}; @@ -174,7 +175,7 @@ mod tests { let token_trees = Box::new([ TokenTree::Leaf( Ident { - text: "struct".into(), + sym: Symbol::intern("struct"), span: Span { range: TextRange::at(TextSize::new(0), TextSize::of("struct")), anchor, @@ -186,7 +187,7 @@ mod tests { ), TokenTree::Leaf( Ident { - text: "Foo".into(), + sym: Symbol::intern("Foo"), span: Span { range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")), anchor, @@ -197,7 +198,7 @@ mod tests { .into(), ), TokenTree::Leaf(Leaf::Literal(Literal { - text: "Foo".into(), + symbol: Symbol::intern("Foo"), span: Span { range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")), anchor, @@ -230,14 +231,14 @@ mod tests { kind: DelimiterKind::Brace, }, token_trees: Box::new([TokenTree::Leaf(Leaf::Literal(Literal { - text: "0".into(), + symbol: sym::INTEGER_0.clone(), span: Span { range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), anchor, ctx: SyntaxContextId::ROOT, }, kind: tt::LitKind::Integer, - suffix: Some(Box::new("u32".into())), + suffix: Some(sym::u32.clone()), }))]), }), ]); diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs index 3d962e99d92c2..19260bc817dae 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs @@ -37,6 +37,7 @@ use std::collections::VecDeque; +use intern::Symbol; use la_arena::RawIdx; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; @@ -433,8 +434,8 @@ impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> { let id = self.token_id_of(lit.span); let (text, suffix) = if self.version >= EXTENDED_LEAF_DATA { ( - self.intern(&lit.text), - lit.suffix.as_ref().map(|s| self.intern(s)).unwrap_or(!0), + self.intern(lit.symbol.as_str()), + lit.suffix.as_ref().map(|s| self.intern(s.as_str())).unwrap_or(!0), ) } else { (self.intern_owned(format!("{lit}")), !0) @@ -469,11 +470,11 @@ impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> { let idx = self.ident.len() as u32; let id = self.token_id_of(ident.span); let text = if self.version >= EXTENDED_LEAF_DATA { - self.intern(&ident.text) + self.intern(ident.sym.as_str()) } else if ident.is_raw.yes() { - self.intern_owned(format!("r#{}", ident.text,)) + self.intern_owned(format!("r#{}", ident.sym.as_str(),)) } else { - self.intern(&ident.text) + self.intern(ident.sym.as_str()) }; self.ident.push(IdentRepr { id, text, is_raw: ident.is_raw.yes() }); idx << 2 | 0b11 @@ -555,7 +556,7 @@ impl<'span, S: InternableSpan> Reader<'span, S> { let span = read_span(repr.id); tt::Leaf::Literal(if self.version >= EXTENDED_LEAF_DATA { tt::Literal { - text: text.into(), + symbol: Symbol::intern(text), span, kind: match u16::to_le_bytes(repr.kind) { [0, _] => Err(()), @@ -572,15 +573,15 @@ impl<'span, S: InternableSpan> Reader<'span, S> { _ => unreachable!(), }, suffix: if repr.suffix != !0 { - Some(Box::new( - self.text[repr.suffix as usize].as_str().into(), + Some(Symbol::intern( + self.text[repr.suffix as usize].as_str(), )) } else { None }, } } else { - tt::token_to_literal(text.into(), span) + tt::token_to_literal(text, span) }) .into() } @@ -609,7 +610,7 @@ impl<'span, S: InternableSpan> Reader<'span, S> { tt::IdentIsRaw::split_from_symbol(text) }; tt::Leaf::Ident(tt::Ident { - text: text.into(), + sym: Symbol::intern(text), span: read_span(repr.id), is_raw, }) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index 065701c05cc7b..673b5bd78a8e9 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -25,6 +25,7 @@ base-db.workspace = true span.workspace = true proc-macro-api.workspace = true ra-ap-rustc_lexer.workspace = true +intern.workspace = true [dev-dependencies] expect-test = "1.4.0" diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index e6281035e1a2e..f0aa6b3f93f95 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -130,14 +130,13 @@ impl ProcMacroSrvSpan for TokenId { type Server = server_impl::token_id::TokenIdServer; fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { - Self::Server { interner: &server_impl::SYMBOL_INTERNER, call_site, def_site, mixed_site } + Self::Server { call_site, def_site, mixed_site } } } impl ProcMacroSrvSpan for Span { type Server = server_impl::rust_analyzer_span::RaSpanServer; fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server { Self::Server { - interner: &server_impl::SYMBOL_INTERNER, call_site, def_site, mixed_site, diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs index 68e0f85978e0c..c9a8621690552 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs @@ -14,9 +14,9 @@ mod token_stream; pub use token_stream::TokenStream; pub mod rust_analyzer_span; -mod symbol; +// mod symbol; pub mod token_id; -pub use symbol::*; +// pub use symbol::*; use tt::Spacing; fn delim_to_internal(d: proc_macro::Delimiter, span: bridge::DelimSpan) -> tt::Delimiter { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 1a71f39612d3b..452ad8e083daa 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -10,13 +10,14 @@ use std::{ ops::{Bound, Range}, }; +use intern::Symbol; use proc_macro::bridge::{self, server}; use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER}; use tt::{TextRange, TextSize}; use crate::server_impl::{ delim_to_external, delim_to_internal, literal_kind_to_external, literal_kind_to_internal, - token_stream::TokenStreamBuilder, Symbol, SymbolInternerRef, SYMBOL_INTERNER, + token_stream::TokenStreamBuilder, }; mod tt { pub use tt::*; @@ -36,7 +37,6 @@ pub struct SourceFile; pub struct FreeFunctions; pub struct RaSpanServer { - pub(crate) interner: SymbolInternerRef, // FIXME: Report this back to the caller to track as dependencies pub tracked_env_vars: HashMap, Option>>, // FIXME: Report this back to the caller to track as dependencies @@ -126,15 +126,10 @@ impl server::FreeFunctions for RaSpanServer { let lit = &lit[start_offset..lit.len() - end_offset]; let suffix = match suffix { "" | "_" => None, - suffix => Some(Symbol::intern(self.interner, suffix)), + suffix => Some(Symbol::intern(suffix)), }; - Ok(bridge::Literal { - kind, - symbol: Symbol::intern(self.interner, lit), - suffix, - span: self.call_site, - }) + Ok(bridge::Literal { kind, symbol: Symbol::intern(lit), suffix, span: self.call_site }) } fn emit_diagnostic(&mut self, _: bridge::Diagnostic) { @@ -170,9 +165,9 @@ impl server::TokenStream for RaSpanServer { } bridge::TokenTree::Ident(ident) => { - let text = ident.sym.text(self.interner); + let text = ident.sym; let ident: tt::Ident = tt::Ident { - text, + sym: text, span: ident.span, is_raw: if ident.is_raw { tt::IdentIsRaw::Yes } else { tt::IdentIsRaw::No }, }; @@ -183,8 +178,8 @@ impl server::TokenStream for RaSpanServer { bridge::TokenTree::Literal(literal) => { let literal = tt::Literal { - text: literal.symbol.text(self.interner), - suffix: literal.suffix.map(|it| Box::new(it.text(self.interner))), + symbol: literal.symbol, + suffix: literal.suffix, span: literal.span, kind: literal_kind_to_internal(literal.kind), }; @@ -255,7 +250,7 @@ impl server::TokenStream for RaSpanServer { .map(|tree| match tree { tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { bridge::TokenTree::Ident(bridge::Ident { - sym: Symbol::intern(self.interner, &ident.text), + sym: ident.sym, is_raw: ident.is_raw.yes(), span: ident.span, }) @@ -264,8 +259,8 @@ impl server::TokenStream for RaSpanServer { bridge::TokenTree::Literal(bridge::Literal { span: lit.span, kind: literal_kind_to_external(lit.kind), - symbol: Symbol::intern(self.interner, &lit.text), - suffix: lit.suffix.map(|it| Symbol::intern(self.interner, &it)), + symbol: lit.symbol, + suffix: lit.suffix, }) } tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => { @@ -464,12 +459,95 @@ impl server::Server for RaSpanServer { } fn intern_symbol(ident: &str) -> Self::Symbol { - // FIXME: should be `self.interner` once the proc-macro api allows it. - Symbol::intern(&SYMBOL_INTERNER, &::tt::SmolStr::from(ident)) + Symbol::intern(ident) } fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) { - // FIXME: should be `self.interner` once the proc-macro api allows it. - f(symbol.text(&SYMBOL_INTERNER).as_str()) + f(symbol.as_str()) + } +} + +#[cfg(test)] +mod tests { + use span::SyntaxContextId; + + use super::*; + + #[test] + fn test_ra_server_to_string() { + let span = Span { + range: TextRange::empty(TextSize::new(0)), + anchor: span::SpanAnchor { + file_id: span::FileId::from_raw(0), + ast_id: span::ErasedFileAstId::from_raw(0.into()), + }, + ctx: SyntaxContextId::ROOT, + }; + let s = TokenStream { + token_trees: vec![ + tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + sym: Symbol::intern("struct"), + span, + is_raw: tt::IdentIsRaw::No, + })), + tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + sym: Symbol::intern("T"), + span: span, + is_raw: tt::IdentIsRaw::No, + })), + tt::TokenTree::Subtree(tt::Subtree { + delimiter: tt::Delimiter { + open: span, + close: span, + kind: tt::DelimiterKind::Brace, + }, + token_trees: Box::new([]), + }), + ], + }; + + assert_eq!(s.to_string(), "struct T {}"); + } + + #[test] + fn test_ra_server_from_str() { + let span = Span { + range: TextRange::empty(TextSize::new(0)), + anchor: span::SpanAnchor { + file_id: span::FileId::from_raw(0), + ast_id: span::ErasedFileAstId::from_raw(0.into()), + }, + ctx: SyntaxContextId::ROOT, + }; + let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree { + delimiter: tt::Delimiter { + open: span, + close: span, + kind: tt::DelimiterKind::Parenthesis, + }, + token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + is_raw: tt::IdentIsRaw::No, + sym: Symbol::intern("a"), + span, + }))]), + }); + + let t1 = TokenStream::from_str("(a)", span).unwrap(); + assert_eq!(t1.token_trees.len(), 1); + assert_eq!(t1.token_trees[0], subtree_paren_a); + + let t2 = TokenStream::from_str("(a);", span).unwrap(); + assert_eq!(t2.token_trees.len(), 2); + assert_eq!(t2.token_trees[0], subtree_paren_a); + + let underscore = TokenStream::from_str("_", span).unwrap(); + assert_eq!( + underscore.token_trees[0], + tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { + sym: Symbol::intern("_"), + span, + is_raw: tt::IdentIsRaw::No, + })) + ); } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/symbol.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/symbol.rs index 540d06457f2f3..6863ce959973e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/symbol.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/symbol.rs @@ -1,7 +1,6 @@ //! Symbol interner for proc-macro-srv use std::{cell::RefCell, collections::HashMap, thread::LocalKey}; -use tt::SmolStr; thread_local! { pub(crate) static SYMBOL_INTERNER: RefCell = Default::default(); diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs index 94d5748b0870f..7720c6d83c38d 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs @@ -5,11 +5,12 @@ use std::{ ops::{Bound, Range}, }; +use intern::Symbol; use proc_macro::bridge::{self, server}; use crate::server_impl::{ delim_to_external, delim_to_internal, literal_kind_to_external, literal_kind_to_internal, - token_stream::TokenStreamBuilder, Symbol, SymbolInternerRef, SYMBOL_INTERNER, + token_stream::TokenStreamBuilder, }; mod tt { pub use proc_macro_api::msg::TokenId; @@ -36,7 +37,6 @@ pub struct SourceFile; pub struct FreeFunctions; pub struct TokenIdServer { - pub(crate) interner: SymbolInternerRef, pub call_site: Span, pub def_site: Span, pub mixed_site: Span, @@ -117,15 +117,10 @@ impl server::FreeFunctions for TokenIdServer { let lit = &lit[start_offset..lit.len() - end_offset]; let suffix = match suffix { "" | "_" => None, - suffix => Some(Symbol::intern(self.interner, suffix)), + suffix => Some(Symbol::intern(suffix)), }; - Ok(bridge::Literal { - kind, - symbol: Symbol::intern(self.interner, lit), - suffix, - span: self.call_site, - }) + Ok(bridge::Literal { kind, symbol: Symbol::intern(lit), suffix, span: self.call_site }) } fn emit_diagnostic(&mut self, _: bridge::Diagnostic) {} @@ -159,9 +154,8 @@ impl server::TokenStream for TokenIdServer { } bridge::TokenTree::Ident(ident) => { - let text = ident.sym.text(self.interner); let ident: tt::Ident = tt::Ident { - text, + sym: ident.sym, span: ident.span, is_raw: if ident.is_raw { tt::IdentIsRaw::Yes } else { tt::IdentIsRaw::No }, }; @@ -172,8 +166,8 @@ impl server::TokenStream for TokenIdServer { bridge::TokenTree::Literal(literal) => { let literal = Literal { - text: literal.symbol.text(self.interner), - suffix: literal.suffix.map(|it| Box::new(it.text(self.interner))), + symbol: literal.symbol, + suffix: literal.suffix, span: literal.span, kind: literal_kind_to_internal(literal.kind), }; @@ -239,7 +233,7 @@ impl server::TokenStream for TokenIdServer { .map(|tree| match tree { tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => { bridge::TokenTree::Ident(bridge::Ident { - sym: Symbol::intern(self.interner, &ident.text), + sym: ident.sym, is_raw: ident.is_raw.yes(), span: ident.span, }) @@ -248,8 +242,8 @@ impl server::TokenStream for TokenIdServer { bridge::TokenTree::Literal(bridge::Literal { span: lit.span, kind: literal_kind_to_external(lit.kind), - symbol: Symbol::intern(self.interner, &lit.text), - suffix: lit.suffix.map(|it| Symbol::intern(self.interner, &it)), + symbol: lit.symbol, + suffix: lit.suffix, }) } tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => { @@ -366,11 +360,11 @@ impl server::Server for TokenIdServer { } fn intern_symbol(ident: &str) -> Self::Symbol { - Symbol::intern(&SYMBOL_INTERNER, &::tt::SmolStr::from(ident)) + Symbol::intern(ident) } fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) { - f(symbol.text(&SYMBOL_INTERNER).as_str()) + f(symbol.as_str()) } } @@ -383,12 +377,12 @@ mod tests { let s = TokenStream { token_trees: vec![ tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { - text: "struct".into(), + sym: Symbol::intern("struct"), span: tt::TokenId(0), is_raw: tt::IdentIsRaw::No, })), tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { - text: "T".into(), + sym: Symbol::intern("T"), span: tt::TokenId(0), is_raw: tt::IdentIsRaw::No, })), @@ -416,7 +410,7 @@ mod tests { }, token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { is_raw: tt::IdentIsRaw::No, - text: "a".into(), + sym: Symbol::intern("a"), span: tt::TokenId(0), }))]), }); @@ -433,7 +427,7 @@ mod tests { assert_eq!( underscore.token_trees[0], tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { - text: "_".into(), + sym: Symbol::intern("_"), span: tt::TokenId(0), is_raw: tt::IdentIsRaw::No, })) diff --git a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml index 35e39229894f2..f9565721dd5f9 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml @@ -16,6 +16,7 @@ base-db.workspace = true rustc-hash.workspace = true span.workspace = true stdx.workspace = true +intern.workspace = true [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index e65186d377151..7a0c474b750b6 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -13,6 +13,7 @@ use hir_expand::{ ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacros, }, }; +use intern::Symbol; use rustc_hash::FxHashMap; use span::{Edition, FileId, FilePosition, FileRange, Span}; use test_utils::{ @@ -640,11 +641,11 @@ impl ProcMacroExpander for ShortenProcMacroExpander { Leaf::Literal(it) => { // XXX Currently replaces any literals with an empty string, but supporting // "shortening" other literals would be nice. - it.text = "\"\"".into(); + it.symbol = Symbol::empty(); } Leaf::Punct(_) => {} Leaf::Ident(it) => { - it.text = it.text.chars().take(1).collect(); + it.sym = Symbol::intern(&it.sym.as_str().chars().take(1).collect::()); } } leaf diff --git a/src/tools/rust-analyzer/crates/tt/Cargo.toml b/src/tools/rust-analyzer/crates/tt/Cargo.toml index 1900635b995ee..cea1519c2dd46 100644 --- a/src/tools/rust-analyzer/crates/tt/Cargo.toml +++ b/src/tools/rust-analyzer/crates/tt/Cargo.toml @@ -13,10 +13,10 @@ doctest = false [dependencies] arrayvec.workspace = true -smol_str.workspace = true text-size.workspace = true stdx.workspace = true +intern.workspace = true ra-ap-rustc_lexer.workspace = true [features] diff --git a/src/tools/rust-analyzer/crates/tt/src/iter.rs b/src/tools/rust-analyzer/crates/tt/src/iter.rs index 175259a3e4719..c0195b835ac6c 100644 --- a/src/tools/rust-analyzer/crates/tt/src/iter.rs +++ b/src/tools/rust-analyzer/crates/tt/src/iter.rs @@ -2,6 +2,7 @@ //! macro definition into a list of patterns and templates. use arrayvec::ArrayVec; +use intern::sym; use crate::{Ident, Leaf, Punct, Spacing, Subtree, TokenTree}; @@ -58,7 +59,7 @@ impl<'a, S: Copy> TtIter<'a, S> { pub fn expect_ident(&mut self) -> Result<&'a Ident, ()> { match self.expect_leaf()? { - Leaf::Ident(it) if it.text != "_" => Ok(it), + Leaf::Ident(it) if it.sym != sym::underscore => Ok(it), _ => Err(()), } } @@ -74,7 +75,7 @@ impl<'a, S: Copy> TtIter<'a, S> { let it = self.expect_leaf()?; match it { Leaf::Literal(_) => Ok(it), - Leaf::Ident(ident) if ident.text == "true" || ident.text == "false" => Ok(it), + Leaf::Ident(ident) if ident.sym == sym::true_ || ident.sym == sym::false_ => Ok(it), _ => Err(()), } } diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs index c328b3f8a3cc8..7b72f9ff108d3 100644 --- a/src/tools/rust-analyzer/crates/tt/src/lib.rs +++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs @@ -14,16 +14,16 @@ pub mod iter; use std::fmt; +use intern::Symbol; use stdx::{impl_from, itertools::Itertools as _}; -pub use smol_str::{format_smolstr, SmolStr}; pub use text_size::{TextRange, TextSize}; #[derive(Clone, PartialEq, Debug)] pub struct Lit { pub kind: LitKind, - pub symbol: SmolStr, - pub suffix: Option, + pub symbol: Symbol, + pub suffix: Option, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -35,6 +35,9 @@ impl IdentIsRaw { pub fn yes(self) -> bool { matches!(self, IdentIsRaw::Yes) } + pub fn no(&self) -> bool { + matches!(self, IdentIsRaw::No) + } pub fn as_str(self) -> &'static str { match self { IdentIsRaw::No => "", @@ -197,25 +200,30 @@ pub enum DelimiterKind { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Literal { // escaped - pub text: SmolStr, + pub symbol: Symbol, pub span: S, pub kind: LitKind, - pub suffix: Option>, + pub suffix: Option, } -pub fn token_to_literal(text: SmolStr, span: S) -> Literal +pub fn token_to_literal(text: &str, span: S) -> Literal where S: Copy, { use rustc_lexer::LiteralKind; - let token = rustc_lexer::tokenize(&text).next_tuple(); + let token = rustc_lexer::tokenize(text).next_tuple(); let Some((rustc_lexer::Token { kind: rustc_lexer::TokenKind::Literal { kind, suffix_start }, .. },)) = token else { - return Literal { span, text, kind: LitKind::Err(()), suffix: None }; + return Literal { + span, + symbol: Symbol::intern(text), + kind: LitKind::Err(()), + suffix: None, + }; }; let (kind, start_offset, end_offset) = match kind { @@ -247,10 +255,10 @@ where let lit = &lit[start_offset..lit.len() - end_offset]; let suffix = match suffix { "" | "_" => None, - suffix => Some(Box::new(suffix.into())), + suffix => Some(Symbol::intern(suffix)), }; - Literal { span, text: lit.into(), kind, suffix } + Literal { span, symbol: Symbol::intern(lit), kind, suffix } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -323,22 +331,16 @@ pub enum Spacing { /// Identifier or keyword. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Ident { - pub text: SmolStr, + pub sym: Symbol, pub span: S, pub is_raw: IdentIsRaw, } impl Ident { - pub fn new(text: impl Into + AsRef, span: S) -> Self { - let t = text.as_ref(); + pub fn new(text: &str, span: S) -> Self { // let raw_stripped = IdentIsRaw::split_from_symbol(text.as_ref()); - let raw_stripped = t.strip_prefix("r#"); - let is_raw = if raw_stripped.is_none() { IdentIsRaw::No } else { IdentIsRaw::Yes }; - let text = match raw_stripped { - Some(derawed) => derawed.into(), - None => text.into(), - }; - Ident { text, span, is_raw } + let (is_raw, text) = IdentIsRaw::split_from_symbol(text); + Ident { sym: Symbol::intern(text), span, is_raw } } } @@ -389,8 +391,8 @@ fn print_debug_token( "{}LITERAL {:?} {}{} {:#?}", align, lit.kind, - lit.text, - lit.suffix.as_ref().map(|it| &***it).unwrap_or(""), + lit.symbol, + lit.suffix.as_ref().map(|it| it.as_str()).unwrap_or(""), lit.span )?; } @@ -410,7 +412,7 @@ fn print_debug_token( "{}IDENT {}{} {:#?}", align, ident.is_raw.as_str(), - ident.text, + ident.sym, ident.span )?; } @@ -479,26 +481,26 @@ impl fmt::Display for Leaf { impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.is_raw.as_str(), f)?; - fmt::Display::fmt(&self.text, f) + fmt::Display::fmt(&self.sym, f) } } impl fmt::Display for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { - LitKind::Byte => write!(f, "b'{}'", self.text), - LitKind::Char => write!(f, "'{}'", self.text), - LitKind::Integer | LitKind::Float | LitKind::Err(_) => write!(f, "{}", self.text), - LitKind::Str => write!(f, "\"{}\"", self.text), - LitKind::ByteStr => write!(f, "b\"{}\"", self.text), - LitKind::CStr => write!(f, "c\"{}\"", self.text), + LitKind::Byte => write!(f, "b'{}'", self.symbol), + LitKind::Char => write!(f, "'{}'", self.symbol), + LitKind::Integer | LitKind::Float | LitKind::Err(_) => write!(f, "{}", self.symbol), + LitKind::Str => write!(f, "\"{}\"", self.symbol), + LitKind::ByteStr => write!(f, "b\"{}\"", self.symbol), + LitKind::CStr => write!(f, "c\"{}\"", self.symbol), LitKind::StrRaw(num_of_hashes) => { let num_of_hashes = num_of_hashes as usize; write!( f, r#"r{0:# { @@ -507,7 +509,7 @@ impl fmt::Display for Literal { f, r#"br{0:# { @@ -516,7 +518,7 @@ impl fmt::Display for Literal { f, r#"cr{0:# Subtree { let s = match child { TokenTree::Leaf(it) => { let s = match it { - Leaf::Literal(it) => it.text.to_string(), + Leaf::Literal(it) => it.symbol.to_string(), Leaf::Punct(it) => it.char.to_string(), - Leaf::Ident(it) => format!("{}{}", it.is_raw.as_str(), it.text), + Leaf::Ident(it) => format!("{}{}", it.is_raw.as_str(), it.sym), }; match (it, last) { (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => { @@ -599,9 +601,9 @@ pub fn pretty(tkns: &[TokenTree]) -> String { fn tokentree_to_text(tkn: &TokenTree) -> String { match tkn { TokenTree::Leaf(Leaf::Ident(ident)) => { - format!("{}{}", ident.is_raw.as_str(), ident.text) + format!("{}{}", ident.is_raw.as_str(), ident.sym) } - TokenTree::Leaf(Leaf::Literal(literal)) => literal.text.clone().into(), + TokenTree::Leaf(Leaf::Literal(literal)) => literal.symbol.as_str().to_owned(), TokenTree::Leaf(Leaf::Punct(punct)) => format!("{}", punct.char), TokenTree::Subtree(subtree) => { let content = pretty(&subtree.token_trees); From 9ce066e6faa1bfcec7792a0fae4231a5bd7a5a56 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 16 Jul 2024 10:36:59 +0200 Subject: [PATCH 031/489] Use symbol in cfg --- src/tools/rust-analyzer/Cargo.lock | 4 +- src/tools/rust-analyzer/Cargo.toml | 2 +- src/tools/rust-analyzer/crates/cfg/Cargo.toml | 4 +- .../rust-analyzer/crates/cfg/src/cfg_expr.rs | 39 +++++++++++-------- src/tools/rust-analyzer/crates/cfg/src/dnf.rs | 19 +++++++-- src/tools/rust-analyzer/crates/cfg/src/lib.rs | 16 ++++---- .../rust-analyzer/crates/cfg/src/tests.rs | 26 +++++++------ .../crates/hir-expand/src/builtin_fn_macro.rs | 7 +++- .../crates/hir-expand/src/cfg_process.rs | 25 +++++++----- .../src/completions/attribute/cfg.rs | 2 + src/tools/rust-analyzer/crates/ide/src/lib.rs | 4 +- .../rust-analyzer/crates/ide/src/runnables.rs | 4 +- .../rust-analyzer/crates/intern/src/symbol.rs | 8 +++- .../crates/intern/src/symbol/symbols.rs | 29 ++++++++------ .../crates/project-model/Cargo.toml | 1 + .../crates/project-model/src/cfg.rs | 7 +++- .../crates/project-model/src/tests.rs | 5 ++- .../crates/project-model/src/workspace.rs | 21 +++++----- .../crates/rust-analyzer/Cargo.toml | 1 + .../crates/rust-analyzer/src/config.rs | 8 +++- .../crates/rust-analyzer/src/target_spec.rs | 3 +- .../crates/test-fixture/src/lib.rs | 4 +- 22 files changed, 147 insertions(+), 92 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 241392edb1e5d..c9542ead79070 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -146,10 +146,10 @@ dependencies = [ "arbitrary", "derive_arbitrary", "expect-test", + "intern", "mbe", "oorandom", "rustc-hash", - "smol_str", "syntax", "tt", ] @@ -1416,6 +1416,7 @@ dependencies = [ "cargo_metadata", "cfg", "expect-test", + "intern", "itertools", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "paths", @@ -1656,6 +1657,7 @@ dependencies = [ "ide", "ide-db", "ide-ssr", + "intern", "itertools", "load-cargo", "lsp-server 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index d4c3b7a3bfbd2..428d11ad60d48 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -50,7 +50,7 @@ debug = 2 [workspace.dependencies] # local crates base-db = { path = "./crates/base-db", version = "0.0.0" } -cfg = { path = "./crates/cfg", version = "0.0.0" } +cfg = { path = "./crates/cfg", version = "0.0.0", features = ["tt"] } flycheck = { path = "./crates/flycheck", version = "0.0.0" } hir = { path = "./crates/hir", version = "0.0.0" } hir-def = { path = "./crates/hir-def", version = "0.0.0" } diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml index 784e86649d1ab..faf93f62c6afb 100644 --- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml +++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml @@ -15,8 +15,8 @@ doctest = false rustc-hash.workspace = true # locals deps -tt.workspace = true -smol_str.workspace = true +tt = { workspace = true, optional = true } +intern.workspace = true [dev-dependencies] expect-test = "1.4.1" diff --git a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs index 9c95f0e4e4baa..e4c2a28fb0607 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs @@ -2,20 +2,20 @@ //! //! See: -use std::{fmt, slice::Iter as SliceIter}; +use std::fmt; -use smol_str::SmolStr; +use intern::Symbol; /// A simple configuration value passed in from the outside. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum CfgAtom { /// eg. `#[cfg(test)]` - Flag(SmolStr), + Flag(Symbol), /// eg. `#[cfg(target_os = "linux")]` /// /// Note that a key can have multiple values that are all considered "active" at the same time. /// For example, `#[cfg(target_feature = "sse")]` and `#[cfg(target_feature = "sse2")]`. - KeyValue { key: SmolStr, value: SmolStr }, + KeyValue { key: Symbol, value: Symbol }, } impl fmt::Display for CfgAtom { @@ -44,6 +44,7 @@ impl From for CfgExpr { } impl CfgExpr { + #[cfg(feature = "tt")] pub fn parse(tt: &tt::Subtree) -> CfgExpr { next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid) } @@ -63,7 +64,11 @@ impl CfgExpr { } } } -fn next_cfg_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option { + +#[cfg(feature = "tt")] +fn next_cfg_expr(it: &mut std::slice::Iter<'_, tt::TokenTree>) -> Option { + use intern::sym; + let name = match it.next() { None => return None, Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(), @@ -77,9 +82,7 @@ fn next_cfg_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option Some(tt::TokenTree::Leaf(tt::Leaf::Literal(literal))) => { it.next(); it.next(); - // FIXME: escape? - let value = literal.symbol.as_str().into(); - CfgAtom::KeyValue { key: name.as_str().into(), value }.into() + CfgAtom::KeyValue { key: name, value: literal.symbol.clone() }.into() } _ => return Some(CfgExpr::Invalid), } @@ -88,14 +91,16 @@ fn next_cfg_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option it.next(); let mut sub_it = subtree.token_trees.iter(); let mut subs = std::iter::from_fn(|| next_cfg_expr(&mut sub_it)).collect(); - match name.as_str() { - "all" => CfgExpr::All(subs), - "any" => CfgExpr::Any(subs), - "not" => CfgExpr::Not(Box::new(subs.pop().unwrap_or(CfgExpr::Invalid))), + match &name { + s if *s == sym::all => CfgExpr::All(subs), + s if *s == sym::any => CfgExpr::Any(subs), + s if *s == sym::not => { + CfgExpr::Not(Box::new(subs.pop().unwrap_or(CfgExpr::Invalid))) + } _ => CfgExpr::Invalid, } } - _ => CfgAtom::Flag(name.as_str().into()).into(), + _ => CfgAtom::Flag(name).into(), }; // Eat comma separator @@ -111,11 +116,11 @@ fn next_cfg_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option impl arbitrary::Arbitrary<'_> for CfgAtom { fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result { if u.arbitrary()? { - Ok(CfgAtom::Flag(String::arbitrary(u)?.into())) + Ok(CfgAtom::Flag(Symbol::intern(<_>::arbitrary(u)?))) } else { Ok(CfgAtom::KeyValue { - key: String::arbitrary(u)?.into(), - value: String::arbitrary(u)?.into(), + key: Symbol::intern(<_>::arbitrary(u)?), + value: Symbol::intern(<_>::arbitrary(u)?), }) } } diff --git a/src/tools/rust-analyzer/crates/cfg/src/dnf.rs b/src/tools/rust-analyzer/crates/cfg/src/dnf.rs index fd80e1ebe683b..58a250829d4f1 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/dnf.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/dnf.rs @@ -66,9 +66,9 @@ impl DnfExpr { } } - res.enabled.sort_unstable(); + res.enabled.sort_unstable_by(compare); res.enabled.dedup(); - res.disabled.sort_unstable(); + res.disabled.sort_unstable_by(compare); res.disabled.dedup(); Some(res) } @@ -114,14 +114,25 @@ impl DnfExpr { }; // Undo the FxHashMap randomization for consistent output. - diff.enable.sort_unstable(); - diff.disable.sort_unstable(); + diff.enable.sort_unstable_by(compare); + diff.disable.sort_unstable_by(compare); Some(diff) }) } } +fn compare(a: &CfgAtom, b: &CfgAtom) -> std::cmp::Ordering { + match (a, b) { + (CfgAtom::Flag(a), CfgAtom::Flag(b)) => a.as_str().cmp(b.as_str()), + (CfgAtom::Flag(_), CfgAtom::KeyValue { .. }) => std::cmp::Ordering::Less, + (CfgAtom::KeyValue { .. }, CfgAtom::Flag(_)) => std::cmp::Ordering::Greater, + (CfgAtom::KeyValue { key, value }, CfgAtom::KeyValue { key: key2, value: value2 }) => { + key.as_str().cmp(key2.as_str()).then(value.as_str().cmp(value2.as_str())) + } + } +} + impl fmt::Display for DnfExpr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.conjunctions.len() != 1 { diff --git a/src/tools/rust-analyzer/crates/cfg/src/lib.rs b/src/tools/rust-analyzer/crates/cfg/src/lib.rs index 5ef7a104dda59..6d46dfb99949b 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/lib.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/lib.rs @@ -9,9 +9,10 @@ use std::fmt; use rustc_hash::FxHashSet; +use intern::Symbol; + pub use cfg_expr::{CfgAtom, CfgExpr}; pub use dnf::DnfExpr; -use smol_str::SmolStr; /// Configuration options used for conditional compilation on items with `cfg` attributes. /// We have two kind of options in different namespaces: atomic options like `unix`, and @@ -48,11 +49,11 @@ impl CfgOptions { cfg.fold(&|atom| self.enabled.contains(atom)) } - pub fn insert_atom(&mut self, key: SmolStr) { + pub fn insert_atom(&mut self, key: Symbol) { self.enabled.insert(CfgAtom::Flag(key)); } - pub fn insert_key_value(&mut self, key: SmolStr, value: SmolStr) { + pub fn insert_key_value(&mut self, key: Symbol, value: Symbol) { self.enabled.insert(CfgAtom::KeyValue { key, value }); } @@ -66,19 +67,16 @@ impl CfgOptions { } } - pub fn get_cfg_keys(&self) -> impl Iterator { + pub fn get_cfg_keys(&self) -> impl Iterator { self.enabled.iter().map(|it| match it { CfgAtom::Flag(key) => key, CfgAtom::KeyValue { key, .. } => key, }) } - pub fn get_cfg_values<'a>( - &'a self, - cfg_key: &'a str, - ) -> impl Iterator + 'a { + pub fn get_cfg_values<'a>(&'a self, cfg_key: &'a str) -> impl Iterator + 'a { self.enabled.iter().filter_map(move |it| match it { - CfgAtom::KeyValue { key, value } if cfg_key == key => Some(value), + CfgAtom::KeyValue { key, value } if cfg_key == key.as_str() => Some(value), _ => None, }) } diff --git a/src/tools/rust-analyzer/crates/cfg/src/tests.rs b/src/tools/rust-analyzer/crates/cfg/src/tests.rs index dddaf2cce1823..278e5f61de251 100644 --- a/src/tools/rust-analyzer/crates/cfg/src/tests.rs +++ b/src/tools/rust-analyzer/crates/cfg/src/tests.rs @@ -1,5 +1,6 @@ use arbitrary::{Arbitrary, Unstructured}; use expect_test::{expect, Expect}; +use intern::Symbol; use mbe::{syntax_node_to_token_tree, DocCommentDesugarMode, DummyTestSpanMap, DUMMY}; use syntax::{ast, AstNode, Edition}; @@ -65,22 +66,25 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) { #[test] fn test_cfg_expr_parser() { - assert_parse_result("#![cfg(foo)]", CfgAtom::Flag("foo".into()).into()); - assert_parse_result("#![cfg(foo,)]", CfgAtom::Flag("foo".into()).into()); + assert_parse_result("#![cfg(foo)]", CfgAtom::Flag(Symbol::intern("foo")).into()); + assert_parse_result("#![cfg(foo,)]", CfgAtom::Flag(Symbol::intern("foo")).into()); assert_parse_result( "#![cfg(not(foo))]", - CfgExpr::Not(Box::new(CfgAtom::Flag("foo".into()).into())), + CfgExpr::Not(Box::new(CfgAtom::Flag(Symbol::intern("foo")).into())), ); assert_parse_result("#![cfg(foo(bar))]", CfgExpr::Invalid); // Only take the first - assert_parse_result(r#"#![cfg(foo, bar = "baz")]"#, CfgAtom::Flag("foo".into()).into()); + assert_parse_result( + r#"#![cfg(foo, bar = "baz")]"#, + CfgAtom::Flag(Symbol::intern("foo")).into(), + ); assert_parse_result( r#"#![cfg(all(foo, bar = "baz"))]"#, CfgExpr::All(vec![ - CfgAtom::Flag("foo".into()).into(), - CfgAtom::KeyValue { key: "bar".into(), value: "baz".into() }.into(), + CfgAtom::Flag(Symbol::intern("foo")).into(), + CfgAtom::KeyValue { key: Symbol::intern("bar"), value: Symbol::intern("baz") }.into(), ]), ); @@ -90,7 +94,7 @@ fn test_cfg_expr_parser() { CfgExpr::Not(Box::new(CfgExpr::Invalid)), CfgExpr::All(vec![]), CfgExpr::Invalid, - CfgAtom::KeyValue { key: "bar".into(), value: "baz".into() }.into(), + CfgAtom::KeyValue { key: Symbol::intern("bar"), value: Symbol::intern("baz") }.into(), ]), ); } @@ -167,7 +171,7 @@ fn hints() { check_enable_hints("#![cfg(all(a, b))]", &opts, &["enable a and b"]); - opts.insert_atom("test".into()); + opts.insert_atom(Symbol::intern("test")); check_enable_hints("#![cfg(test)]", &opts, &[]); check_enable_hints("#![cfg(not(test))]", &opts, &["disable test"]); @@ -180,7 +184,7 @@ fn hints_impossible() { check_enable_hints("#![cfg(all(test, not(test)))]", &opts, &[]); - opts.insert_atom("test".into()); + opts.insert_atom(Symbol::intern("test")); check_enable_hints("#![cfg(all(test, not(test)))]", &opts, &[]); } @@ -188,8 +192,8 @@ fn hints_impossible() { #[test] fn why_inactive() { let mut opts = CfgOptions::default(); - opts.insert_atom("test".into()); - opts.insert_atom("test2".into()); + opts.insert_atom(Symbol::intern("test")); + opts.insert_atom(Symbol::intern("test2")); check_why_inactive("#![cfg(a)]", &opts, expect![["a is disabled"]]); check_why_inactive("#![cfg(not(test))]", &opts, expect![["test is enabled"]]); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs index 4b1a3d697280c..e3290f53432b6 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs @@ -563,7 +563,12 @@ fn concat_bytes_expand( }; for (i, t) in tt.token_trees.iter().enumerate() { match t { - tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { symbol: text, span, kind, suffix: _ })) => { + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + symbol: text, + span, + kind, + suffix: _, + })) => { record_span(*span); match kind { tt::LitKind::Byte => { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs index 5f038cfe6871d..9f927184193e9 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs @@ -3,6 +3,7 @@ use std::iter::Peekable; use base_db::CrateId; use cfg::{CfgAtom, CfgExpr}; +use intern::{sym, Symbol}; use rustc_hash::FxHashSet; use syntax::{ ast::{self, Attr, HasAttrs, Meta, VariantList}, @@ -262,13 +263,13 @@ where let name = match iter.next() { None => return None, Some(NodeOrToken::Token(element)) => match element.kind() { - syntax::T![ident] => element.text().to_owned(), + syntax::T![ident] => Symbol::intern(element.text()), _ => return Some(CfgExpr::Invalid), }, Some(_) => return Some(CfgExpr::Invalid), }; - let result = match name.as_str() { - "all" | "any" | "not" => { + let result = match &name { + s if [&sym::all, &sym::any, &sym::not].contains(&s) => { let mut preds = Vec::new(); let Some(NodeOrToken::Node(tree)) = iter.next() else { return Some(CfgExpr::Invalid); @@ -285,10 +286,12 @@ where preds.push(pred); } } - let group = match name.as_str() { - "all" => CfgExpr::All(preds), - "any" => CfgExpr::Any(preds), - "not" => CfgExpr::Not(Box::new(preds.pop().unwrap_or(CfgExpr::Invalid))), + let group = match &name { + s if *s == sym::all => CfgExpr::All(preds), + s if *s == sym::any => CfgExpr::Any(preds), + s if *s == sym::not => { + CfgExpr::Not(Box::new(preds.pop().unwrap_or(CfgExpr::Invalid))) + } _ => unreachable!(), }; Some(group) @@ -301,13 +304,15 @@ where if (value_token.kind() == syntax::SyntaxKind::STRING) => { let value = value_token.text(); - let value = value.trim_matches('"').into(); - Some(CfgExpr::Atom(CfgAtom::KeyValue { key: name.into(), value })) + Some(CfgExpr::Atom(CfgAtom::KeyValue { + key: name, + value: Symbol::intern(value.trim_matches('"')), + })) } _ => None, } } - _ => Some(CfgExpr::Atom(CfgAtom::Flag(name.into()))), + _ => Some(CfgExpr::Atom(CfgAtom::Flag(name))), }, }; if let Some(NodeOrToken::Token(element)) = iter.peek() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs index 87a286778e631..6e7d50ede066e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs @@ -39,6 +39,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) { "target_vendor" => KNOWN_VENDOR.iter().copied().for_each(add_completion), "target_endian" => ["little", "big"].into_iter().for_each(add_completion), name => ctx.krate.potential_cfg(ctx.db).get_cfg_values(name).cloned().for_each(|s| { + let s = s.as_str(); let insert_text = format!(r#""{s}""#); let mut item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s); item.insert_text(insert_text); @@ -47,6 +48,7 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext<'_>) { }), }, None => ctx.krate.potential_cfg(ctx.db).get_cfg_keys().cloned().unique().for_each(|s| { + let s = s.as_str(); let item = CompletionItem::new(SymbolKind::BuiltinAttr, ctx.source_range(), s); acc.add(item.build(ctx.db)); }), diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index f0b35903f38de..a7073f7062e3e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -62,7 +62,7 @@ use std::panic::UnwindSafe; use cfg::CfgOptions; use fetch_crates::CrateInfo; -use hir::ChangeWithProcMacros; +use hir::{sym, ChangeWithProcMacros}; use ide_db::{ base_db::{ salsa::{self, ParallelDatabase}, @@ -248,7 +248,7 @@ impl Analysis { // FIXME: cfg options // Default to enable test for single file. let mut cfg_options = CfgOptions::default(); - cfg_options.insert_atom("test".into()); + cfg_options.insert_atom(sym::test.clone()); crate_graph.add_crate_root( file_id, Edition::CURRENT, diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index a68ee4f8671f1..362d3238a9aa3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -3,7 +3,7 @@ use std::fmt; use ast::HasName; use cfg::{CfgAtom, CfgExpr}; use hir::{ - db::HirDatabase, AsAssocItem, AttrsWithOwner, HasAttrs, HasSource, HirFileIdExt, Semantics, + db::HirDatabase, sym, AsAssocItem, AttrsWithOwner, HasAttrs, HasSource, HirFileIdExt, Semantics, }; use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn}; use ide_db::{ @@ -403,7 +403,7 @@ pub(crate) fn runnable_impl( } fn has_cfg_test(attrs: AttrsWithOwner) -> bool { - attrs.cfgs().any(|cfg| matches!(cfg, CfgExpr::Atom(CfgAtom::Flag(s)) if s == "test")) + attrs.cfgs().any(|cfg| matches!(&cfg, CfgExpr::Atom(CfgAtom::Flag(s)) if *s == sym::test)) } /// Creates a test mod runnable for outline modules at the top of their definition. diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs index 9e3f6d842f315..ef76192ba83ed 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs @@ -139,11 +139,17 @@ impl TaggedArcPtr { } } -#[derive(PartialEq, Eq, Hash, Debug)] +#[derive(PartialEq, Eq, Hash)] pub struct Symbol { repr: TaggedArcPtr, } +impl fmt::Debug for Symbol { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_str().fmt(f) + } +} + const _: () = assert!(std::mem::size_of::() == std::mem::size_of::>()); const _: () = assert!(std::mem::align_of::() == std::mem::align_of::>()); diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 61b9d099e06a3..04c70e4fae188 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -93,20 +93,20 @@ define_symbols! { __ra_fixup, add_assign, add, - attributes, align_offset, + align, + all, alloc_layout, alloc, + any, as_str, asm, assert, + attributes, begin_panic, bench, bitand_assign, bitand, - notable_trait, - hidden, - local_inner_macros, bitor_assign, bitor, bitxor_assign, @@ -118,6 +118,7 @@ define_symbols! { branch, Break, c_void, + C, call_mut, call_once, call, @@ -146,8 +147,10 @@ define_symbols! { core, coroutine_state, coroutine, + count, crate_type, CStr, + debug_assertions, Debug, default, Default, @@ -172,6 +175,7 @@ define_symbols! { Eq, Err, exchange_malloc, + exhaustive_patterns, f128, f16, f32, @@ -208,11 +212,13 @@ define_symbols! { global_asm, gt, Hash, + hidden, i128, i16, i32, i64, i8, + ignore, Implied, include_bytes, include_str, @@ -237,14 +243,15 @@ define_symbols! { len, line, llvm_asm, + local_inner_macros, log_syntax, lt, macro_rules, - ignore, - count, manually_drop, maybe_uninit, metadata_type, + min_exhaustive_patterns, + miri, missing, module_path, mul_assign, @@ -271,6 +278,7 @@ define_symbols! { None, not, Not, + notable_trait, Ok, opaque, ops, @@ -280,6 +288,7 @@ define_symbols! { Ord, Output, owned_box, + packed, panic_2015, panic_2021, panic_bounds_check, @@ -328,6 +337,7 @@ define_symbols! { rust_2018, rust_2021, rust_2024, + rust_analyzer, rustc_coherence_is_core, rustc_macro_transparency, semitransparent, @@ -335,6 +345,7 @@ define_symbols! { shl, shr_assign, shr, + simd, sized, slice_len_fn, Some, @@ -367,10 +378,6 @@ define_symbols! { u8, Unknown, unpin, - simd, - C, - align, - packed, unreachable_2015, unreachable_2021, unreachable, @@ -378,7 +385,5 @@ define_symbols! { unsize, usize, v1, - exhaustive_patterns, - min_exhaustive_patterns, va_list } diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml index 097ee1f75cd75..8b34bd3fad1a1 100644 --- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml +++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml @@ -25,6 +25,7 @@ itertools.workspace = true # local deps base-db.workspace = true +intern.workspace = true span.workspace = true cfg.workspace = true paths = { workspace = true, features = ["serde1"] } diff --git a/src/tools/rust-analyzer/crates/project-model/src/cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/cfg.rs index b409bc1ce7ad1..e921e3de722d1 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cfg.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cfg.rs @@ -4,6 +4,7 @@ use std::{fmt, str::FromStr}; use cfg::{CfgDiff, CfgOptions}; +use intern::Symbol; use rustc_hash::FxHashMap; use serde::Serialize; @@ -44,8 +45,10 @@ impl Extend for CfgOptions { fn extend>(&mut self, iter: T) { for cfg_flag in iter { match cfg_flag { - CfgFlag::Atom(it) => self.insert_atom(it.into()), - CfgFlag::KeyValue { key, value } => self.insert_key_value(key.into(), value.into()), + CfgFlag::Atom(it) => self.insert_atom(Symbol::intern(&it)), + CfgFlag::KeyValue { key, value } => { + self.insert_key_value(Symbol::intern(&key), Symbol::intern(&value)) + } } } } diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 2762de5997ae9..8d50d4bdfe2c2 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -4,6 +4,7 @@ use base_db::{CrateGraph, FileId, ProcMacroPaths}; use cargo_metadata::Metadata; use cfg::{CfgAtom, CfgDiff}; use expect_test::{expect_file, ExpectFile}; +use intern::sym; use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf}; use rustc_hash::FxHashMap; use serde::de::DeserializeOwned; @@ -180,7 +181,7 @@ fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) { #[test] fn cargo_hello_world_project_model_with_wildcard_overrides() { let cfg_overrides = CfgOverrides { - global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag("test".into())]).unwrap(), + global: CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]).unwrap(), selective: Default::default(), }; let (crate_graph, _proc_macros) = @@ -199,7 +200,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() { global: Default::default(), selective: std::iter::once(( "libc".to_owned(), - CfgDiff::new(Vec::new(), vec![CfgAtom::Flag("test".into())]).unwrap(), + CfgDiff::new(Vec::new(), vec![CfgAtom::Flag(sym::test.clone())]).unwrap(), )) .collect(), }; diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 5e27ce298735e..e006b70362e99 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -10,6 +10,7 @@ use base_db::{ LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult, }; use cfg::{CfgAtom, CfgDiff, CfgOptions}; +use intern::{sym, Symbol}; use paths::{AbsPath, AbsPathBuf}; use rustc_hash::{FxHashMap, FxHashSet}; use semver::Version; @@ -977,8 +978,8 @@ fn cargo_to_crate_graph( if cargo[pkg].is_local { // Add test cfg for local crates - cfg_options.insert_atom("test".into()); - cfg_options.insert_atom("rust_analyzer".into()); + cfg_options.insert_atom(sym::test.clone()); + cfg_options.insert_atom(sym::rust_analyzer.clone()); } override_cfg.apply(&mut cfg_options, &cargo[pkg].name); @@ -1144,8 +1145,8 @@ fn detached_file_to_crate_graph( sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load); let mut cfg_options = CfgOptions::from_iter(rustc_cfg); - cfg_options.insert_atom("test".into()); - cfg_options.insert_atom("rust_analyzer".into()); + cfg_options.insert_atom(sym::test.clone()); + cfg_options.insert_atom(sym::rust_analyzer.clone()); override_cfg.apply(&mut cfg_options, ""); let cfg_options = Arc::new(cfg_options); @@ -1307,7 +1308,7 @@ fn add_target_crate_root( let cfg_options = { let mut opts = cfg_options; for feature in pkg.active_features.iter() { - opts.insert_key_value("feature".into(), feature.into()); + opts.insert_key_value(sym::feature.clone(), Symbol::intern(feature)); } if let Some(cfgs) = build_data.as_ref().map(|it| &it.cfgs) { opts.extend(cfgs.iter().cloned()); @@ -1381,8 +1382,8 @@ fn sysroot_to_crate_graph( &CfgOverrides { global: CfgDiff::new( vec![ - CfgAtom::Flag("debug_assertions".into()), - CfgAtom::Flag("miri".into()), + CfgAtom::Flag(sym::debug_assertions.clone()), + CfgAtom::Flag(sym::miri.clone()), ], vec![], ) @@ -1394,7 +1395,7 @@ fn sysroot_to_crate_graph( let mut pub_deps = vec![]; let mut libproc_macro = None; - let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag("test".into())]).unwrap(); + let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]).unwrap(); for (cid, c) in cg.iter_mut() { // uninject `test` flag so `core` keeps working. Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone()); @@ -1449,8 +1450,8 @@ fn sysroot_to_crate_graph( let cfg_options = Arc::new({ let mut cfg_options = CfgOptions::default(); cfg_options.extend(rustc_cfg); - cfg_options.insert_atom("debug_assertions".into()); - cfg_options.insert_atom("miri".into()); + cfg_options.insert_atom(sym::debug_assertions.clone()); + cfg_options.insert_atom(sym::miri.clone()); cfg_options }); let sysroot_crates: FxHashMap = stitched diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index 93fb55ede8ea2..bc1b13a649700 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -54,6 +54,7 @@ hir-def.workspace = true hir-ty.workspace = true hir.workspace = true ide-db.workspace = true +intern.workspace = true # This should only be used in CLI ide-ssr.workspace = true ide.workspace = true diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 91cde4dc0adbb..a0ec3920e6e29 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -8,6 +8,7 @@ use std::{fmt, iter, ops::Not, sync::OnceLock}; use cfg::{CfgAtom, CfgDiff}; use dirs::config_dir; use flycheck::{CargoOptions, FlycheckConfig}; +use hir::Symbol; use ide::{ AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode, GenericParameterHints, HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, @@ -1691,8 +1692,11 @@ impl Config { self.cargo_cfgs() .iter() .map(|(key, val)| match val { - Some(val) => CfgAtom::KeyValue { key: key.into(), value: val.into() }, - None => CfgAtom::Flag(key.into()), + Some(val) => CfgAtom::KeyValue { + key: Symbol::intern(key), + value: Symbol::intern(val), + }, + None => CfgAtom::Flag(Symbol::intern(key)), }) .collect(), vec![], diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs index 863ff06439961..045b9e4198a64 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs @@ -3,6 +3,7 @@ use std::mem; use cfg::{CfgAtom, CfgExpr}; +use hir::sym; use ide::{Cancellable, CrateId, FileId, RunnableKind, TestId}; use project_model::project_json::Runnable; use project_model::{CargoFeatures, ManifestPath, TargetKind}; @@ -237,7 +238,7 @@ impl CargoTargetSpec { /// Fill minimal features needed fn required_features(cfg_expr: &CfgExpr, features: &mut Vec) { match cfg_expr { - CfgExpr::Atom(CfgAtom::KeyValue { key, value }) if key == "feature" => { + CfgExpr::Atom(CfgAtom::KeyValue { key, value }) if *key == sym::feature => { features.push(value.to_string()) } CfgExpr::All(preds) => { diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index 7a0c474b750b6..e910094c77232 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -481,9 +481,9 @@ impl FileMeta { let mut cfg = CfgOptions::default(); for (k, v) in f.cfgs { if let Some(v) = v { - cfg.insert_key_value(k.into(), v.into()); + cfg.insert_key_value(Symbol::intern(&k), Symbol::intern(&v)); } else { - cfg.insert_atom(k.into()); + cfg.insert_atom(Symbol::intern(&k)); } } From 1a20a0803f82446491be0fddfc142a90126bc15f Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 16 Jul 2024 12:05:16 +0200 Subject: [PATCH 032/489] More symbol usage --- src/tools/rust-analyzer/Cargo.lock | 1 + .../rust-analyzer/crates/base-db/Cargo.toml | 1 + .../rust-analyzer/crates/base-db/src/input.rs | 34 +++--- .../rust-analyzer/crates/hir-def/src/attr.rs | 100 +++++++++--------- .../crates/hir-def/src/body/lower.rs | 45 ++++---- .../crates/hir-def/src/body/scope.rs | 2 +- .../rust-analyzer/crates/hir-def/src/data.rs | 24 ++--- .../crates/hir-def/src/data/adt.rs | 12 +-- .../rust-analyzer/crates/hir-def/src/hir.rs | 31 +++--- .../crates/hir-def/src/hir/format_args.rs | 11 +- .../crates/hir-def/src/hir/type_ref.rs | 14 +-- .../crates/hir-def/src/item_tree.rs | 6 +- .../crates/hir-def/src/item_tree/lower.rs | 8 +- .../crates/hir-def/src/lang_item.rs | 5 +- .../crates/hir-def/src/nameres/collector.rs | 32 +++--- .../crates/hir-def/src/nameres/proc_macro.rs | 4 +- .../crates/hir-def/src/pretty.rs | 2 +- .../crates/hir-expand/src/attrs.rs | 10 +- .../hir-ty/src/diagnostics/decl_check.rs | 5 +- .../diagnostics/match_check/pat_analysis.rs | 2 +- .../crates/hir-ty/src/display.rs | 4 +- .../crates/hir-ty/src/inhabitedness.rs | 3 +- .../crates/hir-ty/src/layout/adt.rs | 6 +- .../rust-analyzer/crates/hir-ty/src/lib.rs | 78 +++++++------- .../rust-analyzer/crates/hir-ty/src/lower.rs | 4 +- .../crates/hir-ty/src/method_resolution.rs | 3 +- .../crates/hir-ty/src/mir/eval.rs | 2 +- .../crates/hir-ty/src/mir/eval/shim.rs | 22 ++-- .../crates/hir-ty/src/mir/lower.rs | 1 + .../rust-analyzer/crates/hir-ty/src/utils.rs | 7 +- .../rust-analyzer/crates/hir/src/display.rs | 3 +- src/tools/rust-analyzer/crates/hir/src/lib.rs | 14 +-- .../rust-analyzer/crates/hir/src/symbols.rs | 4 +- .../src/handlers/add_missing_match_arms.rs | 4 +- .../handlers/destructure_struct_binding.rs | 4 +- .../src/handlers/move_module_to_file.rs | 4 +- .../crates/ide-completion/src/context.rs | 6 +- .../crates/ide-completion/src/render.rs | 4 +- .../ide-completion/src/render/variant.rs | 4 +- .../crates/ide-db/src/documentation.rs | 8 +- .../rust-analyzer/crates/ide-db/src/search.rs | 6 +- .../rust-analyzer/crates/ide/src/doc_links.rs | 15 +-- .../crates/ide/src/fetch_crates.rs | 2 +- .../rust-analyzer/crates/ide/src/moniker.rs | 2 +- .../ide/src/syntax_highlighting/inject.rs | 6 +- .../crates/intern/src/symbol/symbols.rs | 91 ++++++++++++++-- .../crates/project-model/src/project_json.rs | 1 + .../crates/project-model/src/workspace.rs | 24 ++--- .../rust-analyzer/src/cli/analysis_stats.rs | 4 +- .../crates/test-fixture/src/lib.rs | 6 +- 50 files changed, 388 insertions(+), 303 deletions(-) diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index c9542ead79070..4ed4a45014191 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -70,6 +70,7 @@ name = "base-db" version = "0.0.0" dependencies = [ "cfg", + "intern", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lz4_flex", "rustc-hash", diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml index 4ab99fc33c466..1b1ee034cac2f 100644 --- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml +++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml @@ -27,6 +27,7 @@ stdx.workspace = true syntax.workspace = true vfs.workspace = true span.workspace = true +intern.workspace = true [lints] workspace = true diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 1d172ab9e40e3..41b7e271b0c4b 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -9,10 +9,10 @@ use std::{fmt, mem, ops}; use cfg::CfgOptions; +use intern::Symbol; use la_arena::{Arena, Idx, RawIdx}; use rustc_hash::{FxHashMap, FxHashSet}; use span::Edition; -use syntax::SmolStr; use triomphe::Arc; use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath}; @@ -99,8 +99,8 @@ impl fmt::Debug for CrateGraph { pub type CrateId = Idx; -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct CrateName(SmolStr); +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct CrateName(Symbol); impl CrateName { /// Creates a crate name, checking for dashes in the string provided. @@ -110,16 +110,16 @@ impl CrateName { if name.contains('-') { Err(name) } else { - Ok(Self(SmolStr::new(name))) + Ok(Self(Symbol::intern(name))) } } /// Creates a crate name, unconditionally replacing the dashes with underscores. pub fn normalize_dashes(name: &str) -> CrateName { - Self(SmolStr::new(name.replace('-', "_"))) + Self(Symbol::intern(&name.replace('-', "_"))) } - pub fn as_smol_str(&self) -> &SmolStr { + pub fn symbol(&self) -> &Symbol { &self.0 } } @@ -133,7 +133,7 @@ impl fmt::Display for CrateName { impl ops::Deref for CrateName { type Target = str; fn deref(&self) -> &str { - &self.0 + self.0.as_str() } } @@ -141,11 +141,11 @@ impl ops::Deref for CrateName { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum CrateOrigin { /// Crates that are from the rustc workspace. - Rustc { name: String }, + Rustc { name: Symbol }, /// Crates that are workspace members. - Local { repo: Option, name: Option }, + Local { repo: Option, name: Option }, /// Crates that are non member libraries. - Library { repo: Option, name: String }, + Library { repo: Option, name: Symbol }, /// Crates that are provided by the language, like std, core, proc-macro, ... Lang(LangCrateOrigin), } @@ -201,16 +201,16 @@ impl fmt::Display for LangCrateOrigin { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrateDisplayName { // The name we use to display various paths (with `_`). crate_name: CrateName, // The name as specified in Cargo.toml (with `-`). - canonical_name: String, + canonical_name: Symbol, } impl CrateDisplayName { - pub fn canonical_name(&self) -> &str { + pub fn canonical_name(&self) -> &Symbol { &self.canonical_name } pub fn crate_name(&self) -> &CrateName { @@ -220,7 +220,7 @@ impl CrateDisplayName { impl From for CrateDisplayName { fn from(crate_name: CrateName) -> CrateDisplayName { - let canonical_name = crate_name.to_string(); + let canonical_name = crate_name.0.clone(); CrateDisplayName { crate_name, canonical_name } } } @@ -239,9 +239,9 @@ impl ops::Deref for CrateDisplayName { } impl CrateDisplayName { - pub fn from_canonical_name(canonical_name: String) -> CrateDisplayName { - let crate_name = CrateName::normalize_dashes(&canonical_name); - CrateDisplayName { crate_name, canonical_name } + pub fn from_canonical_name(canonical_name: &str) -> CrateDisplayName { + let crate_name = CrateName::normalize_dashes(canonical_name); + CrateDisplayName { crate_name, canonical_name: Symbol::intern(canonical_name) } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 1a5ac96aa29bb..723d675347551 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -1,6 +1,6 @@ //! A higher level attributes based on TokenTree, with also some shortcuts. -use std::{borrow::Cow, hash::Hash, ops, slice::Iter as SliceIter}; +use std::{borrow::Cow, hash::Hash, ops, slice}; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; @@ -14,7 +14,7 @@ use la_arena::{ArenaMap, Idx, RawIdx}; use mbe::DelimiterKind; use syntax::{ ast::{self, HasAttrs}, - AstPtr, SmolStr, + AstPtr, }; use triomphe::Arc; @@ -121,12 +121,12 @@ impl Attrs { } impl Attrs { - pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { + pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'_> { AttrQuery { attrs: self, key } } pub fn cfg(&self) -> Option { - let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse); + let mut cfgs = self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse); let first = cfgs.next()?; match cfgs.next() { Some(second) => { @@ -138,7 +138,7 @@ impl Attrs { } pub fn cfgs(&self) -> impl Iterator + '_ { - self.by_key("cfg").tt_values().map(CfgExpr::parse) + self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse) } pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool { @@ -148,50 +148,50 @@ impl Attrs { } } - pub fn lang(&self) -> Option<&str> { - self.by_key("lang").string_value() + pub fn lang(&self) -> Option<&Symbol> { + self.by_key(&sym::lang).string_value() } pub fn lang_item(&self) -> Option { - self.by_key("lang").string_value().and_then(|it| LangItem::from_symbol(&Symbol::intern(it))) + self.by_key(&sym::lang).string_value().and_then(LangItem::from_symbol) } pub fn has_doc_hidden(&self) -> bool { - self.by_key("doc").tt_values().any(|tt| { + self.by_key(&sym::doc).tt_values().any(|tt| { tt.delimiter.kind == DelimiterKind::Parenthesis && matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::hidden) }) } pub fn has_doc_notable_trait(&self) -> bool { - self.by_key("doc").tt_values().any(|tt| { + self.by_key(&sym::doc).tt_values().any(|tt| { tt.delimiter.kind == DelimiterKind::Parenthesis && matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::notable_trait) }) } pub fn doc_exprs(&self) -> impl Iterator + '_ { - self.by_key("doc").tt_values().map(DocExpr::parse) + self.by_key(&sym::doc).tt_values().map(DocExpr::parse) } - pub fn doc_aliases(&self) -> impl Iterator + '_ { + pub fn doc_aliases(&self) -> impl Iterator + '_ { self.doc_exprs().flat_map(|doc_expr| doc_expr.aliases().to_vec()) } - pub fn export_name(&self) -> Option<&str> { - self.by_key("export_name").string_value() + pub fn export_name(&self) -> Option<&Symbol> { + self.by_key(&sym::export_name).string_value() } pub fn is_proc_macro(&self) -> bool { - self.by_key("proc_macro").exists() + self.by_key(&sym::proc_macro).exists() } pub fn is_proc_macro_attribute(&self) -> bool { - self.by_key("proc_macro_attribute").exists() + self.by_key(&sym::proc_macro_attribute).exists() } pub fn is_proc_macro_derive(&self) -> bool { - self.by_key("proc_macro_derive").exists() + self.by_key(&sym::proc_macro_derive).exists() } pub fn is_test(&self) -> bool { @@ -210,27 +210,27 @@ impl Attrs { } pub fn is_ignore(&self) -> bool { - self.by_key("ignore").exists() + self.by_key(&sym::ignore).exists() } pub fn is_bench(&self) -> bool { - self.by_key("bench").exists() + self.by_key(&sym::bench).exists() } pub fn is_unstable(&self) -> bool { - self.by_key("unstable").exists() + self.by_key(&sym::unstable).exists() } } -#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum DocAtom { /// eg. `#[doc(hidden)]` - Flag(SmolStr), + Flag(Symbol), /// eg. `#[doc(alias = "it")]` /// /// Note that a key can have multiple values that are all considered "active" at the same time. /// For example, `#[doc(alias = "x")]` and `#[doc(alias = "y")]`. - KeyValue { key: SmolStr, value: SmolStr }, + KeyValue { key: Symbol, value: Symbol }, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -239,7 +239,7 @@ pub enum DocExpr { /// eg. `#[doc(hidden)]`, `#[doc(alias = "x")]` Atom(DocAtom), /// eg. `#[doc(alias("x", "y"))]` - Alias(Vec), + Alias(Vec), } impl From for DocExpr { @@ -253,9 +253,9 @@ impl DocExpr { next_doc_expr(&mut tt.token_trees.iter()).unwrap_or(DocExpr::Invalid) } - pub fn aliases(&self) -> &[SmolStr] { + pub fn aliases(&self) -> &[Symbol] { match self { - DocExpr::Atom(DocAtom::KeyValue { key, value }) if key == "alias" => { + DocExpr::Atom(DocAtom::KeyValue { key, value }) if *key == sym::alias => { std::slice::from_ref(value) } DocExpr::Alias(aliases) => aliases, @@ -264,7 +264,7 @@ impl DocExpr { } } -fn next_doc_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option { +fn next_doc_expr(it: &mut slice::Iter<'_, tt::TokenTree>) -> Option { let name = match it.next() { None => return None, Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(), @@ -282,9 +282,7 @@ fn next_doc_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option }))) => { it.next(); it.next(); - // FIXME: escape? raw string? - let value = SmolStr::new(text.as_str()); - DocAtom::KeyValue { key: name.as_str().into(), value }.into() + DocAtom::KeyValue { key: name, value: text.clone() }.into() } _ => return Some(DocExpr::Invalid), } @@ -292,12 +290,12 @@ fn next_doc_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option Some(tt::TokenTree::Subtree(subtree)) => { it.next(); let subs = parse_comma_sep(subtree); - match name.as_str() { - "alias" => DocExpr::Alias(subs), + match &name { + s if *s == sym::alias => DocExpr::Alias(subs), _ => DocExpr::Invalid, } } - _ => DocAtom::Flag(name.as_str().into()).into(), + _ => DocAtom::Flag(name).into(), }; // Eat comma separator @@ -309,16 +307,16 @@ fn next_doc_expr(it: &mut SliceIter<'_, tt::TokenTree>) -> Option Some(ret) } -fn parse_comma_sep(subtree: &tt::Subtree) -> Vec { +fn parse_comma_sep(subtree: &tt::Subtree) -> Vec { subtree .token_trees .iter() .filter_map(|tt| match tt { tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { kind: tt::LitKind::Str, - symbol: text, + symbol, .. - })) => Some(SmolStr::new(text.as_str())), + })) => Some(symbol.clone()), _ => None, }) .collect() @@ -565,7 +563,7 @@ impl AttrSourceMap { #[derive(Debug, Clone, Copy)] pub struct AttrQuery<'attr> { attrs: &'attr Attrs, - key: &'static str, + key: &'attr Symbol, } impl<'attr> AttrQuery<'attr> { @@ -573,11 +571,11 @@ impl<'attr> AttrQuery<'attr> { self.attrs().filter_map(|attr| attr.token_tree_value()) } - pub fn string_value(self) -> Option<&'attr str> { + pub fn string_value(self) -> Option<&'attr Symbol> { self.attrs().find_map(|attr| attr.string_value()) } - pub fn string_value_with_span(self) -> Option<(&'attr str, span::Span)> { + pub fn string_value_with_span(self) -> Option<(&'attr Symbol, span::Span)> { self.attrs().find_map(|attr| attr.string_value_with_span()) } @@ -591,9 +589,7 @@ impl<'attr> AttrQuery<'attr> { pub fn attrs(self) -> impl Iterator + Clone { let key = self.key; - self.attrs - .iter() - .filter(move |attr| attr.path.as_ident().map_or(false, |s| s.to_smol_str() == key)) + self.attrs.iter().filter(move |attr| attr.path.as_ident().map_or(false, |s| *s == *key)) } /// Find string value for a specific key inside token tree @@ -602,10 +598,10 @@ impl<'attr> AttrQuery<'attr> { /// #[doc(html_root_url = "url")] /// ^^^^^^^^^^^^^ key /// ``` - pub fn find_string_value_in_tt(self, key: &'attr str) -> Option<&str> { + pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&str> { self.tt_values().find_map(|tt| { let name = tt.token_trees.iter() - .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if sym.as_str() == key)) + .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key)) .nth(2); match name { @@ -660,6 +656,7 @@ mod tests { //! This module contains tests for doc-expression parsing. //! Currently, it tests `#[doc(hidden)]` and `#[doc(alias)]`. + use intern::Symbol; use triomphe::Arc; use base_db::FileId; @@ -685,24 +682,29 @@ mod tests { #[test] fn test_doc_expr_parser() { - assert_parse_result("#![doc(hidden)]", DocAtom::Flag("hidden".into()).into()); + assert_parse_result("#![doc(hidden)]", DocAtom::Flag(Symbol::intern("hidden")).into()); assert_parse_result( r#"#![doc(alias = "foo")]"#, - DocAtom::KeyValue { key: "alias".into(), value: "foo".into() }.into(), + DocAtom::KeyValue { key: Symbol::intern("alias"), value: Symbol::intern("foo") }.into(), ); - assert_parse_result(r#"#![doc(alias("foo"))]"#, DocExpr::Alias(["foo".into()].into())); + assert_parse_result( + r#"#![doc(alias("foo"))]"#, + DocExpr::Alias([Symbol::intern("foo")].into()), + ); assert_parse_result( r#"#![doc(alias("foo", "bar", "baz"))]"#, - DocExpr::Alias(["foo".into(), "bar".into(), "baz".into()].into()), + DocExpr::Alias( + [Symbol::intern("foo"), Symbol::intern("bar"), Symbol::intern("baz")].into(), + ), ); assert_parse_result( r#" #[doc(alias("Bar", "Qux"))] struct Foo;"#, - DocExpr::Alias(["Bar".into(), "Qux".into()].into()), + DocExpr::Alias([Symbol::intern("Bar"), Symbol::intern("Qux")].into()), ); } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index b96745022a21a..b6d43af2eb04c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -8,7 +8,7 @@ use hir_expand::{ name::{AsName, Name}, ExpandError, InFile, }; -use intern::{sym, Interned}; +use intern::{sym, Interned, Symbol}; use rustc_hash::FxHashMap; use smallvec::SmallVec; use span::AstIdMap; @@ -1623,30 +1623,29 @@ impl ExprCollector<'_> { } } - let lit_pieces = - fmt.template - .iter() - .enumerate() - .filter_map(|(i, piece)| { - match piece { - FormatArgsPiece::Literal(s) => Some( - self.alloc_expr_desugared(Expr::Literal(Literal::String(s.clone()))), - ), - &FormatArgsPiece::Placeholder(_) => { - // Inject empty string before placeholders when not already preceded by a literal piece. - if i == 0 - || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) - { - Some(self.alloc_expr_desugared(Expr::Literal(Literal::String( - "".into(), - )))) - } else { - None - } + let lit_pieces = fmt + .template + .iter() + .enumerate() + .filter_map(|(i, piece)| { + match piece { + FormatArgsPiece::Literal(s) => { + Some(self.alloc_expr_desugared(Expr::Literal(Literal::String(s.clone())))) + } + &FormatArgsPiece::Placeholder(_) => { + // Inject empty string before placeholders when not already preceded by a literal piece. + if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) + { + Some(self.alloc_expr_desugared(Expr::Literal(Literal::String( + Symbol::empty(), + )))) + } else { + None } } - }) - .collect(); + } + }) + .collect(); let lit_pieces = self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: lit_pieces, is_assignee_expr: false, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs index fd685235e17db..3fc244a1e873b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs @@ -338,7 +338,7 @@ mod tests { let actual = scopes .scope_chain(scope) .flat_map(|scope| scopes.entries(scope)) - .map(|it| it.name().to_smol_str()) + .map(|it| it.name().as_str()) .collect::>() .join("\n"); let expected = expected.join("\n"); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index e2bb02c0c13ff..a887612707470 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -6,7 +6,7 @@ use base_db::CrateId; use hir_expand::{ name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, }; -use intern::{sym, Interned}; +use intern::{sym, Interned, Symbol}; use smallvec::SmallVec; use syntax::{ast, Parse}; use triomphe::Arc; @@ -38,7 +38,7 @@ pub struct FunctionData { pub ret_type: Interned, pub attrs: Attrs, pub visibility: RawVisibility, - pub abi: Option>, + pub abi: Option, pub legacy_const_generics_indices: Box<[u32]>, pub rustc_allow_incoherent_impl: bool, flags: FnFlags, @@ -92,12 +92,12 @@ impl FunctionData { let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let legacy_const_generics_indices = attrs - .by_key("rustc_legacy_const_generics") + .by_key(&sym::rustc_legacy_const_generics) .tt_values() .next() .map(parse_rustc_legacy_const_generics) .unwrap_or_default(); - let rustc_allow_incoherent_impl = attrs.by_key("rustc_allow_incoherent_impl").exists(); + let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists(); Arc::new(FunctionData { name: func.name.clone(), @@ -200,8 +200,8 @@ impl TypeAliasData { ModItem::from(loc.id.value).into(), ); let rustc_has_incoherent_inherent_impls = - attrs.by_key("rustc_has_incoherent_inherent_impls").exists(); - let rustc_allow_incoherent_impl = attrs.by_key("rustc_allow_incoherent_impl").exists(); + attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists(); + let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists(); Arc::new(TypeAliasData { name: typ.name.clone(), @@ -251,10 +251,10 @@ impl TraitData { let visibility = item_tree[tr_def.visibility].clone(); let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into()); let skip_array_during_method_dispatch = - attrs.by_key("rustc_skip_array_during_method_dispatch").exists(); + attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists(); let rustc_has_incoherent_inherent_impls = - attrs.by_key("rustc_has_incoherent_inherent_impls").exists(); - let fundamental = attrs.by_key("fundamental").exists(); + attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists(); + let fundamental = attrs.by_key(&sym::fundamental).exists(); let mut collector = AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); @@ -393,7 +393,7 @@ impl Macro2Data { let helpers = item_tree .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()) - .by_key("rustc_builtin_macro") + .by_key(&sym::rustc_builtin_macro) .tt_values() .next() .and_then(|attr| parse_macro_name_and_helper_attrs(&attr.token_trees)) @@ -423,7 +423,7 @@ impl MacroRulesData { let macro_export = item_tree .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()) - .by_key("macro_export") + .by_key(&sym::macro_export) .exists(); Arc::new(MacroRulesData { name: makro.name.clone(), macro_export }) @@ -526,7 +526,7 @@ impl ConstData { let rustc_allow_incoherent_impl = item_tree .attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into()) - .by_key("rustc_allow_incoherent_impl") + .by_key(&sym::rustc_allow_incoherent_impl) .exists(); Arc::new(ConstData { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs index 3942c2a98af78..cc6e408b65bac 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs @@ -95,7 +95,7 @@ fn repr_from_value( item_tree: &ItemTree, of: AttrOwner, ) -> Option { - item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt) + item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt) } fn parse_repr_tt(tt: &Subtree) -> Option { @@ -194,10 +194,10 @@ impl StructData { let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let mut flags = StructFlags::NO_FLAGS; - if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() { + if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL; } - if attrs.by_key("fundamental").exists() { + if attrs.by_key(&sym::fundamental).exists() { flags |= StructFlags::IS_FUNDAMENTAL; } if let Some(lang) = attrs.lang_item() { @@ -248,10 +248,10 @@ impl StructData { let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let mut flags = StructFlags::NO_FLAGS; - if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() { + if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() { flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL; } - if attrs.by_key("fundamental").exists() { + if attrs.by_key(&sym::fundamental).exists() { flags |= StructFlags::IS_FUNDAMENTAL; } @@ -287,7 +287,7 @@ impl EnumData { let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let rustc_has_incoherent_inherent_impls = item_tree .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) - .by_key("rustc_has_incoherent_inherent_impls") + .by_key(&sym::rustc_has_incoherent_inherent_impls) .exists(); let enum_ = &item_tree[loc.id.value]; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index d306f9be657a1..d7eb80a88bfa0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -18,7 +18,7 @@ pub mod type_ref; use std::fmt; use hir_expand::name::Name; -use intern::Interned; +use intern::{Interned, Symbol}; use la_arena::{Idx, RawIdx}; use rustc_apfloat::ieee::{Half as f16, Quad as f128}; use smallvec::SmallVec; @@ -60,41 +60,41 @@ pub type LabelId = Idx
");
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
index c80bb7413f5ab..bc1ec530076ce 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
@@ -3,11 +3,12 @@
 use std::mem;
 
 use either::Either;
-use hir::{sym, InFile, Semantics};
+use hir::{sym, HirFileId, InFile, Semantics};
 use ide_db::{
-    active_parameter::ActiveParameter, base_db::FileId, defs::Definition,
-    documentation::docs_with_rangemap, rust_doc::is_rust_fence, SymbolKind,
+    active_parameter::ActiveParameter, defs::Definition, documentation::docs_with_rangemap,
+    rust_doc::is_rust_fence, SymbolKind,
 };
+use span::EditionedFileId;
 use syntax::{
     ast::{self, AstNode, IsString, QuoteOffsets},
     AstToken, NodeOrToken, SyntaxNode, TextRange, TextSize,
@@ -108,14 +109,14 @@ pub(super) fn doc_comment(
     hl: &mut Highlights,
     sema: &Semantics<'_, RootDatabase>,
     config: HighlightConfig,
-    src_file_id: FileId,
+    src_file_id: EditionedFileId,
     node: &SyntaxNode,
 ) {
     let (attributes, def) = match doc_attributes(sema, node) {
         Some(it) => it,
         None => return,
     };
-    let src_file_id = src_file_id.into();
+    let src_file_id: HirFileId = src_file_id.into();
 
     // Extract intra-doc links and emit highlights for them.
     if let Some((docs, doc_mapping)) = docs_with_rangemap(sema.db, &attributes) {
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_tree.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_tree.rs
index 05cdf430efbb2..e241cb82bd5b2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_tree.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_tree.rs
@@ -1,7 +1,5 @@
-use ide_db::{
-    base_db::{FileId, SourceDatabase},
-    RootDatabase,
-};
+use hir::Semantics;
+use ide_db::{FileId, RootDatabase};
 use syntax::{
     AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize,
 };
@@ -22,9 +20,10 @@ pub(crate) fn syntax_tree(
     file_id: FileId,
     text_range: Option,
 ) -> String {
-    let parse = db.parse(file_id);
+    let sema = Semantics::new(db);
+    let parse = sema.parse_guess_edition(file_id);
     if let Some(text_range) = text_range {
-        let node = match parse.tree().syntax().covering_element(text_range) {
+        let node = match parse.syntax().covering_element(text_range) {
             NodeOrToken::Node(node) => node,
             NodeOrToken::Token(token) => {
                 if let Some(tree) = syntax_tree_for_string(&token, text_range) {
@@ -36,7 +35,7 @@ pub(crate) fn syntax_tree(
 
         format!("{node:#?}")
     } else {
-        format!("{:#?}", parse.tree().syntax())
+        format!("{:#?}", parse.syntax())
     }
 }
 
@@ -88,7 +87,7 @@ fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option Option {
-    let parse = db.parse(position.file_id);
+    let parse = db.parse(EditionedFileId::current_edition(position.file_id));
     let file = parse.tree();
     let token = file.syntax().token_at_offset(position.offset).left_biased()?;
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_hir.rs b/src/tools/rust-analyzer/crates/ide/src/view_hir.rs
index 51cf45bd22b15..fe532f4cc55ee 100644
--- a/src/tools/rust-analyzer/crates/ide/src/view_hir.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/view_hir.rs
@@ -1,6 +1,5 @@
 use hir::{DefWithBody, Semantics};
-use ide_db::base_db::FilePosition;
-use ide_db::RootDatabase;
+use ide_db::{FilePosition, RootDatabase};
 use syntax::{algo::ancestors_at_offset, ast, AstNode};
 
 // Feature: View Hir
@@ -17,7 +16,7 @@ pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String {
 
 fn body_hir(db: &RootDatabase, position: FilePosition) -> Option {
     let sema = Semantics::new(db);
-    let source_file = sema.parse(position.file_id);
+    let source_file = sema.parse_guess_edition(position.file_id);
 
     let item = ancestors_at_offset(source_file.syntax(), position.offset)
         .filter(|it| !ast::MacroCall::can_cast(it.kind()))
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_item_tree.rs b/src/tools/rust-analyzer/crates/ide/src/view_item_tree.rs
index e072df430fc0d..dae79998dc4eb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/view_item_tree.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/view_item_tree.rs
@@ -1,6 +1,6 @@
-use hir::db::DefDatabase;
-use ide_db::base_db::FileId;
-use ide_db::RootDatabase;
+use hir::{db::DefDatabase, Semantics};
+use ide_db::{FileId, RootDatabase};
+use span::EditionedFileId;
 
 // Feature: Debug ItemTree
 //
@@ -12,5 +12,9 @@ use ide_db::RootDatabase;
 // | VS Code | **rust-analyzer: Debug ItemTree**
 // |===
 pub(crate) fn view_item_tree(db: &RootDatabase, file_id: FileId) -> String {
+    let sema = Semantics::new(db);
+    let file_id = sema
+        .attach_first_edition(file_id)
+        .unwrap_or_else(|| EditionedFileId::current_edition(file_id));
     db.file_item_tree(file_id.into()).pretty_print(db)
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
index ad99c2162cd62..df3f2f18b4cdf 100644
--- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs
@@ -84,7 +84,7 @@ pub(crate) fn view_memory_layout(
     position: FilePosition,
 ) -> Option {
     let sema = Semantics::new(db);
-    let file = sema.parse(position.file_id);
+    let file = sema.parse_guess_edition(position.file_id);
     let token =
         pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
             SyntaxKind::IDENT => 3,
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_mir.rs b/src/tools/rust-analyzer/crates/ide/src/view_mir.rs
index 5fb47039890bc..7a228375d5e97 100644
--- a/src/tools/rust-analyzer/crates/ide/src/view_mir.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/view_mir.rs
@@ -1,6 +1,5 @@
 use hir::{DefWithBody, Semantics};
-use ide_db::base_db::FilePosition;
-use ide_db::RootDatabase;
+use ide_db::{FilePosition, RootDatabase};
 use syntax::{algo::ancestors_at_offset, ast, AstNode};
 
 // Feature: View Mir
@@ -16,7 +15,7 @@ pub(crate) fn view_mir(db: &RootDatabase, position: FilePosition) -> String {
 
 fn body_mir(db: &RootDatabase, position: FilePosition) -> Option {
     let sema = Semantics::new(db);
-    let source_file = sema.parse(position.file_id);
+    let source_file = sema.parse_guess_edition(position.file_id);
 
     let item = ancestors_at_offset(source_file.syntax(), position.offset)
         .filter(|it| !ast::MacroCall::can_cast(it.kind()))
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
index 58edd9900ad9c..6d943007b9462 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
@@ -52,7 +52,10 @@ pub(crate) mod dummy_test_span_utils {
     pub const DUMMY: Span = Span {
         range: TextRange::empty(TextSize::new(0)),
         anchor: span::SpanAnchor {
-            file_id: span::FileId::from_raw(0xe4e4e),
+            file_id: span::EditionedFileId::new(
+                span::FileId::from_raw(0xe4e4e),
+                span::Edition::CURRENT,
+            ),
             ast_id: span::ROOT_ERASED_FILE_AST_ID,
         },
         ctx: SyntaxContextId::ROOT,
@@ -65,7 +68,10 @@ pub(crate) mod dummy_test_span_utils {
             Span {
                 range,
                 anchor: span::SpanAnchor {
-                    file_id: span::FileId::from_raw(0xe4e4e),
+                    file_id: span::EditionedFileId::new(
+                        span::FileId::from_raw(0xe4e4e),
+                        span::Edition::CURRENT,
+                    ),
                     ast_id: span::ROOT_ERASED_FILE_AST_ID,
                 },
                 ctx: SyntaxContextId::ROOT,
diff --git a/src/tools/rust-analyzer/crates/parser/src/edition.rs b/src/tools/rust-analyzer/crates/parser/src/edition.rs
index 5d3d3cbd47c80..be0a2c794e58c 100644
--- a/src/tools/rust-analyzer/crates/parser/src/edition.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/edition.rs
@@ -4,6 +4,7 @@
 use std::fmt;
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(u8)]
 pub enum Edition {
     Edition2015,
     Edition2018,
@@ -12,9 +13,11 @@ pub enum Edition {
 }
 
 impl Edition {
-    /// The current latest stable edition, note this is usually not the right choice in code.
-    pub const CURRENT: Edition = Edition::Edition2021;
     pub const DEFAULT: Edition = Edition::Edition2015;
+    pub const LATEST: Edition = Edition::Edition2024;
+    pub const CURRENT: Edition = Edition::Edition2021;
+    /// The current latest stable edition, note this is usually not the right choice in code.
+    pub const CURRENT_FIXME: Edition = Edition::Edition2021;
 
     pub fn at_least_2024(self) -> bool {
         self >= Edition::Edition2024
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
index 65f60a7c5bd28..6a99b5ed1cc84 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
@@ -157,7 +157,6 @@ type ProtocolWrite = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str)
 
 #[cfg(test)]
 mod tests {
-    use base_db::FileId;
     use intern::{sym, Symbol};
     use la_arena::RawIdx;
     use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId};
@@ -168,7 +167,10 @@ mod tests {
 
     fn fixture_token_tree() -> Subtree {
         let anchor = SpanAnchor {
-            file_id: FileId::from_raw(0),
+            file_id: span::EditionedFileId::new(
+                span::FileId::from_raw(0xe4e4e),
+                span::Edition::CURRENT,
+            ),
             ast_id: ErasedFileAstId::from_raw(RawIdx::from(0)),
         };
 
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
index 19260bc817dae..a8661f59b2887 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
@@ -41,7 +41,7 @@ use intern::Symbol;
 use la_arena::RawIdx;
 use rustc_hash::FxHashMap;
 use serde::{Deserialize, Serialize};
-use span::{ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId};
+use span::{EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId};
 use text_size::TextRange;
 
 use crate::msg::{ENCODE_CLOSE_SPAN_VERSION, EXTENDED_LEAF_DATA};
@@ -53,7 +53,7 @@ pub fn serialize_span_data_index_map(map: &SpanDataIndexMap) -> Vec {
     map.iter()
         .flat_map(|span| {
             [
-                span.anchor.file_id.index(),
+                span.anchor.file_id.as_u32(),
                 span.anchor.ast_id.into_raw().into_u32(),
                 span.range.start().into(),
                 span.range.end().into(),
@@ -70,7 +70,7 @@ pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap {
             let &[file_id, ast_id, start, end, e] = span else { unreachable!() };
             Span {
                 anchor: SpanAnchor {
-                    file_id: FileId::from_raw(file_id),
+                    file_id: EditionedFileId::from_raw(file_id),
                     ast_id: ErasedFileAstId::from_raw(RawIdx::from_u32(ast_id)),
                 },
                 range: TextRange::new(start.into(), end.into()),
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index 452ad8e083daa..8b9eb3beb6e88 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -469,7 +469,7 @@ impl server::Server for RaSpanServer {
 
 #[cfg(test)]
 mod tests {
-    use span::SyntaxContextId;
+    use span::{EditionedFileId, FileId, SyntaxContextId};
 
     use super::*;
 
@@ -478,7 +478,7 @@ mod tests {
         let span = Span {
             range: TextRange::empty(TextSize::new(0)),
             anchor: span::SpanAnchor {
-                file_id: span::FileId::from_raw(0),
+                file_id: EditionedFileId::current_edition(FileId::from_raw(0)),
                 ast_id: span::ErasedFileAstId::from_raw(0.into()),
             },
             ctx: SyntaxContextId::ROOT,
@@ -514,7 +514,7 @@ mod tests {
         let span = Span {
             range: TextRange::empty(TextSize::new(0)),
             anchor: span::SpanAnchor {
-                file_id: span::FileId::from_raw(0),
+                file_id: EditionedFileId::current_edition(FileId::from_raw(0)),
                 ast_id: span::ErasedFileAstId::from_raw(0.into()),
             },
             ctx: SyntaxContextId::ROOT,
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
index c382a5b24119c..cdf93fa4251d5 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
@@ -127,7 +127,7 @@ pub(super) mod token_stream {
     impl TokenStream {
         pub(crate) fn from_str(src: &str, call_site: S) -> Result, String> {
             let subtree =
-                mbe::parse_to_token_tree_static_span(span::Edition::CURRENT, call_site, src)
+                mbe::parse_to_token_tree_static_span(span::Edition::CURRENT_FIXME, call_site, src)
                     .ok_or("lexing error")?;
 
             Ok(TokenStream::with_subtree(subtree))
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
index 1080e8c9932e2..70eff51cadea8 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
@@ -2,7 +2,7 @@
 
 use expect_test::Expect;
 use proc_macro_api::msg::TokenId;
-use span::{ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId};
+use span::{EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId};
 use tt::TextRange;
 
 use crate::{dylib, proc_macro_test_dylib_path, EnvSnapshot, ProcMacroSrv};
@@ -68,7 +68,7 @@ fn assert_expand_impl(
     let def_site = Span {
         range: TextRange::new(0.into(), 150.into()),
         anchor: SpanAnchor {
-            file_id: FileId::from_raw(41),
+            file_id: EditionedFileId::current_edition(FileId::from_raw(41)),
             ast_id: ErasedFileAstId::from_raw(From::from(1)),
         },
         ctx: SyntaxContextId::ROOT,
@@ -76,7 +76,7 @@ fn assert_expand_impl(
     let call_site = Span {
         range: TextRange::new(0.into(), 100.into()),
         anchor: SpanAnchor {
-            file_id: FileId::from_raw(42),
+            file_id: EditionedFileId::current_edition(FileId::from_raw(42)),
             ast_id: ErasedFileAstId::from_raw(From::from(2)),
         },
         ctx: SyntaxContextId::ROOT,
diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
index 8d50d4bdfe2c2..8f5457bf99af9 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -1,6 +1,6 @@
 use std::ops::Deref;
 
-use base_db::{CrateGraph, FileId, ProcMacroPaths};
+use base_db::{CrateGraph, ProcMacroPaths};
 use cargo_metadata::Metadata;
 use cfg::{CfgAtom, CfgDiff};
 use expect_test::{expect_file, ExpectFile};
@@ -8,6 +8,7 @@ use intern::sym;
 use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::de::DeserializeOwned;
+use span::FileId;
 use triomphe::Arc;
 
 use crate::{
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index dd7a11ca85f19..c3b0802756340 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -6,7 +6,7 @@ use std::{collections::VecDeque, fmt, fs, iter, sync};
 
 use anyhow::Context;
 use base_db::{
-    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileId,
+    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env,
     LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
 };
 use cfg::{CfgAtom, CfgDiff, CfgOptions};
@@ -14,7 +14,7 @@ use intern::{sym, Symbol};
 use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::{FxHashMap, FxHashSet};
 use semver::Version;
-use span::Edition;
+use span::{Edition, FileId};
 use toolchain::Tool;
 use tracing::instrument;
 use triomphe::Arc;
@@ -1463,7 +1463,7 @@ fn sysroot_to_crate_graph(
                     let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name);
                     let crate_id = crate_graph.add_crate_root(
                         file_id,
-                        Edition::CURRENT,
+                        Edition::CURRENT_FIXME,
                         Some(display_name),
                         None,
                         cfg_options.clone(),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index a0f1c941dd1fc..f26f9abe801b9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -25,7 +25,7 @@ use ide_db::{
         salsa::{self, debug::DebugQueryTable, ParallelDatabase},
         SourceDatabase, SourceDatabaseExt,
     },
-    LineIndexDatabase, SnippetCap,
+    EditionedFileId, LineIndexDatabase, SnippetCap,
 };
 use itertools::Itertools;
 use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
@@ -35,7 +35,7 @@ use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSourc
 use rayon::prelude::*;
 use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::{AstNode, SyntaxNode};
-use vfs::{AbsPathBuf, FileId, Vfs, VfsPath};
+use vfs::{AbsPathBuf, Vfs, VfsPath};
 
 use crate::cli::{
     flags::{self, OutputFormat},
@@ -120,7 +120,7 @@ impl flags::AnalysisStats {
                 for file_id in source_root.iter() {
                     if let Some(p) = source_root.path_for_file(&file_id) {
                         if let Some((_, Some("rs"))) = p.name_and_extension() {
-                            db.file_item_tree(file_id.into());
+                            db.file_item_tree(EditionedFileId::current_edition(file_id).into());
                             num_item_trees += 1;
                         }
                     }
@@ -140,7 +140,7 @@ impl flags::AnalysisStats {
             let module = krate.root_module();
             let file_id = module.definition_source_file_id(db);
             let file_id = file_id.original_file(db);
-            let source_root = db.file_source_root(file_id);
+            let source_root = db.file_source_root(file_id.into());
             let source_root = db.source_root(source_root);
             if !source_root.is_library || self.with_deps {
                 num_crates += 1;
@@ -332,7 +332,7 @@ impl flags::AnalysisStats {
         ws: &ProjectWorkspace,
         db: &RootDatabase,
         vfs: &Vfs,
-        mut file_ids: Vec,
+        mut file_ids: Vec,
         verbosity: Verbosity,
     ) {
         let cargo_config = CargoConfig {
@@ -367,11 +367,10 @@ impl flags::AnalysisStats {
 
         for &file_id in &file_ids {
             let sema = hir::Semantics::new(db);
-            let _ = db.parse(file_id);
 
-            let parse = sema.parse(file_id);
-            let file_txt = db.file_text(file_id);
-            let path = vfs.file_path(file_id).as_path().unwrap();
+            let parse = sema.parse_guess_edition(file_id.into());
+            let file_txt = db.file_text(file_id.into());
+            let path = vfs.file_path(file_id.into()).as_path().unwrap();
 
             for node in parse.syntax().descendants() {
                 let expr = match syntax::ast::Expr::cast(node.clone()) {
@@ -398,7 +397,7 @@ impl flags::AnalysisStats {
 
                 let range = sema.original_range(expected_tail.syntax()).range;
                 let original_text: String = db
-                    .file_text(file_id)
+                    .file_text(file_id.into())
                     .chars()
                     .skip(usize::from(range.start()))
                     .take(usize::from(range.end()) - usize::from(range.start()))
@@ -650,7 +649,7 @@ impl flags::AnalysisStats {
                     };
                     if let Some(src) = source {
                         let original_file = src.file_id.original_file(db);
-                        let path = vfs.file_path(original_file);
+                        let path = vfs.file_path(original_file.into());
                         let syntax_range = src.text_range();
                         format!("processing: {} ({} {:?})", full_name(), path, syntax_range)
                     } else {
@@ -944,7 +943,7 @@ impl flags::AnalysisStats {
                     };
                     if let Some(src) = source {
                         let original_file = src.file_id.original_file(db);
-                        let path = vfs.file_path(original_file);
+                        let path = vfs.file_path(original_file.into());
                         let syntax_range = src.text_range();
                         format!("processing: {} ({} {:?})", full_name(), path, syntax_range)
                     } else {
@@ -968,7 +967,7 @@ impl flags::AnalysisStats {
         report_metric("body lowering time", body_lowering_time.time.as_millis() as u64, "ms");
     }
 
-    fn run_ide_things(&self, analysis: Analysis, mut file_ids: Vec) {
+    fn run_ide_things(&self, analysis: Analysis, mut file_ids: Vec) {
         file_ids.sort();
         file_ids.dedup();
         let mut sw = self.stop_watch();
@@ -998,7 +997,7 @@ impl flags::AnalysisStats {
                     term_search_borrowck: true,
                 },
                 ide::AssistResolveStrategy::All,
-                file_id,
+                file_id.into(),
             );
         }
         for &file_id in &file_ids {
@@ -1031,7 +1030,7 @@ impl flags::AnalysisStats {
                     fields_to_resolve: InlayFieldsToResolve::empty(),
                     range_exclusive_hints: true,
                 },
-                file_id,
+                file_id.into(),
                 None,
             );
         }
@@ -1047,7 +1046,7 @@ impl flags::AnalysisStats {
                         annotate_enum_variant_references: false,
                         location: ide::AnnotationLocation::AboveName,
                     },
-                    file_id,
+                    file_id.into(),
                 )
                 .unwrap()
                 .into_iter()
@@ -1072,8 +1071,8 @@ fn location_csv_expr(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, expr_id:
     let root = db.parse_or_expand(src.file_id);
     let node = src.map(|e| e.to_node(&root).syntax().clone());
     let original_range = node.as_ref().original_file_range_rooted(db);
-    let path = vfs.file_path(original_range.file_id);
-    let line_index = db.line_index(original_range.file_id);
+    let path = vfs.file_path(original_range.file_id.into());
+    let line_index = db.line_index(original_range.file_id.into());
     let text_range = original_range.range;
     let (start, end) =
         (line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
@@ -1088,8 +1087,8 @@ fn location_csv_pat(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, pat_id: Pa
     let root = db.parse_or_expand(src.file_id);
     let node = src.map(|e| e.to_node(&root).syntax().clone());
     let original_range = node.as_ref().original_file_range_rooted(db);
-    let path = vfs.file_path(original_range.file_id);
-    let line_index = db.line_index(original_range.file_id);
+    let path = vfs.file_path(original_range.file_id.into());
+    let line_index = db.line_index(original_range.file_id.into());
     let text_range = original_range.range;
     let (start, end) =
         (line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
@@ -1107,8 +1106,8 @@ fn expr_syntax_range<'a>(
         let root = db.parse_or_expand(src.file_id);
         let node = src.map(|e| e.to_node(&root).syntax().clone());
         let original_range = node.as_ref().original_file_range_rooted(db);
-        let path = vfs.file_path(original_range.file_id);
-        let line_index = db.line_index(original_range.file_id);
+        let path = vfs.file_path(original_range.file_id.into());
+        let line_index = db.line_index(original_range.file_id.into());
         let text_range = original_range.range;
         let (start, end) =
             (line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
@@ -1128,8 +1127,8 @@ fn pat_syntax_range<'a>(
         let root = db.parse_or_expand(src.file_id);
         let node = src.map(|e| e.to_node(&root).syntax().clone());
         let original_range = node.as_ref().original_file_range_rooted(db);
-        let path = vfs.file_path(original_range.file_id);
-        let line_index = db.line_index(original_range.file_id);
+        let path = vfs.file_path(original_range.file_id.into());
+        let line_index = db.line_index(original_range.file_id.into());
         let text_range = original_range.range;
         let (start, end) =
             (line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
index d5eac49ad3a5b..489bb42eec360 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -48,7 +48,7 @@ impl flags::Diagnostics {
 
         let work = all_modules(db).into_iter().filter(|module| {
             let file_id = module.definition_source_file_id(db).original_file(db);
-            let source_root = db.file_source_root(file_id);
+            let source_root = db.file_source_root(file_id.into());
             let source_root = db.source_root(source_root);
             !source_root.is_library
         });
@@ -58,12 +58,15 @@ impl flags::Diagnostics {
             if !visited_files.contains(&file_id) {
                 let crate_name =
                     module.krate().display_name(db).as_deref().unwrap_or("unknown").to_owned();
-                println!("processing crate: {crate_name}, module: {}", _vfs.file_path(file_id));
+                println!(
+                    "processing crate: {crate_name}, module: {}",
+                    _vfs.file_path(file_id.into())
+                );
                 for diagnostic in analysis
                     .diagnostics(
                         &DiagnosticsConfig::test_sample(),
                         AssistResolveStrategy::None,
-                        file_id,
+                        file_id.into(),
                     )
                     .unwrap()
                 {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
index 8f60b17b5943f..ee134b6c507e8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
@@ -342,7 +342,7 @@ mod test {
         let (file_id, range_or_offset) =
             change_fixture.file_position.expect("expected a marker ()");
         let offset = range_or_offset.expect_offset();
-        (host, FilePosition { file_id, offset })
+        (host, FilePosition { file_id: file_id.into(), offset })
     }
 
     /// If expected == "", then assert that there are no symbols (this is basically local symbol)
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
index 28cbd1afd8cfd..7f24fa2835e93 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
@@ -1,6 +1,7 @@
 //! Applies structured search replace rules from the command line.
 
 use anyhow::Context;
+use ide_db::EditionedFileId;
 use ide_ssr::MatchFinder;
 use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
 use project_model::{CargoConfig, RustLibSource};
@@ -67,7 +68,10 @@ impl flags::Search {
             for &root in db.local_roots().iter() {
                 let sr = db.source_root(root);
                 for file_id in sr.iter() {
-                    for debug_info in match_finder.debug_where_text_equal(file_id, debug_snippet) {
+                    for debug_info in match_finder.debug_where_text_equal(
+                        EditionedFileId::current_edition(file_id),
+                        debug_snippet,
+                    ) {
                         println!("{debug_info:#?}");
                     }
                 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
index 60fe847bb7d87..aea424298f8c8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/from_proto.rs
@@ -1,10 +1,7 @@
 //! Conversion lsp_types types to rust-analyzer specific ones.
 use anyhow::format_err;
 use ide::{Annotation, AnnotationKind, AssistKind, LineCol};
-use ide_db::{
-    base_db::{FileId, FilePosition, FileRange},
-    line_index::WideLineCol,
-};
+use ide_db::{line_index::WideLineCol, FileId, FilePosition, FileRange};
 use syntax::{TextRange, TextSize};
 use vfs::AbsPathBuf;
 
diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs
index bbaf1b2a6d59d..057fab89c71f6 100644
--- a/src/tools/rust-analyzer/crates/span/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/span/src/lib.rs
@@ -17,18 +17,6 @@ pub use syntax::Edition;
 pub use text_size::{TextRange, TextSize};
 pub use vfs::FileId;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct FilePosition {
-    pub file_id: FileId,
-    pub offset: TextSize,
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
-pub struct FileRange {
-    pub file_id: FileId,
-    pub range: TextRange,
-}
-
 // The first index is always the root node's AstId
 /// The root ast id always points to the encompassing file, using this in spans is discouraged as
 /// any range relative to it will be effectively absolute, ruining the entire point of anchored
@@ -63,7 +51,7 @@ pub struct SpanData {
 impl fmt::Debug for SpanData {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         if f.alternate() {
-            fmt::Debug::fmt(&self.anchor.file_id.index(), f)?;
+            fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?;
             f.write_char(':')?;
             fmt::Debug::fmt(&self.anchor.ast_id.into_raw(), f)?;
             f.write_char('@')?;
@@ -88,7 +76,7 @@ impl SpanData {
 
 impl fmt::Display for Span {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&self.anchor.file_id.index(), f)?;
+        fmt::Debug::fmt(&self.anchor.file_id.file_id().index(), f)?;
         f.write_char(':')?;
         fmt::Debug::fmt(&self.anchor.ast_id.into_raw(), f)?;
         f.write_char('@')?;
@@ -100,7 +88,7 @@ impl fmt::Display for Span {
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct SpanAnchor {
-    pub file_id: FileId,
+    pub file_id: EditionedFileId,
     pub ast_id: ErasedFileAstId,
 }
 
@@ -110,6 +98,81 @@ impl fmt::Debug for SpanAnchor {
     }
 }
 
+/// A [`FileId`] and [`Edition`] bundled up together.
+/// The MSB is reserved for `HirFileId` encoding, more upper bits are used to then encode the edition.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub struct EditionedFileId(u32);
+
+impl fmt::Debug for EditionedFileId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("EditionedFileId").field(&self.file_id()).field(&self.edition()).finish()
+    }
+}
+
+impl From for FileId {
+    fn from(value: EditionedFileId) -> Self {
+        value.file_id()
+    }
+}
+
+const _: () = assert!(
+    EditionedFileId::RESERVED_HIGH_BITS
+        + EditionedFileId::EDITION_BITS
+        + EditionedFileId::FILE_ID_BITS
+        == u32::BITS
+);
+const _: () = assert!(
+    EditionedFileId::RESERVED_MASK ^ EditionedFileId::EDITION_MASK ^ EditionedFileId::FILE_ID_MASK
+        == 0xFFFF_FFFF
+);
+
+impl EditionedFileId {
+    pub const RESERVED_MASK: u32 = 0x8000_0000;
+    pub const EDITION_MASK: u32 = 0x7F80_0000;
+    pub const FILE_ID_MASK: u32 = 0x007F_FFFF;
+
+    pub const MAX_FILE_ID: u32 = Self::FILE_ID_MASK;
+
+    pub const RESERVED_HIGH_BITS: u32 = Self::RESERVED_MASK.count_ones();
+    pub const FILE_ID_BITS: u32 = Self::FILE_ID_MASK.count_ones();
+    pub const EDITION_BITS: u32 = Self::EDITION_MASK.count_ones();
+
+    pub const fn current_edition(file_id: FileId) -> Self {
+        Self::new(file_id, Edition::CURRENT)
+    }
+
+    pub const fn new(file_id: FileId, edition: Edition) -> Self {
+        let file_id = file_id.index();
+        let edition = edition as u32;
+        assert!(file_id <= Self::MAX_FILE_ID);
+        Self(file_id | (edition << Self::FILE_ID_BITS))
+    }
+
+    pub fn from_raw(u32: u32) -> Self {
+        assert!(u32 & Self::RESERVED_MASK == 0);
+        assert!((u32 & Self::EDITION_MASK) >> Self::FILE_ID_BITS <= Edition::LATEST as u32);
+        Self(u32)
+    }
+
+    pub const fn as_u32(self) -> u32 {
+        self.0
+    }
+
+    pub const fn file_id(self) -> FileId {
+        FileId::from_raw(self.0 & Self::FILE_ID_MASK)
+    }
+
+    pub const fn unpack(self) -> (FileId, Edition) {
+        (self.file_id(), self.edition())
+    }
+
+    pub const fn edition(self) -> Edition {
+        let edition = (self.0 & Self::EDITION_MASK) >> Self::FILE_ID_BITS;
+        debug_assert!(edition <= Edition::LATEST as u32);
+        unsafe { std::mem::transmute(edition as u8) }
+    }
+}
+
 /// Input to the analyzer is a set of files, where each file is identified by
 /// `FileId` and contains source code. However, another source of source code in
 /// Rust are macros: each macro can be thought of as producing a "temporary
@@ -149,6 +212,38 @@ impl fmt::Debug for HirFileId {
     }
 }
 
+impl PartialEq for HirFileId {
+    fn eq(&self, &other: &FileId) -> bool {
+        self.file_id().map(EditionedFileId::file_id) == Some(other)
+    }
+}
+impl PartialEq for FileId {
+    fn eq(&self, other: &HirFileId) -> bool {
+        other.file_id().map(EditionedFileId::file_id) == Some(*self)
+    }
+}
+
+impl PartialEq for HirFileId {
+    fn eq(&self, &other: &EditionedFileId) -> bool {
+        *self == HirFileId::from(other)
+    }
+}
+impl PartialEq for EditionedFileId {
+    fn eq(&self, &other: &HirFileId) -> bool {
+        other == HirFileId::from(*self)
+    }
+}
+impl PartialEq for FileId {
+    fn eq(&self, &other: &EditionedFileId) -> bool {
+        *self == FileId::from(other)
+    }
+}
+impl PartialEq for EditionedFileId {
+    fn eq(&self, &other: &FileId) -> bool {
+        other == FileId::from(*self)
+    }
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct MacroFileId {
     pub macro_call_id: MacroCallId,
@@ -182,14 +277,14 @@ impl MacroCallId {
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum HirFileIdRepr {
-    FileId(FileId),
+    FileId(EditionedFileId),
     MacroFile(MacroFileId),
 }
 
 impl fmt::Debug for HirFileIdRepr {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            Self::FileId(arg0) => f.debug_tuple("FileId").field(&arg0.index()).finish(),
+            Self::FileId(arg0) => arg0.fmt(f),
             Self::MacroFile(arg0) => {
                 f.debug_tuple("MacroFile").field(&arg0.macro_call_id.0).finish()
             }
@@ -197,19 +292,17 @@ impl fmt::Debug for HirFileIdRepr {
     }
 }
 
-impl From for HirFileId {
+impl From for HirFileId {
     #[allow(clippy::let_unit_value)]
-    fn from(id: FileId) -> Self {
-        _ = Self::ASSERT_MAX_FILE_ID_IS_SAME;
-        assert!(id.index() <= Self::MAX_HIR_FILE_ID, "FileId index {} is too large", id.index());
-        HirFileId(id.index())
+    fn from(id: EditionedFileId) -> Self {
+        assert!(id.as_u32() <= Self::MAX_HIR_FILE_ID, "FileId index {} is too large", id.as_u32());
+        HirFileId(id.as_u32())
     }
 }
 
 impl From for HirFileId {
     #[allow(clippy::let_unit_value)]
     fn from(MacroFileId { macro_call_id: MacroCallId(id) }: MacroFileId) -> Self {
-        _ = Self::ASSERT_MAX_FILE_ID_IS_SAME;
         let id = id.as_u32();
         assert!(id <= Self::MAX_HIR_FILE_ID, "MacroCallId index {id} is too large");
         HirFileId(id | Self::MACRO_FILE_TAG_MASK)
@@ -217,9 +310,6 @@ impl From for HirFileId {
 }
 
 impl HirFileId {
-    const ASSERT_MAX_FILE_ID_IS_SAME: () =
-        [()][(Self::MAX_HIR_FILE_ID != FileId::MAX_FILE_ID) as usize];
-
     const MAX_HIR_FILE_ID: u32 = u32::MAX ^ Self::MACRO_FILE_TAG_MASK;
     const MACRO_FILE_TAG_MASK: u32 = 1 << 31;
 
@@ -239,9 +329,9 @@ impl HirFileId {
     }
 
     #[inline]
-    pub fn file_id(self) -> Option {
+    pub fn file_id(self) -> Option {
         match self.0 & Self::MACRO_FILE_TAG_MASK {
-            0 => Some(FileId::from_raw(self.0)),
+            0 => Some(EditionedFileId(self.0)),
             _ => None,
         }
     }
@@ -249,7 +339,7 @@ impl HirFileId {
     #[inline]
     pub fn repr(self) -> HirFileIdRepr {
         match self.0 & Self::MACRO_FILE_TAG_MASK {
-            0 => HirFileIdRepr::FileId(FileId::from_raw(self.0)),
+            0 => HirFileIdRepr::FileId(EditionedFileId(self.0)),
             _ => HirFileIdRepr::MacroFile(MacroFileId {
                 macro_call_id: MacroCallId(InternId::from(self.0 ^ Self::MACRO_FILE_TAG_MASK)),
             }),
diff --git a/src/tools/rust-analyzer/crates/span/src/map.rs b/src/tools/rust-analyzer/crates/span/src/map.rs
index 81fc56c961e46..6269f4c30c7d2 100644
--- a/src/tools/rust-analyzer/crates/span/src/map.rs
+++ b/src/tools/rust-analyzer/crates/span/src/map.rs
@@ -4,11 +4,10 @@
 use std::{fmt, hash::Hash};
 
 use stdx::{always, itertools::Itertools};
-use vfs::FileId;
 
 use crate::{
-    ErasedFileAstId, Span, SpanAnchor, SpanData, SyntaxContextId, TextRange, TextSize,
-    ROOT_ERASED_FILE_AST_ID,
+    EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SpanData, SyntaxContextId, TextRange,
+    TextSize, ROOT_ERASED_FILE_AST_ID,
 };
 
 /// Maps absolute text ranges for the corresponding file to the relevant span data.
@@ -109,7 +108,7 @@ where
 
 #[derive(PartialEq, Eq, Hash, Debug)]
 pub struct RealSpanMap {
-    file_id: FileId,
+    file_id: EditionedFileId,
     /// Invariant: Sorted vec over TextSize
     // FIXME: SortedVec<(TextSize, ErasedFileAstId)>?
     pairs: Box<[(TextSize, ErasedFileAstId)]>,
@@ -128,7 +127,7 @@ impl fmt::Display for RealSpanMap {
 
 impl RealSpanMap {
     /// Creates a real file span map that returns absolute ranges (relative ranges to the root ast id).
-    pub fn absolute(file_id: FileId) -> Self {
+    pub fn absolute(file_id: EditionedFileId) -> Self {
         RealSpanMap {
             file_id,
             pairs: Box::from([(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]),
@@ -137,7 +136,7 @@ impl RealSpanMap {
     }
 
     pub fn from_file(
-        file_id: FileId,
+        file_id: EditionedFileId,
         pairs: Box<[(TextSize, ErasedFileAstId)]>,
         end: TextSize,
     ) -> Self {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
index 6d21ca17471c8..b68374848b90c 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
@@ -150,15 +150,17 @@ impl Parse {
     }
 
     pub fn reparse(&self, indel: &Indel, edition: Edition) -> Parse {
-        self.incremental_reparse(indel).unwrap_or_else(|| self.full_reparse(indel, edition))
+        self.incremental_reparse(indel, edition)
+            .unwrap_or_else(|| self.full_reparse(indel, edition))
     }
 
-    fn incremental_reparse(&self, indel: &Indel) -> Option> {
+    fn incremental_reparse(&self, indel: &Indel, edition: Edition) -> Option> {
         // FIXME: validation errors are not handled here
         parsing::incremental_reparse(
             self.tree().syntax(),
             indel,
             self.errors.as_deref().unwrap_or_default().iter().cloned(),
+            edition,
         )
         .map(|(green_node, errors, _reparsed_range)| Parse {
             green: green_node,
diff --git a/src/tools/rust-analyzer/crates/syntax/src/parsing/reparsing.rs b/src/tools/rust-analyzer/crates/syntax/src/parsing/reparsing.rs
index 1e1a02f445934..a895d9e27482b 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/parsing/reparsing.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/parsing/reparsing.rs
@@ -21,14 +21,13 @@ pub(crate) fn incremental_reparse(
     node: &SyntaxNode,
     edit: &Indel,
     errors: impl IntoIterator,
+    edition: Edition,
 ) -> Option<(GreenNode, Vec, TextRange)> {
-    if let Some((green, new_errors, old_range)) = reparse_token(node, edit) {
+    if let Some((green, new_errors, old_range)) = reparse_token(node, edit, edition) {
         return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
     }
 
-    if let Some((green, new_errors, old_range)) =
-        reparse_block(node, edit, parser::Edition::CURRENT)
-    {
+    if let Some((green, new_errors, old_range)) = reparse_block(node, edit, edition) {
         return Some((green, merge_errors(errors, new_errors, old_range, edit), old_range));
     }
     None
@@ -37,6 +36,7 @@ pub(crate) fn incremental_reparse(
 fn reparse_token(
     root: &SyntaxNode,
     edit: &Indel,
+    edition: Edition,
 ) -> Option<(GreenNode, Vec, TextRange)> {
     let prev_token = root.covering_element(edit.delete).as_token()?.clone();
     let prev_token_kind = prev_token.kind();
@@ -51,8 +51,7 @@ fn reparse_token(
             }
 
             let mut new_text = get_text_after_edit(prev_token.clone().into(), edit);
-            let (new_token_kind, new_err) =
-                parser::LexedStr::single_token(Edition::CURRENT, &new_text)?;
+            let (new_token_kind, new_err) = parser::LexedStr::single_token(edition, &new_text)?;
 
             if new_token_kind != prev_token_kind
                 || (new_token_kind == IDENT && is_contextual_kw(&new_text))
@@ -65,8 +64,7 @@ fn reparse_token(
             // `b` no longer remains an identifier, but becomes a part of byte string literal
             if let Some(next_char) = root.text().char_at(prev_token.text_range().end()) {
                 new_text.push(next_char);
-                let token_with_next_char =
-                    parser::LexedStr::single_token(Edition::CURRENT, &new_text);
+                let token_with_next_char = parser::LexedStr::single_token(edition, &new_text);
                 if let Some((_kind, _error)) = token_with_next_char {
                     return None;
                 }
@@ -93,7 +91,7 @@ fn reparse_block(
     let (node, reparser) = find_reparsable_node(root, edit.delete)?;
     let text = get_text_after_edit(node.clone().into(), edit);
 
-    let lexed = parser::LexedStr::new(Edition::CURRENT, text.as_str());
+    let lexed = parser::LexedStr::new(edition, text.as_str());
     let parser_input = lexed.to_input();
     if !is_balanced(&lexed) {
         return None;
@@ -201,6 +199,7 @@ mod tests {
                 before.tree().syntax(),
                 &edit,
                 before.errors.as_deref().unwrap_or_default().iter().cloned(),
+                Edition::CURRENT,
             )
             .unwrap();
             assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length");
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index d9f9fb82be3f1..19c81a7c5f73d 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -9,13 +9,15 @@ use cfg::CfgOptions;
 use hir_expand::{
     change::ChangeWithProcMacros,
     db::ExpandDatabase,
+    files::FilePosition,
     proc_macro::{
         ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacros,
     },
+    FileRange,
 };
 use intern::Symbol;
 use rustc_hash::FxHashMap;
-use span::{Edition, FileId, FilePosition, FileRange, Span};
+use span::{Edition, EditionedFileId, FileId, Span};
 use test_utils::{
     extract_range_or_offset, Fixture, FixtureWithProjectMeta, RangeOrOffset, CURSOR_MARKER,
     ESCAPED_CURSOR_MARKER,
@@ -26,7 +28,7 @@ pub const WORKSPACE: base_db::SourceRootId = base_db::SourceRootId(0);
 
 pub trait WithFixture: Default + ExpandDatabase + SourceDatabaseExt + 'static {
     #[track_caller]
-    fn with_single_file(ra_fixture: &str) -> (Self, FileId) {
+    fn with_single_file(ra_fixture: &str) -> (Self, EditionedFileId) {
         let fixture = ChangeFixture::parse(ra_fixture);
         let mut db = Self::default();
         fixture.change.apply(&mut db);
@@ -35,7 +37,7 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabaseExt + 'static {
     }
 
     #[track_caller]
-    fn with_many_files(ra_fixture: &str) -> (Self, Vec) {
+    fn with_many_files(ra_fixture: &str) -> (Self, Vec) {
         let fixture = ChangeFixture::parse(ra_fixture);
         let mut db = Self::default();
         fixture.change.apply(&mut db);
@@ -79,7 +81,7 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabaseExt + 'static {
     }
 
     #[track_caller]
-    fn with_range_or_offset(ra_fixture: &str) -> (Self, FileId, RangeOrOffset) {
+    fn with_range_or_offset(ra_fixture: &str) -> (Self, EditionedFileId, RangeOrOffset) {
         let fixture = ChangeFixture::parse(ra_fixture);
         let mut db = Self::default();
         fixture.change.apply(&mut db);
@@ -102,8 +104,8 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabaseExt + 'static {
 impl WithFixture for DB {}
 
 pub struct ChangeFixture {
-    pub file_position: Option<(FileId, RangeOrOffset)>,
-    pub files: Vec,
+    pub file_position: Option<(EditionedFileId, RangeOrOffset)>,
+    pub files: Vec,
     pub change: ChangeWithProcMacros,
 }
 
@@ -151,13 +153,14 @@ impl ChangeFixture {
         let mut file_position = None;
 
         for entry in fixture {
+            let mut range_or_offset = None;
             let text = if entry.text.contains(CURSOR_MARKER) {
                 if entry.text.contains(ESCAPED_CURSOR_MARKER) {
                     entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER)
                 } else {
-                    let (range_or_offset, text) = extract_range_or_offset(&entry.text);
+                    let (roo, text) = extract_range_or_offset(&entry.text);
                     assert!(file_position.is_none());
-                    file_position = Some((file_id, range_or_offset));
+                    range_or_offset = Some(roo);
                     text
                 }
             } else {
@@ -165,6 +168,11 @@ impl ChangeFixture {
             };
 
             let meta = FileMeta::from_fixture(entry, current_source_root_kind);
+            if let Some(range_or_offset) = range_or_offset {
+                file_position =
+                    Some((EditionedFileId::new(file_id, meta.edition), range_or_offset));
+            }
+
             assert!(meta.path.starts_with(SOURCE_ROOT_PREFIX));
             if !meta.deps.is_empty() {
                 assert!(meta.krate.is_some(), "can't specify deps without naming the crate")
@@ -216,7 +224,7 @@ impl ChangeFixture {
             source_change.change_file(file_id, Some(text));
             let path = VfsPath::new_virtual_path(meta.path);
             file_set.insert(file_id, path);
-            files.push(file_id);
+            files.push(EditionedFileId::new(file_id, meta.edition));
             file_id = FileId::from_raw(file_id.index() + 1);
         }
 
diff --git a/src/tools/rust-analyzer/crates/vfs/src/lib.rs b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
index b3aa6e2fe1138..77f890fd7e0de 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
@@ -67,16 +67,16 @@ pub struct FileId(u32);
 // pub struct FileId(NonMaxU32);
 
 impl FileId {
-    pub const MAX_FILE_ID: u32 = 0x7fff_ffff;
+    pub const MAX: u32 = 0x7fff_ffff;
 
     #[inline]
     pub const fn from_raw(raw: u32) -> FileId {
-        assert!(raw <= Self::MAX_FILE_ID);
+        assert!(raw <= Self::MAX);
         FileId(raw)
     }
 
     #[inline]
-    pub fn index(self) -> u32 {
+    pub const fn index(self) -> u32 {
         self.0
     }
 }

From 736723d435e3514717e8a237ad606fc072f25b07 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 18 Jul 2024 09:09:31 +0200
Subject: [PATCH 047/489] Update test fixtures

---
 .../ide-db/src/test_data/test_doc_alias.txt   |  49 ++--
 .../test_symbol_index_collection.txt          | 210 +++++++++++++-----
 .../crates/ide/src/annotations.rs             |  54 ++---
 .../crates/ide/src/hover/tests.rs             | 136 ++++++------
 .../crates/ide/src/inlay_hints/chaining.rs    |  42 ++--
 .../rust-analyzer/editors/code/package.json   |   5 -
 6 files changed, 301 insertions(+), 195 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt
index 7c01ac0693959..efcf53ded64f0 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt
+++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_doc_alias.txt
@@ -20,8 +20,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -50,8 +53,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -80,8 +86,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -110,8 +119,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -140,8 +152,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -170,8 +185,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -200,8 +218,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index f0b97779c736d..9d70942199c8e 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -18,8 +18,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: TYPE_ALIAS,
@@ -46,8 +49,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: CONST,
@@ -74,8 +80,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: CONST,
@@ -104,8 +113,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: ENUM,
@@ -134,8 +146,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: USE_TREE,
@@ -164,8 +179,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: MACRO_DEF,
@@ -192,8 +210,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STATIC,
@@ -222,8 +243,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -282,8 +306,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -314,8 +341,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -346,8 +376,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -376,8 +409,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -404,8 +440,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: TRAIT,
@@ -434,8 +473,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: USE_TREE,
@@ -464,8 +506,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: UNION,
@@ -494,8 +539,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: MODULE,
@@ -524,8 +572,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: MODULE,
@@ -554,8 +605,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: MACRO_RULES,
@@ -582,8 +636,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: FN,
@@ -612,8 +669,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: FN,
@@ -644,8 +704,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: MACRO_RULES,
@@ -672,8 +735,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: FN,
@@ -702,8 +768,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: USE_TREE,
@@ -730,8 +799,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: FN,
@@ -773,8 +845,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        0,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            0,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -814,8 +889,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        1,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            1,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: USE_TREE,
@@ -844,8 +922,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        1,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            1,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: STRUCT,
@@ -874,8 +955,11 @@
                     },
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        1,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            1,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: USE_TREE,
@@ -904,8 +988,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        1,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            1,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: USE_TREE,
@@ -934,8 +1021,11 @@
                     ),
                 ),
                 loc: DeclarationLocation {
-                    hir_file_id: FileId(
-                        1,
+                    hir_file_id: EditionedFileId(
+                        FileId(
+                            1,
+                        ),
+                        Edition2021,
                     ),
                     ptr: SyntaxNodePtr {
                         kind: USE_TREE,
diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
index 670d20241169d..8e0166a4a76ca 100644
--- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
@@ -254,7 +254,7 @@ fn main() {
                     Annotation {
                         range: 6..10,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -262,7 +262,7 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -275,7 +275,7 @@ fn main() {
                     Annotation {
                         range: 30..36,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -308,7 +308,7 @@ fn main() {
                     Annotation {
                         range: 53..57,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -339,7 +339,7 @@ fn main() {
                     Annotation {
                         range: 7..11,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -347,7 +347,7 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -360,7 +360,7 @@ fn main() {
                     Annotation {
                         range: 7..11,
                         kind: HasImpls {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -393,7 +393,7 @@ fn main() {
                     Annotation {
                         range: 17..21,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -428,7 +428,7 @@ fn main() {
                     Annotation {
                         range: 7..11,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -436,13 +436,13 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
                                         range: 57..61,
                                     },
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -455,7 +455,7 @@ fn main() {
                     Annotation {
                         range: 7..11,
                         kind: HasImpls {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -479,7 +479,7 @@ fn main() {
                     Annotation {
                         range: 20..31,
                         kind: HasImpls {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -503,7 +503,7 @@ fn main() {
                     Annotation {
                         range: 20..31,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -511,7 +511,7 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -524,7 +524,7 @@ fn main() {
                     Annotation {
                         range: 69..73,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -589,7 +589,7 @@ fn main() {}
                     Annotation {
                         range: 3..7,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -624,7 +624,7 @@ fn main() {
                     Annotation {
                         range: 7..11,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -632,13 +632,13 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
                                         range: 19..23,
                                     },
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -651,7 +651,7 @@ fn main() {
                     Annotation {
                         range: 7..11,
                         kind: HasImpls {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -675,7 +675,7 @@ fn main() {
                     Annotation {
                         range: 33..44,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -683,7 +683,7 @@ fn main() {
                             },
                             data: Some(
                                 [
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -696,7 +696,7 @@ fn main() {
                     Annotation {
                         range: 61..65,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -747,7 +747,7 @@ mod tests {
                     Annotation {
                         range: 3..7,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -877,7 +877,7 @@ struct Foo;
                     Annotation {
                         range: 0..71,
                         kind: HasReferences {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
@@ -891,7 +891,7 @@ struct Foo;
                     Annotation {
                         range: 0..71,
                         kind: HasImpls {
-                            pos: FilePosition {
+                            pos: FilePositionWrapper {
                                 file_id: FileId(
                                     0,
                                 ),
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index 4a7db2d29567a..3257305184e91 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -2358,17 +2358,17 @@ fn test_hover_trait_show_qualifiers() {
     check_actions(
         r"unsafe trait foo$0() {}",
         expect![[r#"
-                [
-                    Implementation(
-                        FilePosition {
-                            file_id: FileId(
-                                0,
-                            ),
-                            offset: 13,
-                        },
-                    ),
-                ]
-            "#]],
+            [
+                Implementation(
+                    FilePositionWrapper {
+                        file_id: FileId(
+                            0,
+                        ),
+                        offset: 13,
+                    },
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2925,17 +2925,17 @@ fn test_hover_trait_has_impl_action() {
     check_actions(
         r#"trait foo$0() {}"#,
         expect![[r#"
-                [
-                    Implementation(
-                        FilePosition {
-                            file_id: FileId(
-                                0,
-                            ),
-                            offset: 6,
-                        },
-                    ),
-                ]
-            "#]],
+            [
+                Implementation(
+                    FilePositionWrapper {
+                        file_id: FileId(
+                            0,
+                        ),
+                        offset: 6,
+                    },
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2944,17 +2944,17 @@ fn test_hover_struct_has_impl_action() {
     check_actions(
         r"struct foo$0() {}",
         expect![[r#"
-                [
-                    Implementation(
-                        FilePosition {
-                            file_id: FileId(
-                                0,
-                            ),
-                            offset: 7,
-                        },
-                    ),
-                ]
-            "#]],
+            [
+                Implementation(
+                    FilePositionWrapper {
+                        file_id: FileId(
+                            0,
+                        ),
+                        offset: 7,
+                    },
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2963,17 +2963,17 @@ fn test_hover_union_has_impl_action() {
     check_actions(
         r#"union foo$0() {}"#,
         expect![[r#"
-                [
-                    Implementation(
-                        FilePosition {
-                            file_id: FileId(
-                                0,
-                            ),
-                            offset: 6,
-                        },
-                    ),
-                ]
-            "#]],
+            [
+                Implementation(
+                    FilePositionWrapper {
+                        file_id: FileId(
+                            0,
+                        ),
+                        offset: 6,
+                    },
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2982,17 +2982,17 @@ fn test_hover_enum_has_impl_action() {
     check_actions(
         r"enum foo$0() { A, B }",
         expect![[r#"
-                [
-                    Implementation(
-                        FilePosition {
-                            file_id: FileId(
-                                0,
-                            ),
-                            offset: 5,
-                        },
-                    ),
-                ]
-            "#]],
+            [
+                Implementation(
+                    FilePositionWrapper {
+                        file_id: FileId(
+                            0,
+                        ),
+                        offset: 5,
+                    },
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3001,17 +3001,17 @@ fn test_hover_self_has_impl_action() {
     check_actions(
         r#"struct foo where Self$0:;"#,
         expect![[r#"
-                [
-                    Implementation(
-                        FilePosition {
-                            file_id: FileId(
-                                0,
-                            ),
-                            offset: 7,
-                        },
-                    ),
-                ]
-            "#]],
+            [
+                Implementation(
+                    FilePositionWrapper {
+                        file_id: FileId(
+                            0,
+                        ),
+                        offset: 7,
+                    },
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3025,7 +3025,7 @@ fn foo_$0test() {}
         expect![[r#"
             [
                 Reference(
-                    FilePosition {
+                    FilePositionWrapper {
                         file_id: FileId(
                             0,
                         ),
@@ -8450,7 +8450,7 @@ impl Iterator for S {
         expect![[r#"
             [
                 Implementation(
-                    FilePosition {
+                    FilePositionWrapper {
                         file_id: FileId(
                             0,
                         ),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
index 01e748a8fa136..4e15213b8bbf0 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
@@ -143,7 +143,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -162,7 +162,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "A",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -226,7 +226,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "C",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -245,7 +245,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -293,7 +293,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "C",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -312,7 +312,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -361,7 +361,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "B",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -374,7 +374,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "X",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -393,7 +393,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "A",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -406,7 +406,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "X",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -457,7 +457,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             1,
                                         ),
@@ -470,7 +470,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             1,
                                         ),
@@ -489,7 +489,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             1,
                                         ),
@@ -502,7 +502,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             1,
                                         ),
@@ -521,7 +521,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Iterator",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             1,
                                         ),
@@ -534,7 +534,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Item",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             1,
                                         ),
@@ -553,7 +553,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "MyIter",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -601,7 +601,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -620,7 +620,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -639,7 +639,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "Struct",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
@@ -657,7 +657,7 @@ fn main() {
                             InlayHintLabelPart {
                                 text: "self",
                                 linked_location: Some(
-                                    FileRange {
+                                    FileRangeWrapper {
                                         file_id: FileId(
                                             0,
                                         ),
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 9ddfcaa7089b7..0bc6da9dc7ee6 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -310,11 +310,6 @@
                 "command": "rust-analyzer.openWalkthrough",
                 "title": "Open Walkthrough",
                 "category": "rust-analyzer"
-            },
-            {
-                "command": "rust-analyzer.openFAQ",
-                "title": "Open FAQ",
-                "category": "rust-analyzer"
             }
         ],
         "keybindings": [

From eae705e5ed89332ed1a7caabeff19944963a1713 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 18 Jul 2024 10:03:19 +0200
Subject: [PATCH 048/489] Rewrite inline parser test infra to generated proper
 rust test cases

---
 .../crates/parser/src/grammar/items.rs        |   2 +-
 .../crates/parser/src/grammar/types.rs        |   2 +-
 .../rust-analyzer/crates/parser/src/tests.rs  |  47 +-
 .../parser/test_data/generated/runner.rs      | 810 ++++++++++++++++++
 ...ual.rast => angled_path_without_qual.rast} |   0
 ...ut_qual.rs => angled_path_without_qual.rs} |   0
 ...mous_static.rast => anonymous_static.rast} |   0
 ...nonymous_static.rs => anonymous_static.rs} |   0
 ...t_recovery.rast => arg_list_recovery.rast} |   0
 ..._list_recovery.rs => arg_list_recovery.rs} |   0
 ...semi.rast => array_type_missing_semi.rast} |   0
 ...ing_semi.rs => array_type_missing_semi.rs} |   0
 ...olon.rast => async_without_semicolon.rast} |   0
 ...emicolon.rs => async_without_semicolon.rs} |   0
 ...comma_after_functional_update_syntax.rast} |   0
 ...> comma_after_functional_update_syntax.rs} |   0
 ...st => crate_visibility_empty_recover.rast} |   0
 ...r.rs => crate_visibility_empty_recover.rs} |   0
 ..._param_slot.rast => empty_param_slot.rast} |   0
 ...mpty_param_slot.rs => empty_param_slot.rs} |   0
 ..._empty_segment.rast => empty_segment.rast} |   0
 ...0015_empty_segment.rs => empty_segment.rs} |   0
 ...n.rast => fn_pointer_type_missing_fn.rast} |   0
 ...ng_fn.rs => fn_pointer_type_missing_fn.rs} |   0
 .../{0035_gen_blocks.rast => gen_blocks.rast} |   0
 .../err/{0035_gen_blocks.rs => gen_blocks.rs} |   0
 .../err/{0036_gen_fn.rast => gen_fn.rast}     |   0
 .../inline/err/{0036_gen_fn.rs => gen_fn.rs}  |   0
 ...ver.rast => generic_arg_list_recover.rast} |   0
 ...recover.rs => generic_arg_list_recover.rs} |   0
 ...r.rast => generic_param_list_recover.rast} |   0
 ...cover.rs => generic_param_list_recover.rs} |   0
 .../{0004_impl_type.rast => impl_type.rast}   |   0
 .../err/{0004_impl_type.rs => impl_type.rs}   |   0
 ...e.rast => let_else_right_curly_brace.rast} |   0
 ...brace.rs => let_else_right_curly_brace.rs} |   0
 ...me.rast => macro_rules_as_macro_name.rast} |   0
 ...o_name.rs => macro_rules_as_macro_name.rs} |   0
 ...recovery.rast => match_arms_recovery.rast} |   0
 ...rms_recovery.rs => match_arms_recovery.rs} |   0
 ...=> method_call_missing_argument_list.rast} |   0
 ...s => method_call_missing_argument_list.rs} |   0
 ...abel_err.rast => misplaced_label_err.rast} |   0
 ...ed_label_err.rs => misplaced_label_err.rs} |   0
 ...m_type.rast => missing_fn_param_type.rast} |   0
 ...param_type.rs => missing_fn_param_type.rs} |   0
 ...y.rast => pointer_type_no_mutability.rast} |   0
 ...ility.rs => pointer_type_no_mutability.rs} |   0
 .../err/{0008_pub_expr.rast => pub_expr.rast} |   0
 .../err/{0008_pub_expr.rs => pub_expr.rs}     |   0
 ...ord_literal_before_ellipsis_recovery.rast} |   0
 ...ecord_literal_before_ellipsis_recovery.rs} |   0
 ... => record_literal_field_eq_recovery.rast} |   0
 ...rs => record_literal_field_eq_recovery.rs} |   0
 ...rd_literal_missing_ellipsis_recovery.rast} |   0
 ...cord_literal_missing_ellipsis_recovery.rs} |   0
 ...rast => record_pat_field_eq_recovery.rast} |   0
 ...ery.rs => record_pat_field_eq_recovery.rs} |   0
 ...over_from_missing_assoc_item_binding.rast} |   0
 ...ecover_from_missing_assoc_item_binding.rs} |   0
 ...> recover_from_missing_const_default.rast} |   0
 ... => recover_from_missing_const_default.rs} |   0
 ...recover.rast => struct_field_recover.rast} |   0
 ...eld_recover.rs => struct_field_recover.rs} |   0
 ..._top_level_let.rast => top_level_let.rast} |   0
 ...0024_top_level_let.rs => top_level_let.rs} |   0
 ...mma.rast => tuple_expr_leading_comma.rast} |   0
 ...g_comma.rs => tuple_expr_leading_comma.rs} |   0
 ...ry.rast => tuple_field_list_recovery.rast} |   0
 ...covery.rs => tuple_field_list_recovery.rs} |   0
 ...omma.rast => tuple_pat_leading_comma.rast} |   0
 ...ng_comma.rs => tuple_pat_leading_comma.rs} |   0
 ...k_in_mod.rast => unsafe_block_in_mod.rast} |   0
 ...block_in_mod.rs => unsafe_block_in_mod.rs} |   0
 ...y.rast => use_tree_list_err_recovery.rast} |   0
 ...overy.rs => use_tree_list_err_recovery.rs} |   0
 .../parser/inline/ok/0083_struct_items.rast   |  87 --
 ...nymous_const.rast => anonymous_const.rast} |   0
 ..._anonymous_const.rs => anonymous_const.rs} |   0
 ...rb_self_types.rast => arb_self_types.rast} |   0
 ...18_arb_self_types.rs => arb_self_types.rs} |   0
 ..._arg_with_attr.rast => arg_with_attr.rast} |   0
 ...0152_arg_with_attr.rs => arg_with_attr.rs} |   0
 ...0150_array_attrs.rast => array_attrs.rast} |   0
 .../{0150_array_attrs.rs => array_attrs.rs}   |   0
 .../{0103_array_expr.rast => array_expr.rast} |   0
 .../ok/{0103_array_expr.rs => array_expr.rs}  |   0
 .../{0017_array_type.rast => array_type.rast} |   0
 .../ok/{0017_array_type.rs => array_type.rs}  |   0
 ..._as_precedence.rast => as_precedence.rast} |   0
 ...0146_as_precedence.rs => as_precedence.rs} |   0
 ...ssoc_const_eq.rast => assoc_const_eq.rast} |   0
 ...00_assoc_const_eq.rs => assoc_const_eq.rs} |   0
 ...oc_item_list.rast => assoc_item_list.rast} |   0
 ..._assoc_item_list.rs => assoc_item_list.rs} |   0
 ....rast => assoc_item_list_inner_attrs.rast} |   0
 ...ttrs.rs => assoc_item_list_inner_attrs.rs} |   0
 ..._type_bound.rast => assoc_type_bound.rast} |   0
 ...ssoc_type_bound.rs => assoc_type_bound.rs} |   0
 ..._assoc_type_eq.rast => assoc_type_eq.rast} |   0
 ...0187_assoc_type_eq.rs => assoc_type_eq.rs} |   0
 ...ast => associated_return_type_bounds.rast} |   0
 ...ds.rs => associated_return_type_bounds.rs} |   0
 ...ounds.rast => associated_type_bounds.rast} |   0
 ...pe_bounds.rs => associated_type_bounds.rs} |   0
 ...rait_bound.rast => async_trait_bound.rast} |   0
 ...nc_trait_bound.rs => async_trait_bound.rs} |   0
 ..._expr_stmt.rast => attr_on_expr_stmt.rast} |   0
 ...r_on_expr_stmt.rs => attr_on_expr_stmt.rs} |   0
 .../{0137_await_expr.rast => await_expr.rast} |   0
 .../ok/{0137_await_expr.rs => await_expr.rs}  |   0
 ...bare_dyn_types_with_leading_lifetime.rast} |   0
 ...> bare_dyn_types_with_leading_lifetime.rs} |   0
 ...dyn_types_with_paren_as_generic_args.rast} |   0
 ...e_dyn_types_with_paren_as_generic_args.rs} |   0
 ...0209_become_expr.rast => become_expr.rast} |   0
 .../{0209_become_expr.rs => become_expr.rs}   |   0
 .../ok/{0112_bind_pat.rast => bind_pat.rast}  |   0
 .../ok/{0112_bind_pat.rs => bind_pat.rs}      |   0
 ...s.rast => binop_resets_statementness.rast} |   0
 ...tness.rs => binop_resets_statementness.rs} |   0
 .../inline/ok/{0075_block.rast => block.rast} |   0
 .../inline/ok/{0075_block.rs => block.rs}     |   0
 ...0044_block_items.rast => block_items.rast} |   0
 .../{0044_block_items.rs => block_items.rs}   |   0
 .../ok/{0143_box_pat.rast => box_pat.rast}    |   0
 .../inline/ok/{0143_box_pat.rs => box_pat.rs} |   0
 ...ak_ambiguity.rast => break_ambiguity.rast} |   0
 ..._break_ambiguity.rs => break_ambiguity.rs} |   0
 .../{0034_break_expr.rast => break_expr.rast} |   0
 .../ok/{0034_break_expr.rs => break_expr.rs}  |   0
 ...07_builtin_expr.rast => builtin_expr.rast} |   0
 .../{0207_builtin_expr.rs => builtin_expr.rs} |   0
 .../{0042_call_expr.rast => call_expr.rast}   |   0
 .../ok/{0042_call_expr.rs => call_expr.rs}    |   0
 .../{0029_cast_expr.rast => cast_expr.rast}   |   0
 .../ok/{0029_cast_expr.rs => cast_expr.rs}    |   0
 ...> closure_body_underscore_assignment.rast} |   0
 ... => closure_body_underscore_assignment.rs} |   0
 ...losure_params.rast => closure_params.rast} |   0
 ...55_closure_params.rs => closure_params.rs} |   0
 ...ll.rast => closure_range_method_call.rast} |   0
 ...d_call.rs => closure_range_method_call.rs} |   0
 .../{0184_const_arg.rast => const_arg.rast}   |   0
 .../ok/{0184_const_arg.rs => const_arg.rs}    |   0
 ...st_arg_block.rast => const_arg_block.rast} |   0
 ..._const_arg_block.rs => const_arg_block.rs} |   0
 ...teral.rast => const_arg_bool_literal.rast} |   0
 ...l_literal.rs => const_arg_bool_literal.rs} |   0
 ...rg_literal.rast => const_arg_literal.rast} |   0
 ...st_arg_literal.rs => const_arg_literal.rs} |   0
 ...er.rast => const_arg_negative_number.rast} |   0
 ...number.rs => const_arg_negative_number.rs} |   0
 ...st_block_pat.rast => const_block_pat.rast} |   0
 ..._const_block_pat.rs => const_block_pat.rs} |   0
 ..._const_closure.rast => const_closure.rast} |   0
 ...0205_const_closure.rs => const_closure.rs} |   0
 .../{0172_const_item.rast => const_item.rast} |   0
 .../ok/{0172_const_item.rs => const_item.rs}  |   0
 ...0147_const_param.rast => const_param.rast} |   0
 .../{0147_const_param.rs => const_param.rs}   |   0
 ...st => const_param_default_expression.rast} |   0
 ...n.rs => const_param_default_expression.rs} |   0
 ....rast => const_param_default_literal.rast} |   0
 ...eral.rs => const_param_default_literal.rs} |   0
 ...ath.rast => const_param_default_path.rast} |   0
 ...lt_path.rs => const_param_default_path.rs} |   0
 ...rait_bound.rast => const_trait_bound.rast} |   0
 ...st_trait_bound.rs => const_trait_bound.rs} |   0
 ..._continue_expr.rast => continue_expr.rast} |   0
 ...0015_continue_expr.rs => continue_expr.rs} |   0
 .../{0067_crate_path.rast => crate_path.rast} |   0
 .../ok/{0067_crate_path.rs => crate_path.rs}  |   0
 ..._visibility.rast => crate_visibility.rast} |   0
 ...rate_visibility.rs => crate_visibility.rs} |   0
 ...ility_in.rast => crate_visibility_in.rast} |   0
 ...isibility_in.rs => crate_visibility_in.rs} |   0
 ...lt_async_fn.rast => default_async_fn.rast} |   0
 ...efault_async_fn.rs => default_async_fn.rs} |   0
 ...e_fn.rast => default_async_unsafe_fn.rast} |   0
 ...nsafe_fn.rs => default_async_unsafe_fn.rs} |   0
 ...64_default_item.rast => default_item.rast} |   0
 .../{0164_default_item.rs => default_item.rs} |   0
 ...afe_item.rast => default_unsafe_item.rast} |   0
 ..._unsafe_item.rs => default_unsafe_item.rs} |   0
 ...uring_assignment_struct_rest_pattern.rast} |   0
 ...cturing_assignment_struct_rest_pattern.rs} |   0
 ...estructuring_assignment_wildcard_pat.rast} |   0
 ... destructuring_assignment_wildcard_pat.rs} |   0
 ...0144_dot_dot_pat.rast => dot_dot_pat.rast} |   0
 .../{0144_dot_dot_pat.rs => dot_dot_pat.rs}   |   0
 ...yn_trait_type.rast => dyn_trait_type.rast} |   0
 ...65_dyn_trait_type.rs => dyn_trait_type.rs} |   0
 ..._effect_blocks.rast => effect_blocks.rast} |   0
 ...0199_effect_blocks.rs => effect_blocks.rs} |   0
 ...ange_pat.rast => exclusive_range_pat.rast} |   0
 ...ve_range_pat.rs => exclusive_range_pat.rs} |   0
 ..._expr_literals.rast => expr_literals.rast} |   0
 ...0085_expr_literals.rs => expr_literals.rs} |   0
 ...block.rast => expression_after_block.rast} |   0
 ...ter_block.rs => expression_after_block.rs} |   0
 ...10_extern_block.rast => extern_block.rast} |   0
 .../{0010_extern_block.rs => extern_block.rs} |   0
 ...60_extern_crate.rast => extern_crate.rast} |   0
 .../{0060_extern_crate.rs => extern_crate.rs} |   0
 ...e_rename.rast => extern_crate_rename.rast} |   0
 ...crate_rename.rs => extern_crate_rename.rs} |   0
 ...crate_self.rast => extern_crate_self.rast} |   0
 ...ern_crate_self.rs => extern_crate_self.rs} |   0
 .../{0011_field_expr.rast => field_expr.rast} |   0
 .../ok/{0011_field_expr.rs => field_expr.rs}  |   0
 .../inline/ok/{0151_fn.rast => fn_.rast}      |   0
 .../parser/inline/ok/{0151_fn.rs => fn_.rs}   |   0
 .../ok/{0050_fn_decl.rast => fn_decl.rast}    |   0
 .../inline/ok/{0050_fn_decl.rs => fn_decl.rs} |   0
 ...56_fn_def_param.rast => fn_def_param.rast} |   0
 .../{0156_fn_def_param.rs => fn_def_param.rs} |   0
 ....rast => fn_pointer_param_ident_path.rast} |   0
 ...path.rs => fn_pointer_param_ident_path.rs} |   0
 ...pointer_type.rast => fn_pointer_type.rast} |   0
 ..._fn_pointer_type.rs => fn_pointer_type.rs} |   0
 ...ret.rast => fn_pointer_type_with_ret.rast} |   0
 ...ith_ret.rs => fn_pointer_type_with_ret.rs} |   0
 ...d_arg.rast => fn_pointer_unnamed_arg.rast} |   0
 ...named_arg.rs => fn_pointer_unnamed_arg.rs} |   0
 .../ok/{0100_for_expr.rast => for_expr.rast}  |   0
 .../ok/{0100_for_expr.rs => for_expr.rs}      |   0
 ...or_range_from.rast => for_range_from.rast} |   0
 ...42_for_range_from.rs => for_range_from.rs} |   0
 .../ok/{0081_for_type.rast => for_type.rast}  |   0
 .../ok/{0081_for_type.rs => for_type.rs}      |   0
 ...l_range_expr.rast => full_range_expr.rast} |   0
 ..._full_range_expr.rs => full_range_expr.rs} |   0
 ...n_ret_type.rast => function_ret_type.rast} |   0
 ...ction_ret_type.rs => function_ret_type.rs} |   0
 ..._params.rast => function_type_params.rast} |   0
 ...type_params.rs => function_type_params.rs} |   0
 ...clause.rast => function_where_clause.rast} |   0
 ...ere_clause.rs => function_where_clause.rs} |   0
 ...0190_generic_arg.rast => generic_arg.rast} |   0
 .../{0190_generic_arg.rs => generic_arg.rs}   |   0
 ...bute.rast => generic_param_attribute.rast} |   0
 ...ttribute.rs => generic_param_attribute.rs} |   0
 ...ype_param.rast => generic_param_list.rast} |   0
 ...83_type_param.rs => generic_param_list.rs} |   0
 ...ange_pat.rast => half_open_range_pat.rast} |   0
 ...en_range_pat.rs => half_open_range_pat.rs} |   0
 .../ok/{0064_if_expr.rast => if_expr.rast}    |   0
 .../inline/ok/{0064_if_expr.rs => if_expr.rs} |   0
 .../{0079_impl_item.rast => impl_item.rast}   |   0
 .../ok/{0079_impl_item.rs => impl_item.rs}    |   0
 ...l_item_const.rast => impl_item_const.rast} |   0
 ..._impl_item_const.rs => impl_item_const.rs} |   0
 ..._impl_item_neg.rast => impl_item_neg.rast} |   0
 ...0063_impl_item_neg.rs => impl_item_neg.rs} |   0
 ...l_trait_type.rast => impl_trait_type.rast} |   0
 ..._impl_trait_type.rs => impl_trait_type.rs} |   0
 ...type_params.rast => impl_type_params.rast} |   0
 ...mpl_type_params.rs => impl_type_params.rs} |   0
 .../{0093_index_expr.rast => index_expr.rast} |   0
 .../ok/{0093_index_expr.rs => index_expr.rs}  |   0
 .../inline/ok/{0109_label.rast => label.rast} |   0
 .../inline/ok/{0109_label.rs => label.rs}     |   0
 ..._labeled_block.rast => labeled_block.rast} |   0
 ...0161_labeled_block.rs => labeled_block.rs} |   0
 ...0106_lambda_expr.rast => lambda_expr.rast} |   0
 .../{0106_lambda_expr.rs => lambda_expr.rs}   |   0
 ...a_ret_block.rast => lambda_ret_block.rast} |   0
 ...ambda_ret_block.rs => lambda_ret_block.rs} |   0
 .../ok/{0194_let_else.rast => let_else.rast}  |   0
 .../ok/{0194_let_else.rs => let_else.rs}      |   0
 .../ok/{0030_let_expr.rast => let_expr.rast}  |   0
 .../ok/{0030_let_expr.rs => let_expr.rs}      |   0
 .../ok/{0130_let_stmt.rast => let_stmt.rast}  |   0
 .../ok/{0130_let_stmt.rs => let_stmt.rs}      |   0
 ...cription.rast => let_stmt_ascription.rast} |   0
 ...t_ascription.rs => let_stmt_ascription.rs} |   0
 ..._let_stmt_init.rast => let_stmt_init.rast} |   0
 ...0193_let_stmt_init.rs => let_stmt_init.rs} |   0
 ...86_lifetime_arg.rast => lifetime_arg.rast} |   0
 .../{0186_lifetime_arg.rs => lifetime_arg.rs} |   0
 ...ifetime_param.rast => lifetime_param.rast} |   0
 ...82_lifetime_param.rs => lifetime_param.rs} |   0
 ...eral_pattern.rast => literal_pattern.rast} |   0
 ..._literal_pattern.rs => literal_pattern.rs} |   0
 .../{0009_loop_expr.rast => loop_expr.rast}   |   0
 .../ok/{0009_loop_expr.rs => loop_expr.rs}    |   0
 ...ro_call_type.rast => macro_call_type.rast} |   0
 ..._macro_call_type.rs => macro_call_type.rs} |   0
 .../{0147_macro_def.rast => macro_def.rast}   |   0
 .../ok/{0147_macro_def.rs => macro_def.rs}    |   0
 ...ro_def_curly.rast => macro_def_curly.rast} |   0
 ..._macro_def_curly.rs => macro_def_curly.rs} |   0
 ...arg.rast => macro_inside_generic_arg.rast} |   0
 ...ric_arg.rs => macro_inside_generic_arg.rs} |   0
 ...me.rast => macro_rules_as_macro_name.rast} |   0
 ...o_name.rs => macro_rules_as_macro_name.rs} |   0
 ..._brace.rast => macro_rules_non_brace.rast} |   0
 ..._non_brace.rs => macro_rules_non_brace.rs} |   0
 .../{0129_marco_pat.rast => marco_pat.rast}   |   0
 .../ok/{0129_marco_pat.rs => marco_pat.rs}    |   0
 .../{0066_match_arm.rast => match_arm.rast}   |   0
 .../ok/{0066_match_arm.rs => match_arm.rs}    |   0
 ...rms_commas.rast => match_arms_commas.rast} |   0
 ...ch_arms_commas.rs => match_arms_commas.rs} |   0
 ...e.rast => match_arms_inner_attribute.rast} |   0
 ...ibute.rs => match_arms_inner_attribute.rs} |   0
 ....rast => match_arms_outer_attributes.rast} |   0
 ...utes.rs => match_arms_outer_attributes.rs} |   0
 .../{0071_match_expr.rast => match_expr.rast} |   0
 .../ok/{0071_match_expr.rs => match_expr.rs}  |   0
 ...0118_match_guard.rast => match_guard.rast} |   0
 .../{0118_match_guard.rs => match_guard.rs}   |   0
 .../inline/ok/{0213_metas.rast => metas.rast} |   0
 .../inline/ok/{0213_metas.rs => metas.rs}     |   0
 ...d_call_expr.rast => method_call_expr.rast} |   0
 ...ethod_call_expr.rs => method_call_expr.rs} |   0
 ...62_mod_contents.rast => mod_contents.rast} |   0
 .../{0062_mod_contents.rs => mod_contents.rs} |   0
 .../ok/{0169_mod_item.rast => mod_item.rast}  |   0
 .../ok/{0169_mod_item.rs => mod_item.rs}      |   0
 ...od_item_curly.rast => mod_item_curly.rast} |   0
 ...70_mod_item_curly.rs => mod_item_curly.rs} |   0
 .../{0014_never_type.rast => never_type.rast} |   0
 .../ok/{0014_never_type.rs => never_type.rs}  |   0
 ...for.rast => no_dyn_trait_leading_for.rast} |   0
 ...ing_for.rs => no_dyn_trait_leading_for.rs} |   0
 ...er_block.rast => no_semi_after_block.rast} |   0
 ..._after_block.rs => no_semi_after_block.rs} |   0
 ..._nocontentexpr.rast => nocontentexpr.rast} |   0
 ...0113_nocontentexpr.rs => nocontentexpr.rs} |   0
 ...tem.rast => nocontentexpr_after_item.rast} |   0
 ...er_item.rs => nocontentexpr_after_item.rs} |   0
 .../{0156_or_pattern.rast => or_pattern.rast} |   0
 .../ok/{0156_or_pattern.rs => or_pattern.rs}  |   0
 .../{0099_param_list.rast => param_list.rast} |   0
 .../ok/{0099_param_list.rs => param_list.rs}  |   0
 ...erns.rast => param_list_opt_patterns.rast} |   0
 ...patterns.rs => param_list_opt_patterns.rs} |   0
 ...ist_vararg.rast => param_list_vararg.rast} |   0
 ...am_list_vararg.rs => param_list_vararg.rs} |   0
 ...am_outer_arg.rast => param_outer_arg.rast} |   0
 ..._param_outer_arg.rs => param_outer_arg.rs} |   0
 .../{0084_paren_type.rast => paren_type.rast} |   0
 .../ok/{0084_paren_type.rs => paren_type.rs}  |   0
 .../{0053_path_expr.rast => path_expr.rast}   |   0
 .../ok/{0053_path_expr.rs => path_expr.rs}    |   0
 ...rait_args.rast => path_fn_trait_args.rast} |   0
 ...fn_trait_args.rs => path_fn_trait_args.rs} |   0
 .../{0008_path_part.rast => path_part.rast}   |   0
 .../ok/{0008_path_part.rs => path_part.rs}    |   0
 .../{0052_path_type.rast => path_type.rast}   |   0
 .../ok/{0052_path_type.rs => path_type.rs}    |   0
 ...bounds.rast => path_type_with_bounds.rast} |   0
 ...ith_bounds.rs => path_type_with_bounds.rs} |   0
 ...ceholder_pat.rast => placeholder_pat.rast} |   0
 ..._placeholder_pat.rs => placeholder_pat.rs} |   0
 ...holder_type.rast => placeholder_type.rast} |   0
 ...laceholder_type.rs => placeholder_type.rs} |   0
 ...er_type_mut.rast => pointer_type_mut.rast} |   0
 ...ointer_type_mut.rs => pointer_type_mut.rs} |   0
 ..._postfix_range.rast => postfix_range.rast} |   0
 ...0080_postfix_range.rs => postfix_range.rs} |   0
 ...typepath.rast => pub_parens_typepath.rast} |   0
 ...ens_typepath.rs => pub_parens_typepath.rs} |   0
 ..._tuple_field.rast => pub_tuple_field.rast} |   0
 ..._pub_tuple_field.rs => pub_tuple_field.rs} |   0
 .../{0037_qual_paths.rast => qual_paths.rast} |   0
 .../ok/{0037_qual_paths.rs => qual_paths.rs}  |   0
 ...ast => question_for_type_trait_bound.rast} |   0
 ...nd.rs => question_for_type_trait_bound.rs} |   0
 .../{0058_range_pat.rast => range_pat.rast}   |   0
 .../ok/{0058_range_pat.rs => range_pat.rs}    |   0
 ...eld_attrs.rast => record_field_attrs.rast} |   0
 ...d_field_attrs.rs => record_field_attrs.rs} |   0
 ...field_list.rast => record_field_list.rast} |   0
 ...ord_field_list.rs => record_field_list.rs} |   0
 .../{0061_record_lit.rast => record_lit.rast} |   0
 .../ok/{0061_record_lit.rs => record_lit.rs}  |   0
 ...st => record_literal_field_with_attr.rast} |   0
 ...r.rs => record_literal_field_with_attr.rs} |   0
 ...d_pat_field.rast => record_pat_field.rast} |   0
 ...ecord_pat_field.rs => record_pat_field.rs} |   0
 ...d_list.rast => record_pat_field_list.rast} |   0
 ...field_list.rs => record_pat_field_list.rs} |   0
 .../ok/{0082_ref_expr.rast => ref_expr.rast}  |   0
 .../ok/{0082_ref_expr.rs => ref_expr.rs}      |   0
 .../ok/{0027_ref_pat.rast => ref_pat.rast}    |   0
 .../inline/ok/{0027_ref_pat.rs => ref_pat.rs} |   0
 ...ference_type;.rast => reference_type.rast} |   0
 ...3_reference_type;.rs => reference_type.rs} |   0
 ...0072_return_expr.rast => return_expr.rast} |   0
 .../{0072_return_expr.rs => return_expr.rs}   |   0
 .../{0006_self_param.rast => self_param.rast} |   0
 .../ok/{0006_self_param.rs => self_param.rs}  |   0
 ...r_attr.rast => self_param_outer_attr.rast} |   0
 ...outer_attr.rs => self_param_outer_attr.rs} |   0
 ...le_type.rast => singleton_tuple_type.rast} |   0
 ..._tuple_type.rs => singleton_tuple_type.rs} |   0
 .../{0024_slice_pat.rast => slice_pat.rast}   |   0
 .../ok/{0024_slice_pat.rs => slice_pat.rs}    |   0
 .../{0025_slice_type.rast => slice_type.rast} |   0
 .../ok/{0025_slice_type.rs => slice_type.rs}  |   0
 ...uity.rast => stmt_bin_expr_ambiguity.rast} |   0
 ...mbiguity.rs => stmt_bin_expr_ambiguity.rs} |   0
 ....rast => stmt_postfix_expr_ambiguity.rast} |   0
 ...uity.rs => stmt_postfix_expr_ambiguity.rs} |   0
 ...0171_struct_item.rast => struct_item.rast} |   0
 .../{0171_struct_item.rs => struct_item.rs}   |   0
 ...0151_trait_alias.rast => trait_alias.rast} |   0
 .../{0151_trait_alias.rs => trait_alias.rs}   |   0
 ...use.rast => trait_alias_where_clause.rast} |   0
 ..._clause.rs => trait_alias_where_clause.rs} |   0
 .../{0041_trait_item.rast => trait_item.rast} |   0
 .../ok/{0041_trait_item.rs => trait_item.rs}  |   0
 ...tem_bounds.rast => trait_item_bounds.rast} |   0
 ...it_item_bounds.rs => trait_item_bounds.rs} |   0
 ...ms.rast => trait_item_generic_params.rast} |   0
 ...params.rs => trait_item_generic_params.rs} |   0
 ...ause.rast => trait_item_where_clause.rast} |   0
 ...e_clause.rs => trait_item_where_clause.rs} |   0
 ...ry_block_expr.rast => try_block_expr.rast} |   0
 ...30_try_block_expr.rs => try_block_expr.rs} |   0
 .../ok/{0077_try_expr.rast => try_expr.rast}  |   0
 .../ok/{0077_try_expr.rs => try_expr.rs}      |   0
 ..._fallback.rast => try_macro_fallback.rast} |   0
 ...acro_fallback.rs => try_macro_fallback.rs} |   0
 ..._macro_rules.rast => try_macro_rules.rast} |   0
 ..._try_macro_rules.rs => try_macro_rules.rs} |   0
 ...0154_tuple_attrs.rast => tuple_attrs.rast} |   0
 .../{0154_tuple_attrs.rs => tuple_attrs.rs}   |   0
 .../{0108_tuple_expr.rast => tuple_expr.rast} |   0
 .../ok/{0108_tuple_expr.rs => tuple_expr.rs}  |   0
 ...ield_attrs.rast => tuple_field_attrs.rast} |   0
 ...le_field_attrs.rs => tuple_field_attrs.rs} |   0
 .../{0111_tuple_pat.rast => tuple_pat.rast}   |   0
 .../ok/{0111_tuple_pat.rs => tuple_pat.rs}    |   0
 ..._pat_fields.rast => tuple_pat_fields.rast} |   0
 ...uple_pat_fields.rs => tuple_pat_fields.rs} |   0
 ...70_tuple_struct.rast => tuple_struct.rast} |   0
 .../{0170_tuple_struct.rs => tuple_struct.rs} |   0
 ...uct_where.rast => tuple_struct_where.rast} |   0
 ..._struct_where.rs => tuple_struct_where.rs} |   0
 .../{0078_type_alias.rast => type_alias.rast} |   0
 .../ok/{0078_type_alias.rs => type_alias.rs}  |   0
 ...params.rast => type_item_type_params.rast} |   0
 ...ype_params.rs => type_item_type_params.rs} |   0
 ...lause.rast => type_item_where_clause.rast} |   0
 ...re_clause.rs => type_item_where_clause.rs} |   0
 ...=> type_item_where_clause_deprecated.rast} |   0
 ...s => type_item_where_clause_deprecated.rs} |   0
 ...eneric_param_list.rast => type_param.rast} |   0
 ...84_generic_param_list.rs => type_param.rs} |   0
 ...ram_bounds.rast => type_param_bounds.rast} |   0
 ...e_param_bounds.rs => type_param_bounds.rs} |   0
 ...m_default.rast => type_param_default.rast} |   0
 ...param_default.rs => type_param_default.rs} |   0
 ...pattern.rast => type_path_in_pattern.rast} |   0
 ..._in_pattern.rs => type_path_in_pattern.rs} |   0
 ...n.rast => typepathfn_with_coloncolon.rast} |   0
 ...colon.rs => typepathfn_with_coloncolon.rs} |   0
 .../{0019_unary_expr.rast => unary_expr.rast} |   0
 .../ok/{0019_unary_expr.rs => unary_expr.rs}  |   0
 .../{0173_union_item.rast => union_item.rast} |   0
 .../ok/{0173_union_item.rs => union_item.rs}  |   0
 ...0174_unit_struct.rast => unit_struct.rast} |   0
 .../{0174_unit_struct.rs => unit_struct.rs}   |   0
 .../{0051_unit_type.rast => unit_type.rast}   |   0
 .../ok/{0051_unit_type.rs => unit_type.rs}    |   0
 .../ok/{0181_use_item.rast => use_item.rast}  |   0
 .../ok/{0181_use_item.rs => use_item.rs}      |   0
 .../ok/{0177_use_tree.rast => use_tree.rast}  |   0
 .../ok/{0177_use_tree.rs => use_tree.rs}      |   0
 ...e_abs_star.rast => use_tree_abs_star.rast} |   0
 ..._tree_abs_star.rs => use_tree_abs_star.rs} |   0
 ...se_tree_alias.rast => use_tree_alias.rast} |   0
 ...76_use_tree_alias.rs => use_tree_alias.rs} |   0
 ..._use_tree_list.rast => use_tree_list.rast} |   0
 ...0002_use_tree_list.rs => use_tree_list.rs} |   0
 ..._use_tree_path.rast => use_tree_path.rast} |   0
 ...0177_use_tree_path.rs => use_tree_path.rs} |   0
 ...path_star.rast => use_tree_path_star.rast} |   0
 ...ree_path_star.rs => use_tree_path_star.rs} |   0
 ..._tree.rast => use_tree_path_use_tree.rast} |   0
 ..._use_tree.rs => use_tree_path_use_tree.rs} |   0
 ..._use_tree_star.rast => use_tree_star.rast} |   0
 ...0174_use_tree_star.rs => use_tree_star.rs} |   0
 ...rast => value_parameters_no_patterns.rast} |   0
 ...rns.rs => value_parameters_no_patterns.rs} |   0
 ...iminant.rast => variant_discriminant.rast} |   0
 ...iscriminant.rs => variant_discriminant.rs} |   0
 ...56_where_clause.rast => where_clause.rast} |   0
 .../{0056_where_clause.rs => where_clause.rs} |   0
 ...here_pred_for.rast => where_pred_for.rast} |   0
 ...03_where_pred_for.rs => where_pred_for.rs} |   0
 .../{0031_while_expr.rast => while_expr.rast} |   0
 .../ok/{0031_while_expr.rs => while_expr.rs}  |   0
 .../{0204_yeet_expr.rast => yeet_expr.rast}   |   0
 .../ok/{0204_yeet_expr.rs => yeet_expr.rs}    |   0
 .../{0159_yield_expr.rast => yield_expr.rast} |   0
 .../ok/{0159_yield_expr.rs => yield_expr.rs}  |   0
 src/tools/rust-analyzer/xtask/src/codegen.rs  |   5 +-
 .../xtask/src/codegen/parser_inline_tests.rs  | 165 ++--
 503 files changed, 955 insertions(+), 163 deletions(-)
 create mode 100644 src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0016_angled_path_without_qual.rast => angled_path_without_qual.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0016_angled_path_without_qual.rs => angled_path_without_qual.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0013_anonymous_static.rast => anonymous_static.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0013_anonymous_static.rs => anonymous_static.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0015_arg_list_recovery.rast => arg_list_recovery.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0015_arg_list_recovery.rs => arg_list_recovery.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0001_array_type_missing_semi.rast => array_type_missing_semi.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0001_array_type_missing_semi.rs => array_type_missing_semi.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0007_async_without_semicolon.rast => async_without_semicolon.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0007_async_without_semicolon.rs => async_without_semicolon.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0024_comma_after_functional_update_syntax.rast => comma_after_functional_update_syntax.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0024_comma_after_functional_update_syntax.rs => comma_after_functional_update_syntax.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0018_crate_visibility_empty_recover.rast => crate_visibility_empty_recover.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0018_crate_visibility_empty_recover.rs => crate_visibility_empty_recover.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0023_empty_param_slot.rast => empty_param_slot.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0023_empty_param_slot.rs => empty_param_slot.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0015_empty_segment.rast => empty_segment.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0015_empty_segment.rs => empty_segment.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0005_fn_pointer_type_missing_fn.rast => fn_pointer_type_missing_fn.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0005_fn_pointer_type_missing_fn.rs => fn_pointer_type_missing_fn.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0035_gen_blocks.rast => gen_blocks.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0035_gen_blocks.rs => gen_blocks.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0036_gen_fn.rast => gen_fn.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0036_gen_fn.rs => gen_fn.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0030_generic_arg_list_recover.rast => generic_arg_list_recover.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0030_generic_arg_list_recover.rs => generic_arg_list_recover.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0031_generic_param_list_recover.rast => generic_param_list_recover.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0031_generic_param_list_recover.rs => generic_param_list_recover.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0004_impl_type.rast => impl_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0004_impl_type.rs => impl_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0017_let_else_right_curly_brace.rast => let_else_right_curly_brace.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0017_let_else_right_curly_brace.rs => let_else_right_curly_brace.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0026_macro_rules_as_macro_name.rast => macro_rules_as_macro_name.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0026_macro_rules_as_macro_name.rs => macro_rules_as_macro_name.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0034_match_arms_recovery.rast => match_arms_recovery.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0034_match_arms_recovery.rs => match_arms_recovery.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0028_method_call_missing_argument_list.rast => method_call_missing_argument_list.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0028_method_call_missing_argument_list.rs => method_call_missing_argument_list.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0002_misplaced_label_err.rast => misplaced_label_err.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0002_misplaced_label_err.rs => misplaced_label_err.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0015_missing_fn_param_type.rast => missing_fn_param_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0015_missing_fn_param_type.rs => missing_fn_param_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0003_pointer_type_no_mutability.rast => pointer_type_no_mutability.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0003_pointer_type_no_mutability.rs => pointer_type_no_mutability.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0008_pub_expr.rast => pub_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0008_pub_expr.rs => pub_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0014_record_literal_before_ellipsis_recovery.rast => record_literal_before_ellipsis_recovery.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0014_record_literal_before_ellipsis_recovery.rs => record_literal_before_ellipsis_recovery.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0032_record_literal_field_eq_recovery.rast => record_literal_field_eq_recovery.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0032_record_literal_field_eq_recovery.rs => record_literal_field_eq_recovery.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0014_record_literal_missing_ellipsis_recovery.rast => record_literal_missing_ellipsis_recovery.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0014_record_literal_missing_ellipsis_recovery.rs => record_literal_missing_ellipsis_recovery.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0033_record_pat_field_eq_recovery.rast => record_pat_field_eq_recovery.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0033_record_pat_field_eq_recovery.rs => record_pat_field_eq_recovery.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0021_recover_from_missing_assoc_item_binding.rast => recover_from_missing_assoc_item_binding.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0021_recover_from_missing_assoc_item_binding.rs => recover_from_missing_assoc_item_binding.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0022_recover_from_missing_const_default.rast => recover_from_missing_const_default.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0022_recover_from_missing_const_default.rs => recover_from_missing_const_default.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0014_struct_field_recover.rast => struct_field_recover.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0014_struct_field_recover.rs => struct_field_recover.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0024_top_level_let.rast => top_level_let.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0024_top_level_let.rs => top_level_let.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0019_tuple_expr_leading_comma.rast => tuple_expr_leading_comma.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0019_tuple_expr_leading_comma.rs => tuple_expr_leading_comma.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0029_tuple_field_list_recovery.rast => tuple_field_list_recovery.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0029_tuple_field_list_recovery.rs => tuple_field_list_recovery.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0020_tuple_pat_leading_comma.rast => tuple_pat_leading_comma.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0020_tuple_pat_leading_comma.rs => tuple_pat_leading_comma.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0006_unsafe_block_in_mod.rast => unsafe_block_in_mod.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0006_unsafe_block_in_mod.rs => unsafe_block_in_mod.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0026_use_tree_list_err_recovery.rast => use_tree_list_err_recovery.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/{0026_use_tree_list_err_recovery.rs => use_tree_list_err_recovery.rs} (100%)
 delete mode 100644 src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0083_struct_items.rast
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0173_anonymous_const.rast => anonymous_const.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0173_anonymous_const.rs => anonymous_const.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0018_arb_self_types.rast => arb_self_types.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0018_arb_self_types.rs => arb_self_types.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0152_arg_with_attr.rast => arg_with_attr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0152_arg_with_attr.rs => arg_with_attr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0150_array_attrs.rast => array_attrs.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0150_array_attrs.rs => array_attrs.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0103_array_expr.rast => array_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0103_array_expr.rs => array_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0017_array_type.rast => array_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0017_array_type.rs => array_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0146_as_precedence.rast => as_precedence.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0146_as_precedence.rs => as_precedence.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0200_assoc_const_eq.rast => assoc_const_eq.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0200_assoc_const_eq.rs => assoc_const_eq.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0021_assoc_item_list.rast => assoc_item_list.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0021_assoc_item_list.rs => assoc_item_list.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0177_assoc_item_list_inner_attrs.rast => assoc_item_list_inner_attrs.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0177_assoc_item_list_inner_attrs.rs => assoc_item_list_inner_attrs.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0185_assoc_type_bound.rast => assoc_type_bound.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0185_assoc_type_bound.rs => assoc_type_bound.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0187_assoc_type_eq.rast => assoc_type_eq.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0187_assoc_type_eq.rs => assoc_type_eq.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0208_associated_return_type_bounds.rast => associated_return_type_bounds.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0208_associated_return_type_bounds.rs => associated_return_type_bounds.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0138_associated_type_bounds.rast => associated_type_bounds.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0138_associated_type_bounds.rs => associated_type_bounds.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0211_async_trait_bound.rast => async_trait_bound.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0211_async_trait_bound.rs => async_trait_bound.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0126_attr_on_expr_stmt.rast => attr_on_expr_stmt.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0126_attr_on_expr_stmt.rs => attr_on_expr_stmt.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0137_await_expr.rast => await_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0137_await_expr.rs => await_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0208_bare_dyn_types_with_leading_lifetime.rast => bare_dyn_types_with_leading_lifetime.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0208_bare_dyn_types_with_leading_lifetime.rs => bare_dyn_types_with_leading_lifetime.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0209_bare_dyn_types_with_paren_as_generic_args.rast => bare_dyn_types_with_paren_as_generic_args.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0209_bare_dyn_types_with_paren_as_generic_args.rs => bare_dyn_types_with_paren_as_generic_args.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0209_become_expr.rast => become_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0209_become_expr.rs => become_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0112_bind_pat.rast => bind_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0112_bind_pat.rs => bind_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0158_binop_resets_statementness.rast => binop_resets_statementness.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0158_binop_resets_statementness.rs => binop_resets_statementness.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0075_block.rast => block.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0075_block.rs => block.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0044_block_items.rast => block_items.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0044_block_items.rs => block_items.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0143_box_pat.rast => box_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0143_box_pat.rs => box_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0088_break_ambiguity.rast => break_ambiguity.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0088_break_ambiguity.rs => break_ambiguity.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0034_break_expr.rast => break_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0034_break_expr.rs => break_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0207_builtin_expr.rast => builtin_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0207_builtin_expr.rs => builtin_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0042_call_expr.rast => call_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0042_call_expr.rs => call_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0029_cast_expr.rast => cast_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0029_cast_expr.rs => cast_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0203_closure_body_underscore_assignment.rast => closure_body_underscore_assignment.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0203_closure_body_underscore_assignment.rs => closure_body_underscore_assignment.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0155_closure_params.rast => closure_params.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0155_closure_params.rs => closure_params.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0208_closure_range_method_call.rast => closure_range_method_call.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0208_closure_range_method_call.rs => closure_range_method_call.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0184_const_arg.rast => const_arg.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0184_const_arg.rs => const_arg.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0183_const_arg_block.rast => const_arg_block.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0183_const_arg_block.rs => const_arg_block.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0192_const_arg_bool_literal.rast => const_arg_bool_literal.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0192_const_arg_bool_literal.rs => const_arg_bool_literal.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0189_const_arg_literal.rast => const_arg_literal.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0189_const_arg_literal.rs => const_arg_literal.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0191_const_arg_negative_number.rast => const_arg_negative_number.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0191_const_arg_negative_number.rs => const_arg_negative_number.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0156_const_block_pat.rast => const_block_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0156_const_block_pat.rs => const_block_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0205_const_closure.rast => const_closure.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0205_const_closure.rs => const_closure.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0172_const_item.rast => const_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0172_const_item.rs => const_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0147_const_param.rast => const_param.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0147_const_param.rs => const_param.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0199_const_param_default_expression.rast => const_param_default_expression.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0199_const_param_default_expression.rs => const_param_default_expression.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0200_const_param_default_literal.rast => const_param_default_literal.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0200_const_param_default_literal.rs => const_param_default_literal.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0188_const_param_default_path.rast => const_param_default_path.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0188_const_param_default_path.rs => const_param_default_path.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0212_const_trait_bound.rast => const_trait_bound.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0212_const_trait_bound.rs => const_trait_bound.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0015_continue_expr.rast => continue_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0015_continue_expr.rs => continue_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0067_crate_path.rast => crate_path.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0067_crate_path.rs => crate_path.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0022_crate_visibility.rast => crate_visibility.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0022_crate_visibility.rs => crate_visibility.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0160_crate_visibility_in.rast => crate_visibility_in.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0160_crate_visibility_in.rs => crate_visibility_in.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0163_default_async_fn.rast => default_async_fn.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0163_default_async_fn.rs => default_async_fn.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0162_default_async_unsafe_fn.rast => default_async_unsafe_fn.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0162_default_async_unsafe_fn.rs => default_async_unsafe_fn.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0164_default_item.rast => default_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0164_default_item.rs => default_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0163_default_unsafe_item.rast => default_unsafe_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0163_default_unsafe_item.rs => default_unsafe_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0197_destructuring_assignment_struct_rest_pattern.rast => destructuring_assignment_struct_rest_pattern.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0197_destructuring_assignment_struct_rest_pattern.rs => destructuring_assignment_struct_rest_pattern.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0198_destructuring_assignment_wildcard_pat.rast => destructuring_assignment_wildcard_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0198_destructuring_assignment_wildcard_pat.rs => destructuring_assignment_wildcard_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0144_dot_dot_pat.rast => dot_dot_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0144_dot_dot_pat.rs => dot_dot_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0065_dyn_trait_type.rast => dyn_trait_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0065_dyn_trait_type.rs => dyn_trait_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0199_effect_blocks.rast => effect_blocks.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0199_effect_blocks.rs => effect_blocks.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0207_exclusive_range_pat.rast => exclusive_range_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0207_exclusive_range_pat.rs => exclusive_range_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0085_expr_literals.rast => expr_literals.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0085_expr_literals.rs => expr_literals.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0138_expression_after_block.rast => expression_after_block.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0138_expression_after_block.rs => expression_after_block.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0010_extern_block.rast => extern_block.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0010_extern_block.rs => extern_block.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0060_extern_crate.rast => extern_crate.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0060_extern_crate.rs => extern_crate.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0168_extern_crate_rename.rast => extern_crate_rename.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0168_extern_crate_rename.rs => extern_crate_rename.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0168_extern_crate_self.rast => extern_crate_self.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0168_extern_crate_self.rs => extern_crate_self.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0011_field_expr.rast => field_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0011_field_expr.rs => field_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0151_fn.rast => fn_.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0151_fn.rs => fn_.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0050_fn_decl.rast => fn_decl.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0050_fn_decl.rs => fn_decl.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0156_fn_def_param.rast => fn_def_param.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0156_fn_def_param.rs => fn_def_param.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0154_fn_pointer_param_ident_path.rast => fn_pointer_param_ident_path.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0154_fn_pointer_param_ident_path.rs => fn_pointer_param_ident_path.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0032_fn_pointer_type.rast => fn_pointer_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0032_fn_pointer_type.rs => fn_pointer_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0092_fn_pointer_type_with_ret.rast => fn_pointer_type_with_ret.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0092_fn_pointer_type_with_ret.rs => fn_pointer_type_with_ret.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0157_fn_pointer_unnamed_arg.rast => fn_pointer_unnamed_arg.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0157_fn_pointer_unnamed_arg.rs => fn_pointer_unnamed_arg.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0100_for_expr.rast => for_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0100_for_expr.rs => for_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0142_for_range_from.rast => for_range_from.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0142_for_range_from.rs => for_range_from.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0081_for_type.rast => for_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0081_for_type.rs => for_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0038_full_range_expr.rast => full_range_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0038_full_range_expr.rs => full_range_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0086_function_ret_type.rast => function_ret_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0086_function_ret_type.rs => function_ret_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0005_function_type_params.rast => function_type_params.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0005_function_type_params.rs => function_type_params.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0076_function_where_clause.rast => function_where_clause.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0076_function_where_clause.rs => function_where_clause.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0190_generic_arg.rast => generic_arg.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0190_generic_arg.rs => generic_arg.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0181_generic_param_attribute.rast => generic_param_attribute.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0181_generic_param_attribute.rs => generic_param_attribute.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0183_type_param.rast => generic_param_list.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0183_type_param.rs => generic_param_list.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0166_half_open_range_pat.rast => half_open_range_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0166_half_open_range_pat.rs => half_open_range_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0064_if_expr.rast => if_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0064_if_expr.rs => if_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0079_impl_item.rast => impl_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0079_impl_item.rs => impl_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0161_impl_item_const.rast => impl_item_const.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0161_impl_item_const.rs => impl_item_const.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0063_impl_item_neg.rast => impl_item_neg.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0063_impl_item_neg.rs => impl_item_neg.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0028_impl_trait_type.rast => impl_trait_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0028_impl_trait_type.rs => impl_trait_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0150_impl_type_params.rast => impl_type_params.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0150_impl_type_params.rs => impl_type_params.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0093_index_expr.rast => index_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0093_index_expr.rs => index_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0109_label.rast => label.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0109_label.rs => label.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0161_labeled_block.rast => labeled_block.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0161_labeled_block.rs => labeled_block.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0106_lambda_expr.rast => lambda_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0106_lambda_expr.rs => lambda_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0158_lambda_ret_block.rast => lambda_ret_block.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0158_lambda_ret_block.rs => lambda_ret_block.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0194_let_else.rast => let_else.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0194_let_else.rs => let_else.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0030_let_expr.rast => let_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0030_let_expr.rs => let_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0130_let_stmt.rast => let_stmt.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0130_let_stmt.rs => let_stmt.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0194_let_stmt_ascription.rast => let_stmt_ascription.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0194_let_stmt_ascription.rs => let_stmt_ascription.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0193_let_stmt_init.rast => let_stmt_init.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0193_let_stmt_init.rs => let_stmt_init.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0186_lifetime_arg.rast => lifetime_arg.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0186_lifetime_arg.rs => lifetime_arg.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0182_lifetime_param.rast => lifetime_param.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0182_lifetime_param.rs => lifetime_param.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0055_literal_pattern.rast => literal_pattern.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0055_literal_pattern.rs => literal_pattern.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0009_loop_expr.rast => loop_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0009_loop_expr.rs => loop_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0117_macro_call_type.rast => macro_call_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0117_macro_call_type.rs => macro_call_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0147_macro_def.rast => macro_def.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0147_macro_def.rs => macro_def.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0173_macro_def_curly.rast => macro_def_curly.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0173_macro_def_curly.rs => macro_def_curly.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0194_macro_inside_generic_arg.rast => macro_inside_generic_arg.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0194_macro_inside_generic_arg.rs => macro_inside_generic_arg.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0208_macro_rules_as_macro_name.rast => macro_rules_as_macro_name.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0208_macro_rules_as_macro_name.rs => macro_rules_as_macro_name.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0158_macro_rules_non_brace.rast => macro_rules_non_brace.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0158_macro_rules_non_brace.rs => macro_rules_non_brace.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0129_marco_pat.rast => marco_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0129_marco_pat.rs => marco_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0066_match_arm.rast => match_arm.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0066_match_arm.rs => match_arm.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0059_match_arms_commas.rast => match_arms_commas.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0059_match_arms_commas.rs => match_arms_commas.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0120_match_arms_inner_attribute.rast => match_arms_inner_attribute.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0120_match_arms_inner_attribute.rs => match_arms_inner_attribute.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0121_match_arms_outer_attributes.rast => match_arms_outer_attributes.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0121_match_arms_outer_attributes.rs => match_arms_outer_attributes.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0071_match_expr.rast => match_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0071_match_expr.rs => match_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0118_match_guard.rast => match_guard.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0118_match_guard.rs => match_guard.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0213_metas.rast => metas.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0213_metas.rs => metas.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0107_method_call_expr.rast => method_call_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0107_method_call_expr.rs => method_call_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0062_mod_contents.rast => mod_contents.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0062_mod_contents.rs => mod_contents.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0169_mod_item.rast => mod_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0169_mod_item.rs => mod_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0170_mod_item_curly.rast => mod_item_curly.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0170_mod_item_curly.rs => mod_item_curly.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0014_never_type.rast => never_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0014_never_type.rs => never_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0154_no_dyn_trait_leading_for.rast => no_dyn_trait_leading_for.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0154_no_dyn_trait_leading_for.rs => no_dyn_trait_leading_for.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0096_no_semi_after_block.rast => no_semi_after_block.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0096_no_semi_after_block.rs => no_semi_after_block.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0113_nocontentexpr.rast => nocontentexpr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0113_nocontentexpr.rs => nocontentexpr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0134_nocontentexpr_after_item.rast => nocontentexpr_after_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0134_nocontentexpr_after_item.rs => nocontentexpr_after_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0156_or_pattern.rast => or_pattern.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0156_or_pattern.rs => or_pattern.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0099_param_list.rast => param_list.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0099_param_list.rs => param_list.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0045_param_list_opt_patterns.rast => param_list_opt_patterns.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0045_param_list_opt_patterns.rs => param_list_opt_patterns.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0123_param_list_vararg.rast => param_list_vararg.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0123_param_list_vararg.rs => param_list_vararg.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0139_param_outer_arg.rast => param_outer_arg.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0139_param_outer_arg.rs => param_outer_arg.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0084_paren_type.rast => paren_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0084_paren_type.rs => paren_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0053_path_expr.rast => path_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0053_path_expr.rs => path_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0104_path_fn_trait_args.rast => path_fn_trait_args.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0104_path_fn_trait_args.rs => path_fn_trait_args.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0008_path_part.rast => path_part.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0008_path_part.rs => path_part.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0052_path_type.rast => path_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0052_path_type.rs => path_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0048_path_type_with_bounds.rast => path_type_with_bounds.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0048_path_type_with_bounds.rs => path_type_with_bounds.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0095_placeholder_pat.rast => placeholder_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0095_placeholder_pat.rs => placeholder_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0023_placeholder_type.rast => placeholder_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0023_placeholder_type.rs => placeholder_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0013_pointer_type_mut.rast => pointer_type_mut.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0013_pointer_type_mut.rs => pointer_type_mut.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0080_postfix_range.rast => postfix_range.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0080_postfix_range.rs => postfix_range.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0153_pub_parens_typepath.rast => pub_parens_typepath.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0153_pub_parens_typepath.rs => pub_parens_typepath.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0196_pub_tuple_field.rast => pub_tuple_field.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0196_pub_tuple_field.rs => pub_tuple_field.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0037_qual_paths.rast => qual_paths.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0037_qual_paths.rs => qual_paths.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0201_question_for_type_trait_bound.rast => question_for_type_trait_bound.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0201_question_for_type_trait_bound.rs => question_for_type_trait_bound.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0058_range_pat.rast => range_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0058_range_pat.rs => range_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0054_record_field_attrs.rast => record_field_attrs.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0054_record_field_attrs.rs => record_field_attrs.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0172_record_field_list.rast => record_field_list.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0172_record_field_list.rs => record_field_list.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0061_record_lit.rast => record_lit.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0061_record_lit.rs => record_lit.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0125_record_literal_field_with_attr.rast => record_literal_field_with_attr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0125_record_literal_field_with_attr.rs => record_literal_field_with_attr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0145_record_pat_field.rast => record_pat_field.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0145_record_pat_field.rs => record_pat_field.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0102_record_pat_field_list.rast => record_pat_field_list.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0102_record_pat_field_list.rs => record_pat_field_list.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0082_ref_expr.rast => ref_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0082_ref_expr.rs => ref_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0027_ref_pat.rast => ref_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0027_ref_pat.rs => ref_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0033_reference_type;.rast => reference_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0033_reference_type;.rs => reference_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0072_return_expr.rast => return_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0072_return_expr.rs => return_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0006_self_param.rast => self_param.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0006_self_param.rs => self_param.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0138_self_param_outer_attr.rast => self_param_outer_attr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0138_self_param_outer_attr.rs => self_param_outer_attr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0046_singleton_tuple_type.rast => singleton_tuple_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0046_singleton_tuple_type.rs => singleton_tuple_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0024_slice_pat.rast => slice_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0024_slice_pat.rs => slice_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0025_slice_type.rast => slice_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0025_slice_type.rs => slice_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0070_stmt_bin_expr_ambiguity.rast => stmt_bin_expr_ambiguity.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0070_stmt_bin_expr_ambiguity.rs => stmt_bin_expr_ambiguity.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0074_stmt_postfix_expr_ambiguity.rast => stmt_postfix_expr_ambiguity.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0074_stmt_postfix_expr_ambiguity.rs => stmt_postfix_expr_ambiguity.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0171_struct_item.rast => struct_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0171_struct_item.rs => struct_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0151_trait_alias.rast => trait_alias.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0151_trait_alias.rs => trait_alias.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0177_trait_alias_where_clause.rast => trait_alias_where_clause.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0177_trait_alias_where_clause.rs => trait_alias_where_clause.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0041_trait_item.rast => trait_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0041_trait_item.rs => trait_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0175_trait_item_bounds.rast => trait_item_bounds.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0175_trait_item_bounds.rs => trait_item_bounds.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0174_trait_item_generic_params.rast => trait_item_generic_params.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0174_trait_item_generic_params.rs => trait_item_generic_params.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0176_trait_item_where_clause.rast => trait_item_where_clause.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0176_trait_item_where_clause.rs => trait_item_where_clause.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0130_try_block_expr.rast => try_block_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0130_try_block_expr.rs => try_block_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0077_try_expr.rast => try_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0077_try_expr.rs => try_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0159_try_macro_fallback.rast => try_macro_fallback.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0159_try_macro_fallback.rs => try_macro_fallback.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0160_try_macro_rules.rast => try_macro_rules.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0160_try_macro_rules.rs => try_macro_rules.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0154_tuple_attrs.rast => tuple_attrs.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0154_tuple_attrs.rs => tuple_attrs.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0108_tuple_expr.rast => tuple_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0108_tuple_expr.rs => tuple_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0115_tuple_field_attrs.rast => tuple_field_attrs.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0115_tuple_field_attrs.rs => tuple_field_attrs.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0111_tuple_pat.rast => tuple_pat.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0111_tuple_pat.rs => tuple_pat.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0026_tuple_pat_fields.rast => tuple_pat_fields.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0026_tuple_pat_fields.rs => tuple_pat_fields.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0170_tuple_struct.rast => tuple_struct.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0170_tuple_struct.rs => tuple_struct.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0114_tuple_struct_where.rast => tuple_struct_where.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0114_tuple_struct_where.rs => tuple_struct_where.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0078_type_alias.rast => type_alias.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0078_type_alias.rs => type_alias.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0073_type_item_type_params.rast => type_item_type_params.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0073_type_item_type_params.rs => type_item_type_params.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0012_type_item_where_clause.rast => type_item_where_clause.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0012_type_item_where_clause.rs => type_item_where_clause.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0199_type_item_where_clause_deprecated.rast => type_item_where_clause_deprecated.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0199_type_item_where_clause_deprecated.rs => type_item_where_clause_deprecated.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0184_generic_param_list.rast => type_param.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0184_generic_param_list.rs => type_param.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0007_type_param_bounds.rast => type_param_bounds.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0007_type_param_bounds.rs => type_param_bounds.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0090_type_param_default.rast => type_param_default.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0090_type_param_default.rs => type_param_default.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0164_type_path_in_pattern.rast => type_path_in_pattern.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0164_type_path_in_pattern.rs => type_path_in_pattern.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0202_typepathfn_with_coloncolon.rast => typepathfn_with_coloncolon.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0202_typepathfn_with_coloncolon.rs => typepathfn_with_coloncolon.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0019_unary_expr.rast => unary_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0019_unary_expr.rs => unary_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0173_union_item.rast => union_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0173_union_item.rs => union_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0174_unit_struct.rast => unit_struct.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0174_unit_struct.rs => unit_struct.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0051_unit_type.rast => unit_type.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0051_unit_type.rs => unit_type.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0181_use_item.rast => use_item.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0181_use_item.rs => use_item.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0177_use_tree.rast => use_tree.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0177_use_tree.rs => use_tree.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0179_use_tree_abs_star.rast => use_tree_abs_star.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0179_use_tree_abs_star.rs => use_tree_abs_star.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0176_use_tree_alias.rast => use_tree_alias.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0176_use_tree_alias.rs => use_tree_alias.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0002_use_tree_list.rast => use_tree_list.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0002_use_tree_list.rs => use_tree_list.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0177_use_tree_path.rast => use_tree_path.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0177_use_tree_path.rs => use_tree_path.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0180_use_tree_path_star.rast => use_tree_path_star.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0180_use_tree_path_star.rs => use_tree_path_star.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0178_use_tree_path_use_tree.rast => use_tree_path_use_tree.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0178_use_tree_path_use_tree.rs => use_tree_path_use_tree.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0174_use_tree_star.rast => use_tree_star.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0174_use_tree_star.rs => use_tree_star.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0004_value_parameters_no_patterns.rast => value_parameters_no_patterns.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0004_value_parameters_no_patterns.rs => value_parameters_no_patterns.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0157_variant_discriminant.rast => variant_discriminant.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0157_variant_discriminant.rs => variant_discriminant.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0056_where_clause.rast => where_clause.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0056_where_clause.rs => where_clause.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0003_where_pred_for.rast => where_pred_for.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0003_where_pred_for.rs => where_pred_for.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0031_while_expr.rast => while_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0031_while_expr.rs => while_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0204_yeet_expr.rast => yeet_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0204_yeet_expr.rs => yeet_expr.rs} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0159_yield_expr.rast => yield_expr.rast} (100%)
 rename src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/{0159_yield_expr.rs => yield_expr.rs} (100%)

diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
index d8468ba3cb68e..df117d7aa92c4 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
@@ -388,7 +388,7 @@ fn macro_def(p: &mut Parser<'_>, m: Marker) {
     m.complete(p, MACRO_DEF);
 }
 
-// test fn
+// test fn_
 // fn foo() {}
 fn fn_(p: &mut Parser<'_>, m: Marker) {
     p.bump(T![fn]);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
index 18ec570cd5697..f95425824a8d8 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
@@ -169,7 +169,7 @@ fn array_or_slice_type(p: &mut Parser<'_>) {
     m.complete(p, kind);
 }
 
-// test reference_type;
+// test reference_type
 // type A = &();
 // type B = &'static ();
 // type C = &mut ();
diff --git a/src/tools/rust-analyzer/crates/parser/src/tests.rs b/src/tools/rust-analyzer/crates/parser/src/tests.rs
index b837387be10f4..e0042fbdecc15 100644
--- a/src/tools/rust-analyzer/crates/parser/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/tests.rs
@@ -11,6 +11,9 @@ use expect_test::expect_file;
 
 use crate::{Edition, LexedStr, TopEntryPoint};
 
+#[path = "../test_data/generated/runner.rs"]
+mod runner;
+
 #[test]
 fn lex_ok() {
     for case in TestCase::list("lexer/ok") {
@@ -54,16 +57,6 @@ fn parse_ok() {
     }
 }
 
-#[test]
-fn parse_inline_ok() {
-    for case in TestCase::list("parser/inline/ok") {
-        let _guard = stdx::panic_context::enter(format!("{:?}", case.rs));
-        let (actual, errors) = parse(TopEntryPoint::SourceFile, &case.text);
-        assert!(!errors, "errors in an OK file {}:\n{actual}", case.rs.display());
-        expect_file![case.rast].assert_eq(&actual);
-    }
-}
-
 #[test]
 fn parse_err() {
     for case in TestCase::list("parser/err") {
@@ -74,16 +67,6 @@ fn parse_err() {
     }
 }
 
-#[test]
-fn parse_inline_err() {
-    for case in TestCase::list("parser/inline/err") {
-        let _guard = stdx::panic_context::enter(format!("{:?}", case.rs));
-        let (actual, errors) = parse(TopEntryPoint::SourceFile, &case.text);
-        assert!(errors, "no errors in an ERR file {}:\n{actual}", case.rs.display());
-        expect_file![case.rast].assert_eq(&actual)
-    }
-}
-
 fn parse(entry: TopEntryPoint, text: &str) -> (String, bool) {
     let lexed = LexedStr::new(Edition::CURRENT, text);
     let input = lexed.to_input();
@@ -167,3 +150,27 @@ impl TestCase {
         res
     }
 }
+
+#[track_caller]
+fn run_and_expect_no_errors(path: &str) {
+    let path = PathBuf::from(path);
+    let text = std::fs::read_to_string(&path).unwrap();
+    let (actual, errors) = parse(TopEntryPoint::SourceFile, &text);
+    assert!(!errors, "errors in an OK file {}:\n{actual}", path.display());
+    let mut p = PathBuf::from("..");
+    p.push(path);
+    p.set_extension("rast");
+    expect_file![p].assert_eq(&actual)
+}
+
+#[track_caller]
+fn run_and_expect_errors(path: &str) {
+    let path = PathBuf::from(path);
+    let text = std::fs::read_to_string(&path).unwrap();
+    let (actual, errors) = parse(TopEntryPoint::SourceFile, &text);
+    assert!(errors, "no errors in an ERR file {}:\n{actual}", path.display());
+    let mut p = PathBuf::from("..");
+    p.push(path);
+    p.set_extension("rast");
+    expect_file![p].assert_eq(&actual)
+}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
new file mode 100644
index 0000000000000..f82d1ed320c86
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
@@ -0,0 +1,810 @@
+mod ok {
+    use crate::tests::run_and_expect_no_errors;
+    #[test]
+    fn anonymous_const() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/anonymous_const.rs");
+    }
+    #[test]
+    fn arb_self_types() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/arb_self_types.rs");
+    }
+    #[test]
+    fn arg_with_attr() { run_and_expect_no_errors("test_data/parser/inline/ok/arg_with_attr.rs"); }
+    #[test]
+    fn array_attrs() { run_and_expect_no_errors("test_data/parser/inline/ok/array_attrs.rs"); }
+    #[test]
+    fn array_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/array_expr.rs"); }
+    #[test]
+    fn array_type() { run_and_expect_no_errors("test_data/parser/inline/ok/array_type.rs"); }
+    #[test]
+    fn as_precedence() { run_and_expect_no_errors("test_data/parser/inline/ok/as_precedence.rs"); }
+    #[test]
+    fn assoc_const_eq() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/assoc_const_eq.rs");
+    }
+    #[test]
+    fn assoc_item_list() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/assoc_item_list.rs");
+    }
+    #[test]
+    fn assoc_item_list_inner_attrs() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/assoc_item_list_inner_attrs.rs");
+    }
+    #[test]
+    fn assoc_type_bound() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/assoc_type_bound.rs");
+    }
+    #[test]
+    fn assoc_type_eq() { run_and_expect_no_errors("test_data/parser/inline/ok/assoc_type_eq.rs"); }
+    #[test]
+    fn associated_return_type_bounds() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/associated_return_type_bounds.rs");
+    }
+    #[test]
+    fn associated_type_bounds() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/associated_type_bounds.rs");
+    }
+    #[test]
+    fn async_trait_bound() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/async_trait_bound.rs");
+    }
+    #[test]
+    fn attr_on_expr_stmt() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/attr_on_expr_stmt.rs");
+    }
+    #[test]
+    fn await_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/await_expr.rs"); }
+    #[test]
+    fn bare_dyn_types_with_leading_lifetime() {
+        run_and_expect_no_errors(
+            "test_data/parser/inline/ok/bare_dyn_types_with_leading_lifetime.rs",
+        );
+    }
+    #[test]
+    fn bare_dyn_types_with_paren_as_generic_args() {
+        run_and_expect_no_errors(
+            "test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs",
+        );
+    }
+    #[test]
+    fn become_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/become_expr.rs"); }
+    #[test]
+    fn bind_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/bind_pat.rs"); }
+    #[test]
+    fn binop_resets_statementness() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/binop_resets_statementness.rs");
+    }
+    #[test]
+    fn block() { run_and_expect_no_errors("test_data/parser/inline/ok/block.rs"); }
+    #[test]
+    fn block_items() { run_and_expect_no_errors("test_data/parser/inline/ok/block_items.rs"); }
+    #[test]
+    fn box_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/box_pat.rs"); }
+    #[test]
+    fn break_ambiguity() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/break_ambiguity.rs");
+    }
+    #[test]
+    fn break_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/break_expr.rs"); }
+    #[test]
+    fn builtin_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/builtin_expr.rs"); }
+    #[test]
+    fn call_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/call_expr.rs"); }
+    #[test]
+    fn cast_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/cast_expr.rs"); }
+    #[test]
+    fn closure_body_underscore_assignment() {
+        run_and_expect_no_errors(
+            "test_data/parser/inline/ok/closure_body_underscore_assignment.rs",
+        );
+    }
+    #[test]
+    fn closure_params() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/closure_params.rs");
+    }
+    #[test]
+    fn closure_range_method_call() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/closure_range_method_call.rs");
+    }
+    #[test]
+    fn const_arg() { run_and_expect_no_errors("test_data/parser/inline/ok/const_arg.rs"); }
+    #[test]
+    fn const_arg_block() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_arg_block.rs");
+    }
+    #[test]
+    fn const_arg_bool_literal() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_arg_bool_literal.rs");
+    }
+    #[test]
+    fn const_arg_literal() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_arg_literal.rs");
+    }
+    #[test]
+    fn const_arg_negative_number() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_arg_negative_number.rs");
+    }
+    #[test]
+    fn const_block_pat() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_block_pat.rs");
+    }
+    #[test]
+    fn const_closure() { run_and_expect_no_errors("test_data/parser/inline/ok/const_closure.rs"); }
+    #[test]
+    fn const_item() { run_and_expect_no_errors("test_data/parser/inline/ok/const_item.rs"); }
+    #[test]
+    fn const_param() { run_and_expect_no_errors("test_data/parser/inline/ok/const_param.rs"); }
+    #[test]
+    fn const_param_default_expression() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_param_default_expression.rs");
+    }
+    #[test]
+    fn const_param_default_literal() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_param_default_literal.rs");
+    }
+    #[test]
+    fn const_param_default_path() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_param_default_path.rs");
+    }
+    #[test]
+    fn const_trait_bound() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/const_trait_bound.rs");
+    }
+    #[test]
+    fn continue_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/continue_expr.rs"); }
+    #[test]
+    fn crate_path() { run_and_expect_no_errors("test_data/parser/inline/ok/crate_path.rs"); }
+    #[test]
+    fn crate_visibility() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/crate_visibility.rs");
+    }
+    #[test]
+    fn crate_visibility_in() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/crate_visibility_in.rs");
+    }
+    #[test]
+    fn default_async_fn() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/default_async_fn.rs");
+    }
+    #[test]
+    fn default_async_unsafe_fn() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/default_async_unsafe_fn.rs");
+    }
+    #[test]
+    fn default_item() { run_and_expect_no_errors("test_data/parser/inline/ok/default_item.rs"); }
+    #[test]
+    fn default_unsafe_item() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/default_unsafe_item.rs");
+    }
+    #[test]
+    fn destructuring_assignment_struct_rest_pattern() {
+        run_and_expect_no_errors(
+            "test_data/parser/inline/ok/destructuring_assignment_struct_rest_pattern.rs",
+        );
+    }
+    #[test]
+    fn destructuring_assignment_wildcard_pat() {
+        run_and_expect_no_errors(
+            "test_data/parser/inline/ok/destructuring_assignment_wildcard_pat.rs",
+        );
+    }
+    #[test]
+    fn dot_dot_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/dot_dot_pat.rs"); }
+    #[test]
+    fn dyn_trait_type() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/dyn_trait_type.rs");
+    }
+    #[test]
+    fn effect_blocks() { run_and_expect_no_errors("test_data/parser/inline/ok/effect_blocks.rs"); }
+    #[test]
+    fn exclusive_range_pat() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/exclusive_range_pat.rs");
+    }
+    #[test]
+    fn expr_literals() { run_and_expect_no_errors("test_data/parser/inline/ok/expr_literals.rs"); }
+    #[test]
+    fn expression_after_block() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/expression_after_block.rs");
+    }
+    #[test]
+    fn extern_block() { run_and_expect_no_errors("test_data/parser/inline/ok/extern_block.rs"); }
+    #[test]
+    fn extern_crate() { run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate.rs"); }
+    #[test]
+    fn extern_crate_rename() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_rename.rs");
+    }
+    #[test]
+    fn extern_crate_self() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/extern_crate_self.rs");
+    }
+    #[test]
+    fn field_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/field_expr.rs"); }
+    #[test]
+    fn fn_() { run_and_expect_no_errors("test_data/parser/inline/ok/fn_.rs"); }
+    #[test]
+    fn fn_decl() { run_and_expect_no_errors("test_data/parser/inline/ok/fn_decl.rs"); }
+    #[test]
+    fn fn_def_param() { run_and_expect_no_errors("test_data/parser/inline/ok/fn_def_param.rs"); }
+    #[test]
+    fn fn_pointer_param_ident_path() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/fn_pointer_param_ident_path.rs");
+    }
+    #[test]
+    fn fn_pointer_type() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/fn_pointer_type.rs");
+    }
+    #[test]
+    fn fn_pointer_type_with_ret() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/fn_pointer_type_with_ret.rs");
+    }
+    #[test]
+    fn fn_pointer_unnamed_arg() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/fn_pointer_unnamed_arg.rs");
+    }
+    #[test]
+    fn for_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/for_expr.rs"); }
+    #[test]
+    fn for_range_from() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/for_range_from.rs");
+    }
+    #[test]
+    fn for_type() { run_and_expect_no_errors("test_data/parser/inline/ok/for_type.rs"); }
+    #[test]
+    fn full_range_expr() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/full_range_expr.rs");
+    }
+    #[test]
+    fn function_ret_type() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/function_ret_type.rs");
+    }
+    #[test]
+    fn function_type_params() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/function_type_params.rs");
+    }
+    #[test]
+    fn function_where_clause() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/function_where_clause.rs");
+    }
+    #[test]
+    fn generic_arg() { run_and_expect_no_errors("test_data/parser/inline/ok/generic_arg.rs"); }
+    #[test]
+    fn generic_param_attribute() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_attribute.rs");
+    }
+    #[test]
+    fn generic_param_list() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/generic_param_list.rs");
+    }
+    #[test]
+    fn half_open_range_pat() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/half_open_range_pat.rs");
+    }
+    #[test]
+    fn if_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/if_expr.rs"); }
+    #[test]
+    fn impl_item() { run_and_expect_no_errors("test_data/parser/inline/ok/impl_item.rs"); }
+    #[test]
+    fn impl_item_const() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/impl_item_const.rs");
+    }
+    #[test]
+    fn impl_item_neg() { run_and_expect_no_errors("test_data/parser/inline/ok/impl_item_neg.rs"); }
+    #[test]
+    fn impl_trait_type() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/impl_trait_type.rs");
+    }
+    #[test]
+    fn impl_type_params() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/impl_type_params.rs");
+    }
+    #[test]
+    fn index_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/index_expr.rs"); }
+    #[test]
+    fn label() { run_and_expect_no_errors("test_data/parser/inline/ok/label.rs"); }
+    #[test]
+    fn labeled_block() { run_and_expect_no_errors("test_data/parser/inline/ok/labeled_block.rs"); }
+    #[test]
+    fn lambda_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/lambda_expr.rs"); }
+    #[test]
+    fn lambda_ret_block() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/lambda_ret_block.rs");
+    }
+    #[test]
+    fn let_else() { run_and_expect_no_errors("test_data/parser/inline/ok/let_else.rs"); }
+    #[test]
+    fn let_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/let_expr.rs"); }
+    #[test]
+    fn let_stmt() { run_and_expect_no_errors("test_data/parser/inline/ok/let_stmt.rs"); }
+    #[test]
+    fn let_stmt_ascription() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/let_stmt_ascription.rs");
+    }
+    #[test]
+    fn let_stmt_init() { run_and_expect_no_errors("test_data/parser/inline/ok/let_stmt_init.rs"); }
+    #[test]
+    fn lifetime_arg() { run_and_expect_no_errors("test_data/parser/inline/ok/lifetime_arg.rs"); }
+    #[test]
+    fn lifetime_param() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/lifetime_param.rs");
+    }
+    #[test]
+    fn literal_pattern() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/literal_pattern.rs");
+    }
+    #[test]
+    fn loop_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/loop_expr.rs"); }
+    #[test]
+    fn macro_call_type() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/macro_call_type.rs");
+    }
+    #[test]
+    fn macro_def() { run_and_expect_no_errors("test_data/parser/inline/ok/macro_def.rs"); }
+    #[test]
+    fn macro_def_curly() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/macro_def_curly.rs");
+    }
+    #[test]
+    fn macro_inside_generic_arg() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/macro_inside_generic_arg.rs");
+    }
+    #[test]
+    fn macro_rules_as_macro_name() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/macro_rules_as_macro_name.rs");
+    }
+    #[test]
+    fn macro_rules_non_brace() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/macro_rules_non_brace.rs");
+    }
+    #[test]
+    fn marco_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/marco_pat.rs"); }
+    #[test]
+    fn match_arm() { run_and_expect_no_errors("test_data/parser/inline/ok/match_arm.rs"); }
+    #[test]
+    fn match_arms_commas() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/match_arms_commas.rs");
+    }
+    #[test]
+    fn match_arms_inner_attribute() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/match_arms_inner_attribute.rs");
+    }
+    #[test]
+    fn match_arms_outer_attributes() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/match_arms_outer_attributes.rs");
+    }
+    #[test]
+    fn match_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/match_expr.rs"); }
+    #[test]
+    fn match_guard() { run_and_expect_no_errors("test_data/parser/inline/ok/match_guard.rs"); }
+    #[test]
+    fn metas() { run_and_expect_no_errors("test_data/parser/inline/ok/metas.rs"); }
+    #[test]
+    fn method_call_expr() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/method_call_expr.rs");
+    }
+    #[test]
+    fn mod_contents() { run_and_expect_no_errors("test_data/parser/inline/ok/mod_contents.rs"); }
+    #[test]
+    fn mod_item() { run_and_expect_no_errors("test_data/parser/inline/ok/mod_item.rs"); }
+    #[test]
+    fn mod_item_curly() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/mod_item_curly.rs");
+    }
+    #[test]
+    fn never_type() { run_and_expect_no_errors("test_data/parser/inline/ok/never_type.rs"); }
+    #[test]
+    fn no_dyn_trait_leading_for() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/no_dyn_trait_leading_for.rs");
+    }
+    #[test]
+    fn no_semi_after_block() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/no_semi_after_block.rs");
+    }
+    #[test]
+    fn nocontentexpr() { run_and_expect_no_errors("test_data/parser/inline/ok/nocontentexpr.rs"); }
+    #[test]
+    fn nocontentexpr_after_item() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/nocontentexpr_after_item.rs");
+    }
+    #[test]
+    fn or_pattern() { run_and_expect_no_errors("test_data/parser/inline/ok/or_pattern.rs"); }
+    #[test]
+    fn param_list() { run_and_expect_no_errors("test_data/parser/inline/ok/param_list.rs"); }
+    #[test]
+    fn param_list_opt_patterns() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/param_list_opt_patterns.rs");
+    }
+    #[test]
+    fn param_list_vararg() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/param_list_vararg.rs");
+    }
+    #[test]
+    fn param_outer_arg() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/param_outer_arg.rs");
+    }
+    #[test]
+    fn paren_type() { run_and_expect_no_errors("test_data/parser/inline/ok/paren_type.rs"); }
+    #[test]
+    fn path_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/path_expr.rs"); }
+    #[test]
+    fn path_fn_trait_args() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/path_fn_trait_args.rs");
+    }
+    #[test]
+    fn path_part() { run_and_expect_no_errors("test_data/parser/inline/ok/path_part.rs"); }
+    #[test]
+    fn path_type() { run_and_expect_no_errors("test_data/parser/inline/ok/path_type.rs"); }
+    #[test]
+    fn path_type_with_bounds() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/path_type_with_bounds.rs");
+    }
+    #[test]
+    fn placeholder_pat() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/placeholder_pat.rs");
+    }
+    #[test]
+    fn placeholder_type() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/placeholder_type.rs");
+    }
+    #[test]
+    fn pointer_type_mut() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/pointer_type_mut.rs");
+    }
+    #[test]
+    fn postfix_range() { run_and_expect_no_errors("test_data/parser/inline/ok/postfix_range.rs"); }
+    #[test]
+    fn pub_parens_typepath() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/pub_parens_typepath.rs");
+    }
+    #[test]
+    fn pub_tuple_field() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/pub_tuple_field.rs");
+    }
+    #[test]
+    fn qual_paths() { run_and_expect_no_errors("test_data/parser/inline/ok/qual_paths.rs"); }
+    #[test]
+    fn question_for_type_trait_bound() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/question_for_type_trait_bound.rs");
+    }
+    #[test]
+    fn range_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/range_pat.rs"); }
+    #[test]
+    fn record_field_attrs() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/record_field_attrs.rs");
+    }
+    #[test]
+    fn record_field_list() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/record_field_list.rs");
+    }
+    #[test]
+    fn record_lit() { run_and_expect_no_errors("test_data/parser/inline/ok/record_lit.rs"); }
+    #[test]
+    fn record_literal_field_with_attr() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/record_literal_field_with_attr.rs");
+    }
+    #[test]
+    fn record_pat_field() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/record_pat_field.rs");
+    }
+    #[test]
+    fn record_pat_field_list() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/record_pat_field_list.rs");
+    }
+    #[test]
+    fn ref_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/ref_expr.rs"); }
+    #[test]
+    fn ref_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/ref_pat.rs"); }
+    #[test]
+    fn reference_type() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/reference_type.rs");
+    }
+    #[test]
+    fn return_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/return_expr.rs"); }
+    #[test]
+    fn self_param() { run_and_expect_no_errors("test_data/parser/inline/ok/self_param.rs"); }
+    #[test]
+    fn self_param_outer_attr() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/self_param_outer_attr.rs");
+    }
+    #[test]
+    fn singleton_tuple_type() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/singleton_tuple_type.rs");
+    }
+    #[test]
+    fn slice_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/slice_pat.rs"); }
+    #[test]
+    fn slice_type() { run_and_expect_no_errors("test_data/parser/inline/ok/slice_type.rs"); }
+    #[test]
+    fn stmt_bin_expr_ambiguity() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/stmt_bin_expr_ambiguity.rs");
+    }
+    #[test]
+    fn stmt_postfix_expr_ambiguity() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/stmt_postfix_expr_ambiguity.rs");
+    }
+    #[test]
+    fn struct_item() { run_and_expect_no_errors("test_data/parser/inline/ok/struct_item.rs"); }
+    #[test]
+    fn trait_alias() { run_and_expect_no_errors("test_data/parser/inline/ok/trait_alias.rs"); }
+    #[test]
+    fn trait_alias_where_clause() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/trait_alias_where_clause.rs");
+    }
+    #[test]
+    fn trait_item() { run_and_expect_no_errors("test_data/parser/inline/ok/trait_item.rs"); }
+    #[test]
+    fn trait_item_bounds() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/trait_item_bounds.rs");
+    }
+    #[test]
+    fn trait_item_generic_params() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/trait_item_generic_params.rs");
+    }
+    #[test]
+    fn trait_item_where_clause() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/trait_item_where_clause.rs");
+    }
+    #[test]
+    fn try_block_expr() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/try_block_expr.rs");
+    }
+    #[test]
+    fn try_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/try_expr.rs"); }
+    #[test]
+    fn try_macro_fallback() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/try_macro_fallback.rs");
+    }
+    #[test]
+    fn try_macro_rules() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/try_macro_rules.rs");
+    }
+    #[test]
+    fn tuple_attrs() { run_and_expect_no_errors("test_data/parser/inline/ok/tuple_attrs.rs"); }
+    #[test]
+    fn tuple_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/tuple_expr.rs"); }
+    #[test]
+    fn tuple_field_attrs() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/tuple_field_attrs.rs");
+    }
+    #[test]
+    fn tuple_pat() { run_and_expect_no_errors("test_data/parser/inline/ok/tuple_pat.rs"); }
+    #[test]
+    fn tuple_pat_fields() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/tuple_pat_fields.rs");
+    }
+    #[test]
+    fn tuple_struct() { run_and_expect_no_errors("test_data/parser/inline/ok/tuple_struct.rs"); }
+    #[test]
+    fn tuple_struct_where() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/tuple_struct_where.rs");
+    }
+    #[test]
+    fn type_alias() { run_and_expect_no_errors("test_data/parser/inline/ok/type_alias.rs"); }
+    #[test]
+    fn type_item_type_params() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/type_item_type_params.rs");
+    }
+    #[test]
+    fn type_item_where_clause() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/type_item_where_clause.rs");
+    }
+    #[test]
+    fn type_item_where_clause_deprecated() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/type_item_where_clause_deprecated.rs");
+    }
+    #[test]
+    fn type_param() { run_and_expect_no_errors("test_data/parser/inline/ok/type_param.rs"); }
+    #[test]
+    fn type_param_bounds() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/type_param_bounds.rs");
+    }
+    #[test]
+    fn type_param_default() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/type_param_default.rs");
+    }
+    #[test]
+    fn type_path_in_pattern() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/type_path_in_pattern.rs");
+    }
+    #[test]
+    fn typepathfn_with_coloncolon() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/typepathfn_with_coloncolon.rs");
+    }
+    #[test]
+    fn unary_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/unary_expr.rs"); }
+    #[test]
+    fn union_item() { run_and_expect_no_errors("test_data/parser/inline/ok/union_item.rs"); }
+    #[test]
+    fn unit_struct() { run_and_expect_no_errors("test_data/parser/inline/ok/unit_struct.rs"); }
+    #[test]
+    fn unit_type() { run_and_expect_no_errors("test_data/parser/inline/ok/unit_type.rs"); }
+    #[test]
+    fn use_item() { run_and_expect_no_errors("test_data/parser/inline/ok/use_item.rs"); }
+    #[test]
+    fn use_tree() { run_and_expect_no_errors("test_data/parser/inline/ok/use_tree.rs"); }
+    #[test]
+    fn use_tree_abs_star() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_abs_star.rs");
+    }
+    #[test]
+    fn use_tree_alias() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_alias.rs");
+    }
+    #[test]
+    fn use_tree_list() { run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_list.rs"); }
+    #[test]
+    fn use_tree_path() { run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_path.rs"); }
+    #[test]
+    fn use_tree_path_star() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_path_star.rs");
+    }
+    #[test]
+    fn use_tree_path_use_tree() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_path_use_tree.rs");
+    }
+    #[test]
+    fn use_tree_star() { run_and_expect_no_errors("test_data/parser/inline/ok/use_tree_star.rs"); }
+    #[test]
+    fn value_parameters_no_patterns() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/value_parameters_no_patterns.rs");
+    }
+    #[test]
+    fn variant_discriminant() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/variant_discriminant.rs");
+    }
+    #[test]
+    fn where_clause() { run_and_expect_no_errors("test_data/parser/inline/ok/where_clause.rs"); }
+    #[test]
+    fn where_pred_for() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/where_pred_for.rs");
+    }
+    #[test]
+    fn while_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/while_expr.rs"); }
+    #[test]
+    fn yeet_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/yeet_expr.rs"); }
+    #[test]
+    fn yield_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/yield_expr.rs"); }
+}
+mod err {
+    use crate::tests::run_and_expect_errors;
+    #[test]
+    fn angled_path_without_qual() {
+        run_and_expect_errors("test_data/parser/inline/err/angled_path_without_qual.rs");
+    }
+    #[test]
+    fn anonymous_static() {
+        run_and_expect_errors("test_data/parser/inline/err/anonymous_static.rs");
+    }
+    #[test]
+    fn arg_list_recovery() {
+        run_and_expect_errors("test_data/parser/inline/err/arg_list_recovery.rs");
+    }
+    #[test]
+    fn array_type_missing_semi() {
+        run_and_expect_errors("test_data/parser/inline/err/array_type_missing_semi.rs");
+    }
+    #[test]
+    fn async_without_semicolon() {
+        run_and_expect_errors("test_data/parser/inline/err/async_without_semicolon.rs");
+    }
+    #[test]
+    fn comma_after_functional_update_syntax() {
+        run_and_expect_errors(
+            "test_data/parser/inline/err/comma_after_functional_update_syntax.rs",
+        );
+    }
+    #[test]
+    fn crate_visibility_empty_recover() {
+        run_and_expect_errors("test_data/parser/inline/err/crate_visibility_empty_recover.rs");
+    }
+    #[test]
+    fn empty_param_slot() {
+        run_and_expect_errors("test_data/parser/inline/err/empty_param_slot.rs");
+    }
+    #[test]
+    fn empty_segment() { run_and_expect_errors("test_data/parser/inline/err/empty_segment.rs"); }
+    #[test]
+    fn fn_pointer_type_missing_fn() {
+        run_and_expect_errors("test_data/parser/inline/err/fn_pointer_type_missing_fn.rs");
+    }
+    #[test]
+    fn gen_blocks() { run_and_expect_errors("test_data/parser/inline/err/gen_blocks.rs"); }
+    #[test]
+    fn gen_fn() { run_and_expect_errors("test_data/parser/inline/err/gen_fn.rs"); }
+    #[test]
+    fn generic_arg_list_recover() {
+        run_and_expect_errors("test_data/parser/inline/err/generic_arg_list_recover.rs");
+    }
+    #[test]
+    fn generic_param_list_recover() {
+        run_and_expect_errors("test_data/parser/inline/err/generic_param_list_recover.rs");
+    }
+    #[test]
+    fn impl_type() { run_and_expect_errors("test_data/parser/inline/err/impl_type.rs"); }
+    #[test]
+    fn let_else_right_curly_brace() {
+        run_and_expect_errors("test_data/parser/inline/err/let_else_right_curly_brace.rs");
+    }
+    #[test]
+    fn macro_rules_as_macro_name() {
+        run_and_expect_errors("test_data/parser/inline/err/macro_rules_as_macro_name.rs");
+    }
+    #[test]
+    fn match_arms_recovery() {
+        run_and_expect_errors("test_data/parser/inline/err/match_arms_recovery.rs");
+    }
+    #[test]
+    fn method_call_missing_argument_list() {
+        run_and_expect_errors("test_data/parser/inline/err/method_call_missing_argument_list.rs");
+    }
+    #[test]
+    fn misplaced_label_err() {
+        run_and_expect_errors("test_data/parser/inline/err/misplaced_label_err.rs");
+    }
+    #[test]
+    fn missing_fn_param_type() {
+        run_and_expect_errors("test_data/parser/inline/err/missing_fn_param_type.rs");
+    }
+    #[test]
+    fn pointer_type_no_mutability() {
+        run_and_expect_errors("test_data/parser/inline/err/pointer_type_no_mutability.rs");
+    }
+    #[test]
+    fn pub_expr() { run_and_expect_errors("test_data/parser/inline/err/pub_expr.rs"); }
+    #[test]
+    fn record_literal_before_ellipsis_recovery() {
+        run_and_expect_errors(
+            "test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs",
+        );
+    }
+    #[test]
+    fn record_literal_field_eq_recovery() {
+        run_and_expect_errors("test_data/parser/inline/err/record_literal_field_eq_recovery.rs");
+    }
+    #[test]
+    fn record_literal_missing_ellipsis_recovery() {
+        run_and_expect_errors(
+            "test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rs",
+        );
+    }
+    #[test]
+    fn record_pat_field_eq_recovery() {
+        run_and_expect_errors("test_data/parser/inline/err/record_pat_field_eq_recovery.rs");
+    }
+    #[test]
+    fn recover_from_missing_assoc_item_binding() {
+        run_and_expect_errors(
+            "test_data/parser/inline/err/recover_from_missing_assoc_item_binding.rs",
+        );
+    }
+    #[test]
+    fn recover_from_missing_const_default() {
+        run_and_expect_errors("test_data/parser/inline/err/recover_from_missing_const_default.rs");
+    }
+    #[test]
+    fn struct_field_recover() {
+        run_and_expect_errors("test_data/parser/inline/err/struct_field_recover.rs");
+    }
+    #[test]
+    fn top_level_let() { run_and_expect_errors("test_data/parser/inline/err/top_level_let.rs"); }
+    #[test]
+    fn tuple_expr_leading_comma() {
+        run_and_expect_errors("test_data/parser/inline/err/tuple_expr_leading_comma.rs");
+    }
+    #[test]
+    fn tuple_field_list_recovery() {
+        run_and_expect_errors("test_data/parser/inline/err/tuple_field_list_recovery.rs");
+    }
+    #[test]
+    fn tuple_pat_leading_comma() {
+        run_and_expect_errors("test_data/parser/inline/err/tuple_pat_leading_comma.rs");
+    }
+    #[test]
+    fn unsafe_block_in_mod() {
+        run_and_expect_errors("test_data/parser/inline/err/unsafe_block_in_mod.rs");
+    }
+    #[test]
+    fn use_tree_list_err_recovery() {
+        run_and_expect_errors("test_data/parser/inline/err/use_tree_list_err_recovery.rs");
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0016_angled_path_without_qual.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/angled_path_without_qual.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0016_angled_path_without_qual.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/angled_path_without_qual.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0016_angled_path_without_qual.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/angled_path_without_qual.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0016_angled_path_without_qual.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/angled_path_without_qual.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0013_anonymous_static.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/anonymous_static.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0013_anonymous_static.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/anonymous_static.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0013_anonymous_static.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/anonymous_static.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0013_anonymous_static.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/anonymous_static.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_arg_list_recovery.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/arg_list_recovery.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0001_array_type_missing_semi.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/array_type_missing_semi.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0001_array_type_missing_semi.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/array_type_missing_semi.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0001_array_type_missing_semi.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/array_type_missing_semi.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0001_array_type_missing_semi.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/array_type_missing_semi.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0007_async_without_semicolon.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/async_without_semicolon.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0007_async_without_semicolon.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/async_without_semicolon.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0007_async_without_semicolon.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/async_without_semicolon.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0007_async_without_semicolon.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/async_without_semicolon.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_functional_update_syntax.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_functional_update_syntax.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_functional_update_syntax.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_comma_after_functional_update_syntax.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_functional_update_syntax.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0018_crate_visibility_empty_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0018_crate_visibility_empty_recover.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0018_crate_visibility_empty_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0018_crate_visibility_empty_recover.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/crate_visibility_empty_recover.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_param_slot.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_param_slot.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_param_slot.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0023_empty_param_slot.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_param_slot.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_empty_segment.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_empty_segment.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_empty_segment.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_empty_segment.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/empty_segment.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/fn_pointer_type_missing_fn.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/fn_pointer_type_missing_fn.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/fn_pointer_type_missing_fn.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/fn_pointer_type_missing_fn.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0035_gen_blocks.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/gen_blocks.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0035_gen_blocks.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/gen_blocks.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0035_gen_blocks.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/gen_blocks.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0035_gen_blocks.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/gen_blocks.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0036_gen_fn.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/gen_fn.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0036_gen_fn.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/gen_fn.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0036_gen_fn.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/gen_fn.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0036_gen_fn.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/gen_fn.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0030_generic_arg_list_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0030_generic_arg_list_recover.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0030_generic_arg_list_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0030_generic_arg_list_recover.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_arg_list_recover.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0031_generic_param_list_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_param_list_recover.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0031_generic_param_list_recover.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_param_list_recover.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0031_generic_param_list_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_param_list_recover.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0031_generic_param_list_recover.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/generic_param_list_recover.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0004_impl_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/impl_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0004_impl_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/impl_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0004_impl_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/impl_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0004_impl_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/impl_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/let_else_right_curly_brace.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/let_else_right_curly_brace.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/let_else_right_curly_brace.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0017_let_else_right_curly_brace.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/let_else_right_curly_brace.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0026_macro_rules_as_macro_name.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/macro_rules_as_macro_name.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0026_macro_rules_as_macro_name.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/macro_rules_as_macro_name.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0026_macro_rules_as_macro_name.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/macro_rules_as_macro_name.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0026_macro_rules_as_macro_name.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/macro_rules_as_macro_name.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/match_arms_recovery.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/match_arms_recovery.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/match_arms_recovery.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/match_arms_recovery.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0028_method_call_missing_argument_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/method_call_missing_argument_list.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0028_method_call_missing_argument_list.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/method_call_missing_argument_list.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0028_method_call_missing_argument_list.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/method_call_missing_argument_list.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0028_method_call_missing_argument_list.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/method_call_missing_argument_list.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/misplaced_label_err.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/misplaced_label_err.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/misplaced_label_err.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0002_misplaced_label_err.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/misplaced_label_err.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/missing_fn_param_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/missing_fn_param_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/missing_fn_param_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0015_missing_fn_param_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/missing_fn_param_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/pointer_type_no_mutability.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0003_pointer_type_no_mutability.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/pointer_type_no_mutability.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0003_pointer_type_no_mutability.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/pointer_type_no_mutability.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0003_pointer_type_no_mutability.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/pointer_type_no_mutability.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0008_pub_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/pub_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0008_pub_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/pub_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0008_pub_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/pub_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0008_pub_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/pub_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_before_ellipsis_recovery.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0032_record_literal_field_eq_recovery.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_field_eq_recovery.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_record_literal_missing_ellipsis_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_record_literal_missing_ellipsis_recovery.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_record_literal_missing_ellipsis_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_record_literal_missing_ellipsis_recovery.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_literal_missing_ellipsis_recovery.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0033_record_pat_field_eq_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_pat_field_eq_recovery.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0033_record_pat_field_eq_recovery.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_pat_field_eq_recovery.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0033_record_pat_field_eq_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_pat_field_eq_recovery.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0033_record_pat_field_eq_recovery.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/record_pat_field_eq_recovery.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/recover_from_missing_assoc_item_binding.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/recover_from_missing_assoc_item_binding.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/recover_from_missing_assoc_item_binding.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0021_recover_from_missing_assoc_item_binding.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/recover_from_missing_assoc_item_binding.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/recover_from_missing_const_default.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/recover_from_missing_const_default.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/recover_from_missing_const_default.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/recover_from_missing_const_default.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_struct_field_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_struct_field_recover.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_struct_field_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0014_struct_field_recover.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/top_level_let.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/top_level_let.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/top_level_let.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0024_top_level_let.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/top_level_let.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0019_tuple_expr_leading_comma.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_expr_leading_comma.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0019_tuple_expr_leading_comma.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_expr_leading_comma.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0019_tuple_expr_leading_comma.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_expr_leading_comma.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0019_tuple_expr_leading_comma.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_expr_leading_comma.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0029_tuple_field_list_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_field_list_recovery.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0029_tuple_field_list_recovery.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_field_list_recovery.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0029_tuple_field_list_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_field_list_recovery.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0029_tuple_field_list_recovery.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_field_list_recovery.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0020_tuple_pat_leading_comma.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_pat_leading_comma.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0020_tuple_pat_leading_comma.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_pat_leading_comma.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0020_tuple_pat_leading_comma.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_pat_leading_comma.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0020_tuple_pat_leading_comma.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/tuple_pat_leading_comma.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/unsafe_block_in_mod.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/unsafe_block_in_mod.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0006_unsafe_block_in_mod.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/unsafe_block_in_mod.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0006_unsafe_block_in_mod.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/unsafe_block_in_mod.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/use_tree_list_err_recovery.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/use_tree_list_err_recovery.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/use_tree_list_err_recovery.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0026_use_tree_list_err_recovery.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/use_tree_list_err_recovery.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0083_struct_items.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0083_struct_items.rast
deleted file mode 100644
index cdbc40fe0b2fb..0000000000000
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0083_struct_items.rast
+++ /dev/null
@@ -1,87 +0,0 @@
-SOURCE_FILE@0..106
-  STRUCT@0..11
-    STRUCT_KW@0..6 "struct"
-    WHITESPACE@6..7 " "
-    NAME@7..10
-      IDENT@7..10 "Foo"
-    SEMICOLON@10..11 ";"
-  WHITESPACE@11..12 "\n"
-  STRUCT@12..25
-    STRUCT_KW@12..18 "struct"
-    WHITESPACE@18..19 " "
-    NAME@19..22
-      IDENT@19..22 "Foo"
-    WHITESPACE@22..23 " "
-    RECORD_FIELD_LIST@23..25
-      L_CURLY@23..24 "{"
-      R_CURLY@24..25 "}"
-  WHITESPACE@25..26 "\n"
-  STRUCT@26..39
-    STRUCT_KW@26..32 "struct"
-    WHITESPACE@32..33 " "
-    NAME@33..36
-      IDENT@33..36 "Foo"
-    TUPLE_FIELD_LIST@36..38
-      L_PAREN@36..37 "("
-      R_PAREN@37..38 ")"
-    SEMICOLON@38..39 ";"
-  WHITESPACE@39..40 "\n"
-  STRUCT@40..66
-    STRUCT_KW@40..46 "struct"
-    WHITESPACE@46..47 " "
-    NAME@47..50
-      IDENT@47..50 "Foo"
-    TUPLE_FIELD_LIST@50..65
-      L_PAREN@50..51 "("
-      TUPLE_FIELD@51..57
-        PATH_TYPE@51..57
-          PATH@51..57
-            PATH_SEGMENT@51..57
-              NAME_REF@51..57
-                IDENT@51..57 "String"
-      COMMA@57..58 ","
-      WHITESPACE@58..59 " "
-      TUPLE_FIELD@59..64
-        PATH_TYPE@59..64
-          PATH@59..64
-            PATH_SEGMENT@59..64
-              NAME_REF@59..64
-                IDENT@59..64 "usize"
-      R_PAREN@64..65 ")"
-    SEMICOLON@65..66 ";"
-  WHITESPACE@66..67 "\n"
-  STRUCT@67..105
-    STRUCT_KW@67..73 "struct"
-    WHITESPACE@73..74 " "
-    NAME@74..77
-      IDENT@74..77 "Foo"
-    WHITESPACE@77..78 " "
-    RECORD_FIELD_LIST@78..105
-      L_CURLY@78..79 "{"
-      WHITESPACE@79..84 "\n    "
-      RECORD_FIELD@84..90
-        NAME@84..85
-          IDENT@84..85 "a"
-        COLON@85..86 ":"
-        WHITESPACE@86..87 " "
-        PATH_TYPE@87..90
-          PATH@87..90
-            PATH_SEGMENT@87..90
-              NAME_REF@87..90
-                IDENT@87..90 "i32"
-      COMMA@90..91 ","
-      WHITESPACE@91..96 "\n    "
-      RECORD_FIELD@96..102
-        NAME@96..97
-          IDENT@96..97 "b"
-        COLON@97..98 ":"
-        WHITESPACE@98..99 " "
-        PATH_TYPE@99..102
-          PATH@99..102
-            PATH_SEGMENT@99..102
-              NAME_REF@99..102
-                IDENT@99..102 "f32"
-      COMMA@102..103 ","
-      WHITESPACE@103..104 "\n"
-      R_CURLY@104..105 "}"
-  WHITESPACE@105..106 "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_anonymous_const.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/anonymous_const.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_anonymous_const.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/anonymous_const.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_anonymous_const.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/anonymous_const.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_anonymous_const.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/anonymous_const.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0018_arb_self_types.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arb_self_types.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0018_arb_self_types.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arb_self_types.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0018_arb_self_types.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arb_self_types.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0018_arb_self_types.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arb_self_types.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0152_arg_with_attr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arg_with_attr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0152_arg_with_attr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arg_with_attr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0152_arg_with_attr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arg_with_attr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0152_arg_with_attr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/arg_with_attr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0150_array_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_attrs.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0150_array_attrs.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_attrs.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0150_array_attrs.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_attrs.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0150_array_attrs.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_attrs.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0103_array_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0103_array_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0103_array_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0103_array_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0017_array_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0017_array_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0017_array_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0017_array_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/array_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0146_as_precedence.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/as_precedence.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0146_as_precedence.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/as_precedence.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0146_as_precedence.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/as_precedence.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0146_as_precedence.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/as_precedence.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_assoc_const_eq.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_const_eq.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_assoc_const_eq.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_const_eq.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_assoc_const_eq.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_const_eq.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_assoc_const_eq.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_const_eq.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0021_assoc_item_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0021_assoc_item_list.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0021_assoc_item_list.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0021_assoc_item_list.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_assoc_item_list_inner_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list_inner_attrs.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_assoc_item_list_inner_attrs.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list_inner_attrs.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_assoc_item_list_inner_attrs.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list_inner_attrs.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_assoc_item_list_inner_attrs.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_item_list_inner_attrs.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0185_assoc_type_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0185_assoc_type_bound.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0185_assoc_type_bound.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0185_assoc_type_bound.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_bound.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0187_assoc_type_eq.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_eq.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0187_assoc_type_eq.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_eq.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0187_assoc_type_eq.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_eq.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0187_assoc_type_eq.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/assoc_type_eq.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_return_type_bounds.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_return_type_bounds.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_return_type_bounds.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_return_type_bounds.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_associated_type_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_associated_type_bounds.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_associated_type_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_associated_type_bounds.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/associated_type_bounds.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0211_async_trait_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0211_async_trait_bound.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0211_async_trait_bound.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0211_async_trait_bound.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/async_trait_bound.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/attr_on_expr_stmt.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/attr_on_expr_stmt.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/attr_on_expr_stmt.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/attr_on_expr_stmt.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/await_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/await_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/await_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0137_await_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/await_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_leading_lifetime.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_leading_lifetime.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_leading_lifetime.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_leading_lifetime.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bare_dyn_types_with_paren_as_generic_args.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_become_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/become_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_become_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/become_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_become_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/become_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_become_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/become_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0112_bind_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bind_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0112_bind_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bind_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0112_bind_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bind_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0112_bind_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/bind_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_binop_resets_statementness.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/binop_resets_statementness.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_binop_resets_statementness.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/binop_resets_statementness.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_binop_resets_statementness.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/binop_resets_statementness.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_binop_resets_statementness.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/binop_resets_statementness.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0075_block.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/block.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0075_block.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/block.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0075_block.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/block.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0075_block.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/block.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0044_block_items.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/block_items.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0044_block_items.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/block_items.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0044_block_items.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/block_items.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0044_block_items.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/block_items.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0143_box_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/box_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0143_box_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/box_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0143_box_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/box_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0143_box_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/box_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0088_break_ambiguity.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/break_ambiguity.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0088_break_ambiguity.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/break_ambiguity.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0088_break_ambiguity.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/break_ambiguity.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0088_break_ambiguity.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/break_ambiguity.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0034_break_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/break_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0034_break_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/break_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0034_break_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/break_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0034_break_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/break_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0207_builtin_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/builtin_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0042_call_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/call_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0042_call_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/call_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0042_call_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/call_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0042_call_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/call_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0029_cast_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cast_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0029_cast_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cast_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0029_cast_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cast_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0029_cast_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/cast_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0203_closure_body_underscore_assignment.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_body_underscore_assignment.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0203_closure_body_underscore_assignment.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_body_underscore_assignment.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0203_closure_body_underscore_assignment.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_body_underscore_assignment.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0203_closure_body_underscore_assignment.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_body_underscore_assignment.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0155_closure_params.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_params.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0155_closure_params.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_params.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0155_closure_params.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_params.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0155_closure_params.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_params.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_range_method_call.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_range_method_call.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_range_method_call.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/closure_range_method_call.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0184_const_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0184_const_arg.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0184_const_arg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0184_const_arg.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0183_const_arg_block.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_block.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0183_const_arg_block.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_block.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0183_const_arg_block.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_block.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0183_const_arg_block.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_block.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0192_const_arg_bool_literal.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_bool_literal.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0192_const_arg_bool_literal.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_bool_literal.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0192_const_arg_bool_literal.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_bool_literal.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0192_const_arg_bool_literal.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_bool_literal.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0189_const_arg_literal.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_literal.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0189_const_arg_literal.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_literal.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0189_const_arg_literal.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_literal.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0189_const_arg_literal.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_literal.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0191_const_arg_negative_number.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_negative_number.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0191_const_arg_negative_number.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_negative_number.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0191_const_arg_negative_number.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_negative_number.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0191_const_arg_negative_number.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_arg_negative_number.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_block_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_block_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_block_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_const_block_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_block_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_closure.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_closure.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_closure.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0205_const_closure.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_closure.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0172_const_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0172_const_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0172_const_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0172_const_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0147_const_param.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0147_const_param.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0147_const_param.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0147_const_param.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_expression.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_expression.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_expression.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_expression.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_literal.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_literal.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_literal.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_literal.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_path.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_path.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_path.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_param_default_path.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0212_const_trait_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_trait_bound.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0212_const_trait_bound.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_trait_bound.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0212_const_trait_bound.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_trait_bound.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0212_const_trait_bound.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/const_trait_bound.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0015_continue_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/continue_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0015_continue_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/continue_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0015_continue_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/continue_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0015_continue_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/continue_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0067_crate_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_path.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0067_crate_path.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_path.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0067_crate_path.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_path.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0067_crate_path.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_path.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0022_crate_visibility.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_visibility.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0022_crate_visibility.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_visibility.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0022_crate_visibility.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_visibility.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0022_crate_visibility.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_visibility.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_crate_visibility_in.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_visibility_in.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_crate_visibility_in.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_visibility_in.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_crate_visibility_in.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_visibility_in.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_crate_visibility_in.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/crate_visibility_in.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0163_default_async_fn.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_async_fn.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0163_default_async_fn.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_async_fn.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0163_default_async_fn.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_async_fn.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0163_default_async_fn.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_async_fn.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0162_default_async_unsafe_fn.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_async_unsafe_fn.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0162_default_async_unsafe_fn.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_async_unsafe_fn.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0162_default_async_unsafe_fn.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_async_unsafe_fn.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0162_default_async_unsafe_fn.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_async_unsafe_fn.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0164_default_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0164_default_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0164_default_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0164_default_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0163_default_unsafe_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_unsafe_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0163_default_unsafe_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_unsafe_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0163_default_unsafe_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_unsafe_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0163_default_unsafe_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/default_unsafe_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/destructuring_assignment_struct_rest_pattern.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/destructuring_assignment_struct_rest_pattern.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/destructuring_assignment_struct_rest_pattern.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0197_destructuring_assignment_struct_rest_pattern.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/destructuring_assignment_struct_rest_pattern.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/destructuring_assignment_wildcard_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/destructuring_assignment_wildcard_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/destructuring_assignment_wildcard_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0198_destructuring_assignment_wildcard_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/destructuring_assignment_wildcard_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0144_dot_dot_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dot_dot_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0144_dot_dot_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dot_dot_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0144_dot_dot_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dot_dot_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0144_dot_dot_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dot_dot_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0065_dyn_trait_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dyn_trait_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0065_dyn_trait_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dyn_trait_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0065_dyn_trait_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dyn_trait_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0065_dyn_trait_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/dyn_trait_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_effect_blocks.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/effect_blocks.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_effect_blocks.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/effect_blocks.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_effect_blocks.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/effect_blocks.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_effect_blocks.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/effect_blocks.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/exclusive_range_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/exclusive_range_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/exclusive_range_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0207_exclusive_range_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/exclusive_range_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0085_expr_literals.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/expr_literals.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0085_expr_literals.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/expr_literals.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0085_expr_literals.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/expr_literals.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0085_expr_literals.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/expr_literals.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_expression_after_block.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/expression_after_block.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_expression_after_block.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/expression_after_block.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_expression_after_block.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/expression_after_block.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_expression_after_block.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/expression_after_block.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0010_extern_block.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_block.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0010_extern_block.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_block.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0010_extern_block.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_block.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0010_extern_block.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_block.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0060_extern_crate.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0060_extern_crate.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0060_extern_crate.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0060_extern_crate.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0168_extern_crate_rename.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0168_extern_crate_rename.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0168_extern_crate_rename.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0168_extern_crate_rename.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_rename.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0168_extern_crate_self.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0168_extern_crate_self.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0168_extern_crate_self.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0168_extern_crate_self.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/extern_crate_self.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0011_field_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/field_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0151_fn.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0151_fn.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0151_fn.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0151_fn.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0050_fn_decl.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_decl.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0050_fn_decl.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_decl.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0050_fn_decl.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_decl.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0050_fn_decl.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_decl.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_def_param.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_def_param.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_def_param.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_def_param.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_param_ident_path.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_param_ident_path.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_param_ident_path.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_fn_pointer_param_ident_path.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_param_ident_path.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0032_fn_pointer_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0032_fn_pointer_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0032_fn_pointer_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0032_fn_pointer_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_type_with_ret.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_type_with_ret.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_type_with_ret.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0092_fn_pointer_type_with_ret.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_type_with_ret.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_unnamed_arg.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_unnamed_arg.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_unnamed_arg.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/fn_pointer_unnamed_arg.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0100_for_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0100_for_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0100_for_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0100_for_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0142_for_range_from.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_range_from.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0142_for_range_from.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_range_from.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0142_for_range_from.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_range_from.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0142_for_range_from.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_range_from.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0081_for_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0081_for_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0081_for_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0081_for_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/for_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0038_full_range_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/full_range_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0038_full_range_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/full_range_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0038_full_range_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/full_range_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0038_full_range_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/full_range_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0086_function_ret_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_ret_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0086_function_ret_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_ret_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0086_function_ret_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_ret_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0086_function_ret_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_ret_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0005_function_type_params.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_type_params.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0005_function_type_params.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_type_params.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0005_function_type_params.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_type_params.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0005_function_type_params.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_type_params.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0076_function_where_clause.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_where_clause.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0076_function_where_clause.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_where_clause.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0076_function_where_clause.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_where_clause.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0076_function_where_clause.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/function_where_clause.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0190_generic_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0190_generic_arg.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0190_generic_arg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0190_generic_arg.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_arg.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0181_generic_param_attribute.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_attribute.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0181_generic_param_attribute.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_attribute.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0181_generic_param_attribute.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_attribute.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0181_generic_param_attribute.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_attribute.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0183_type_param.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_list.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0183_type_param.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_list.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0183_type_param.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_list.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0183_type_param.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/generic_param_list.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0166_half_open_range_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/half_open_range_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0166_half_open_range_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/half_open_range_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0166_half_open_range_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/half_open_range_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0166_half_open_range_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/half_open_range_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0064_if_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/if_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0064_if_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/if_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0064_if_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/if_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0064_if_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/if_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0079_impl_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0079_impl_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0079_impl_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0079_impl_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0161_impl_item_const.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item_const.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0161_impl_item_const.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item_const.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0161_impl_item_const.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item_const.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0161_impl_item_const.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item_const.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0063_impl_item_neg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item_neg.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0063_impl_item_neg.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item_neg.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0063_impl_item_neg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item_neg.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0063_impl_item_neg.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_item_neg.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0028_impl_trait_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_trait_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0028_impl_trait_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_trait_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0028_impl_trait_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_trait_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0028_impl_trait_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_trait_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0150_impl_type_params.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_type_params.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0150_impl_type_params.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_type_params.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0150_impl_type_params.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_type_params.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0150_impl_type_params.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/impl_type_params.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0093_index_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/index_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0093_index_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/index_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0093_index_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/index_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0093_index_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/index_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0109_label.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/label.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0109_label.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/label.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0109_label.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/label.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0109_label.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/label.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0161_labeled_block.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/labeled_block.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0161_labeled_block.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/labeled_block.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0161_labeled_block.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/labeled_block.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0161_labeled_block.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/labeled_block.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0106_lambda_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lambda_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0106_lambda_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lambda_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0106_lambda_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lambda_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0106_lambda_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lambda_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_lambda_ret_block.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lambda_ret_block.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_lambda_ret_block.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lambda_ret_block.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_lambda_ret_block.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lambda_ret_block.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_lambda_ret_block.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lambda_ret_block.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_let_else.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_else.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_let_else.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_else.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_let_else.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_else.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_let_else.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_else.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0030_let_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0030_let_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0030_let_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0030_let_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0130_let_stmt.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0130_let_stmt.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0130_let_stmt.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0130_let_stmt.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_let_stmt_ascription.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt_ascription.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_let_stmt_ascription.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt_ascription.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_let_stmt_ascription.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt_ascription.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_let_stmt_ascription.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt_ascription.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0193_let_stmt_init.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt_init.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0193_let_stmt_init.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt_init.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0193_let_stmt_init.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt_init.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0193_let_stmt_init.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/let_stmt_init.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0186_lifetime_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_arg.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0186_lifetime_arg.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_arg.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0186_lifetime_arg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_arg.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0186_lifetime_arg.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_arg.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0182_lifetime_param.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0182_lifetime_param.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0182_lifetime_param.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0182_lifetime_param.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/lifetime_param.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0055_literal_pattern.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/literal_pattern.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0055_literal_pattern.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/literal_pattern.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0055_literal_pattern.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/literal_pattern.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0055_literal_pattern.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/literal_pattern.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0009_loop_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/loop_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0009_loop_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/loop_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0009_loop_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/loop_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0009_loop_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/loop_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0117_macro_call_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_call_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0117_macro_call_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_call_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0117_macro_call_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_call_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0117_macro_call_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_call_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0147_macro_def.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_def.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0147_macro_def.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_def.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0147_macro_def.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_def.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0147_macro_def.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_def.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_macro_def_curly.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_def_curly.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_macro_def_curly.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_def_curly.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_macro_def_curly.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_def_curly.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_macro_def_curly.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_def_curly.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_inside_generic_arg.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_inside_generic_arg.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_inside_generic_arg.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_inside_generic_arg.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_macro_rules_as_macro_name.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_rules_as_macro_name.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_macro_rules_as_macro_name.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_rules_as_macro_name.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_macro_rules_as_macro_name.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_rules_as_macro_name.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_macro_rules_as_macro_name.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_rules_as_macro_name.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_macro_rules_non_brace.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_rules_non_brace.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_macro_rules_non_brace.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_rules_non_brace.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_macro_rules_non_brace.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_rules_non_brace.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0158_macro_rules_non_brace.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/macro_rules_non_brace.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0129_marco_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/marco_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0129_marco_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/marco_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0129_marco_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/marco_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0129_marco_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/marco_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0066_match_arm.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arm.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0066_match_arm.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arm.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0066_match_arm.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arm.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0066_match_arm.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arm.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0059_match_arms_commas.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_commas.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0059_match_arms_commas.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_commas.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0059_match_arms_commas.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_commas.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0059_match_arms_commas.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_commas.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_inner_attribute.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_inner_attribute.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_inner_attribute.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_inner_attribute.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_outer_attributes.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_outer_attributes.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_outer_attributes.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_arms_outer_attributes.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0071_match_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0071_match_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0071_match_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0071_match_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0118_match_guard.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_guard.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0118_match_guard.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_guard.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0118_match_guard.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_guard.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0118_match_guard.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/match_guard.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0213_metas.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/metas.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0213_metas.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/metas.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0213_metas.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/metas.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0213_metas.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/metas.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0107_method_call_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/method_call_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0062_mod_contents.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_contents.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0062_mod_contents.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_contents.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0062_mod_contents.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_contents.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0062_mod_contents.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_contents.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0169_mod_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0169_mod_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0169_mod_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0169_mod_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0170_mod_item_curly.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_item_curly.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0170_mod_item_curly.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_item_curly.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0170_mod_item_curly.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_item_curly.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0170_mod_item_curly.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/mod_item_curly.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0014_never_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/never_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0014_never_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/never_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0014_never_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/never_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0014_never_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/never_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/no_dyn_trait_leading_for.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/no_dyn_trait_leading_for.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/no_dyn_trait_leading_for.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/no_dyn_trait_leading_for.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0096_no_semi_after_block.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/no_semi_after_block.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0096_no_semi_after_block.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/no_semi_after_block.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0096_no_semi_after_block.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/no_semi_after_block.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0096_no_semi_after_block.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/no_semi_after_block.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0113_nocontentexpr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/nocontentexpr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0113_nocontentexpr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/nocontentexpr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0113_nocontentexpr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/nocontentexpr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0113_nocontentexpr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/nocontentexpr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/nocontentexpr_after_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/nocontentexpr_after_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/nocontentexpr_after_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/nocontentexpr_after_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_or_pattern.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/or_pattern.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_or_pattern.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/or_pattern.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_or_pattern.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/or_pattern.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_or_pattern.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/or_pattern.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0099_param_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0099_param_list.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0099_param_list.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0099_param_list.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0045_param_list_opt_patterns.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0045_param_list_opt_patterns.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_opt_patterns.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_vararg.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_vararg.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_vararg.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_list_vararg.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0139_param_outer_arg.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_outer_arg.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0139_param_outer_arg.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_outer_arg.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0139_param_outer_arg.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_outer_arg.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0139_param_outer_arg.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/param_outer_arg.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0084_paren_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/paren_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0084_paren_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/paren_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0084_paren_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/paren_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0084_paren_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/paren_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0053_path_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0053_path_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0053_path_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0053_path_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0104_path_fn_trait_args.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0104_path_fn_trait_args.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0104_path_fn_trait_args.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0104_path_fn_trait_args.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_fn_trait_args.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0008_path_part.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_part.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0008_path_part.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_part.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0008_path_part.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_part.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0008_path_part.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_part.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0052_path_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0052_path_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0052_path_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0052_path_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0048_path_type_with_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_type_with_bounds.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0048_path_type_with_bounds.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_type_with_bounds.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0048_path_type_with_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_type_with_bounds.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0048_path_type_with_bounds.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/path_type_with_bounds.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0095_placeholder_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/placeholder_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0095_placeholder_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/placeholder_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0095_placeholder_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/placeholder_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0095_placeholder_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/placeholder_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0023_placeholder_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/placeholder_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0023_placeholder_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/placeholder_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0023_placeholder_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/placeholder_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0023_placeholder_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/placeholder_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0013_pointer_type_mut.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pointer_type_mut.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0013_pointer_type_mut.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pointer_type_mut.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0013_pointer_type_mut.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pointer_type_mut.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0013_pointer_type_mut.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pointer_type_mut.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0080_postfix_range.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/postfix_range.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0080_postfix_range.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/postfix_range.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0080_postfix_range.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/postfix_range.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0080_postfix_range.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/postfix_range.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0153_pub_parens_typepath.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pub_parens_typepath.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0153_pub_parens_typepath.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pub_parens_typepath.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0153_pub_parens_typepath.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pub_parens_typepath.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0153_pub_parens_typepath.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pub_parens_typepath.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0196_pub_tuple_field.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pub_tuple_field.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0196_pub_tuple_field.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pub_tuple_field.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0196_pub_tuple_field.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pub_tuple_field.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0196_pub_tuple_field.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/pub_tuple_field.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0037_qual_paths.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/qual_paths.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0037_qual_paths.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/qual_paths.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0037_qual_paths.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/qual_paths.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0037_qual_paths.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/qual_paths.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0201_question_for_type_trait_bound.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0201_question_for_type_trait_bound.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0201_question_for_type_trait_bound.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0201_question_for_type_trait_bound.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/question_for_type_trait_bound.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0058_range_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/range_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0058_range_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/range_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0058_range_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/range_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0058_range_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/range_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0054_record_field_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_attrs.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0054_record_field_attrs.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_attrs.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0054_record_field_attrs.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_attrs.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0054_record_field_attrs.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_attrs.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0172_record_field_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0172_record_field_list.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0172_record_field_list.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0172_record_field_list.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_list.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0061_record_lit.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_lit.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0061_record_lit.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_lit.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0061_record_lit.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_lit.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0061_record_lit.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_lit.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_literal_field_with_attr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_literal_field_with_attr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_literal_field_with_attr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_literal_field_with_attr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0145_record_pat_field.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0145_record_pat_field.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0145_record_pat_field.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0145_record_pat_field.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0102_record_pat_field_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field_list.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0102_record_pat_field_list.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field_list.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0102_record_pat_field_list.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field_list.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0102_record_pat_field_list.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_pat_field_list.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0082_ref_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0082_ref_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0082_ref_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0082_ref_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0027_ref_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0027_ref_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0027_ref_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0027_ref_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0033_reference_type;.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/reference_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0033_reference_type;.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/reference_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0033_reference_type;.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/reference_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0033_reference_type;.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/reference_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0072_return_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0072_return_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0072_return_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0072_return_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/return_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0006_self_param.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0006_self_param.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0006_self_param.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0006_self_param.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_self_param_outer_attr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param_outer_attr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param_outer_attr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_self_param_outer_attr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param_outer_attr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0138_self_param_outer_attr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/self_param_outer_attr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0046_singleton_tuple_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/singleton_tuple_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0046_singleton_tuple_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/singleton_tuple_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0046_singleton_tuple_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/singleton_tuple_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0046_singleton_tuple_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/singleton_tuple_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0024_slice_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0025_slice_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0025_slice_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0025_slice_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0025_slice_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/slice_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/stmt_bin_expr_ambiguity.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/stmt_bin_expr_ambiguity.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/stmt_bin_expr_ambiguity.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/stmt_bin_expr_ambiguity.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/stmt_postfix_expr_ambiguity.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/stmt_postfix_expr_ambiguity.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/stmt_postfix_expr_ambiguity.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/stmt_postfix_expr_ambiguity.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0171_struct_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/struct_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0171_struct_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/struct_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0171_struct_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/struct_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0171_struct_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/struct_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0151_trait_alias.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_alias.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0151_trait_alias.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_alias.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0151_trait_alias.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_alias.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0151_trait_alias.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_alias.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_trait_alias_where_clause.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_alias_where_clause.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_trait_alias_where_clause.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_alias_where_clause.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_trait_alias_where_clause.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_alias_where_clause.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_trait_alias_where_clause.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_alias_where_clause.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0041_trait_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0041_trait_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0041_trait_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0041_trait_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0175_trait_item_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_bounds.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0175_trait_item_bounds.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_bounds.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0175_trait_item_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_bounds.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0175_trait_item_bounds.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_bounds.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_trait_item_generic_params.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_generic_params.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_trait_item_generic_params.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_generic_params.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_trait_item_generic_params.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_generic_params.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_trait_item_generic_params.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_generic_params.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0176_trait_item_where_clause.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_where_clause.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0176_trait_item_where_clause.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_where_clause.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0176_trait_item_where_clause.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_where_clause.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0176_trait_item_where_clause.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/trait_item_where_clause.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0130_try_block_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_block_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0130_try_block_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_block_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0130_try_block_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_block_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0130_try_block_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_block_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0077_try_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0077_try_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0077_try_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0077_try_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_try_macro_fallback.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_macro_fallback.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_try_macro_fallback.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_macro_fallback.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_try_macro_fallback.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_macro_fallback.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_try_macro_fallback.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_macro_fallback.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_try_macro_rules.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_macro_rules.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_try_macro_rules.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_macro_rules.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_try_macro_rules.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_macro_rules.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_try_macro_rules.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/try_macro_rules.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_tuple_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_attrs.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_tuple_attrs.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_attrs.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_tuple_attrs.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_attrs.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0154_tuple_attrs.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_attrs.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0108_tuple_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0108_tuple_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0108_tuple_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0108_tuple_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0115_tuple_field_attrs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_field_attrs.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0115_tuple_field_attrs.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_field_attrs.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0115_tuple_field_attrs.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_field_attrs.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0115_tuple_field_attrs.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_field_attrs.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0111_tuple_pat.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat_fields.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat_fields.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat_fields.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0026_tuple_pat_fields.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_pat_fields.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0170_tuple_struct.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_struct.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0170_tuple_struct.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_struct.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0170_tuple_struct.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_struct.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0170_tuple_struct.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_struct.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0114_tuple_struct_where.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_struct_where.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0114_tuple_struct_where.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_struct_where.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0114_tuple_struct_where.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_struct_where.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0114_tuple_struct_where.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/tuple_struct_where.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0078_type_alias.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_alias.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0078_type_alias.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_alias.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0078_type_alias.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_alias.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0078_type_alias.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_alias.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0073_type_item_type_params.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_type_params.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0073_type_item_type_params.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_type_params.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0073_type_item_type_params.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_type_params.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0073_type_item_type_params.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_type_params.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_type_item_where_clause_deprecated.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause_deprecated.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_type_item_where_clause_deprecated.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause_deprecated.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_type_item_where_clause_deprecated.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause_deprecated.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_type_item_where_clause_deprecated.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_item_where_clause_deprecated.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0184_generic_param_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0184_generic_param_list.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0184_generic_param_list.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0184_generic_param_list.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0007_type_param_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0007_type_param_bounds.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0007_type_param_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0007_type_param_bounds.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0090_type_param_default.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_default.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0090_type_param_default.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_default.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0090_type_param_default.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_default.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0090_type_param_default.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_default.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0164_type_path_in_pattern.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0164_type_path_in_pattern.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0164_type_path_in_pattern.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0164_type_path_in_pattern.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_path_in_pattern.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/typepathfn_with_coloncolon.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0019_unary_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unary_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0019_unary_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unary_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0019_unary_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unary_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0019_unary_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unary_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_union_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/union_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_union_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/union_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_union_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/union_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0173_union_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/union_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_unit_struct.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unit_struct.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_unit_struct.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unit_struct.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_unit_struct.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unit_struct.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_unit_struct.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unit_struct.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0051_unit_type.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unit_type.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0051_unit_type.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unit_type.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0051_unit_type.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unit_type.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0051_unit_type.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/unit_type.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0181_use_item.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_item.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0181_use_item.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_item.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0181_use_item.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_item.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0181_use_item.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_item.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_use_tree.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_use_tree.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_use_tree.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_use_tree.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_abs_star.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_abs_star.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_abs_star.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_abs_star.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0176_use_tree_alias.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_alias.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0176_use_tree_alias.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_alias.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0176_use_tree_alias.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_alias.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0176_use_tree_alias.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_alias.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0002_use_tree_list.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_list.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0002_use_tree_list.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_list.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0002_use_tree_list.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_list.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0002_use_tree_list.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_list.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_use_tree_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_use_tree_path.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_use_tree_path.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0177_use_tree_path.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0180_use_tree_path_star.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path_star.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0180_use_tree_path_star.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path_star.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0180_use_tree_path_star.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path_star.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0180_use_tree_path_star.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path_star.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0178_use_tree_path_use_tree.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path_use_tree.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0178_use_tree_path_use_tree.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path_use_tree.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0178_use_tree_path_use_tree.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path_use_tree.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0178_use_tree_path_use_tree.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_path_use_tree.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_use_tree_star.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_star.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_use_tree_star.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_star.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_use_tree_star.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_star.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0174_use_tree_star.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/use_tree_star.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/value_parameters_no_patterns.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0157_variant_discriminant.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/variant_discriminant.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0157_variant_discriminant.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/variant_discriminant.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0157_variant_discriminant.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/variant_discriminant.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0157_variant_discriminant.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/variant_discriminant.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0056_where_clause.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_clause.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0056_where_clause.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_clause.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0056_where_clause.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_clause.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0056_where_clause.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_clause.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0003_where_pred_for.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0003_where_pred_for.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0003_where_pred_for.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0003_where_pred_for.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/where_pred_for.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0031_while_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/while_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0031_while_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/while_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0031_while_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/while_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0031_while_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/while_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yeet_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yeet_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yeet_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yeet_expr.rs
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_yield_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yield_expr.rast
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_yield_expr.rast
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yield_expr.rast
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_yield_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yield_expr.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_yield_expr.rs
rename to src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/yield_expr.rs
diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs
index 2491952f52f37..aeb0c00ae6aad 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen.rs
@@ -162,12 +162,12 @@ fn add_preamble(cg: CodegenType, mut text: String) -> String {
 /// Checks that the `file` has the specified `contents`. If that is not the
 /// case, updates the file and then fails the test.
 #[allow(clippy::print_stderr)]
-fn ensure_file_contents(cg: CodegenType, file: &Path, contents: &str, check: bool) {
+fn ensure_file_contents(cg: CodegenType, file: &Path, contents: &str, check: bool) -> bool {
     let contents = normalize_newlines(contents);
     if let Ok(old_contents) = fs::read_to_string(file) {
         if normalize_newlines(&old_contents) == contents {
             // File is already up to date.
-            return;
+            return false;
         }
     }
 
@@ -194,6 +194,7 @@ fn ensure_file_contents(cg: CodegenType, file: &Path, contents: &str, check: boo
             let _ = fs::create_dir_all(parent);
         }
         fs::write(file, contents).unwrap();
+        true
     }
 }
 
diff --git a/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs b/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs
index 5983b06e1b9cf..3a9073b4e407a 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs
@@ -6,68 +6,132 @@ use std::{
     collections::HashMap,
     fs, iter,
     path::{Path, PathBuf},
+    time::SystemTime,
 };
 
+use anyhow::Result;
+use itertools::Itertools as _;
+
 use crate::{
-    codegen::{ensure_file_contents, CommentBlock},
+    codegen::{ensure_file_contents, reformat, CommentBlock},
     project_root,
     util::list_rust_files,
 };
 
+const PARSER_CRATE_ROOT: &str = "crates/parser";
+const PARSER_TEST_DATA: &str = "crates/parser/test_data";
+const PARSER_TEST_DATA_INLINE: &str = "crates/parser/test_data/parser/inline";
+
 pub(crate) fn generate(check: bool) {
-    let grammar_dir = project_root().join(Path::new("crates/parser/src/grammar"));
-    let tests = tests_from_dir(&grammar_dir);
+    let tests = tests_from_dir(
+        &project_root().join(Path::new(&format!("{PARSER_CRATE_ROOT}/src/grammar"))),
+    );
 
-    install_tests(&tests.ok, "crates/parser/test_data/parser/inline/ok", check);
-    install_tests(&tests.err, "crates/parser/test_data/parser/inline/err", check);
+    let mut some_file_was_updated = false;
+    some_file_was_updated |=
+        install_tests(&tests.ok, &format!("{PARSER_TEST_DATA_INLINE}/ok"), check).unwrap();
+    some_file_was_updated |=
+        install_tests(&tests.err, &format!("{PARSER_TEST_DATA_INLINE}/err"), check).unwrap();
 
-    fn install_tests(tests: &HashMap, into: &str, check: bool) {
-        let tests_dir = project_root().join(into);
-        if !tests_dir.is_dir() {
-            fs::create_dir_all(&tests_dir).unwrap();
-        }
-        // ok is never actually read, but it needs to be specified to create a Test in existing_tests
-        let existing = existing_tests(&tests_dir, true);
-        if let Some(t) = existing.keys().find(|&t| !tests.contains_key(t)) {
-            panic!("Test is deleted: {t}");
-        }
+    if some_file_was_updated {
+        let _ = fs::File::open(&format!("{PARSER_CRATE_ROOT}/src/tests.rs"))
+            .unwrap()
+            .set_modified(SystemTime::now());
 
-        let mut new_idx = existing.len() + 1;
-        for (name, test) in tests {
-            let path = match existing.get(name) {
-                Some((path, _test)) => path.clone(),
-                None => {
-                    let file_name = format!("{new_idx:04}_{name}.rs");
-                    new_idx += 1;
-                    tests_dir.join(file_name)
+        let ok_tests = tests.ok.keys().sorted().map(|k| {
+            let test_name = quote::format_ident!("{}", k);
+            let test_file = format!("test_data/parser/inline/ok/{test_name}.rs");
+            quote::quote! {
+                #[test]
+                fn #test_name() {
+                    run_and_expect_no_errors(#test_file);
                 }
-            };
-            ensure_file_contents(crate::flags::CodegenType::ParserTests, &path, &test.text, check);
+            }
+        });
+        let err_tests = tests.err.keys().sorted().map(|k| {
+            let test_name = quote::format_ident!("{}", k);
+            let test_file = format!("test_data/parser/inline/err/{test_name}.rs");
+            quote::quote! {
+                #[test]
+                fn #test_name() {
+                    run_and_expect_errors(#test_file);
+                }
+            }
+        });
+
+        let output = quote::quote! {
+            mod ok {
+                use crate::tests::run_and_expect_no_errors;
+                #(#ok_tests)*
+            }
+            mod err {
+                use crate::tests::run_and_expect_errors;
+                #(#err_tests)*
+            }
+        };
+
+        let pretty = reformat(output.to_string());
+        ensure_file_contents(
+            crate::flags::CodegenType::ParserTests,
+            format!("{PARSER_TEST_DATA}/generated/runner.rs").as_ref(),
+            &pretty,
+            check,
+        );
+    }
+}
+
+fn install_tests(tests: &HashMap, into: &str, check: bool) -> Result {
+    let tests_dir = project_root().join(into);
+    if !tests_dir.is_dir() {
+        fs::create_dir_all(&tests_dir)?;
+    }
+    let existing = existing_tests(&tests_dir, TestKind::Ok)?;
+    if let Some((t, (path, _))) = existing.iter().find(|&(t, _)| !tests.contains_key(t)) {
+        panic!("Test `{t}` is deleted: {}", path.display());
+    }
+
+    let mut some_file_was_updated = false;
+
+    for (name, test) in tests {
+        let path = match existing.get(name) {
+            Some((path, _test)) => path.clone(),
+            None => tests_dir.join(name).with_extension("rs"),
+        };
+        if ensure_file_contents(crate::flags::CodegenType::ParserTests, &path, &test.text, check) {
+            some_file_was_updated = true;
         }
     }
+
+    Ok(some_file_was_updated)
 }
 
 #[derive(Debug)]
 struct Test {
-    name: String,
-    text: String,
-    ok: bool,
+    pub name: String,
+    pub text: String,
+    pub kind: TestKind,
+}
+
+#[derive(Copy, Clone, Debug)]
+enum TestKind {
+    Ok,
+    Err,
 }
 
 #[derive(Default, Debug)]
 struct Tests {
-    ok: HashMap,
-    err: HashMap,
+    pub ok: HashMap,
+    pub err: HashMap,
 }
 
 fn collect_tests(s: &str) -> Vec {
     let mut res = Vec::new();
     for comment_block in CommentBlock::extract_untagged(s) {
         let first_line = &comment_block.contents[0];
-        let (name, ok) = if let Some(name) = first_line.strip_prefix("test ") {
-            (name.to_owned(), true)
+        let (name, kind) = if let Some(name) = first_line.strip_prefix("test ") {
+            (name.to_owned(), TestKind::Ok)
         } else if let Some(name) = first_line.strip_prefix("test_err ") {
-            (name.to_owned(), false)
+            (name.to_owned(), TestKind::Err)
         } else {
             continue;
         };
@@ -78,7 +142,7 @@ fn collect_tests(s: &str) -> Vec {
             .collect::>()
             .join("\n");
         assert!(!text.trim().is_empty() && text.ends_with('\n'));
-        res.push(Test { name, text, ok })
+        res.push(Test { name, text, kind })
     }
     res
 }
@@ -96,7 +160,7 @@ fn tests_from_dir(dir: &Path) -> Tests {
         let text = fs::read_to_string(path).unwrap();
 
         for test in collect_tests(&text) {
-            if test.ok {
+            if let TestKind::Ok = test.kind {
                 if let Some(old_test) = res.ok.insert(test.name.clone(), test) {
                     panic!("Duplicate test: {}", old_test.name);
                 }
@@ -107,25 +171,22 @@ fn tests_from_dir(dir: &Path) -> Tests {
     }
 }
 
-fn existing_tests(dir: &Path, ok: bool) -> HashMap {
-    let mut res = HashMap::default();
-    for file in fs::read_dir(dir).unwrap() {
-        let file = file.unwrap();
-        let path = file.path();
-        if path.extension().unwrap_or_default() != "rs" {
-            continue;
-        }
-        let name = {
-            let file_name = path.file_name().unwrap().to_str().unwrap();
-            file_name[5..file_name.len() - 3].to_string()
-        };
-        let text = fs::read_to_string(&path).unwrap();
-        let test = Test { name: name.clone(), text, ok };
-        if let Some(old) = res.insert(name, (path, test)) {
-            println!("Duplicate test: {old:?}");
+fn existing_tests(dir: &Path, ok: TestKind) -> Result> {
+    let mut res = HashMap::new();
+    for file in fs::read_dir(dir)? {
+        let path = file?.path();
+        let rust_file = path.extension().and_then(|ext| ext.to_str()) == Some("rs");
+
+        if rust_file {
+            let name = path.file_stem().map(|x| x.to_string_lossy().to_string()).unwrap();
+            let text = fs::read_to_string(&path)?;
+            let test = Test { name: name.clone(), text, kind: ok };
+            if let Some(old) = res.insert(name, (path, test)) {
+                println!("Duplicate test: {:?}", old);
+            }
         }
     }
-    res
+    Ok(res)
 }
 
 #[test]

From 2e582ad8485e6c2359305926d8749be2d845b0f7 Mon Sep 17 00:00:00 2001
From: David Barsky 
Date: Thu, 18 Jul 2024 12:01:26 -0400
Subject: [PATCH 049/489] feature: move `linked_projects` discovery to the
 rust-analyzer server

---
 src/tools/rust-analyzer/Cargo.lock            | 127 +++++------
 .../rust-analyzer/crates/flycheck/Cargo.toml  |   1 +
 .../rust-analyzer/crates/flycheck/src/lib.rs  |   3 +-
 .../crates/flycheck/src/project_json.rs       | 152 +++++++++++++
 .../crates/load-cargo/src/lib.rs              |   2 -
 .../crates/project-model/src/project_json.rs  |  20 +-
 .../crates/project-model/src/workspace.rs     |  17 +-
 .../crates/rust-analyzer/src/bin/main.rs      |   6 +-
 .../crates/rust-analyzer/src/config.rs        | 208 +++++++++++++++++-
 .../crates/rust-analyzer/src/global_state.rs  |  46 +++-
 .../src/handlers/notification.rs              |  42 +++-
 .../rust-analyzer/src/handlers/request.rs     |   5 +-
 .../crates/rust-analyzer/src/lsp/ext.rs       |   2 +-
 .../crates/rust-analyzer/src/lsp/utils.rs     |   1 -
 .../crates/rust-analyzer/src/main_loop.rs     | 173 +++++++++++----
 .../crates/rust-analyzer/src/op_queue.rs      |   1 +
 .../crates/rust-analyzer/src/reload.rs        | 100 +++++++--
 .../rust-analyzer/src/tracing/config.rs       |   5 +-
 .../rust-analyzer/tests/slow-tests/main.rs    |   1 -
 .../rust-analyzer/docs/dev/lsp-extensions.md  |   2 +-
 .../docs/user/generated_config.adoc           |  98 +++++++++
 .../rust-analyzer/editors/code/package.json   |  34 +++
 22 files changed, 877 insertions(+), 169 deletions(-)
 create mode 100644 src/tools/rust-analyzer/crates/flycheck/src/project_json.rs

diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 2a1e7c4d59aaa..b98a1195d8bb7 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.21.0"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
 dependencies = [
  "gimli",
 ]
@@ -28,9 +28,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.83"
+version = "1.0.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
 
 [[package]]
 name = "arbitrary"
@@ -52,16 +52,16 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
 
 [[package]]
 name = "backtrace"
-version = "0.3.71"
+version = "0.3.72"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
+checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11"
 dependencies = [
  "addr2line",
  "cc",
  "cfg-if",
  "libc",
  "miniz_oxide",
- "object 0.32.2",
+ "object 0.35.0",
  "rustc-demangle",
 ]
 
@@ -104,9 +104,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "camino"
-version = "1.1.6"
+version = "1.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
+checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239"
 dependencies = [
  "serde",
 ]
@@ -136,9 +136,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.97"
+version = "1.0.98"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
+checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
 
 [[package]]
 name = "cfg"
@@ -232,18 +232,18 @@ checksum = "0d48d8f76bd9331f19fe2aaf3821a9f9fb32c3963e1e3d6ce82a8c09cef7444a"
 
 [[package]]
 name = "crc32fast"
-version = "1.4.0"
+version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
 dependencies = [
  "cfg-if",
 ]
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.12"
+version = "0.5.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
+checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
 dependencies = [
  "crossbeam-utils",
 ]
@@ -269,9 +269,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.19"
+version = "0.8.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
 
 [[package]]
 name = "ctrlc"
@@ -366,9 +366,9 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
 
 [[package]]
 name = "either"
-version = "1.11.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
+checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
 
 [[package]]
 name = "ena"
@@ -431,6 +431,7 @@ dependencies = [
  "crossbeam-channel",
  "paths",
  "process-wrap",
+ "project-model",
  "rustc-hash",
  "serde",
  "serde_json",
@@ -476,9 +477,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.28.1"
+version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
+checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
 
 [[package]]
 name = "hashbrown"
@@ -916,9 +917,9 @@ dependencies = [
 
 [[package]]
 name = "libmimalloc-sys"
-version = "0.1.37"
+version = "0.1.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7"
+checksum = "0e7bb23d733dfcc8af652a78b7bf232f0e967710d044732185e561e47c0336b6"
 dependencies = [
  "cc",
  "libc",
@@ -1086,18 +1087,18 @@ dependencies = [
 
 [[package]]
 name = "mimalloc"
-version = "0.1.41"
+version = "0.1.42"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d"
+checksum = "e9186d86b79b52f4a77af65604b51225e8db1d6ee7e3f41aec1e40829c71a176"
 dependencies = [
  "libmimalloc-sys",
 ]
 
 [[package]]
 name = "miniz_oxide"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
+checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
 dependencies = [
  "adler",
 ]
@@ -1162,9 +1163,9 @@ dependencies = [
 
 [[package]]
 name = "nu-ansi-term"
-version = "0.49.0"
+version = "0.50.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68"
+checksum = "dd2800e1520bdc966782168a627aa5d1ad92e33b984bf7c7615d31280c83ff14"
 dependencies = [
  "windows-sys 0.48.0",
 ]
@@ -1187,18 +1188,18 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.32.2"
+version = "0.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
+checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "object"
-version = "0.33.0"
+version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d"
+checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
 dependencies = [
  "memchr",
 ]
@@ -1223,9 +1224,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
 
 [[package]]
 name = "parking_lot"
-version = "0.12.2"
+version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
+checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
 dependencies = [
  "lock_api",
  "parking_lot_core",
@@ -1379,9 +1380,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.82"
+version = "1.0.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
+checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
 dependencies = [
  "unicode-ident",
 ]
@@ -1800,18 +1801,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.201"
+version = "1.0.203"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c"
+checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.201"
+version = "1.0.203"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865"
+checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1843,9 +1844,9 @@ dependencies = [
 
 [[package]]
 name = "serde_spanned"
-version = "0.6.5"
+version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
+checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
 dependencies = [
  "serde",
 ]
@@ -1867,9 +1868,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
 name = "smol_str"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49"
+checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead"
 dependencies = [
  "serde",
 ]
@@ -1922,9 +1923,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.63"
+version = "2.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"
+checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2009,18 +2010,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
 
 [[package]]
 name = "thiserror"
-version = "1.0.60"
+version = "1.0.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
+checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.60"
+version = "1.0.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
+checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2104,9 +2105,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "toml"
-version = "0.8.12"
+version = "0.8.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
+checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
 dependencies = [
  "serde",
  "serde_spanned",
@@ -2116,18 +2117,18 @@ dependencies = [
 
 [[package]]
 name = "toml_datetime"
-version = "0.6.5"
+version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
+checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "toml_edit"
-version = "0.22.12"
+version = "0.22.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"
+checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
 dependencies = [
  "indexmap",
  "serde",
@@ -2201,9 +2202,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-tree"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65139ecd2c3f6484c3b99bc01c77afe21e95473630747c7aca525e78b0666675"
+checksum = "b56c62d2c80033cb36fae448730a2f2ef99410fe3ecbffc916681a32f6807dbe"
 dependencies = [
  "nu-ansi-term",
  "tracing-core",
@@ -2213,9 +2214,9 @@ dependencies = [
 
 [[package]]
 name = "triomphe"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3"
+checksum = "1b2cb4fbb9995eeb36ac86fadf24031ccd58f99d6b4b2d7b911db70bddb80d90"
 dependencies = [
  "serde",
  "stable_deref_trait",
@@ -2555,9 +2556,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
 
 [[package]]
 name = "winnow"
-version = "0.6.8"
+version = "0.6.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
+checksum = "56c52728401e1dc672a56e81e593e912aa54c78f40246869f78359a2bf24d29d"
 dependencies = [
  "memchr",
 ]
diff --git a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
index d81a5fe340066..bb3a94c8da678 100644
--- a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
@@ -24,6 +24,7 @@ process-wrap.workspace = true
 paths.workspace = true
 stdx.workspace = true
 toolchain.workspace = true
+project-model.workspace = true
 
 [lints]
 workspace = true
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index 778def5d2bed6..ce148037fcfb4 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -20,6 +20,7 @@ pub use cargo_metadata::diagnostic::{
 use toolchain::Tool;
 
 mod command;
+pub mod project_json;
 mod test_runner;
 
 use command::{CommandHandle, ParseFromLine};
@@ -240,7 +241,7 @@ enum FlycheckStatus {
     Finished,
 }
 
-const SAVED_FILE_PLACEHOLDER: &str = "$saved_file";
+pub const SAVED_FILE_PLACEHOLDER: &str = "$saved_file";
 
 impl FlycheckActor {
     fn new(
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/project_json.rs b/src/tools/rust-analyzer/crates/flycheck/src/project_json.rs
new file mode 100644
index 0000000000000..b6e4495bc6d6e
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/flycheck/src/project_json.rs
@@ -0,0 +1,152 @@
+//! A `cargo-metadata`-equivalent for non-Cargo build systems.
+use std::{io, process::Command};
+
+use crossbeam_channel::Sender;
+use paths::{AbsPathBuf, Utf8Path, Utf8PathBuf};
+use project_model::ProjectJsonData;
+use serde::{Deserialize, Serialize};
+use serde_json::Value;
+
+use crate::command::{CommandHandle, ParseFromLine};
+
+pub const ARG_PLACEHOLDER: &str = "{arg}";
+
+/// A command wrapper for getting a `rust-project.json`.
+///
+/// This is analogous to `cargo-metadata`, but for non-Cargo build systems.
+pub struct Discover {
+    command: Vec,
+    sender: Sender,
+}
+
+#[derive(PartialEq, Clone, Debug, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub enum DiscoverArgument {
+    Path(#[serde(serialize_with = "serialize_abs_pathbuf")] AbsPathBuf),
+    Buildfile(#[serde(serialize_with = "serialize_abs_pathbuf")] AbsPathBuf),
+}
+
+fn serialize_abs_pathbuf(path: &AbsPathBuf, se: S) -> Result
+where
+    S: serde::Serializer,
+{
+    let path: &Utf8Path = path.as_ref();
+    se.serialize_str(path.as_str())
+}
+
+impl Discover {
+    /// Create a new [Discover].
+    pub fn new(sender: Sender, command: Vec) -> Self {
+        Self { sender, command }
+    }
+
+    /// Spawn the command inside [Discover] and report progress, if any.
+    pub fn spawn(&self, discover_arg: DiscoverArgument) -> io::Result {
+        let command = &self.command[0];
+        let args = &self.command[1..];
+
+        let args: Vec = args
+            .iter()
+            .map(|arg| {
+                if arg == ARG_PLACEHOLDER {
+                    serde_json::to_string(&discover_arg).expect("Unable to serialize args")
+                } else {
+                    arg.to_owned()
+                }
+            })
+            .collect();
+
+        let mut cmd = Command::new(command);
+        cmd.args(args);
+
+        Ok(DiscoverHandle { _handle: CommandHandle::spawn(cmd, self.sender.clone())? })
+    }
+}
+
+/// A handle to a spawned [Discover].
+#[derive(Debug)]
+pub struct DiscoverHandle {
+    _handle: CommandHandle,
+}
+
+/// An enum containing either progress messages, an error,
+/// or the materialized `rust-project`.
+#[derive(Debug, Clone, Deserialize, Serialize)]
+#[serde(tag = "kind")]
+#[serde(rename_all = "snake_case")]
+enum DiscoverProjectData {
+    Finished { buildfile: Utf8PathBuf, project: ProjectJsonData },
+    Error { error: String, source: Option },
+    Progress { message: String },
+}
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum DiscoverProjectMessage {
+    Finished { project: ProjectJsonData, buildfile: AbsPathBuf },
+    Error { error: String, source: Option },
+    Progress { message: String },
+}
+
+impl DiscoverProjectMessage {
+    fn new(data: DiscoverProjectData) -> Self {
+        match data {
+            DiscoverProjectData::Finished { project, buildfile, .. } => {
+                let buildfile = buildfile.try_into().expect("Unable to make path absolute");
+                DiscoverProjectMessage::Finished { project, buildfile }
+            }
+            DiscoverProjectData::Error { error, source } => {
+                DiscoverProjectMessage::Error { error, source }
+            }
+            DiscoverProjectData::Progress { message } => {
+                DiscoverProjectMessage::Progress { message }
+            }
+        }
+    }
+}
+
+impl ParseFromLine for DiscoverProjectMessage {
+    fn from_line(line: &str, _error: &mut String) -> Option {
+        // can the line even be deserialized as JSON?
+        let Ok(data) = serde_json::from_str::(line) else {
+            let err = DiscoverProjectData::Error { error: line.to_owned(), source: None };
+            return Some(DiscoverProjectMessage::new(err));
+        };
+
+        let Ok(data) = serde_json::from_value::(data) else {
+            return None;
+        };
+
+        let msg = DiscoverProjectMessage::new(data);
+        Some(msg)
+    }
+
+    fn from_eof() -> Option {
+        None
+    }
+}
+
+#[test]
+fn test_deserialization() {
+    let message = r#"
+    {"kind": "progress", "message":"querying build system","input":{"files":["src/main.rs"]}}
+    "#;
+    let message: DiscoverProjectData =
+        serde_json::from_str(message).expect("Unable to deserialize message");
+    assert!(matches!(message, DiscoverProjectData::Progress { .. }));
+
+    let message = r#"
+    {"kind": "error", "error":"failed to deserialize command output","source":"command"}
+    "#;
+
+    let message: DiscoverProjectData =
+        serde_json::from_str(message).expect("Unable to deserialize message");
+    assert!(matches!(message, DiscoverProjectData::Error { .. }));
+
+    let message = r#"
+    {"kind": "finished", "project": {"sysroot": "foo", "crates": [], "runnables": []}, "buildfile":"rust-analyzer/BUILD"}
+    "#;
+
+    let message: DiscoverProjectData =
+        serde_json::from_str(message).expect("Unable to deserialize message");
+    assert!(matches!(message, DiscoverProjectData::Finished { .. }));
+}
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index b7ddbc9665a5b..1c81240e4f9c1 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -17,7 +17,6 @@ use itertools::Itertools;
 use proc_macro_api::{MacroDylib, ProcMacroServer};
 use project_model::{CargoConfig, ManifestPath, PackageRoot, ProjectManifest, ProjectWorkspace};
 use span::Span;
-use tracing::instrument;
 use vfs::{file_set::FileSetConfig, loader::Handle, AbsPath, AbsPathBuf, VfsPath};
 
 pub struct LoadCargoConfig {
@@ -51,7 +50,6 @@ pub fn load_workspace_at(
     load_workspace(workspace, &cargo_config.extra_env, load_config)
 }
 
-#[instrument(skip_all)]
 pub fn load_workspace(
     ws: ProjectWorkspace,
     extra_env: &FxHashMap,
diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
index 4b55f9d2b9e4c..421ef25a45ac5 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
@@ -276,6 +276,16 @@ impl ProjectJson {
         self.manifest.as_ref()
     }
 
+    pub fn crate_by_buildfile(&self, path: &AbsPath) -> Option {
+        // this is fast enough for now, but it's unfortunate that this is O(crates).
+        let path: &std::path::Path = path.as_ref();
+        self.crates
+            .iter()
+            .filter(|krate| krate.is_workspace_member)
+            .filter_map(|krate| krate.build.clone())
+            .find(|build| build.build_file.as_std_path() == path)
+    }
+
     /// Returns the path to the project's manifest or root folder, if no manifest exists.
     pub fn manifest_or_root(&self) -> &AbsPath {
         self.manifest.as_ref().map_or(&self.project_root, |manifest| manifest.as_ref())
@@ -286,7 +296,7 @@ impl ProjectJson {
     }
 }
 
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
 pub struct ProjectJsonData {
     sysroot: Option,
     sysroot_src: Option,
@@ -295,7 +305,7 @@ pub struct ProjectJsonData {
     runnables: Vec,
 }
 
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
 struct CrateData {
     display_name: Option,
     root_module: Utf8PathBuf,
@@ -319,7 +329,7 @@ struct CrateData {
     build: Option,
 }
 
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
 #[serde(rename = "edition")]
 enum EditionData {
     #[serde(rename = "2015")]
@@ -332,7 +342,7 @@ enum EditionData {
     Edition2024,
 }
 
-#[derive(Debug, Clone, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
 pub struct BuildData {
     label: String,
     build_file: Utf8PathBuf,
@@ -419,7 +429,7 @@ pub(crate) struct Dep {
     pub(crate) name: CrateName,
 }
 
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
 struct CrateSource {
     include_dirs: Vec,
     exclude_dirs: Vec,
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index dd7a11ca85f19..ec6cbf369a361 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -31,6 +31,7 @@ use crate::{
     utf8_stdout, CargoConfig, CargoWorkspace, InvocationStrategy, ManifestPath, Package,
     ProjectJson, ProjectManifest, Sysroot, TargetData, TargetKind, WorkspaceBuildScripts,
 };
+use tracing::{debug, error, info};
 
 pub type FileLoader<'a> = &'a mut dyn for<'b> FnMut(&'b AbsPath) -> Option;
 
@@ -250,7 +251,7 @@ impl ProjectWorkspace {
                 };
 
                 let rustc =  rustc_dir.and_then(|rustc_dir| {
-                    tracing::info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
+                    info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
                     match CargoWorkspace::fetch_metadata(
                         &rustc_dir,
                         cargo_toml.parent(),
@@ -767,9 +768,9 @@ impl ProjectWorkspace {
         };
 
         if matches!(sysroot.mode(), SysrootMode::Stitched(_)) && crate_graph.patch_cfg_if() {
-            tracing::debug!("Patched std to depend on cfg-if")
+            debug!("Patched std to depend on cfg-if")
         } else {
-            tracing::debug!("Did not patch std to depend on cfg-if")
+            debug!("Did not patch std to depend on cfg-if")
         }
         (crate_graph, proc_macros)
     }
@@ -917,6 +918,11 @@ fn project_json_to_crate_graph(
                         CrateOrigin::Local { repo: None, name: None }
                     },
                 );
+                debug!(
+                    ?crate_graph_crate_id,
+                    crate = display_name.as_ref().map(|name| name.canonical_name().as_str()),
+                    "added root to crate graph"
+                );
                 if *is_proc_macro {
                     if let Some(path) = proc_macro_dylib_path.clone() {
                         let node = Ok((
@@ -931,6 +937,7 @@ fn project_json_to_crate_graph(
         )
         .collect();
 
+    debug!(map = ?idx_to_crate_id);
     for (from_idx, krate) in project.crates() {
         if let Some(&from) = idx_to_crate_id.get(&from_idx) {
             public_deps.add_to_crate_graph(crate_graph, from);
@@ -1156,7 +1163,7 @@ fn detached_file_to_crate_graph(
     let file_id = match load(detached_file) {
         Some(file_id) => file_id,
         None => {
-            tracing::error!("Failed to load detached file {:?}", detached_file);
+            error!("Failed to load detached file {:?}", detached_file);
             return (crate_graph, FxHashMap::default());
         }
     };
@@ -1351,7 +1358,7 @@ fn add_target_crate_root(
     crate_id
 }
 
-#[derive(Default)]
+#[derive(Default, Debug)]
 struct SysrootPublicDeps {
     deps: Vec<(CrateName, CrateId, bool)>,
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
index 1985093bc5c34..6a980a153c991 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
@@ -175,6 +175,7 @@ fn run_server() -> anyhow::Result<()> {
             return Err(e.into());
         }
     };
+
     tracing::info!("InitializeParams: {}", initialize_params);
     let lsp_types::InitializeParams {
         root_uri,
@@ -264,7 +265,10 @@ fn run_server() -> anyhow::Result<()> {
         return Err(e.into());
     }
 
-    if !config.has_linked_projects() && config.detached_files().is_empty() {
+    if config.discover_workspace_config().is_none()
+        && !config.has_linked_projects()
+        && config.detached_files().is_empty()
+    {
         config.rediscover_workspaces();
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index a0ec3920e6e29..c13a98d223279 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -328,6 +328,102 @@ config_data! {
         /// `textDocument/rangeFormatting` request. The rustfmt option is unstable and only
         /// available on a nightly build.
         rustfmt_rangeFormatting_enable: bool = false,
+
+        /// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`].
+        ///
+        /// [`DiscoverWorkspaceConfig`] also requires setting `progress_label` and `files_to_watch`.
+        /// `progress_label` is used for the title in progress indicators, whereas `files_to_watch`
+        /// is used to determine which build system-specific files should be watched in order to
+        /// reload rust-analyzer.
+        ///
+        /// Below is an example of a valid configuration:
+        /// ```json
+        /// "rust-analyzer.workspace.discoverConfig": {
+        ///     "command": [
+        ///         "rust-project",
+        ///         "develop-json",
+        ///         {arg}
+        ///     ],
+        ///     "progressLabel": "rust-analyzer",
+        ///     "filesToWatch": [
+        ///         "BUCK",
+        ///     ],
+        /// }
+        /// ```
+        ///
+        /// ## On `DiscoverWorkspaceConfig::command`
+        ///
+        /// **Warning**: This format is provisional and subject to change.
+        ///
+        /// [`DiscoverWorkspaceConfig::command`] *must* return a JSON object
+        /// corresponding to `DiscoverProjectData::Finished`:
+        ///
+        /// ```norun
+        /// #[derive(Debug, Clone, Deserialize, Serialize)]
+        /// #[serde(tag = "kind")]
+        /// #[serde(rename_all = "snake_case")]
+        /// enum DiscoverProjectData {
+        ///     Finished { buildfile: Utf8PathBuf, project: ProjectJsonData },
+        ///     Error { error: String, source: Option },
+        ///     Progress { message: String },
+        /// }
+        /// ```
+        ///
+        /// As JSON, `DiscoverProjectData::Finished` is:
+        ///
+        /// ```json
+        /// {
+        ///     // the internally-tagged representation of the enum.
+        ///     "kind": "finished",
+        ///     // the file used by a non-Cargo build system to define
+        ///     // a package or target.
+        ///     "buildfile": "rust-analyzer/BUILD",
+        ///     // the contents of a rust-project.json, elided for brevity
+        ///     "project": {
+        ///         "sysroot": "foo",
+        ///         "crates": []
+        ///     }
+        /// }
+        /// ```
+        ///
+        /// It is encouraged, but not required, to use the other variants on
+        /// `DiscoverProjectData` to provide a more polished end-user experience.
+        ///
+        /// `DiscoverWorkspaceConfig::command` may *optionally* include an `{arg}`,
+        /// which will be substituted with the JSON-serialized form of the following
+        /// enum:
+        ///
+        /// ```norun
+        /// #[derive(PartialEq, Clone, Debug, Serialize)]
+        /// #[serde(rename_all = "camelCase")]
+        /// pub enum DiscoverArgument {
+        ///    Path(AbsPathBuf),
+        ///    Buildfile(AbsPathBuf),
+        /// }
+        /// ```
+        ///
+        /// The JSON representation of `DiscoverArgument::Path` is:
+        ///
+        /// ```json
+        /// {
+        ///     "path": "src/main.rs"
+        /// }
+        /// ```
+        ///
+        /// Similarly, the JSON representation of `DiscoverArgument::Buildfile` is:
+        ///
+        /// ```
+        /// {
+        ///     "buildfile": "BUILD"
+        /// }
+        /// ```
+        ///
+        /// `DiscoverArgument::Path` is used to find and generate a `rust-project.json`,
+        /// and therefore, a workspace, whereas `DiscoverArgument::buildfile` is used to
+        /// to update an existing workspace. As a reference for implementors,
+        /// buck2's `rust-project` will likely be useful:
+        /// https://github.com/facebook/buck2/tree/main/integrations/rust-project.
+        workspace_discoverConfig: Option = None,
     }
 }
 
@@ -924,6 +1020,21 @@ impl Config {
         );
         (config, e, should_update)
     }
+
+    pub fn add_linked_projects(&mut self, data: ProjectJsonData, buildfile: AbsPathBuf) {
+        let linked_projects = &mut self.client_config.0.global.linkedProjects;
+
+        let new_project = ManifestOrProjectJson::DiscoveredProjectJson { data, buildfile };
+        match linked_projects {
+            Some(projects) => {
+                match projects.iter_mut().find(|p| p.manifest() == new_project.manifest()) {
+                    Some(p) => *p = new_project,
+                    None => projects.push(new_project),
+                }
+            }
+            None => *linked_projects = Some(vec![new_project]),
+        }
+    }
 }
 
 #[derive(Default, Debug)]
@@ -988,6 +1099,14 @@ impl From for LinkedProject {
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct DiscoverWorkspaceConfig {
+    pub command: Vec,
+    pub progress_label: String,
+    pub files_to_watch: Vec,
+}
+
 pub struct CallInfoConfig {
     pub params_only: bool,
     pub docs: bool,
@@ -1528,15 +1647,27 @@ impl Config {
     pub fn has_linked_projects(&self) -> bool {
         !self.linkedProjects().is_empty()
     }
-    pub fn linked_manifests(&self) -> impl Iterator + '_ {
+
+    pub fn linked_manifests(&self) -> impl Iterator + '_ {
         self.linkedProjects().iter().filter_map(|it| match it {
             ManifestOrProjectJson::Manifest(p) => Some(&**p),
-            ManifestOrProjectJson::ProjectJson(_) => None,
+            // despite having a buildfile, using this variant as a manifest
+            // will fail.
+            ManifestOrProjectJson::DiscoveredProjectJson { .. } => None,
+            ManifestOrProjectJson::ProjectJson { .. } => None,
         })
     }
+
     pub fn has_linked_project_jsons(&self) -> bool {
-        self.linkedProjects().iter().any(|it| matches!(it, ManifestOrProjectJson::ProjectJson(_)))
+        self.linkedProjects()
+            .iter()
+            .any(|it| matches!(it, ManifestOrProjectJson::ProjectJson { .. }))
     }
+
+    pub fn discover_workspace_config(&self) -> Option<&DiscoverWorkspaceConfig> {
+        self.workspace_discoverConfig().as_ref()
+    }
+
     pub fn linked_or_discovered_projects(&self) -> Vec {
         match self.linkedProjects().as_slice() {
             [] => {
@@ -1561,6 +1692,12 @@ impl Config {
                             .ok()
                             .map(Into::into)
                     }
+                    ManifestOrProjectJson::DiscoveredProjectJson { data, buildfile } => {
+                        let root_path =
+                            buildfile.parent().expect("Unable to get parent of buildfile");
+
+                        Some(ProjectJson::new(None, root_path, data.clone()).into())
+                    }
                     ManifestOrProjectJson::ProjectJson(it) => {
                         Some(ProjectJson::new(None, &self.root_path, it.clone()).into())
                     }
@@ -2101,11 +2238,49 @@ mod single_or_array {
     }
 }
 
-#[derive(Serialize, Deserialize, Debug, Clone)]
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
 #[serde(untagged)]
 enum ManifestOrProjectJson {
-    Manifest(Utf8PathBuf),
+    Manifest(
+        #[serde(serialize_with = "serialize_abs_pathbuf")]
+        #[serde(deserialize_with = "deserialize_abs_pathbuf")]
+        AbsPathBuf,
+    ),
     ProjectJson(ProjectJsonData),
+    DiscoveredProjectJson {
+        data: ProjectJsonData,
+        #[serde(serialize_with = "serialize_abs_pathbuf")]
+        #[serde(deserialize_with = "deserialize_abs_pathbuf")]
+        buildfile: AbsPathBuf,
+    },
+}
+
+fn deserialize_abs_pathbuf<'de, D>(de: D) -> std::result::Result
+where
+    D: serde::de::Deserializer<'de>,
+{
+    let path = String::deserialize(de)?;
+
+    AbsPathBuf::try_from(path.as_ref())
+        .map_err(|err| serde::de::Error::custom(format!("invalid path name: {err:?}")))
+}
+
+fn serialize_abs_pathbuf(path: &AbsPathBuf, se: S) -> Result
+where
+    S: serde::Serializer,
+{
+    let path: &Utf8Path = path.as_ref();
+    se.serialize_str(path.as_str())
+}
+
+impl ManifestOrProjectJson {
+    fn manifest(&self) -> Option<&AbsPath> {
+        match self {
+            ManifestOrProjectJson::Manifest(manifest) => Some(manifest),
+            ManifestOrProjectJson::DiscoveredProjectJson { buildfile, .. } => Some(buildfile),
+            ManifestOrProjectJson::ProjectJson(_) => None,
+        }
+    }
 }
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
@@ -3084,6 +3259,29 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
                 },
             ],
         },
+        "Option" => set! {
+            "anyOf": [
+                {
+                    "type": "null"
+                },
+                {
+                    "type": "object",
+                    "properties": {
+                        "command": {
+                            "type": "array",
+                            "items": { "type": "string" }
+                        },
+                        "progressLabel": {
+                            "type": "string"
+                        },
+                        "filesToWatch": {
+                            "type": "array",
+                            "items": { "type": "string" }
+                        },
+                    }
+                }
+            ]
+        },
         _ => panic!("missing entry for {ty}: {default} (field {field})"),
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index 1976e4de3068c..9fd9bee5377a8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -6,7 +6,7 @@
 use std::{ops::Not as _, time::Instant};
 
 use crossbeam_channel::{unbounded, Receiver, Sender};
-use flycheck::FlycheckHandle;
+use flycheck::{project_json, FlycheckHandle};
 use hir::ChangeWithProcMacros;
 use ide::{Analysis, AnalysisHost, Cancellable, FileId, SourceRootId};
 use ide_db::base_db::{CrateId, ProcMacroPaths, SourceDatabaseExt};
@@ -20,9 +20,9 @@ use parking_lot::{
 use proc_macro_api::ProcMacroServer;
 use project_model::{ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, WorkspaceBuildScripts};
 use rustc_hash::{FxHashMap, FxHashSet};
-use tracing::{span, Level};
+use tracing::{span, trace, Level};
 use triomphe::Arc;
-use vfs::{AnchoredPathBuf, ChangeKind, Vfs};
+use vfs::{AbsPathBuf, AnchoredPathBuf, ChangeKind, Vfs};
 
 use crate::{
     config::{Config, ConfigChange, ConfigErrors},
@@ -41,6 +41,11 @@ use crate::{
     task_pool::{TaskPool, TaskQueue},
 };
 
+pub(crate) struct FetchWorkspaceRequest {
+    pub(crate) path: Option,
+    pub(crate) force_crate_graph_reload: bool,
+}
+
 // Enforces drop order
 pub(crate) struct Handle {
     pub(crate) handle: H,
@@ -95,6 +100,11 @@ pub(crate) struct GlobalState {
     pub(crate) test_run_receiver: Receiver,
     pub(crate) test_run_remaining_jobs: usize,
 
+    // Project loading
+    pub(crate) discover_handle: Option,
+    pub(crate) discover_sender: Sender,
+    pub(crate) discover_receiver: Receiver,
+
     // VFS
     pub(crate) loader: Handle, Receiver>,
     pub(crate) vfs: Arc)>>,
@@ -134,11 +144,12 @@ pub(crate) struct GlobalState {
 
     // op queues
     pub(crate) fetch_workspaces_queue:
-        OpQueue>, bool)>>,
+        OpQueue>, bool)>>,
     pub(crate) fetch_build_data_queue:
         OpQueue<(), (Arc>, Vec>)>,
     pub(crate) fetch_proc_macros_queue: OpQueue, bool>,
     pub(crate) prime_caches_queue: OpQueue,
+    pub(crate) discover_workspace_queue: OpQueue,
 
     /// A deferred task queue.
     ///
@@ -146,7 +157,7 @@ pub(crate) struct GlobalState {
     /// handlers, as accessing the database may block latency-sensitive
     /// interactions and should be moved away from the main thread.
     ///
-    /// For certain features, such as [`lsp_ext::UnindexedProjectParams`],
+    /// For certain features, such as [`GlobalState::handle_discover_msg`],
     /// this queue should run only *after* [`GlobalState::process_changes`] has
     /// been called.
     pub(crate) deferred_task_queue: TaskQueue,
@@ -202,6 +213,9 @@ impl GlobalState {
         }
         let (flycheck_sender, flycheck_receiver) = unbounded();
         let (test_run_sender, test_run_receiver) = unbounded();
+
+        let (discover_sender, discover_receiver) = unbounded();
+
         let mut this = GlobalState {
             sender,
             req_queue: ReqQueue::default(),
@@ -233,6 +247,10 @@ impl GlobalState {
             test_run_receiver,
             test_run_remaining_jobs: 0,
 
+            discover_handle: None,
+            discover_sender,
+            discover_receiver,
+
             vfs: Arc::new(RwLock::new((vfs::Vfs::default(), IntMap::default()))),
             vfs_config_version: 0,
             vfs_progress_config_version: 0,
@@ -247,6 +265,7 @@ impl GlobalState {
             fetch_proc_macros_queue: OpQueue::default(),
 
             prime_caches_queue: OpQueue::default(),
+            discover_workspace_queue: OpQueue::default(),
 
             deferred_task_queue: task_queue,
         };
@@ -296,11 +315,24 @@ impl GlobalState {
                         modified_rust_files.push(file.file_id);
                     }
 
+                    let additional_files = self
+                        .config
+                        .discover_workspace_config()
+                        .map(|cfg| {
+                            cfg.files_to_watch.iter().map(String::as_str).collect::>()
+                        })
+                        .unwrap_or_default();
+
                     let path = path.to_path_buf();
                     if file.is_created_or_deleted() {
                         workspace_structure_change.get_or_insert((path, false)).1 |=
                             self.crate_graph_file_dependencies.contains(vfs_path);
-                    } else if reload::should_refresh_for_change(&path, file.kind()) {
+                    } else if reload::should_refresh_for_change(
+                        &path,
+                        file.kind(),
+                        &additional_files,
+                    ) {
+                        trace!(?path, kind = ?file.kind(), "refreshing for a change");
                         workspace_structure_change.get_or_insert((path.clone(), false));
                     }
                 }
@@ -419,7 +451,7 @@ impl GlobalState {
 
                 self.fetch_workspaces_queue.request_op(
                     format!("workspace vfs file change: {path}"),
-                    force_crate_graph_reload,
+                    FetchWorkspaceRequest { path: Some(path.to_owned()), force_crate_graph_reload },
                 );
             }
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
index 095d7c941c104..4d9cbae7d1f58 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
@@ -14,7 +14,7 @@ use vfs::{AbsPathBuf, ChangeKind, VfsPath};
 
 use crate::{
     config::{Config, ConfigChange},
-    global_state::GlobalState,
+    global_state::{FetchWorkspaceRequest, GlobalState},
     lsp::{from_proto, utils::apply_document_changes},
     lsp_ext::{self, RunFlycheckParams},
     mem_docs::DocumentData,
@@ -73,7 +73,9 @@ pub(crate) fn handle_did_open_text_document(
 
         tracing::info!("New file content set {:?}", params.text_document.text);
         state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
-        if state.config.notifications().unindexed_project {
+        if state.config.discover_workspace_config().is_some()
+            || state.config.notifications().unindexed_project
+        {
             tracing::debug!("queuing task");
             let _ = state
                 .deferred_task_queue
@@ -150,15 +152,29 @@ pub(crate) fn handle_did_save_text_document(
 
     if let Ok(vfs_path) = from_proto::vfs_path(¶ms.text_document.uri) {
         // Re-fetch workspaces if a workspace related file has changed
-        if let Some(abs_path) = vfs_path.as_path() {
-            if reload::should_refresh_for_change(abs_path, ChangeKind::Modify) {
-                state
-                    .fetch_workspaces_queue
-                    .request_op(format!("workspace vfs file change saved {abs_path}"), false);
-            } else if state.detached_files.contains(abs_path) {
-                state
-                    .fetch_workspaces_queue
-                    .request_op(format!("detached file saved {abs_path}"), false);
+        if let Some(path) = vfs_path.as_path() {
+            let additional_files = &state
+                .config
+                .discover_workspace_config()
+                .map(|cfg| cfg.files_to_watch.iter().map(String::as_str).collect::>())
+                .unwrap_or_default();
+
+            if reload::should_refresh_for_change(path, ChangeKind::Modify, additional_files) {
+                state.fetch_workspaces_queue.request_op(
+                    format!("workspace vfs file change saved {path}"),
+                    FetchWorkspaceRequest {
+                        path: Some(path.to_owned()),
+                        force_crate_graph_reload: false,
+                    },
+                );
+            } else if state.detached_files.contains(path) {
+                state.fetch_workspaces_queue.request_op(
+                    format!("detached file saved {path}"),
+                    FetchWorkspaceRequest {
+                        path: Some(path.to_owned()),
+                        force_crate_graph_reload: false,
+                    },
+                );
             }
         }
 
@@ -240,7 +256,9 @@ pub(crate) fn handle_did_change_workspace_folders(
 
     if !config.has_linked_projects() && config.detached_files().is_empty() {
         config.rediscover_workspaces();
-        state.fetch_workspaces_queue.request_op("client workspaces changed".to_owned(), false)
+
+        let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
+        state.fetch_workspaces_queue.request_op("client workspaces changed".to_owned(), req);
     }
 
     Ok(())
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 89961431143cd..8ec159278d4d9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -37,7 +37,7 @@ use vfs::{AbsPath, AbsPathBuf, FileId, VfsPath};
 use crate::{
     config::{Config, RustfmtConfig, WorkspaceSymbolConfig},
     diff::diff,
-    global_state::{GlobalState, GlobalStateSnapshot},
+    global_state::{FetchWorkspaceRequest, GlobalState, GlobalStateSnapshot},
     hack_recover_crate_name,
     line_index::LineEndings,
     lsp::{
@@ -57,7 +57,8 @@ pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> anyhow:
     state.proc_macro_clients = Arc::from_iter([]);
     state.build_deps_changed = false;
 
-    state.fetch_workspaces_queue.request_op("reload workspace request".to_owned(), false);
+    let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
+    state.fetch_workspaces_queue.request_op("reload workspace request".to_owned(), req);
     Ok(())
 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index 9a852067f2ea0..efa5d47fbaab1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -531,7 +531,7 @@ pub struct ServerStatusParams {
     pub message: Option,
 }
 
-#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
+#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Debug)]
 #[serde(rename_all = "camelCase")]
 pub enum Health {
     Ok,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs
index 800c0eee53a02..46797ec658458 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/utils.rs
@@ -74,7 +74,6 @@ impl GlobalState {
         }
     }
 
-    /// Sends a notification to the client containing the error `message`.
     /// If `additional_info` is [`Some`], appends a note to the notification telling to check the logs.
     /// This will always log `message` + `additional_info` to the server's error log.
     pub(crate) fn show_and_log_error(&mut self, message: String, additional_info: Option) {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 07414a6e49cc3..db90d2d964c17 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -9,18 +9,19 @@ use std::{
 
 use always_assert::always;
 use crossbeam_channel::{select, Receiver};
+use flycheck::project_json;
 use ide_db::base_db::{SourceDatabase, SourceDatabaseExt, VfsPath};
 use lsp_server::{Connection, Notification, Request};
 use lsp_types::{notification::Notification as _, TextDocumentIdentifier};
 use stdx::thread::ThreadIntent;
 use tracing::{span, Level};
-use vfs::FileId;
+use vfs::{AbsPathBuf, FileId};
 
 use crate::{
     config::Config,
     diagnostics::{fetch_native_diagnostics, DiagnosticsGeneration},
     dispatch::{NotificationDispatcher, RequestDispatcher},
-    global_state::{file_id_to_url, url_to_file_id, GlobalState},
+    global_state::{file_id_to_url, url_to_file_id, FetchWorkspaceRequest, GlobalState},
     hack_recover_crate_name,
     lsp::{
         from_proto, to_proto,
@@ -62,6 +63,7 @@ enum Event {
     Vfs(vfs::loader::Message),
     Flycheck(flycheck::Message),
     TestResult(flycheck::CargoTestMessage),
+    DiscoverProject(project_json::DiscoverProjectMessage),
 }
 
 impl fmt::Display for Event {
@@ -73,6 +75,7 @@ impl fmt::Display for Event {
             Event::Flycheck(_) => write!(f, "Event::Flycheck"),
             Event::QueuedTask(_) => write!(f, "Event::QueuedTask"),
             Event::TestResult(_) => write!(f, "Event::TestResult"),
+            Event::DiscoverProject(_) => write!(f, "Event::DiscoverProject"),
         }
     }
 }
@@ -86,6 +89,7 @@ pub(crate) enum QueuedTask {
 #[derive(Debug)]
 pub(crate) enum Task {
     Response(lsp_server::Response),
+    DiscoverLinkedProjects(DiscoverProjectParam),
     ClientNotification(lsp_ext::UnindexedProjectParams),
     Retry(lsp_server::Request),
     Diagnostics(DiagnosticsGeneration, Vec<(FileId, Vec)>),
@@ -97,6 +101,12 @@ pub(crate) enum Task {
     BuildDepsHaveChanged,
 }
 
+#[derive(Debug)]
+pub(crate) enum DiscoverProjectParam {
+    Buildfile(AbsPathBuf),
+    Path(AbsPathBuf),
+}
+
 #[derive(Debug)]
 pub(crate) enum PrimeCachesProgress {
     Begin,
@@ -134,6 +144,7 @@ impl fmt::Debug for Event {
             Event::Vfs(it) => fmt::Debug::fmt(it, f),
             Event::Flycheck(it) => fmt::Debug::fmt(it, f),
             Event::TestResult(it) => fmt::Debug::fmt(it, f),
+            Event::DiscoverProject(it) => fmt::Debug::fmt(it, f),
         }
     }
 }
@@ -143,14 +154,24 @@ impl GlobalState {
         self.update_status_or_notify();
 
         if self.config.did_save_text_document_dynamic_registration() {
-            self.register_did_save_capability();
+            let additional_patterns = self
+                .config
+                .discover_workspace_config()
+                .map(|cfg| cfg.files_to_watch.clone().into_iter())
+                .into_iter()
+                .flatten()
+                .map(|f| format!("**/{f}"));
+            self.register_did_save_capability(additional_patterns);
         }
 
-        self.fetch_workspaces_queue.request_op("startup".to_owned(), false);
-        if let Some((cause, force_crate_graph_reload)) =
-            self.fetch_workspaces_queue.should_start_op()
-        {
-            self.fetch_workspaces(cause, force_crate_graph_reload);
+        if self.config.discover_workspace_config().is_none() {
+            let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
+            self.fetch_workspaces_queue.request_op("startup".to_owned(), req);
+            if let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) =
+                self.fetch_workspaces_queue.should_start_op()
+            {
+                self.fetch_workspaces(cause, path, force_crate_graph_reload);
+            }
         }
 
         while let Some(event) = self.next_event(&inbox) {
@@ -167,32 +188,36 @@ impl GlobalState {
         anyhow::bail!("client exited without proper shutdown sequence")
     }
 
-    fn register_did_save_capability(&mut self) {
+    fn register_did_save_capability(&mut self, additional_patterns: impl Iterator) {
+        let additional_filters = additional_patterns.map(|pattern| lsp_types::DocumentFilter {
+            language: None,
+            scheme: None,
+            pattern: (Some(pattern)),
+        });
+
+        let mut selectors = vec![
+            lsp_types::DocumentFilter {
+                language: None,
+                scheme: None,
+                pattern: Some("**/*.rs".into()),
+            },
+            lsp_types::DocumentFilter {
+                language: None,
+                scheme: None,
+                pattern: Some("**/Cargo.toml".into()),
+            },
+            lsp_types::DocumentFilter {
+                language: None,
+                scheme: None,
+                pattern: Some("**/Cargo.lock".into()),
+            },
+        ];
+        selectors.extend(additional_filters);
+
         let save_registration_options = lsp_types::TextDocumentSaveRegistrationOptions {
             include_text: Some(false),
             text_document_registration_options: lsp_types::TextDocumentRegistrationOptions {
-                document_selector: Some(vec![
-                    lsp_types::DocumentFilter {
-                        language: None,
-                        scheme: None,
-                        pattern: Some("**/*.rs".into()),
-                    },
-                    lsp_types::DocumentFilter {
-                        language: None,
-                        scheme: None,
-                        pattern: Some("**/Cargo.toml".into()),
-                    },
-                    lsp_types::DocumentFilter {
-                        language: None,
-                        scheme: None,
-                        pattern: Some("**/Cargo.lock".into()),
-                    },
-                    lsp_types::DocumentFilter {
-                        language: None,
-                        scheme: None,
-                        pattern: Some("**/rust-analyzer.toml".into()),
-                    },
-                ]),
+                document_selector: Some(selectors),
             },
         };
 
@@ -230,6 +255,8 @@ impl GlobalState {
             recv(self.test_run_receiver) -> task =>
                 Some(Event::TestResult(task.unwrap())),
 
+            recv(self.discover_receiver) -> task =>
+                Some(Event::DiscoverProject(task.unwrap())),
         }
     }
 
@@ -340,6 +367,13 @@ impl GlobalState {
                     self.handle_cargo_test_msg(message);
                 }
             }
+            Event::DiscoverProject(message) => {
+                self.handle_discover_msg(message);
+                // Coalesce many project discovery events into a single loop turn.
+                while let Ok(message) = self.discover_receiver.try_recv() {
+                    self.handle_discover_msg(message);
+                }
+            }
         }
         let event_handling_duration = loop_start.elapsed();
 
@@ -427,11 +461,13 @@ impl GlobalState {
             }
         }
 
-        if self.config.cargo_autoreload_config() {
-            if let Some((cause, force_crate_graph_reload)) =
+        if self.config.cargo_autoreload_config()
+            || self.config.discover_workspace_config().is_some()
+        {
+            if let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) =
                 self.fetch_workspaces_queue.should_start_op()
             {
-                self.fetch_workspaces(cause, force_crate_graph_reload);
+                self.fetch_workspaces(cause, path, force_crate_graph_reload);
             }
         }
 
@@ -647,6 +683,35 @@ impl GlobalState {
 
                 self.report_progress("Fetching", state, msg, None, None);
             }
+            Task::DiscoverLinkedProjects(arg) => {
+                if let Some(cfg) = self.config.discover_workspace_config() {
+                    if !self.discover_workspace_queue.op_in_progress() {
+                        // the clone is unfortunately necessary to avoid a borrowck error when
+                        // `self.report_progress` is called later
+                        let title = &cfg.progress_label.clone();
+                        let command = cfg.command.clone();
+                        let discover =
+                            project_json::Discover::new(self.discover_sender.clone(), command);
+
+                        self.report_progress(title, Progress::Begin, None, None, None);
+                        self.discover_workspace_queue
+                            .request_op("Discovering workspace".to_owned(), ());
+                        let _ = self.discover_workspace_queue.should_start_op();
+
+                        let arg = match arg {
+                            DiscoverProjectParam::Buildfile(it) => {
+                                project_json::DiscoverArgument::Buildfile(it)
+                            }
+                            DiscoverProjectParam::Path(it) => {
+                                project_json::DiscoverArgument::Path(it)
+                            }
+                        };
+
+                        let handle = discover.spawn(arg).unwrap();
+                        self.discover_handle = Some(handle);
+                    }
+                }
+            }
             Task::FetchBuildData(progress) => {
                 let (state, msg) = match progress {
                     BuildDataProgress::Begin => (Some(Progress::Begin), None),
@@ -755,10 +820,17 @@ impl GlobalState {
                     let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId");
                     if let Ok(crates) = &snap.analysis.crates_for(id) {
                         if crates.is_empty() {
-                            let params = lsp_ext::UnindexedProjectParams {
-                                text_documents: vec![lsp_types::TextDocumentIdentifier { uri }],
+                            if snap.config.discover_workspace_config().is_some() {
+                                let path =
+                                    from_proto::abs_path(&uri).expect("Unable to get AbsPath");
+                                let arg = DiscoverProjectParam::Path(path);
+                                sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
+                            } else if snap.config.notifications().unindexed_project {
+                                let params = lsp_ext::UnindexedProjectParams {
+                                    text_documents: vec![lsp_types::TextDocumentIdentifier { uri }],
+                                };
+                                sender.send(Task::ClientNotification(params)).unwrap();
                             };
-                            sender.send(Task::ClientNotification(params)).unwrap();
                         } else {
                             tracing::debug!(?uri, "is indexed");
                         }
@@ -787,6 +859,33 @@ impl GlobalState {
         }
     }
 
+    fn handle_discover_msg(&mut self, message: project_json::DiscoverProjectMessage) {
+        let title = self
+            .config
+            .discover_workspace_config()
+            .map(|cfg| cfg.progress_label.clone())
+            .expect("No title could be found; this is a bug");
+        match message {
+            project_json::DiscoverProjectMessage::Finished { project, buildfile } => {
+                self.report_progress(&title, Progress::End, None, None, None);
+                self.discover_workspace_queue.op_completed(());
+
+                let mut config = Config::clone(&*self.config);
+                config.add_linked_projects(project, buildfile);
+                self.update_configuration(config);
+            }
+            project_json::DiscoverProjectMessage::Progress { message } => {
+                self.report_progress(&title, Progress::Report, Some(message), None, None)
+            }
+            project_json::DiscoverProjectMessage::Error { error, source } => {
+                let message = format!("Project discovery failed: {error}");
+                self.discover_workspace_queue.op_completed(());
+                self.show_and_log_error(message.clone(), source);
+                self.report_progress(&title, Progress::End, Some(message), None, None)
+            }
+        }
+    }
+
     fn handle_cargo_test_msg(&mut self, message: flycheck::CargoTestMessage) {
         match message {
             flycheck::CargoTestMessage::Test { name, state } => {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
index 932730fc234b4..99f9e9829c936 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
@@ -3,6 +3,7 @@
 
 pub(crate) type Cause = String;
 
+#[derive(Debug)]
 pub(crate) struct OpQueue {
     op_requested: Option<(Cause, Args)>,
     op_in_progress: bool,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index 1039daf850caa..fb16f28a14bd4 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -33,11 +33,12 @@ use vfs::{AbsPath, AbsPathBuf, ChangeKind};
 
 use crate::{
     config::{Config, FilesWatcher, LinkedProject},
-    global_state::GlobalState,
+    global_state::{FetchWorkspaceRequest, GlobalState},
     lsp_ext,
-    main_loop::Task,
+    main_loop::{DiscoverProjectParam, Task},
     op_queue::Cause,
 };
+use tracing::{debug, info};
 
 #[derive(Debug)]
 pub(crate) enum ProjectWorkspaceProgress {
@@ -66,6 +67,7 @@ impl GlobalState {
             || self.fetch_workspaces_queue.op_in_progress()
             || self.fetch_build_data_queue.op_in_progress()
             || self.fetch_proc_macros_queue.op_in_progress()
+            || self.discover_workspace_queue.op_in_progress()
             || self.vfs_progress_config_version < self.vfs_config_version
             || self.vfs_progress_n_done < self.vfs_progress_n_total)
     }
@@ -81,9 +83,11 @@ impl GlobalState {
                 &self.config.lru_query_capacities_config().cloned().unwrap_or_default(),
             );
         }
+
         if self.config.linked_or_discovered_projects() != old_config.linked_or_discovered_projects()
         {
-            self.fetch_workspaces_queue.request_op("discovered projects changed".to_owned(), false)
+            let req = FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
+            self.fetch_workspaces_queue.request_op("discovered projects changed".to_owned(), req)
         } else if self.config.flycheck() != old_config.flycheck() {
             self.reload_flycheck();
         }
@@ -109,6 +113,7 @@ impl GlobalState {
         if !self.config.cargo_autoreload()
             && self.is_quiescent()
             && self.fetch_workspaces_queue.op_requested()
+            && self.config.discover_workspace_config().is_none()
         {
             status.health |= lsp_ext::Health::Warning;
             message.push_str("Auto-reloading is disabled and the workspace has changed, a manual workspace reload is required.\n\n");
@@ -124,7 +129,6 @@ impl GlobalState {
             status.health |= lsp_ext::Health::Warning;
             message.push_str("Failed to run build scripts of some packages.\n\n");
         }
-
         if let Some(err) = &self.config_errors {
             status.health |= lsp_ext::Health::Warning;
             format_to!(message, "{err}\n");
@@ -217,8 +221,13 @@ impl GlobalState {
         status
     }
 
-    pub(crate) fn fetch_workspaces(&mut self, cause: Cause, force_crate_graph_reload: bool) {
-        tracing::info!(%cause, "will fetch workspaces");
+    pub(crate) fn fetch_workspaces(
+        &mut self,
+        cause: Cause,
+        path: Option,
+        force_crate_graph_reload: bool,
+    ) {
+        info!(%cause, "will fetch workspaces");
 
         self.task_pool.handle.spawn_with_sender(ThreadIntent::Worker, {
             let linked_projects = self.config.linked_or_discovered_projects();
@@ -231,6 +240,10 @@ impl GlobalState {
                 .filter_map(Result::ok)
                 .collect();
             let cargo_config = self.config.cargo();
+            let discover_command = self.config.discover_workspace_config().cloned();
+            let is_quiescent = !(self.discover_workspace_queue.op_in_progress()
+                || self.vfs_progress_config_version < self.vfs_config_version
+                || self.vfs_progress_n_done < self.vfs_progress_n_total);
 
             move |sender| {
                 let progress = {
@@ -244,10 +257,28 @@ impl GlobalState {
 
                 sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::Begin)).unwrap();
 
+                if let (Some(_command), Some(path)) = (&discover_command, &path) {
+                    let build = linked_projects.iter().find_map(|project| match project {
+                        LinkedProject::InlineJsonProject(it) => it.crate_by_buildfile(path),
+                        _ => None,
+                    });
+
+                    if let Some(build) = build {
+                        if is_quiescent {
+                            let path = AbsPathBuf::try_from(build.build_file)
+                                .expect("Unable to convert to an AbsPath");
+                            let arg = DiscoverProjectParam::Buildfile(path);
+                            sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
+                        }
+                    }
+                }
+
                 let mut workspaces = linked_projects
                     .iter()
                     .map(|project| match project {
                         LinkedProject::ProjectManifest(manifest) => {
+                            debug!(path = %manifest, "loading project from manifest");
+
                             project_model::ProjectWorkspace::load(
                                 manifest.clone(),
                                 &cargo_config,
@@ -255,12 +286,13 @@ impl GlobalState {
                             )
                         }
                         LinkedProject::InlineJsonProject(it) => {
-                            Ok(project_model::ProjectWorkspace::load_inline(
+                            let workspace = project_model::ProjectWorkspace::load_inline(
                                 it.clone(),
                                 cargo_config.target.as_deref(),
                                 &cargo_config.extra_env,
                                 &cargo_config.cfg_overrides,
-                            ))
+                            );
+                            Ok(workspace)
                         }
                     })
                     .collect::>();
@@ -286,7 +318,7 @@ impl GlobalState {
                     ));
                 }
 
-                tracing::info!("did fetch workspaces {:?}", workspaces);
+                info!(?workspaces, "did fetch workspaces");
                 sender
                     .send(Task::FetchWorkspace(ProjectWorkspaceProgress::End(
                         workspaces,
@@ -298,7 +330,7 @@ impl GlobalState {
     }
 
     pub(crate) fn fetch_build_data(&mut self, cause: Cause) {
-        tracing::info!(%cause, "will fetch build data");
+        info!(%cause, "will fetch build data");
         let workspaces = Arc::clone(&self.workspaces);
         let config = self.config.cargo();
         let root_path = self.config.root_path().clone();
@@ -324,7 +356,7 @@ impl GlobalState {
     }
 
     pub(crate) fn fetch_proc_macros(&mut self, cause: Cause, paths: Vec) {
-        tracing::info!(%cause, "will load proc macros");
+        info!(%cause, "will load proc macros");
         let ignored_proc_macros = self.config.ignored_proc_macros().clone();
         let proc_macro_clients = self.proc_macro_clients.clone();
 
@@ -395,6 +427,7 @@ impl GlobalState {
             return;
         };
 
+        info!(%cause, ?force_reload_crate_graph);
         if self.fetch_workspace_error().is_err() && !self.workspaces.is_empty() {
             if *force_reload_crate_graph {
                 self.recreate_crate_graph(cause);
@@ -416,7 +449,7 @@ impl GlobalState {
         if same_workspaces {
             let (workspaces, build_scripts) = self.fetch_build_data_queue.last_op_result();
             if Arc::ptr_eq(workspaces, &self.workspaces) {
-                tracing::debug!("set build scripts to workspaces");
+                info!("set build scripts to workspaces");
 
                 let workspaces = workspaces
                     .iter()
@@ -428,9 +461,10 @@ impl GlobalState {
                     })
                     .collect::>();
                 // Workspaces are the same, but we've updated build data.
+                info!("same workspace, but new build data");
                 self.workspaces = Arc::new(workspaces);
             } else {
-                tracing::info!("build scripts do not match the version of the active workspace");
+                info!("build scripts do not match the version of the active workspace");
                 if *force_reload_crate_graph {
                     self.recreate_crate_graph(cause);
                 }
@@ -440,7 +474,7 @@ impl GlobalState {
                 return;
             }
         } else {
-            tracing::debug!("abandon build scripts for workspaces");
+            info!("abandon build scripts for workspaces");
 
             // Here, we completely changed the workspace (Cargo.toml edit), so
             // we don't care about build-script results, they are stale.
@@ -535,7 +569,7 @@ impl GlobalState {
         if (self.proc_macro_clients.is_empty() || !same_workspaces)
             && self.config.expand_proc_macros()
         {
-            tracing::info!("Spawning proc-macro servers");
+            info!("Spawning proc-macro servers");
 
             self.proc_macro_clients = Arc::from_iter(self.workspaces.iter().map(|ws| {
                 let path = match self.config.proc_macro_srv() {
@@ -562,7 +596,7 @@ impl GlobalState {
 
                     _ => Default::default(),
                 };
-                tracing::info!("Using proc-macro server at {path}");
+                info!("Using proc-macro server at {path}");
 
                 ProcMacroServer::spawn(&path, &env).map_err(|err| {
                     tracing::error!(
@@ -588,12 +622,14 @@ impl GlobalState {
         self.source_root_config = project_folders.source_root_config;
         self.local_roots_parent_map = Arc::new(self.source_root_config.source_root_parent_map());
 
+        info!(?cause, "recreating the crate graph");
         self.recreate_crate_graph(cause);
 
-        tracing::info!("did switch workspaces");
+        info!("did switch workspaces");
     }
 
     fn recreate_crate_graph(&mut self, cause: String) {
+        info!(?cause, "Building Crate Graph");
         self.report_progress(
             "Building CrateGraph",
             crate::lsp::utils::Progress::Begin,
@@ -658,12 +694,19 @@ impl GlobalState {
         let Some((last_op_result, _)) = self.fetch_workspaces_queue.last_op_result() else {
             return Ok(());
         };
-        if last_op_result.is_empty() {
-            stdx::format_to!(buf, "rust-analyzer failed to discover workspace");
-        } else {
-            for ws in last_op_result {
-                if let Err(err) = ws {
-                    stdx::format_to!(buf, "rust-analyzer failed to load workspace: {:#}\n", err);
+
+        if !self.discover_workspace_queue.op_in_progress() {
+            if last_op_result.is_empty() {
+                stdx::format_to!(buf, "rust-analyzer failed to discover workspace");
+            } else {
+                for ws in last_op_result {
+                    if let Err(err) = ws {
+                        stdx::format_to!(
+                            buf,
+                            "rust-analyzer failed to load workspace: {:#}\n",
+                            err
+                        );
+                    }
                 }
             }
         }
@@ -818,7 +861,11 @@ pub fn ws_to_crate_graph(
     (crate_graph, proc_macro_paths, layouts, toolchains)
 }
 
-pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind) -> bool {
+pub(crate) fn should_refresh_for_change(
+    path: &AbsPath,
+    change_kind: ChangeKind,
+    additional_paths: &[&str],
+) -> bool {
     const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
     const IMPLICIT_TARGET_DIRS: &[&str] = &["src/bin", "examples", "tests", "benches"];
 
@@ -830,6 +877,11 @@ pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind)
     if let "Cargo.toml" | "Cargo.lock" = file_name {
         return true;
     }
+
+    if additional_paths.contains(&file_name) {
+        return true;
+    }
+
     if change_kind == ChangeKind::Modify {
         return false;
     }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
index fcdbf6c694979..f330754f19a1e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
@@ -48,7 +48,10 @@ where
 
         let writer = self.writer;
 
-        let ra_fmt_layer = tracing_subscriber::fmt::layer().with_writer(writer).with_filter(filter);
+        let ra_fmt_layer = tracing_subscriber::fmt::layer()
+            .with_target(false)
+            .with_writer(writer)
+            .with_filter(filter);
 
         let mut chalk_layer = None;
         if let Some(chalk_filter) = self.chalk_filter {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
index aa17b587e0228..6bbf82a77547d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -27,7 +27,6 @@ use lsp_types::{
     InlayHint, InlayHintLabel, InlayHintParams, PartialResultParams, Position, Range,
     RenameFilesParams, TextDocumentItem, TextDocumentPositionParams, WorkDoneProgressParams,
 };
-
 use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams, UnindexedProject};
 use serde_json::json;
 use stdx::format_to_acc;
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index 74acb6f9940be..fbb4fc6113f9a 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
  $DIR/feature-gate-unsafe-extern-blocks.rs:1:1
-   |
-LL | unsafe extern "C" {
-   | ^^^^^^
-   |
-   = note: see issue #123743  for more information
-   = help: add `#![feature(unsafe_extern_blocks)]` 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]: `unsafe extern {}` blocks and `safe` keyword are experimental
-  --> $DIR/feature-gate-unsafe-extern-blocks.rs:9:5
-   |
-LL |     safe fn foo();
-   |     ^^^^
-   |
-   = note: see issue #123743  for more information
-   = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
index 6f2ead70db80c..c264fa1c8daf1 100644
--- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
+++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
@@ -1,4 +1,3 @@
-#![feature(unsafe_extern_blocks)]
 #![deny(unsafe_code)]
 
 #[allow(unsafe_code)]
diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
index 5439a3112560e..6d3b064da344f 100644
--- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
+++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
@@ -1,5 +1,5 @@
 error: usage of an `unsafe extern` block
-  --> $DIR/unsafe-extern-blocks.rs:9:1
+  --> $DIR/unsafe-extern-blocks.rs:8:1
    |
 LL | / unsafe extern "C" {
 LL | |
@@ -8,7 +8,7 @@ LL | | }
    | |_^
    |
 note: the lint level is defined here
-  --> $DIR/unsafe-extern-blocks.rs:2:9
+  --> $DIR/unsafe-extern-blocks.rs:1:9
    |
 LL | #![deny(unsafe_code)]
    |         ^^^^^^^^^^^
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs
index 0b63a993c5b9e..6d339cd90881f 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.rs
+++ b/tests/ui/parser/unsafe-foreign-mod-2.rs
@@ -1,8 +1,6 @@
 extern "C" unsafe {
     //~^ ERROR expected `{`, found keyword `unsafe`
-    //~| ERROR extern block cannot be declared unsafe
     unsafe fn foo();
-    //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
 }
 
 fn main() {}
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr
index 8bd592b5d4311..0625e3362ed72 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.stderr
+++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr
@@ -4,21 +4,5 @@ error: expected `{`, found keyword `unsafe`
 LL | extern "C" unsafe {
    |            ^^^^^^ expected `{`
 
-error: extern block cannot be declared unsafe
-  --> $DIR/unsafe-foreign-mod-2.rs:1:12
-   |
-LL | extern "C" unsafe {
-   |            ^^^^^^
-   |
-   = note: see issue #123743  for more information
-   = help: add `#![feature(unsafe_extern_blocks)]` 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: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/unsafe-foreign-mod-2.rs:4:5
-   |
-LL |     unsafe fn foo();
-   |     ^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/unsafe-foreign-mod.rs b/tests/ui/parser/unsafe-foreign-mod.rs
index eab134a4a4de4..623c3bb81e458 100644
--- a/tests/ui/parser/unsafe-foreign-mod.rs
+++ b/tests/ui/parser/unsafe-foreign-mod.rs
@@ -1,5 +1,5 @@
-unsafe extern "C" {
-    //~^ ERROR extern block cannot be declared unsafe
-}
+//@ check-pass
+
+unsafe extern "C" {}
 
 fn main() {}
diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr
deleted file mode 100644
index 60b918a89b34d..0000000000000
--- a/tests/ui/parser/unsafe-foreign-mod.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error: extern block cannot be declared unsafe
-  --> $DIR/unsafe-foreign-mod.rs:1:1
-   |
-LL | unsafe extern "C" {
-   | ^^^^^^
-   |
-   = note: see issue #123743  for more information
-   = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/rust-2024/safe-outside-extern.rs b/tests/ui/rust-2024/safe-outside-extern.rs
index 6773df5ef03b7..674b78dc571ea 100644
--- a/tests/ui/rust-2024/safe-outside-extern.rs
+++ b/tests/ui/rust-2024/safe-outside-extern.rs
@@ -1,29 +1,21 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
 safe fn foo() {}
 //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 
 safe static FOO: i32 = 1;
 //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 
 trait Foo {
     safe fn foo();
     //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-    //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 }
 
 impl Foo for () {
     safe fn foo() {}
     //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-    //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 }
 
 type FnPtr = safe fn(i32, i32) -> i32;
 //~^ ERROR: function pointers cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 
 unsafe static LOL: u8 = 0;
 //~^ ERROR: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
diff --git a/tests/ui/rust-2024/safe-outside-extern.stderr b/tests/ui/rust-2024/safe-outside-extern.stderr
new file mode 100644
index 0000000000000..19d7c5fde0bdf
--- /dev/null
+++ b/tests/ui/rust-2024/safe-outside-extern.stderr
@@ -0,0 +1,38 @@
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:1:1
+   |
+LL | safe fn foo() {}
+   | ^^^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:4:1
+   |
+LL | safe static FOO: i32 = 1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:8:5
+   |
+LL |     safe fn foo();
+   |     ^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:13:5
+   |
+LL |     safe fn foo() {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: function pointers cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:17:14
+   |
+LL | type FnPtr = safe fn(i32, i32) -> i32;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+  --> $DIR/safe-outside-extern.rs:20:1
+   |
+LL | unsafe static LOL: u8 = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
index 3a99caa719b53..77554da10e60b 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
-  --> $DIR/extern-items-unsafe.rs:14:5
+  --> $DIR/extern-items-unsafe.rs:12:5
    |
 LL |     test1(TEST1);
    |     ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     test1(TEST1);
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/extern-items-unsafe.rs:14:11
+  --> $DIR/extern-items-unsafe.rs:12:11
    |
 LL |     test1(TEST1);
    |           ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
index fcf937b7ac577..33b752782d599 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
-  --> $DIR/extern-items-unsafe.rs:14:5
+  --> $DIR/extern-items-unsafe.rs:12:5
    |
 LL |     test1(TEST1);
    |     ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     test1(TEST1);
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: use of extern static is unsafe and requires unsafe block
-  --> $DIR/extern-items-unsafe.rs:14:11
+  --> $DIR/extern-items-unsafe.rs:12:11
    |
 LL |     test1(TEST1);
    |           ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
index ad569a256db90..721e07acca588 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
@@ -3,8 +3,6 @@
 //@[edition2024] edition:2024
 //@[edition2024] compile-flags: -Zunstable-options
 
-#![feature(unsafe_extern_blocks)]
-
 unsafe extern "C" {
     static TEST1: i32;
     fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
index d456cfc6829e1..8ef7c2caf21ee 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
@@ -1,5 +1,5 @@
 error: extern blocks must be unsafe
-  --> $DIR/extern-items.rs:9:1
+  --> $DIR/extern-items.rs:7:1
    |
 LL | / extern "C" {
 LL | |
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
index 16fa1bbb8a404..08805c3634765 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
@@ -4,8 +4,6 @@
 //@[edition2024] edition:2024
 //@[edition2024] compile-flags: -Zunstable-options
 
-#![feature(unsafe_extern_blocks)]
-
 extern "C" {
     //[edition2024]~^ ERROR extern blocks must be unsafe
     static TEST1: i32;
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
index 57c03e4d896be..67df8c14b39fd 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
@@ -1,6 +1,3 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
 trait Bar {}
 safe impl Bar for () { }
 //~^ ERROR expected one of `!` or `::`, found keyword `impl`
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
similarity index 83%
rename from tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr
rename to tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
index 80e7a45f57e79..f1021726b1816 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
@@ -1,5 +1,5 @@
 error: expected one of `!` or `::`, found keyword `impl`
-  --> $DIR/safe-impl-trait.rs:5:6
+  --> $DIR/safe-impl-trait.rs:2:6
    |
 LL | safe impl Bar for () { }
    |      ^^^^ expected one of `!` or `::`
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
index 74cd5621fce93..b0b8a8b012a6a 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
@@ -4,8 +4,6 @@
 //@[edition2024] compile-flags: -Zunstable-options
 //@ check-pass
 
-#![feature(unsafe_extern_blocks)]
-
 unsafe extern "C" {
     safe static TEST1: i32;
     safe fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
index e73cb45b18877..52773b4cbbbbf 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
@@ -1,6 +1,3 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
 safe trait Foo {}
 //~^ ERROR expected one of `!` or `::`, found keyword `trait`
 
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr
new file mode 100644
index 0000000000000..1733336a797b2
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found keyword `trait`
+  --> $DIR/safe-trait.rs:1:6
+   |
+LL | safe trait Foo {}
+   |      ^^^^^ expected one of `!` or `::`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
index e90613357b1ca..9379798728669 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
@@ -1,5 +1,5 @@
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5
    |
 LL |     safe static TEST1: i32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -10,7 +10,7 @@ LL | unsafe extern "C" {
    | ++++++
 
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
    |
 LL |     safe fn test1(i: i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
index 1207ee158cc13..e9db6006c0b58 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
@@ -1,5 +1,5 @@
 error: extern blocks must be unsafe
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:1
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:6:1
    |
 LL | / extern "C" {
 LL | |
@@ -11,7 +11,7 @@ LL | | }
    | |_^
 
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5
    |
 LL |     safe static TEST1: i32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | unsafe extern "C" {
    | ++++++
 
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
    |
 LL |     safe fn test1(i: i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
index 11f55cb195f29..4badb50b26735 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
@@ -3,8 +3,6 @@
 //@[edition2024] edition:2024
 //@[edition2024] compile-flags: -Zunstable-options
 
-#![feature(unsafe_extern_blocks)]
-
 extern "C" {
     //[edition2024]~^ ERROR extern blocks must be unsafe
     safe static TEST1: i32;
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
index 10c19759d8aaa..f686809615fb0 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
@@ -1,6 +1,5 @@
 //@ run-rustfix
 
-#![feature(unsafe_extern_blocks)]
 #![deny(missing_unsafe_on_extern)]
 #![allow(unused)]
 
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
index b81e52ddc5843..00f1cbdab54ff 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
@@ -1,6 +1,5 @@
 //@ run-rustfix
 
-#![feature(unsafe_extern_blocks)]
 #![deny(missing_unsafe_on_extern)]
 #![allow(unused)]
 
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
index 0a3c2cd25e3fe..bb1d068ceb91b 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
@@ -1,5 +1,5 @@
 error: extern blocks should be unsafe
-  --> $DIR/unsafe-extern-suggestion.rs:7:1
+  --> $DIR/unsafe-extern-suggestion.rs:6:1
    |
 LL |   extern "C" {
    |   ^
@@ -16,7 +16,7 @@ LL | | }
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
    = note: for more information, see issue #123743 
 note: the lint level is defined here
-  --> $DIR/unsafe-extern-suggestion.rs:4:9
+  --> $DIR/unsafe-extern-suggestion.rs:3:9
    |
 LL | #![deny(missing_unsafe_on_extern)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
index 8bb7ffefeea9e..e3626bb497e4f 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-items.rs:20:5
+  --> $DIR/unsafe-items.rs:18:5
    |
 LL |     test1(TEST1);
    |     ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     test1(TEST1);
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-items.rs:20:11
+  --> $DIR/unsafe-items.rs:18:11
    |
 LL |     test1(TEST1);
    |           ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
index 9a30142a632c5..89bc501b7b5a5 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
-  --> $DIR/unsafe-items.rs:20:5
+  --> $DIR/unsafe-items.rs:18:5
    |
 LL |     test1(TEST1);
    |     ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     test1(TEST1);
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: use of extern static is unsafe and requires unsafe block
-  --> $DIR/unsafe-items.rs:20:11
+  --> $DIR/unsafe-items.rs:18:11
    |
 LL |     test1(TEST1);
    |           ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
index 9066953abc615..dc2bae892a988 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
@@ -3,8 +3,6 @@
 //@[edition2024] edition:2024
 //@[edition2024] compile-flags: -Zunstable-options
 
-#![feature(unsafe_extern_blocks)]
-
 unsafe extern "C" {
     unsafe static TEST1: i32;
     unsafe fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
index 2ff595cc44d1e..857d34eef8521 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
@@ -1,6 +1,5 @@
 //@ run-rustfix
 
-#![feature(unsafe_extern_blocks)]
 #![allow(dead_code)]
 
 unsafe extern "C" {
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
index 6fe43f7a5b46d..edab9850d796f 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
@@ -1,6 +1,5 @@
 //@ run-rustfix
 
-#![feature(unsafe_extern_blocks)]
 #![allow(dead_code)]
 
 extern "C" {
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
index 05d23d001ada7..073245e650b1c 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
@@ -1,5 +1,5 @@
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/unsafe-on-extern-block-issue-126756.rs:7:5
+  --> $DIR/unsafe-on-extern-block-issue-126756.rs:6:5
    |
 LL |     unsafe fn foo();
    |     ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
index 92c2e7b488478..29472df897a1f 100644
--- a/tests/ui/unpretty/expanded-exhaustive.rs
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -25,7 +25,6 @@
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(unnamed_fields)]
-#![feature(unsafe_extern_blocks)]
 #![feature(yeet_expr)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 137a8aa5510d0..cf2f6f8cbaa99 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -26,7 +26,6 @@
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(unnamed_fields)]
-#![feature(unsafe_extern_blocks)]
 #![feature(yeet_expr)]
 #![allow(incomplete_features)]
 #[prelude_import]

From fdbd9bee574746f4a3d9a2be31f332c9a8a38a62 Mon Sep 17 00:00:00 2001
From: PaulDotSH <84643540+PaulDotSH@users.noreply.github.com>
Date: Tue, 23 Jul 2024 03:27:28 -0400
Subject: [PATCH 114/489] Remove lens.forceCustomCommands config

---
 .../rust-analyzer/crates/rust-analyzer/src/config.rs   |  9 ++-------
 .../rust-analyzer/docs/user/generated_config.adoc      |  6 ------
 src/tools/rust-analyzer/editors/code/package.json      | 10 ----------
 3 files changed, 2 insertions(+), 23 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index e71ad9da9572c..5905137967890 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -655,9 +655,6 @@ config_data! {
         lens_debug_enable: bool            = true,
         /// Whether to show CodeLens in Rust files.
         lens_enable: bool           = true,
-        /// Internal config: use custom client-side commands even when the
-        /// client doesn't set the corresponding capability.
-        lens_forceCustomCommands: bool = true,
         /// Whether to show `Implementations` lens. Only applies when
         /// `#rust-analyzer.lens.enable#` is set.
         lens_implementations_enable: bool  = true,
@@ -2031,11 +2028,9 @@ impl Config {
     }
 
     pub fn client_commands(&self) -> ClientCommandsConfig {
-        let commands = self.commands();
-        let force = commands.is_none() && *self.lens_forceCustomCommands();
-        let commands = commands.map(|it| it.commands).unwrap_or_default();
+        let commands = self.commands().map(|it| it.commands).unwrap_or_default();
 
-        let get = |name: &str| commands.iter().any(|it| it == name) || force;
+        let get = |name: &str| commands.iter().any(|it| it == name);
 
         ClientCommandsConfig {
             run_single: get("rust-analyzer.runSingle"),
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index cb876e8536604..542c539bde428 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -764,12 +764,6 @@ Whether to show `Debug` lens. Only applies when
 --
 Whether to show CodeLens in Rust files.
 --
-[[rust-analyzer.lens.forceCustomCommands]]rust-analyzer.lens.forceCustomCommands (default: `true`)::
-+
---
-Internal config: use custom client-side commands even when the
-client doesn't set the corresponding capability.
---
 [[rust-analyzer.lens.implementations.enable]]rust-analyzer.lens.implementations.enable (default: `true`)::
 +
 --
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 575033a588641..eee4fe3706d2f 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -2138,16 +2138,6 @@
                     }
                 }
             },
-            {
-                "title": "lens",
-                "properties": {
-                    "rust-analyzer.lens.forceCustomCommands": {
-                        "markdownDescription": "Internal config: use custom client-side commands even when the\nclient doesn't set the corresponding capability.",
-                        "default": true,
-                        "type": "boolean"
-                    }
-                }
-            },
             {
                 "title": "lens",
                 "properties": {

From 0cbee3bba577475f896413e48f89e23d86463c02 Mon Sep 17 00:00:00 2001
From: Vincent Esche 
Date: Tue, 16 Jul 2024 18:17:06 +0200
Subject: [PATCH 115/489] =?UTF-8?q?Add=20method=20`Impl::all=5Fin=5Fmodule?=
 =?UTF-8?q?(=E2=80=A6)`=20for=20supporting=20more=20localized=20querying?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/tools/rust-analyzer/crates/hir/src/lib.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 32057fbaff01c..dd9f1e880369b 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -3724,6 +3724,10 @@ impl Impl {
         inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
     }
 
+    pub fn all_in_module(db: &dyn HirDatabase, module: Module) -> Vec {
+        module.id.def_map(db.upcast())[module.id.local_id].scope.impls().map(Into::into).collect()
+    }
+
     pub fn all_for_type(db: &dyn HirDatabase, Type { ty, env }: Type) -> Vec {
         let def_crates = match method_resolution::def_crates(db, &ty, env.krate) {
             Some(def_crates) => def_crates,

From f1e237139bffea48e156de7a9a99703928cbadf9 Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Tue, 23 Jul 2024 15:50:12 +0200
Subject: [PATCH 116/489] minor changes

---
 .../rust-analyzer/crates/load-cargo/src/lib.rs     | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index 3310614c21a93..9ad5c68a5599e 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -243,23 +243,25 @@ impl ProjectFolders {
         for ws in workspaces.iter() {
             let mut file_set_roots: Vec = vec![];
             let mut entries = vec![];
-            let mut register = false;
 
             if let Some(manifest) = ws.manifest().map(ManifestPath::as_ref) {
                 file_set_roots.push(VfsPath::from(manifest.to_owned()));
                 entries.push(manifest.to_owned());
-                register = true;
             }
 
             // In case of detached files we do **not** look for a rust-analyzer.toml.
             if !matches!(ws.kind, ProjectWorkspaceKind::DetachedFile { .. }) {
                 let ws_root = ws.workspace_root();
-                file_set_roots.push(VfsPath::from(ws_root.to_owned()));
-                entries.push(ws_root.to_owned());
-                register = true;
+                let ratoml_path = {
+                    let mut p = ws_root.to_path_buf();
+                    p.push("rust-analyzer.toml");
+                    p
+                };
+                file_set_roots.push(VfsPath::from(ratoml_path.to_owned()));
+                entries.push(ratoml_path.to_owned());
             }
 
-            if register {
+            if !file_set_roots.is_empty() {
                 let entry = vfs::loader::Entry::Files(entries);
                 res.watch.push(res.load.len());
                 res.load.push(entry);

From abdad6f45caeecba1cc18e2777034ef4ba2f60eb Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Tue, 23 Jul 2024 15:54:39 +0200
Subject: [PATCH 117/489] rename config::ConfigChange::other_errors to
 validation_errors

---
 .../rust-analyzer/crates/rust-analyzer/src/config.rs  | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 107179c6593f1..71c0407ae27d5 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -801,8 +801,7 @@ pub struct Config {
     /// Since it is a `global` command at the moment, its final value can only be determined by
     /// traversing through `global` configs and the `client` config. However the non-null value constraint
     /// is config level agnostic, so this requires an independent error storage
-    /// FIXME : bad name I know...
-    other_errors: ConfigErrors,
+    validation_errors: ConfigErrors,
 
     detached_files: Vec,
 }
@@ -833,7 +832,7 @@ impl Config {
     /// The return tuple's bool component signals whether the `GlobalState` should call its `update_configuration()` method.
     fn apply_change_with_sink(&self, change: ConfigChange) -> (Config, bool) {
         let mut config = self.clone();
-        config.other_errors = ConfigErrors::default();
+        config.validation_errors = ConfigErrors::default();
 
         let mut should_update = false;
 
@@ -1013,7 +1012,7 @@ impl Config {
         }
 
         if config.check_command().is_empty() {
-            config.other_errors.0.push(Arc::new(ConfigErrorInner::Json {
+            config.validation_errors.0.push(Arc::new(ConfigErrorInner::Json {
                 config_key: "/check/command".to_owned(),
                 error: serde_json::Error::custom("expected a non-empty string"),
             }));
@@ -1036,7 +1035,7 @@ impl Config {
                 .chain(config.root_ratoml.as_ref().into_iter().flat_map(|it| it.1 .0.iter()))
                 .chain(config.user_config.as_ref().into_iter().flat_map(|it| it.1 .0.iter()))
                 .chain(config.ratoml_files.values().flat_map(|it| it.1 .0.iter()))
-                .chain(config.other_errors.0.iter())
+                .chain(config.validation_errors.0.iter())
                 .cloned()
                 .collect(),
         );
@@ -1363,7 +1362,7 @@ impl Config {
             root_ratoml: None,
             root_ratoml_path,
             detached_files: Default::default(),
-            other_errors: Default::default(),
+            validation_errors: Default::default(),
         }
     }
 

From 06fe4e6b6e4aec29a21bcaa8a1a5582d6fb3eb78 Mon Sep 17 00:00:00 2001
From: David Barsky 
Date: Tue, 23 Jul 2024 13:34:03 -0400
Subject: [PATCH 118/489] internal: remove UnindexedProject notification

Summary:

Test Plan:

Reviewers:

Subscribers:

Tasks:

Tags:
---
 .../crates/rust-analyzer/src/config.rs        |   5 -
 .../src/handlers/notification.rs              |   4 +-
 .../crates/rust-analyzer/src/lsp/ext.rs       |  13 ---
 .../crates/rust-analyzer/src/main_loop.rs     |  11 +-
 .../rust-analyzer/tests/slow-tests/main.rs    |  62 +---------
 .../rust-analyzer/tests/slow-tests/support.rs |  34 ------
 .../rust-analyzer/docs/dev/lsp-extensions.md  |  21 +---
 .../docs/user/generated_config.adoc           |   5 -
 .../rust-analyzer/editors/code/package.json   |  10 --
 .../rust-analyzer/editors/code/src/client.ts  |  11 +-
 .../rust-analyzer/editors/code/src/config.ts  |  25 +---
 .../rust-analyzer/editors/code/src/ctx.ts     |  57 +--------
 .../rust-analyzer/editors/code/src/lsp_ext.ts |   6 -
 .../rust-analyzer/editors/code/src/main.ts    |   6 +-
 .../editors/code/src/rust_project.ts          | 110 ------------------
 15 files changed, 14 insertions(+), 366 deletions(-)
 delete mode 100644 src/tools/rust-analyzer/editors/code/src/rust_project.ts

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 5905137967890..c9c2c516bd6b2 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -679,9 +679,6 @@ config_data! {
         /// Whether to show `can't find Cargo.toml` error message.
         notifications_cargoTomlNotFound: bool      = true,
 
-        /// Whether to send an UnindexedProject notification to the client.
-        notifications_unindexedProject: bool      = false,
-
         /// How many worker threads in the main loop. The default `null` means to pick automatically.
         numThreads: Option = None,
 
@@ -1215,7 +1212,6 @@ pub enum FilesWatcher {
 #[derive(Debug, Clone)]
 pub struct NotificationsConfig {
     pub cargo_toml_not_found: bool,
-    pub unindexed_project: bool,
 }
 
 #[derive(Debug, Clone)]
@@ -1776,7 +1772,6 @@ impl Config {
     pub fn notifications(&self) -> NotificationsConfig {
         NotificationsConfig {
             cargo_toml_not_found: self.notifications_cargoTomlNotFound().to_owned(),
-            unindexed_project: self.notifications_unindexedProject().to_owned(),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
index 06e893f0f4719..4b14dcfc3721b 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
@@ -73,9 +73,7 @@ pub(crate) fn handle_did_open_text_document(
 
         tracing::info!("New file content set {:?}", params.text_document.text);
         state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
-        if state.config.discover_workspace_config().is_some()
-            || state.config.notifications().unindexed_project
-        {
+        if state.config.discover_workspace_config().is_some() {
             tracing::debug!("queuing task");
             let _ = state
                 .deferred_task_queue
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index efa5d47fbaab1..813e9fcd476a5 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -834,16 +834,3 @@ pub struct CompletionImport {
 pub struct ClientCommandOptions {
     pub commands: Vec,
 }
-
-pub enum UnindexedProject {}
-
-impl Notification for UnindexedProject {
-    type Params = UnindexedProjectParams;
-    const METHOD: &'static str = "rust-analyzer/unindexedProject";
-}
-
-#[derive(Deserialize, Serialize, Debug)]
-#[serde(rename_all = "camelCase")]
-pub struct UnindexedProjectParams {
-    pub text_documents: Vec,
-}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index db90d2d964c17..7d5c0e093aae6 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -90,7 +90,6 @@ pub(crate) enum QueuedTask {
 pub(crate) enum Task {
     Response(lsp_server::Response),
     DiscoverLinkedProjects(DiscoverProjectParam),
-    ClientNotification(lsp_ext::UnindexedProjectParams),
     Retry(lsp_server::Request),
     Diagnostics(DiagnosticsGeneration, Vec<(FileId, Vec)>),
     DiscoverTest(lsp_ext::DiscoverTestResults),
@@ -642,9 +641,6 @@ impl GlobalState {
     fn handle_task(&mut self, prime_caches_progress: &mut Vec, task: Task) {
         match task {
             Task::Response(response) => self.respond(response),
-            Task::ClientNotification(params) => {
-                self.send_notification::(params)
-            }
             // Only retry requests that haven't been cancelled. Otherwise we do unnecessary work.
             Task::Retry(req) if !self.is_completed(&req) => self.on_request(req),
             Task::Retry(_) => (),
@@ -825,12 +821,7 @@ impl GlobalState {
                                     from_proto::abs_path(&uri).expect("Unable to get AbsPath");
                                 let arg = DiscoverProjectParam::Path(path);
                                 sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
-                            } else if snap.config.notifications().unindexed_project {
-                                let params = lsp_ext::UnindexedProjectParams {
-                                    text_documents: vec![lsp_types::TextDocumentIdentifier { uri }],
-                                };
-                                sender.send(Task::ClientNotification(params)).unwrap();
-                            };
+                            }
                         } else {
                             tracing::debug!(?uri, "is indexed");
                         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
index 6bbf82a77547d..b1ef48377178b 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -27,7 +27,7 @@ use lsp_types::{
     InlayHint, InlayHintLabel, InlayHintParams, PartialResultParams, Position, Range,
     RenameFilesParams, TextDocumentItem, TextDocumentPositionParams, WorkDoneProgressParams,
 };
-use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams, UnindexedProject};
+use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams};
 use serde_json::json;
 use stdx::format_to_acc;
 
@@ -811,66 +811,6 @@ fn main() {{}}
     );
 }
 
-#[test]
-fn test_opening_a_file_outside_of_indexed_workspace() {
-    if skip_slow_tests() {
-        return;
-    }
-
-    let tmp_dir = TestDir::new();
-    let path = tmp_dir.path();
-
-    let project = json!({
-        "roots": [path],
-        "crates": [ {
-            "root_module": path.join("src/crate_one/lib.rs"),
-            "deps": [],
-            "edition": "2015",
-            "cfg": [ "cfg_atom_1", "feature=\"cfg_1\""],
-        } ]
-    });
-
-    let code = format!(
-        r#"
-//- /rust-project.json
-{project}
-
-//- /src/crate_one/lib.rs
-mod bar;
-
-fn main() {{}}
-"#,
-    );
-
-    let server = Project::with_fixture(&code)
-        .tmp_dir(tmp_dir)
-        .with_config(serde_json::json!({
-            "notifications": {
-                "unindexedProject": true
-            },
-        }))
-        .server()
-        .wait_until_workspace_is_loaded();
-
-    let uri = server.doc_id("src/crate_two/lib.rs").uri;
-    server.notification::(DidOpenTextDocumentParams {
-        text_document: TextDocumentItem {
-            uri: uri.clone(),
-            language_id: "rust".to_owned(),
-            version: 0,
-            text: "/// Docs\nfn foo() {}".to_owned(),
-        },
-    });
-    let expected = json!({
-        "textDocuments": [
-            {
-                "uri": uri
-            }
-        ]
-    });
-    server.expect_notification::(expected);
-}
-
 #[test]
 fn diagnostics_dont_block_typing() {
     if skip_slow_tests() {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
index 66100971fbf34..081ee5fa3e4e7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -256,40 +256,6 @@ impl Server {
         self.send_notification(r)
     }
 
-    pub(crate) fn expect_notification(&self, expected: Value)
-    where
-        N: lsp_types::notification::Notification,
-        N::Params: Serialize,
-    {
-        while let Some(Message::Notification(actual)) =
-            recv_timeout(&self.client.receiver).unwrap_or_else(|_| panic!("timed out"))
-        {
-            if actual.method == N::METHOD {
-                let actual = actual
-                    .clone()
-                    .extract::(N::METHOD)
-                    .expect("was not able to extract notification");
-
-                tracing::debug!(?actual, "got notification");
-                if let Some((expected_part, actual_part)) = find_mismatch(&expected, &actual) {
-                    panic!(
-                            "JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
-                            to_string_pretty(&expected).unwrap(),
-                            to_string_pretty(&actual).unwrap(),
-                            to_string_pretty(expected_part).unwrap(),
-                            to_string_pretty(actual_part).unwrap(),
-                        );
-                } else {
-                    tracing::debug!("successfully matched notification");
-                    return;
-                }
-            } else {
-                continue;
-            }
-        }
-        panic!("never got expected notification");
-    }
-
     #[track_caller]
     pub(crate) fn request(&self, params: R::Params, expected_resp: Value)
     where
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index fbb4fc6113f9a..a29b42a857c95 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
  $DIR/extern-type-field-offset.rs:LL:CC
+   |
+LL |     let x: &Newtype = unsafe { &*(&buf as *const _ as *const Newtype) };
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reborrow of a reference to `extern type` is not properly supported
+   |
+   = help: `extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code
+   = help: try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/extern-type-field-offset.rs:LL:CC
+
 error: unsupported operation: `extern type` field does not have a known offset
   --> $DIR/extern-type-field-offset.rs:LL:CC
    |
@@ -10,5 +21,5 @@ LL |     let _field = &x.a;
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
-error: aborting due to 1 previous error
+error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
index 217bc82010df9..84023cf793713 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr
@@ -4,11 +4,11 @@ warning: integer-to-pointer cast
 LL |         (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
    |
-   = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program.
-   = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation.
-   = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
-   = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics.
-   = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning.
+   = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+   = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+   = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+   = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+   = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
    = note: BACKTRACE:
    = note: inside `main` at $DIR/ptr_metadata_uninit_slice_len.rs:LL:CC
 
diff --git a/src/tools/miri/tests/pass/box.stack.stderr b/src/tools/miri/tests/pass/box.stack.stderr
index 341f84c8992df..f2d01b518fc80 100644
--- a/src/tools/miri/tests/pass/box.stack.stderr
+++ b/src/tools/miri/tests/pass/box.stack.stderr
@@ -4,11 +4,11 @@ warning: integer-to-pointer cast
 LL |         let r2 = ((r as usize) + 0) as *mut i32;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
    |
-   = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program.
-   = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation.
-   = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
-   = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics.
-   = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning.
+   = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+   = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+   = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+   = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+   = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
    = note: BACKTRACE:
    = note: inside `into_raw` at $DIR/box.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/pass/extern_types.stack.stderr b/src/tools/miri/tests/pass/extern_types.stack.stderr
index 03a9167abbc7c..9b6f632eb5a22 100644
--- a/src/tools/miri/tests/pass/extern_types.stack.stderr
+++ b/src/tools/miri/tests/pass/extern_types.stack.stderr
@@ -4,11 +4,22 @@ warning: integer-to-pointer cast
 LL |     let x: &Foo = unsafe { &*(16 as *const Foo) };
    |                              ^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
    |
-   = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program.
-   = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation.
-   = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
-   = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics.
-   = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning.
+   = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+   = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+   = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+   = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+   = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/extern_types.rs:LL:CC
+
+warning: reborrow of reference to `extern type`
+  --> $DIR/extern_types.rs:LL:CC
+   |
+LL |     let x: &Foo = unsafe { &*(16 as *const Foo) };
+   |                            ^^^^^^^^^^^^^^^^^^^^ reborrow of a reference to `extern type` is not properly supported
+   |
+   = help: `extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code
+   = help: try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead
    = note: BACKTRACE:
    = note: inside `main` at $DIR/extern_types.rs:LL:CC
 
diff --git a/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr b/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr
index b0e1adf27d183..216bb6c76bc9a 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr
+++ b/src/tools/miri/tests/pass/stacked-borrows/issue-miri-2389.stderr
@@ -4,11 +4,11 @@ warning: integer-to-pointer cast
 LL |         let wildcard = &root0 as *const Cell as usize as *const Cell;
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
    |
-   = help: This program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program.
-   = help: See https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation.
-   = help: To ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead.
-   = help: You can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics.
-   = help: Alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning.
+   = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+   = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+   = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+   = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+   = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
    = note: BACKTRACE:
    = note: inside `main` at $DIR/issue-miri-2389.rs:LL:CC
 

From 12f1463b7e9b1d01b5e46b50d375de0a9026f2b1 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Thu, 25 Jul 2024 00:32:50 -0400
Subject: [PATCH 128/489] Don't record trait aliases as marker traits

---
 compiler/rustc_hir_analysis/src/collect.rs | 14 +++++++++-----
 tests/crashes/127222.rs                    |  3 ---
 tests/ui/traits/alias/not-a-marker.rs      |  7 +++++++
 tests/ui/traits/alias/not-a-marker.stderr  | 11 +++++++++++
 4 files changed, 27 insertions(+), 8 deletions(-)
 delete mode 100644 tests/crashes/127222.rs
 create mode 100644 tests/ui/traits/alias/not-a-marker.rs
 create mode 100644 tests/ui/traits/alias/not-a-marker.stderr

diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 565351268c96b..71f466ef5da04 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1207,25 +1207,29 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
 fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
     let item = tcx.hir().expect_item(def_id);
 
-    let (is_auto, safety, items) = match item.kind {
+    let (is_alias, is_auto, safety, items) = match item.kind {
         hir::ItemKind::Trait(is_auto, safety, .., items) => {
-            (is_auto == hir::IsAuto::Yes, safety, items)
+            (false, is_auto == hir::IsAuto::Yes, safety, items)
         }
-        hir::ItemKind::TraitAlias(..) => (false, hir::Safety::Safe, &[][..]),
+        hir::ItemKind::TraitAlias(..) => (true, false, hir::Safety::Safe, &[][..]),
         _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
     };
 
-    let constness = if tcx.has_attr(def_id, sym::const_trait) {
+    // Only regular traits can be const.
+    let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) {
         hir::Constness::Const
     } else {
         hir::Constness::NotConst
     };
+
     let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
     if paren_sugar && !tcx.features().unboxed_closures {
         tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
     }
 
-    let is_marker = tcx.has_attr(def_id, sym::marker);
+    // Only regular traits can be marker.
+    let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker);
+
     let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
     let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
 
diff --git a/tests/crashes/127222.rs b/tests/crashes/127222.rs
deleted file mode 100644
index eda0ea3d9b729..0000000000000
--- a/tests/crashes/127222.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//@ known-bug: rust-lang/rust#127222
-#[marker]
-trait Foo = PartialEq + Send;
diff --git a/tests/ui/traits/alias/not-a-marker.rs b/tests/ui/traits/alias/not-a-marker.rs
new file mode 100644
index 0000000000000..b004b9ff9ae3f
--- /dev/null
+++ b/tests/ui/traits/alias/not-a-marker.rs
@@ -0,0 +1,7 @@
+#![feature(trait_alias, marker_trait_attr)]
+
+#[marker]
+//~^ ERROR attribute should be applied to a trait
+trait Foo = Send;
+
+fn main() {}
diff --git a/tests/ui/traits/alias/not-a-marker.stderr b/tests/ui/traits/alias/not-a-marker.stderr
new file mode 100644
index 0000000000000..2f3f6fea30f6a
--- /dev/null
+++ b/tests/ui/traits/alias/not-a-marker.stderr
@@ -0,0 +1,11 @@
+error: attribute should be applied to a trait
+  --> $DIR/not-a-marker.rs:3:1
+   |
+LL | #[marker]
+   | ^^^^^^^^^
+LL |
+LL | trait Foo = Send;
+   | ----------------- not a trait
+
+error: aborting due to 1 previous error
+

From 6da04f95a7233089cf714d24a160a5dbaa8d84b9 Mon Sep 17 00:00:00 2001
From: The Miri Cronjob Bot 
Date: Thu, 25 Jul 2024 05:10:15 +0000
Subject: [PATCH 129/489] Preparing for merge from rustc

---
 src/tools/miri/rust-version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 60497630ae0d0..9868188eeee70 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-42103d69b73fb4e9d03d5cf66ec12985bb526f6e
+e7d66eac5e8e8f60370c98d186aee9fa0ebd7845

From d7968e539312e3a7e30c0ea0f79729f1027fc7f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= 
Date: Thu, 25 Jul 2024 08:27:15 +0300
Subject: [PATCH 130/489] Fix and enable unsafe_op_in_unsafe_fn

---
 .../rust-analyzer/.github/workflows/ci.yaml   |  2 +-
 src/tools/rust-analyzer/Cargo.toml            |  6 ++---
 .../crates/salsa/src/intern_id.rs             |  3 ++-
 .../rust-analyzer/crates/stdx/src/anymap.rs   |  4 +--
 .../rust-analyzer/crates/stdx/src/process.rs  | 18 ++++++-------
 .../rust-analyzer/lib/line-index/src/lib.rs   | 26 +++++++++----------
 6 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 87a1729d2b418..6d3e488bb0821 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -15,7 +15,7 @@ env:
   CARGO_NET_RETRY: 10
   CI: 1
   RUST_BACKTRACE: short
-  RUSTFLAGS: "-D warnings -W unreachable-pub -W bare-trait-objects"
+  RUSTFLAGS: "-D warnings -D elided_lifetimes_in_paths -D explicit_outlives_requirements -D unsafe_op_in_unsafe_fn -D unused_extern_crates -D unused_lifetimes -D unreachable_pub"
   RUSTUP_MAX_RETRIES: 10
 
 jobs:
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 428d11ad60d48..c2f601a91bc7a 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -163,14 +163,14 @@ xshell = "0.2.5"
 dashmap = { version = "=5.5.3", features = ["raw-api"] }
 
 [workspace.lints.rust]
-bare_trait_objects = "warn"
+# remember to update RUSTFLAGS in ci.yml if you add something here
+
 elided_lifetimes_in_paths = "warn"
-ellipsis_inclusive_range_patterns = "warn"
 explicit_outlives_requirements = "warn"
+unsafe_op_in_unsafe_fn = "warn"
 unused_extern_crates = "warn"
 unused_lifetimes = "warn"
 unreachable_pub = "warn"
-semicolon_in_expressions_from_macros = "warn"
 
 [workspace.lints.clippy]
 # FIXME Remove the tidy test once the lint table is stable
diff --git a/src/tools/rust-analyzer/crates/salsa/src/intern_id.rs b/src/tools/rust-analyzer/crates/salsa/src/intern_id.rs
index b060d8aab6881..8e74c100acab9 100644
--- a/src/tools/rust-analyzer/crates/salsa/src/intern_id.rs
+++ b/src/tools/rust-analyzer/crates/salsa/src/intern_id.rs
@@ -63,7 +63,8 @@ impl InternId {
     /// `value` must be less than `MAX`
     pub const unsafe fn new_unchecked(value: u32) -> Self {
         debug_assert!(value < InternId::MAX);
-        InternId { value: NonZeroU32::new_unchecked(value + 1) }
+        let value = unsafe { NonZeroU32::new_unchecked(value + 1) };
+        InternId { value }
     }
 
     /// Convert this raw-id into a u32 value.
diff --git a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
index 4eafcfb060f22..91fab8e92380f 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
@@ -271,12 +271,12 @@ macro_rules! implement {
 
             #[inline]
             unsafe fn downcast_ref_unchecked(&self) -> &T {
-                &*(self as *const Self as *const T)
+                unsafe { &*(self as *const Self as *const T) }
             }
 
             #[inline]
             unsafe fn downcast_mut_unchecked(&mut self) -> &mut T {
-                &mut *(self as *mut Self as *mut T)
+                unsafe { &mut *(self as *mut Self as *mut T) }
             }
         }
 
diff --git a/src/tools/rust-analyzer/crates/stdx/src/process.rs b/src/tools/rust-analyzer/crates/stdx/src/process.rs
index c54d850d7b56e..75ae064db9a4d 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/process.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/process.rs
@@ -212,17 +212,13 @@ mod imp {
 
     impl<'a> Pipe<'a> {
         unsafe fn new(p: P, dst: &'a mut Vec) -> Pipe<'a> {
-            Pipe {
-                dst,
-                pipe: NamedPipe::from_raw_handle(p.into_raw_handle()),
-                overlapped: Overlapped::zero(),
-                done: false,
-            }
+            let pipe = unsafe { NamedPipe::from_raw_handle(p.into_raw_handle()) };
+            Pipe { dst, pipe, overlapped: Overlapped::zero(), done: false }
         }
 
         unsafe fn read(&mut self) -> io::Result<()> {
-            let dst = slice_to_end(self.dst);
-            match self.pipe.read_overlapped(dst, self.overlapped.raw()) {
+            let dst = unsafe { slice_to_end(self.dst) };
+            match unsafe { self.pipe.read_overlapped(dst, self.overlapped.raw()) } {
                 Ok(_) => Ok(()),
                 Err(e) => {
                     if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) {
@@ -237,7 +233,7 @@ mod imp {
 
         unsafe fn complete(&mut self, status: &CompletionStatus) {
             let prev = self.dst.len();
-            self.dst.set_len(prev + status.bytes_transferred() as usize);
+            unsafe { self.dst.set_len(prev + status.bytes_transferred() as usize) };
             if status.bytes_transferred() == 0 {
                 self.done = true;
             }
@@ -251,7 +247,9 @@ mod imp {
         if v.capacity() == v.len() {
             v.reserve(1);
         }
-        slice::from_raw_parts_mut(v.as_mut_ptr().add(v.len()), v.capacity() - v.len())
+        let data = unsafe { v.as_mut_ptr().add(v.len()) };
+        let len = v.capacity() - v.len();
+        unsafe { slice::from_raw_parts_mut(data, len) }
     }
 }
 
diff --git a/src/tools/rust-analyzer/lib/line-index/src/lib.rs b/src/tools/rust-analyzer/lib/line-index/src/lib.rs
index 1ab62e99235f6..66875e25242b5 100644
--- a/src/tools/rust-analyzer/lib/line-index/src/lib.rs
+++ b/src/tools/rust-analyzer/lib/line-index/src/lib.rs
@@ -275,21 +275,21 @@ unsafe fn analyze_source_file_sse2(
         let ptr = src_bytes.as_ptr() as *const __m128i;
         // We don't know if the pointer is aligned to 16 bytes, so we
         // use `loadu`, which supports unaligned loading.
-        let chunk = _mm_loadu_si128(ptr.add(chunk_index));
+        let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) };
 
         // For character in the chunk, see if its byte value is < 0, which
         // indicates that it's part of a UTF-8 char.
-        let multibyte_test = _mm_cmplt_epi8(chunk, _mm_set1_epi8(0));
+        let multibyte_test = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)) };
         // Create a bit mask from the comparison results.
-        let multibyte_mask = _mm_movemask_epi8(multibyte_test);
+        let multibyte_mask = unsafe { _mm_movemask_epi8(multibyte_test) };
 
         // If the bit mask is all zero, we only have ASCII chars here:
         if multibyte_mask == 0 {
             assert!(intra_chunk_offset == 0);
 
             // Check for newlines in the chunk
-            let newlines_test = _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8));
-            let newlines_mask = _mm_movemask_epi8(newlines_test);
+            let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
+            let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
 
             if newlines_mask != 0 {
                 // All control characters are newlines, record them
@@ -349,8 +349,8 @@ unsafe fn analyze_source_file_sse2(
 unsafe fn move_mask(v: std::arch::aarch64::uint8x16_t) -> u64 {
     use std::arch::aarch64::*;
 
-    let nibble_mask = vshrn_n_u16(vreinterpretq_u16_u8(v), 4);
-    vget_lane_u64(vreinterpret_u64_u8(nibble_mask), 0)
+    let nibble_mask = unsafe { vshrn_n_u16(vreinterpretq_u16_u8(v), 4) };
+    unsafe { vget_lane_u64(vreinterpret_u64_u8(nibble_mask), 0) }
 }
 
 #[target_feature(enable = "neon")]
@@ -368,7 +368,7 @@ unsafe fn analyze_source_file_neon(
 
     let chunk_count = src.len() / CHUNK_SIZE;
 
-    let newline = vdupq_n_s8(b'\n' as i8);
+    let newline = unsafe { vdupq_n_s8(b'\n' as i8) };
 
     // This variable keeps track of where we should start decoding a
     // chunk. If a multi-byte character spans across chunk boundaries,
@@ -378,21 +378,21 @@ unsafe fn analyze_source_file_neon(
 
     for chunk_index in 0..chunk_count {
         let ptr = src_bytes.as_ptr() as *const i8;
-        let chunk = vld1q_s8(ptr.add(chunk_index * CHUNK_SIZE));
+        let chunk = unsafe { vld1q_s8(ptr.add(chunk_index * CHUNK_SIZE)) };
 
         // For character in the chunk, see if its byte value is < 0, which
         // indicates that it's part of a UTF-8 char.
-        let multibyte_test = vcltzq_s8(chunk);
+        let multibyte_test = unsafe { vcltzq_s8(chunk) };
         // Create a bit mask from the comparison results.
-        let multibyte_mask = move_mask(multibyte_test);
+        let multibyte_mask = unsafe { move_mask(multibyte_test) };
 
         // If the bit mask is all zero, we only have ASCII chars here:
         if multibyte_mask == 0 {
             assert!(intra_chunk_offset == 0);
 
             // Check for newlines in the chunk
-            let newlines_test = vceqq_s8(chunk, newline);
-            let mut newlines_mask = move_mask(newlines_test);
+            let newlines_test = unsafe { vceqq_s8(chunk, newline) };
+            let mut newlines_mask = unsafe { move_mask(newlines_test) };
 
             // If the bit mask is not all zero, there are newlines in this chunk.
             if newlines_mask != 0 {

From 113c45847a7cb47ed4d93749d9d88fe97f5edbf5 Mon Sep 17 00:00:00 2001
From: winstxnhdw 
Date: Thu, 25 Jul 2024 07:40:08 +0100
Subject: [PATCH 131/489] fix: temporarily use `ast::GenericParamList`

---
 src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
index 911e3d823de6f..16abb2984d74b 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
@@ -794,6 +794,8 @@ pub enum TypeBoundKind {
     PathType(ast::PathType),
     /// for<'a> ...
     ForType(ast::ForType),
+    /// use
+    Use(ast::GenericParamList),
     /// 'a
     Lifetime(ast::Lifetime),
 }
@@ -804,6 +806,8 @@ impl ast::TypeBound {
             TypeBoundKind::PathType(path_type)
         } else if let Some(for_type) = support::children(self.syntax()).next() {
             TypeBoundKind::ForType(for_type)
+        } else if let Some(generic_param_list) = self.generic_param_list() {
+            TypeBoundKind::Use(generic_param_list)
         } else if let Some(lifetime) = self.lifetime() {
             TypeBoundKind::Lifetime(lifetime)
         } else {

From 896639683c9d5e49e262cf4b82b4040787cba763 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 25 Jul 2024 10:18:01 +0200
Subject: [PATCH 132/489] Generate From impls for Any* nodes

---
 .../crates/syntax/src/ast/generated/nodes.rs  | 624 ++++++++++++++++++
 .../crates/syntax/src/ast/node_ext.rs         |  18 -
 .../xtask/src/codegen/grammar.rs              |  11 +-
 3 files changed, 634 insertions(+), 19 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index ceecffba5d219..b8c5c22983348 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -5106,6 +5106,14 @@ impl AstNode for AnyHasArgList {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasArgList {
+    #[inline]
+    fn from(node: CallExpr) -> AnyHasArgList { AnyHasArgList { syntax: node.syntax } }
+}
+impl From for AnyHasArgList {
+    #[inline]
+    fn from(node: MethodCallExpr) -> AnyHasArgList { AnyHasArgList { syntax: node.syntax } }
+}
 impl AnyHasAttrs {
     #[inline]
     pub fn new(node: T) -> AnyHasAttrs {
@@ -5198,6 +5206,294 @@ impl AstNode for AnyHasAttrs {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ArrayExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: AsmExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: AssocItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: AwaitExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: BecomeExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: BinExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: BlockExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: BreakExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: CallExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: CastExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ClosureExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Const) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ConstParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ContinueExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Enum) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ExternBlock) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ExternCrate) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ExternItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: FieldExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Fn) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ForExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: FormatArgsExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: IdentPat) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: IfExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Impl) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: IndexExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ItemList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: LetExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: LetStmt) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: LifetimeParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Literal) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: LoopExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: MacroCall) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: MacroDef) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: MacroRules) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: MatchArm) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: MatchArmList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: MatchExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: MethodCallExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Module) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: OffsetOfExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Param) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ParenExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: PathExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: PrefixExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: RangeExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: RecordExprField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: RecordExprFieldList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: RecordField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: RecordPatField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: RefExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: RestPat) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: ReturnExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: SelfParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: SourceFile) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Static) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: StmtList) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Struct) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Trait) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: TraitAlias) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: TryExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: TupleExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: TupleField) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: TypeAlias) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: TypeParam) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: UnderscoreExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Union) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Use) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: Variant) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: WhileExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: YeetExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
+impl From for AnyHasAttrs {
+    #[inline]
+    fn from(node: YieldExpr) -> AnyHasAttrs { AnyHasAttrs { syntax: node.syntax } }
+}
 impl AnyHasDocComments {
     #[inline]
     pub fn new(node: T) -> AnyHasDocComments {
@@ -5239,6 +5535,90 @@ impl AstNode for AnyHasDocComments {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Const) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Enum) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: ExternBlock) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: ExternCrate) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Fn) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Impl) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: MacroCall) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: MacroDef) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: MacroRules) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Module) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: RecordField) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: SourceFile) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Static) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Struct) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Trait) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: TraitAlias) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: TupleField) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: TypeAlias) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Union) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Use) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
+impl From for AnyHasDocComments {
+    #[inline]
+    fn from(node: Variant) -> AnyHasDocComments { AnyHasDocComments { syntax: node.syntax } }
+}
 impl AnyHasGenericArgs {
     #[inline]
     pub fn new(node: T) -> AnyHasGenericArgs {
@@ -5257,6 +5637,18 @@ impl AstNode for AnyHasGenericArgs {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasGenericArgs {
+    #[inline]
+    fn from(node: AssocTypeArg) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } }
+}
+impl From for AnyHasGenericArgs {
+    #[inline]
+    fn from(node: MethodCallExpr) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } }
+}
+impl From for AnyHasGenericArgs {
+    #[inline]
+    fn from(node: PathSegment) -> AnyHasGenericArgs { AnyHasGenericArgs { syntax: node.syntax } }
+}
 impl AnyHasGenericParams {
     #[inline]
     pub fn new(node: T) -> AnyHasGenericParams {
@@ -5275,6 +5667,38 @@ impl AstNode for AnyHasGenericParams {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasGenericParams {
+    #[inline]
+    fn from(node: Enum) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
+impl From for AnyHasGenericParams {
+    #[inline]
+    fn from(node: Fn) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
+impl From for AnyHasGenericParams {
+    #[inline]
+    fn from(node: Impl) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
+impl From for AnyHasGenericParams {
+    #[inline]
+    fn from(node: Struct) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
+impl From for AnyHasGenericParams {
+    #[inline]
+    fn from(node: Trait) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
+impl From for AnyHasGenericParams {
+    #[inline]
+    fn from(node: TraitAlias) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
+impl From for AnyHasGenericParams {
+    #[inline]
+    fn from(node: TypeAlias) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
+impl From for AnyHasGenericParams {
+    #[inline]
+    fn from(node: Union) -> AnyHasGenericParams { AnyHasGenericParams { syntax: node.syntax } }
+}
 impl AnyHasLoopBody {
     #[inline]
     pub fn new(node: T) -> AnyHasLoopBody {
@@ -5291,6 +5715,18 @@ impl AstNode for AnyHasLoopBody {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasLoopBody {
+    #[inline]
+    fn from(node: ForExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } }
+}
+impl From for AnyHasLoopBody {
+    #[inline]
+    fn from(node: LoopExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } }
+}
+impl From for AnyHasLoopBody {
+    #[inline]
+    fn from(node: WhileExpr) -> AnyHasLoopBody { AnyHasLoopBody { syntax: node.syntax } }
+}
 impl AnyHasModuleItem {
     #[inline]
     pub fn new(node: T) -> AnyHasModuleItem {
@@ -5307,6 +5743,18 @@ impl AstNode for AnyHasModuleItem {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasModuleItem {
+    #[inline]
+    fn from(node: ItemList) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } }
+}
+impl From for AnyHasModuleItem {
+    #[inline]
+    fn from(node: MacroItems) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } }
+}
+impl From for AnyHasModuleItem {
+    #[inline]
+    fn from(node: SourceFile) -> AnyHasModuleItem { AnyHasModuleItem { syntax: node.syntax } }
+}
 impl AnyHasName {
     #[inline]
     pub fn new(node: T) -> AnyHasName {
@@ -5347,6 +5795,86 @@ impl AstNode for AnyHasName {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Const) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: ConstParam) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Enum) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Fn) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: FormatArgsArg) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: IdentPat) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: MacroDef) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: MacroRules) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Module) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: RecordField) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Rename) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: SelfParam) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Static) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Struct) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Trait) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: TraitAlias) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: TypeAlias) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: TypeParam) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Union) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
+impl From for AnyHasName {
+    #[inline]
+    fn from(node: Variant) -> AnyHasName { AnyHasName { syntax: node.syntax } }
+}
 impl AnyHasTypeBounds {
     #[inline]
     pub fn new(node: T) -> AnyHasTypeBounds {
@@ -5368,6 +5896,30 @@ impl AstNode for AnyHasTypeBounds {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasTypeBounds {
+    #[inline]
+    fn from(node: AssocTypeArg) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
+}
+impl From for AnyHasTypeBounds {
+    #[inline]
+    fn from(node: LifetimeParam) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
+}
+impl From for AnyHasTypeBounds {
+    #[inline]
+    fn from(node: Trait) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
+}
+impl From for AnyHasTypeBounds {
+    #[inline]
+    fn from(node: TypeAlias) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
+}
+impl From for AnyHasTypeBounds {
+    #[inline]
+    fn from(node: TypeParam) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
+}
+impl From for AnyHasTypeBounds {
+    #[inline]
+    fn from(node: WherePred) -> AnyHasTypeBounds { AnyHasTypeBounds { syntax: node.syntax } }
+}
 impl AnyHasVisibility {
     #[inline]
     pub fn new(node: T) -> AnyHasVisibility {
@@ -5406,6 +5958,78 @@ impl AstNode for AnyHasVisibility {
     #[inline]
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Const) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Enum) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: ExternCrate) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Fn) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Impl) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: MacroDef) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: MacroRules) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Module) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: RecordField) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Static) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Struct) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Trait) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: TraitAlias) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: TupleField) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: TypeAlias) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Union) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Use) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
+impl From for AnyHasVisibility {
+    #[inline]
+    fn from(node: Variant) -> AnyHasVisibility { AnyHasVisibility { syntax: node.syntax } }
+}
 impl std::fmt::Display for Adt {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
index 911e3d823de6f..9e0eef483b561 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
@@ -1127,21 +1127,3 @@ impl From for ast::AnyHasAttrs {
         Self::new(node)
     }
 }
-
-impl From for ast::AnyHasAttrs {
-    fn from(node: ast::Variant) -> Self {
-        Self::new(node)
-    }
-}
-
-impl From for ast::AnyHasAttrs {
-    fn from(node: ast::RecordField) -> Self {
-        Self::new(node)
-    }
-}
-
-impl From for ast::AnyHasAttrs {
-    fn from(node: ast::TupleField) -> Self {
-        Self::new(node)
-    }
-}
diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
index 44f12ba4ad992..0352539754b05 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
@@ -261,7 +261,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
                 .iter()
                 .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string())))
                 .collect();
-
+            let nodes = nodes.iter().map(|node| format_ident!("{}", node.name));
             (
                 quote! {
                     #[pretty_doc_comment_placeholder_workaround]
@@ -294,6 +294,15 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
                             &self.syntax
                         }
                     }
+
+                    #(
+                        impl From<#nodes> for #name {
+                            #[inline]
+                            fn from(node: #nodes) -> #name {
+                                #name { syntax: node.syntax }
+                            }
+                        }
+                    )*
                 },
             )
         })

From 8e0d60e11594593b0adae236242f5b43a120ddaf Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 25 Jul 2024 10:18:06 +0200
Subject: [PATCH 133/489] Remove Params and Fields from AstIdMap

---
 .../rust-analyzer/crates/hir-def/src/attr.rs  |  26 +--
 .../rust-analyzer/crates/hir-def/src/body.rs  |  16 +-
 .../rust-analyzer/crates/hir-def/src/data.rs  |  42 ++--
 .../crates/hir-def/src/data/adt.rs            | 125 +++++-----
 .../crates/hir-def/src/item_tree.rs           | 173 ++++++--------
 .../crates/hir-def/src/item_tree/lower.rs     | 213 ++++++++++--------
 .../crates/hir-def/src/item_tree/pretty.rs    | 129 ++++++-----
 .../crates/hir-def/src/item_tree/tests.rs     |  35 +--
 .../crates/hir-def/src/nameres/collector.rs   |  27 +--
 .../crates/hir-def/src/nameres/diagnostics.rs |  15 +-
 .../hir-def/src/nameres/path_resolution.rs    |   8 +-
 .../rust-analyzer/crates/hir-def/src/src.rs   |  19 +-
 .../rust-analyzer/crates/hir-ty/src/infer.rs  |   4 +-
 .../rust-analyzer/crates/hir/src/display.rs   |  13 +-
 src/tools/rust-analyzer/crates/hir/src/lib.rs |  92 +++++++-
 .../rust-analyzer/crates/span/src/ast_id.rs   |   6 +-
 16 files changed, 494 insertions(+), 449 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index b0f16ad6f4df1..ba88495e14d30 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -20,7 +20,7 @@ use triomphe::Arc;
 
 use crate::{
     db::DefDatabase,
-    item_tree::{AttrOwner, Fields, ItemTreeNode},
+    item_tree::{AttrOwner, FieldParent, ItemTreeNode},
     lang_item::LangItem,
     nameres::{ModuleOrigin, ModuleSource},
     src::{HasChildSource, HasSource},
@@ -76,40 +76,36 @@ impl Attrs {
         let mut res = ArenaMap::default();
 
         let crate_graph = db.crate_graph();
-        let (fields, item_tree, krate) = match v {
+        let item_tree;
+        let (parent, fields, krate) = match v {
             VariantId::EnumVariantId(it) => {
                 let loc = it.lookup(db);
                 let krate = loc.parent.lookup(db).container.krate;
-                let item_tree = loc.id.item_tree(db);
+                item_tree = loc.id.item_tree(db);
                 let variant = &item_tree[loc.id.value];
-                (variant.fields.clone(), item_tree, krate)
+                (FieldParent::Variant(loc.id.value), &variant.fields, krate)
             }
             VariantId::StructId(it) => {
                 let loc = it.lookup(db);
                 let krate = loc.container.krate;
-                let item_tree = loc.id.item_tree(db);
+                item_tree = loc.id.item_tree(db);
                 let struct_ = &item_tree[loc.id.value];
-                (struct_.fields.clone(), item_tree, krate)
+                (FieldParent::Struct(loc.id.value), &struct_.fields, krate)
             }
             VariantId::UnionId(it) => {
                 let loc = it.lookup(db);
                 let krate = loc.container.krate;
-                let item_tree = loc.id.item_tree(db);
+                item_tree = loc.id.item_tree(db);
                 let union_ = &item_tree[loc.id.value];
-                (union_.fields.clone(), item_tree, krate)
+                (FieldParent::Union(loc.id.value), &union_.fields, krate)
             }
         };
 
-        let fields = match fields {
-            Fields::Record(fields) | Fields::Tuple(fields) => fields,
-            Fields::Unit => return Arc::new(res),
-        };
-
         let cfg_options = &crate_graph[krate].cfg_options;
 
         let mut idx = 0;
-        for field in fields {
-            let attrs = item_tree.attrs(db, krate, field.into());
+        for (id, _field) in fields.iter().enumerate() {
+            let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id));
             if attrs.is_cfg_enabled(cfg_options) {
                 res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
                 idx += 1;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index 3486928e41467..9e1bff98f8a7b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -11,7 +11,7 @@ use std::ops::{Deref, Index};
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
 use hir_expand::{name::Name, InFile};
-use la_arena::{Arena, ArenaMap};
+use la_arena::{Arena, ArenaMap, Idx, RawIdx};
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::MacroFileId;
@@ -24,6 +24,7 @@ use crate::{
     hir::{
         dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId, RecordFieldPat,
     },
+    item_tree::AttrOwner,
     nameres::DefMap,
     path::{ModPath, Path},
     src::HasSource,
@@ -136,16 +137,23 @@ impl Body {
                     let data = db.function_data(f);
                     let f = f.lookup(db);
                     let src = f.source(db);
-                    params = src.value.param_list().map(|param_list| {
+                    params = src.value.param_list().map(move |param_list| {
                         let item_tree = f.id.item_tree(db);
                         let func = &item_tree[f.id.value];
                         let krate = f.container.module(db).krate;
                         let crate_graph = db.crate_graph();
                         (
                             param_list,
-                            func.params.clone().map(move |param| {
+                            (0..func.params.len()).map(move |idx| {
                                 item_tree
-                                    .attrs(db, krate, param.into())
+                                    .attrs(
+                                        db,
+                                        krate,
+                                        AttrOwner::Param(
+                                            f.id.value,
+                                            Idx::from_raw(RawIdx::from(idx as u32)),
+                                        ),
+                                    )
                                     .is_cfg_enabled(&crate_graph[krate].cfg_options)
                             }),
                         )
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 37506b6cdc296..a03140e2a92d6 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -7,6 +7,7 @@ use hir_expand::{
     name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
 };
 use intern::{sym, Interned, Symbol};
+use la_arena::{Idx, RawIdx};
 use smallvec::SmallVec;
 use syntax::{ast, Parse};
 use triomphe::Arc;
@@ -58,32 +59,15 @@ impl FunctionData {
 
         let crate_graph = db.crate_graph();
         let cfg_options = &crate_graph[krate].cfg_options;
-        let enabled_params = func
-            .params
-            .clone()
-            .filter(|¶m| item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options));
-
-        // If last cfg-enabled param is a `...` param, it's a varargs function.
-        let is_varargs = enabled_params
-            .clone()
-            .next_back()
-            .map_or(false, |param| item_tree[param].type_ref.is_none());
+        let attr_owner = |idx| {
+            item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32)))
+        };
 
         let mut flags = func.flags;
-        if is_varargs {
-            flags |= FnFlags::IS_VARARGS;
-        }
         if flags.contains(FnFlags::HAS_SELF_PARAM) {
             // If there's a self param in the syntax, but it is cfg'd out, remove the flag.
-            let is_cfgd_out = match func.params.clone().next() {
-                Some(param) => {
-                    !item_tree.attrs(db, krate, param.into()).is_cfg_enabled(cfg_options)
-                }
-                None => {
-                    stdx::never!("fn HAS_SELF_PARAM but no parameters allocated");
-                    true
-                }
-            };
+            let is_cfgd_out =
+                !item_tree.attrs(db, krate, attr_owner(0usize)).is_cfg_enabled(cfg_options);
             if is_cfgd_out {
                 cov_mark::hit!(cfgd_out_self_param);
                 flags.remove(FnFlags::HAS_SELF_PARAM);
@@ -101,9 +85,14 @@ impl FunctionData {
 
         Arc::new(FunctionData {
             name: func.name.clone(),
-            params: enabled_params
-                .clone()
-                .filter_map(|id| item_tree[id].type_ref.clone())
+            params: func
+                .params
+                .iter()
+                .enumerate()
+                .filter(|&(idx, _)| {
+                    item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options)
+                })
+                .map(|(_, param)| param.type_ref.clone())
                 .collect(),
             ret_type: func.ret_type.clone(),
             attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
@@ -629,7 +618,8 @@ impl<'a> AssocItemCollector<'a> {
             if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
                 self.diagnostics.push(DefDiagnostic::unconfigured_code(
                     self.module_id.local_id,
-                    InFile::new(self.expander.current_file_id(), item.ast_id(item_tree).erase()),
+                    tree_id,
+                    ModItem::from(item).into(),
                     attrs.cfg().unwrap(),
                     self.expander.cfg_options().clone(),
                 ));
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
index cc6e408b65bac..827cce706be6a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
@@ -7,7 +7,7 @@ use either::Either;
 
 use hir_expand::{
     name::{AsName, Name},
-    HirFileId, InFile,
+    InFile,
 };
 use intern::{sym, Interned};
 use la_arena::Arena;
@@ -18,7 +18,9 @@ use triomphe::Arc;
 use crate::{
     builtin_type::{BuiltinInt, BuiltinUint},
     db::DefDatabase,
-    item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
+    item_tree::{
+        AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId,
+    },
     lang_item::LangItem,
     lower::LowerCtx,
     nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
@@ -211,20 +213,25 @@ impl StructData {
         }
 
         let strukt = &item_tree[loc.id.value];
-        let (variant_data, diagnostics) = lower_fields(
+        let (data, diagnostics) = lower_fields(
             db,
             krate,
-            loc.id.file_id(),
             loc.container.local_id,
+            loc.id.tree_id(),
             &item_tree,
             &db.crate_graph()[krate].cfg_options,
+            FieldParent::Struct(loc.id.value),
             &strukt.fields,
             None,
         );
         (
             Arc::new(StructData {
                 name: strukt.name.clone(),
-                variant_data: Arc::new(variant_data),
+                variant_data: Arc::new(match strukt.shape {
+                    FieldsShape::Record => VariantData::Record(data),
+                    FieldsShape::Tuple => VariantData::Tuple(data),
+                    FieldsShape::Unit => VariantData::Unit,
+                }),
                 repr,
                 visibility: item_tree[strukt.visibility].clone(),
                 flags,
@@ -256,20 +263,21 @@ impl StructData {
         }
 
         let union = &item_tree[loc.id.value];
-        let (variant_data, diagnostics) = lower_fields(
+        let (data, diagnostics) = lower_fields(
             db,
             krate,
-            loc.id.file_id(),
             loc.container.local_id,
+            loc.id.tree_id(),
             &item_tree,
             &db.crate_graph()[krate].cfg_options,
+            FieldParent::Union(loc.id.value),
             &union.fields,
             None,
         );
         (
             Arc::new(StructData {
                 name: union.name.clone(),
-                variant_data: Arc::new(variant_data),
+                variant_data: Arc::new(VariantData::Record(data)),
                 repr,
                 visibility: item_tree[union.visibility].clone(),
                 flags,
@@ -336,13 +344,14 @@ impl EnumVariantData {
         let item_tree = loc.id.item_tree(db);
         let variant = &item_tree[loc.id.value];
 
-        let (var_data, diagnostics) = lower_fields(
+        let (data, diagnostics) = lower_fields(
             db,
             krate,
-            loc.id.file_id(),
             container.local_id,
+            loc.id.tree_id(),
             &item_tree,
             &db.crate_graph()[krate].cfg_options,
+            FieldParent::Variant(loc.id.value),
             &variant.fields,
             Some(item_tree[loc.parent.lookup(db).id.value].visibility),
         );
@@ -350,7 +359,11 @@ impl EnumVariantData {
         (
             Arc::new(EnumVariantData {
                 name: variant.name.clone(),
-                variant_data: Arc::new(var_data),
+                variant_data: Arc::new(match variant.shape {
+                    FieldsShape::Record => VariantData::Record(data),
+                    FieldsShape::Tuple => VariantData::Tuple(data),
+                    FieldsShape::Unit => VariantData::Unit,
+                }),
             }),
             DefDiagnostics::new(diagnostics),
         )
@@ -396,21 +409,23 @@ pub enum StructKind {
     Unit,
 }
 
+// FIXME This is only used for mapping back source now?
 pub(crate) fn lower_struct(
     db: &dyn DefDatabase,
     trace: &mut Trace>,
     ast: &InFile,
     krate: CrateId,
     item_tree: &ItemTree,
-    fields: &Fields,
+    parent: FieldParent,
 ) -> StructKind {
     let ctx = LowerCtx::new(db, ast.file_id);
 
-    match (&ast.value, fields) {
-        (ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => {
+    match &ast.value {
+        ast::StructKind::Tuple(fl) => {
             let cfg_options = &db.crate_graph()[krate].cfg_options;
-            for ((i, fd), item_tree_id) in fl.fields().enumerate().zip(fields.clone()) {
-                if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) {
+            for (i, fd) in fl.fields().enumerate() {
+                let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, i));
+                if !attrs.is_cfg_enabled(cfg_options) {
                     continue;
                 }
 
@@ -427,10 +442,11 @@ pub(crate) fn lower_struct(
             }
             StructKind::Tuple
         }
-        (ast::StructKind::Record(fl), Fields::Record(fields)) => {
+        ast::StructKind::Record(fl) => {
             let cfg_options = &db.crate_graph()[krate].cfg_options;
-            for (fd, item_tree_id) in fl.fields().zip(fields.clone()) {
-                if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) {
+            for (i, fd) in fl.fields().enumerate() {
+                let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, i));
+                if !attrs.is_cfg_enabled(cfg_options) {
                     continue;
                 }
 
@@ -454,65 +470,32 @@ pub(crate) fn lower_struct(
 fn lower_fields(
     db: &dyn DefDatabase,
     krate: CrateId,
-    current_file_id: HirFileId,
     container: LocalModuleId,
+    tree_id: TreeId,
     item_tree: &ItemTree,
     cfg_options: &CfgOptions,
-    fields: &Fields,
+    parent: FieldParent,
+    fields: &[Field],
     override_visibility: Option,
-) -> (VariantData, Vec) {
+) -> (Arena, Vec) {
     let mut diagnostics = Vec::new();
-    match fields {
-        Fields::Record(flds) => {
-            let mut arena = Arena::new();
-            for field_id in flds.clone() {
-                let attrs = item_tree.attrs(db, krate, field_id.into());
-                let field = &item_tree[field_id];
-                if attrs.is_cfg_enabled(cfg_options) {
-                    arena.alloc(lower_field(item_tree, field, override_visibility));
-                } else {
-                    diagnostics.push(DefDiagnostic::unconfigured_code(
-                        container,
-                        InFile::new(
-                            current_file_id,
-                            match field.ast_id {
-                                FieldAstId::Record(it) => it.erase(),
-                                FieldAstId::Tuple(it) => it.erase(),
-                            },
-                        ),
-                        attrs.cfg().unwrap(),
-                        cfg_options.clone(),
-                    ))
-                }
-            }
-            (VariantData::Record(arena), diagnostics)
-        }
-        Fields::Tuple(flds) => {
-            let mut arena = Arena::new();
-            for field_id in flds.clone() {
-                let attrs = item_tree.attrs(db, krate, field_id.into());
-                let field = &item_tree[field_id];
-                if attrs.is_cfg_enabled(cfg_options) {
-                    arena.alloc(lower_field(item_tree, field, override_visibility));
-                } else {
-                    diagnostics.push(DefDiagnostic::unconfigured_code(
-                        container,
-                        InFile::new(
-                            current_file_id,
-                            match field.ast_id {
-                                FieldAstId::Record(it) => it.erase(),
-                                FieldAstId::Tuple(it) => it.erase(),
-                            },
-                        ),
-                        attrs.cfg().unwrap(),
-                        cfg_options.clone(),
-                    ))
-                }
-            }
-            (VariantData::Tuple(arena), diagnostics)
+    let mut arena = Arena::new();
+    for (idx, field) in fields.iter().enumerate() {
+        let attr_owner = AttrOwner::make_field_indexed(parent, idx);
+        let attrs = item_tree.attrs(db, krate, attr_owner);
+        if attrs.is_cfg_enabled(cfg_options) {
+            arena.alloc(lower_field(item_tree, field, override_visibility));
+        } else {
+            diagnostics.push(DefDiagnostic::unconfigured_code(
+                container,
+                tree_id,
+                attr_owner,
+                attrs.cfg().unwrap(),
+                cfg_options.clone(),
+            ))
         }
-        Fields::Unit => (VariantData::Unit, diagnostics),
     }
+    (arena, diagnostics)
 }
 
 fn lower_field(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index 479beea4a9e7a..f6709680d0cdd 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -47,7 +47,7 @@ use base_db::CrateId;
 use either::Either;
 use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
 use intern::{Interned, Symbol};
-use la_arena::{Arena, Idx, IdxRange, RawIdx};
+use la_arena::{Arena, Idx, RawIdx};
 use once_cell::sync::OnceCell;
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
@@ -218,9 +218,7 @@ impl ItemTree {
                 extern_crates,
                 extern_blocks,
                 functions,
-                params,
                 structs,
-                fields,
                 unions,
                 enums,
                 variants,
@@ -241,9 +239,7 @@ impl ItemTree {
             extern_crates.shrink_to_fit();
             extern_blocks.shrink_to_fit();
             functions.shrink_to_fit();
-            params.shrink_to_fit();
             structs.shrink_to_fit();
-            fields.shrink_to_fit();
             unions.shrink_to_fit();
             enums.shrink_to_fit();
             variants.shrink_to_fit();
@@ -295,9 +291,7 @@ struct ItemTreeData {
     extern_crates: Arena,
     extern_blocks: Arena,
     functions: Arena,
-    params: Arena,
     structs: Arena,
-    fields: Arena,
     unions: Arena,
     enums: Arena,
     variants: Arena,
@@ -315,7 +309,7 @@ struct ItemTreeData {
     vis: ItemVisibilities,
 }
 
-#[derive(Debug, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 pub enum AttrOwner {
     /// Attributes on an item.
     ModItem(ModItem),
@@ -323,12 +317,28 @@ pub enum AttrOwner {
     TopLevel,
 
     Variant(FileItemTreeId),
-    Field(Idx),
-    Param(Idx),
+    Field(FieldParent, ItemTreeFieldId),
+    Param(FileItemTreeId, ItemTreeParamId),
     TypeOrConstParamData(GenericModItem, LocalTypeOrConstParamId),
     LifetimeParamData(GenericModItem, LocalLifetimeParamId),
 }
 
+impl AttrOwner {
+    pub fn make_field_indexed(parent: FieldParent, idx: usize) -> Self {
+        AttrOwner::Field(parent, ItemTreeFieldId::from_raw(RawIdx::from_u32(idx as u32)))
+    }
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub enum FieldParent {
+    Struct(FileItemTreeId),
+    Union(FileItemTreeId),
+    Variant(FileItemTreeId),
+}
+
+pub type ItemTreeParamId = Idx;
+pub type ItemTreeFieldId = Idx;
+
 macro_rules! from_attrs {
     ( $( $var:ident($t:ty) ),+ $(,)? ) => {
         $(
@@ -341,12 +351,7 @@ macro_rules! from_attrs {
     };
 }
 
-from_attrs!(
-    ModItem(ModItem),
-    Variant(FileItemTreeId),
-    Field(Idx),
-    Param(Idx),
-);
+from_attrs!(ModItem(ModItem), Variant(FileItemTreeId));
 
 /// Trait implemented by all nodes in the item tree.
 pub trait ItemTreeNode: Clone {
@@ -365,7 +370,7 @@ pub trait GenericsItemTreeNode: ItemTreeNode {
 pub struct FileItemTreeId(Idx);
 
 impl FileItemTreeId {
-    pub fn range_iter(range: Range) -> impl Iterator {
+    pub fn range_iter(range: Range) -> impl Iterator + Clone {
         (range.start.index().into_raw().into_u32()..range.end.index().into_raw().into_u32())
             .map(RawIdx::from_u32)
             .map(Idx::from_raw)
@@ -417,18 +422,18 @@ impl TreeId {
         Self { file, block }
     }
 
-    pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc {
+    pub fn item_tree(&self, db: &dyn DefDatabase) -> Arc {
         match self.block {
             Some(block) => db.block_item_tree(block),
             None => db.file_item_tree(self.file),
         }
     }
 
-    pub(crate) fn file_id(self) -> HirFileId {
+    pub fn file_id(self) -> HirFileId {
         self.file
     }
 
-    pub(crate) fn is_block(self) -> bool {
+    pub fn is_block(self) -> bool {
         self.block.is_some()
     }
 }
@@ -505,6 +510,27 @@ macro_rules! mod_items {
             )+
         }
 
+        impl ModItem {
+            pub fn ast_id(&self, tree: &ItemTree) -> FileAstId {
+                match self {
+                    $(ModItem::$typ(it) => tree[it.index()].ast_id().upcast()),+
+                }
+            }
+        }
+
+        impl GenericModItem {
+            pub fn ast_id(&self, tree: &ItemTree) -> FileAstId {
+                match self {
+                    $(
+                        $(
+                            #[cfg_attr(ignore_fragment, $generic_params)]
+                            GenericModItem::$typ(it) => tree[it.index()].ast_id().upcast(),
+                        )?
+                    )+
+                }
+            }
+        }
+
         impl From for ModItem {
             fn from(id: GenericModItem) -> ModItem {
                 match id {
@@ -596,22 +622,6 @@ mod_items! {
     Macro2 in macro_defs -> ast::MacroDef,
 }
 
-macro_rules! impl_index {
-    ( $($fld:ident: $t:ty),+ $(,)? ) => {
-        $(
-            impl Index> for ItemTree {
-                type Output = $t;
-
-                fn index(&self, index: Idx<$t>) -> &Self::Output {
-                    &self.data().$fld[index]
-                }
-            }
-        )+
-    };
-}
-
-impl_index!(fields: Field, variants: Variant, params: Param);
-
 impl Index for ItemTree {
     type Output = RawVisibility;
     fn index(&self, index: RawVisibilityId) -> &Self::Output {
@@ -723,7 +733,7 @@ pub struct Function {
     pub visibility: RawVisibilityId,
     pub explicit_generic_params: Interned,
     pub abi: Option,
-    pub params: IdxRange,
+    pub params: Box<[Param]>,
     pub ret_type: Interned,
     pub ast_id: FileAstId,
     pub(crate) flags: FnFlags,
@@ -731,15 +741,7 @@ pub struct Function {
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Param {
-    /// This is [`None`] for varargs
-    pub type_ref: Option>,
-    pub ast_id: ParamAstId,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum ParamAstId {
-    Param(FileAstId),
-    SelfParam(FileAstId),
+    pub type_ref: Interned,
 }
 
 bitflags::bitflags! {
@@ -760,7 +762,8 @@ pub struct Struct {
     pub name: Name,
     pub visibility: RawVisibilityId,
     pub generic_params: Interned,
-    pub fields: Fields,
+    pub fields: Box<[Field]>,
+    pub shape: FieldsShape,
     pub ast_id: FileAstId,
 }
 
@@ -769,7 +772,7 @@ pub struct Union {
     pub name: Name,
     pub visibility: RawVisibilityId,
     pub generic_params: Interned,
-    pub fields: Fields,
+    pub fields: Box<[Field]>,
     pub ast_id: FileAstId,
 }
 
@@ -782,6 +785,29 @@ pub struct Enum {
     pub ast_id: FileAstId,
 }
 
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Variant {
+    pub name: Name,
+    pub fields: Box<[Field]>,
+    pub shape: FieldsShape,
+    pub ast_id: FileAstId,
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum FieldsShape {
+    Record,
+    Tuple,
+    Unit,
+}
+
+/// A single field of an enum variant or struct
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Field {
+    pub name: Name,
+    pub type_ref: Interned,
+    pub visibility: RawVisibilityId,
+}
+
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct Const {
     /// `None` for `const _: () = ();`
@@ -1039,28 +1065,6 @@ impl ModItem {
             &ModItem::Function(func) => Some(AssocItem::Function(func)),
         }
     }
-
-    pub fn ast_id(&self, tree: &ItemTree) -> FileAstId {
-        match self {
-            ModItem::Use(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::ExternCrate(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::ExternBlock(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Function(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Struct(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Union(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Enum(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Const(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Static(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Trait(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::TraitAlias(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Impl(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::TypeAlias(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Mod(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::MacroCall(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::MacroRules(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::Macro2(it) => tree[it.index()].ast_id().upcast(),
-        }
-    }
 }
 
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
@@ -1099,32 +1103,3 @@ impl AssocItem {
         }
     }
 }
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Variant {
-    pub name: Name,
-    pub fields: Fields,
-    pub ast_id: FileAstId,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Fields {
-    Record(IdxRange),
-    Tuple(IdxRange),
-    Unit,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum FieldAstId {
-    Record(FileAstId),
-    Tuple(FileAstId),
-}
-
-/// A single field of an enum variant or struct
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Field {
-    pub name: Name,
-    pub type_ref: Interned,
-    pub visibility: RawVisibilityId,
-    pub ast_id: FieldAstId,
-}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index 67092ae0c0016..c9e9719c909dc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -17,12 +17,12 @@ use crate::{
     db::DefDatabase,
     generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
     item_tree::{
-        AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldAstId,
-        Fields, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, IdxRange,
-        Impl, ImportAlias, Interned, ItemTree, ItemTreeData, ItemTreeNode, Macro2, MacroCall,
-        MacroRules, Mod, ModItem, ModKind, ModPath, Mutability, Name, Param, ParamAstId, Path,
-        Range, RawAttrs, RawIdx, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias,
-        TypeAlias, Union, Use, UseTree, UseTreeKind, Variant,
+        AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldParent,
+        FieldsShape, FileItemTreeId, FnFlags, Function, GenericArgs, GenericModItem, Idx, Impl,
+        ImportAlias, Interned, ItemTree, ItemTreeData, Macro2, MacroCall, MacroRules, Mod, ModItem,
+        ModKind, ModPath, Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId,
+        Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
+        Variant,
     },
     path::AssociatedTypeBinding,
     type_ref::{LifetimeRef, TraitBoundModifier, TraitRef, TypeBound, TypeRef},
@@ -30,7 +30,7 @@ use crate::{
     LocalLifetimeParamId, LocalTypeOrConstParamId,
 };
 
-fn id(index: Idx) -> FileItemTreeId {
+fn id(index: Idx) -> FileItemTreeId {
     FileItemTreeId(index)
 }
 
@@ -193,82 +193,98 @@ impl<'a> Ctx<'a> {
         let visibility = self.lower_visibility(strukt);
         let name = strukt.name()?.as_name();
         let ast_id = self.source_ast_id_map.ast_id(strukt);
-        let fields = self.lower_fields(&strukt.kind());
+        let (fields, kind, attrs) = self.lower_fields(&strukt.kind());
         let generic_params = self.lower_generic_params(HasImplicitSelf::No, strukt);
-        let res = Struct { name, visibility, generic_params, fields, ast_id };
+        let res = Struct { name, visibility, generic_params, fields, shape: kind, ast_id };
         let id = id(self.data().structs.alloc(res));
+        for (idx, attr) in attrs {
+            self.add_attrs(
+                AttrOwner::Field(
+                    FieldParent::Struct(id),
+                    Idx::from_raw(RawIdx::from_u32(idx as u32)),
+                ),
+                attr,
+            );
+        }
         self.write_generic_params_attributes(id.into());
         Some(id)
     }
 
-    fn lower_fields(&mut self, strukt_kind: &ast::StructKind) -> Fields {
+    fn lower_fields(
+        &mut self,
+        strukt_kind: &ast::StructKind,
+    ) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) {
         match strukt_kind {
             ast::StructKind::Record(it) => {
-                let range = self.lower_record_fields(it);
-                Fields::Record(range)
+                let mut fields = vec![];
+                let mut attrs = vec![];
+
+                for (i, field) in it.fields().enumerate() {
+                    let data = self.lower_record_field(&field);
+                    fields.push(data);
+                    let attr = RawAttrs::new(self.db.upcast(), &field, self.span_map());
+                    if !attr.is_empty() {
+                        attrs.push((i, attr))
+                    }
+                }
+                (fields.into(), FieldsShape::Record, attrs)
             }
             ast::StructKind::Tuple(it) => {
-                let range = self.lower_tuple_fields(it);
-                Fields::Tuple(range)
-            }
-            ast::StructKind::Unit => Fields::Unit,
-        }
-    }
-
-    fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdxRange {
-        let start = self.next_field_idx();
-        for field in fields.fields() {
-            if let Some(data) = self.lower_record_field(&field) {
-                let idx = self.data().fields.alloc(data);
-                self.add_attrs(
-                    idx.into(),
-                    RawAttrs::new(self.db.upcast(), &field, self.span_map()),
-                );
+                let mut fields = vec![];
+                let mut attrs = vec![];
+
+                for (i, field) in it.fields().enumerate() {
+                    let data = self.lower_tuple_field(i, &field);
+                    fields.push(data);
+                    let attr = RawAttrs::new(self.db.upcast(), &field, self.span_map());
+                    if !attr.is_empty() {
+                        attrs.push((i, attr))
+                    }
+                }
+                (fields.into(), FieldsShape::Tuple, attrs)
             }
+            ast::StructKind::Unit => (Box::default(), FieldsShape::Unit, Vec::default()),
         }
-        let end = self.next_field_idx();
-        IdxRange::new(start..end)
     }
 
-    fn lower_record_field(&mut self, field: &ast::RecordField) -> Option {
-        let name = field.name()?.as_name();
+    fn lower_record_field(&mut self, field: &ast::RecordField) -> Field {
+        let name = match field.name() {
+            Some(name) => name.as_name(),
+            None => Name::missing(),
+        };
         let visibility = self.lower_visibility(field);
         let type_ref = self.lower_type_ref_opt(field.ty());
-        let ast_id = FieldAstId::Record(self.source_ast_id_map.ast_id(field));
-        let res = Field { name, type_ref, visibility, ast_id };
-        Some(res)
-    }
 
-    fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldList) -> IdxRange {
-        let start = self.next_field_idx();
-        for (i, field) in fields.fields().enumerate() {
-            let data = self.lower_tuple_field(i, &field);
-            let idx = self.data().fields.alloc(data);
-            self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), &field, self.span_map()));
-        }
-        let end = self.next_field_idx();
-        IdxRange::new(start..end)
+        Field { name, type_ref, visibility }
     }
 
     fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field {
         let name = Name::new_tuple_field(idx);
         let visibility = self.lower_visibility(field);
         let type_ref = self.lower_type_ref_opt(field.ty());
-        let ast_id = FieldAstId::Tuple(self.source_ast_id_map.ast_id(field));
-        Field { name, type_ref, visibility, ast_id }
+        Field { name, type_ref, visibility }
     }
 
     fn lower_union(&mut self, union: &ast::Union) -> Option> {
         let visibility = self.lower_visibility(union);
         let name = union.name()?.as_name();
         let ast_id = self.source_ast_id_map.ast_id(union);
-        let fields = match union.record_field_list() {
+        let (fields, _, attrs) = match union.record_field_list() {
             Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
-            None => Fields::Record(IdxRange::new(self.next_field_idx()..self.next_field_idx())),
+            None => (Box::default(), FieldsShape::Record, Vec::default()),
         };
         let generic_params = self.lower_generic_params(HasImplicitSelf::No, union);
         let res = Union { name, visibility, generic_params, fields, ast_id };
         let id = id(self.data().unions.alloc(res));
+        for (idx, attr) in attrs {
+            self.add_attrs(
+                AttrOwner::Field(
+                    FieldParent::Union(id),
+                    Idx::from_raw(RawIdx::from_u32(idx as u32)),
+                ),
+                attr,
+            );
+        }
         self.write_generic_params_attributes(id.into());
         Some(id)
     }
@@ -293,24 +309,35 @@ impl<'a> Ctx<'a> {
     fn lower_variants(&mut self, variants: &ast::VariantList) -> Range> {
         let start = self.next_variant_idx();
         for variant in variants.variants() {
-            if let Some(data) = self.lower_variant(&variant) {
-                let idx = self.data().variants.alloc(data);
-                self.add_attrs(
-                    id(idx).into(),
-                    RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
-                );
-            }
+            let idx = self.lower_variant(&variant);
+            self.add_attrs(
+                id(idx).into(),
+                RawAttrs::new(self.db.upcast(), &variant, self.span_map()),
+            );
         }
         let end = self.next_variant_idx();
         FileItemTreeId(start)..FileItemTreeId(end)
     }
 
-    fn lower_variant(&mut self, variant: &ast::Variant) -> Option {
-        let name = variant.name()?.as_name();
-        let fields = self.lower_fields(&variant.kind());
+    fn lower_variant(&mut self, variant: &ast::Variant) -> Idx {
+        let name = match variant.name() {
+            Some(name) => name.as_name(),
+            None => Name::missing(),
+        };
+        let (fields, kind, attrs) = self.lower_fields(&variant.kind());
         let ast_id = self.source_ast_id_map.ast_id(variant);
-        let res = Variant { name, fields, ast_id };
-        Some(res)
+        let res = Variant { name, fields, shape: kind, ast_id };
+        let id = self.data().variants.alloc(res);
+        for (idx, attr) in attrs {
+            self.add_attrs(
+                AttrOwner::Field(
+                    FieldParent::Variant(FileItemTreeId(id)),
+                    Idx::from_raw(RawIdx::from_u32(idx as u32)),
+                ),
+                attr,
+            );
+        }
+        id
     }
 
     fn lower_function(&mut self, func: &ast::Fn) -> Option> {
@@ -318,9 +345,20 @@ impl<'a> Ctx<'a> {
         let name = func.name()?.as_name();
 
         let mut has_self_param = false;
-        let start_param = self.next_param_idx();
+        let mut has_var_args = false;
+        let mut params = vec![];
+        let mut attrs = vec![];
+        let mut push_attr = |idx, attr: RawAttrs| {
+            if !attr.is_empty() {
+                attrs.push((idx, attr))
+            }
+        };
         if let Some(param_list) = func.param_list() {
             if let Some(self_param) = param_list.self_param() {
+                push_attr(
+                    params.len(),
+                    RawAttrs::new(self.db.upcast(), &self_param, self.span_map()),
+                );
                 let self_type = match self_param.ty() {
                     Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
                     None => {
@@ -342,40 +380,25 @@ impl<'a> Ctx<'a> {
                     }
                 };
                 let type_ref = Interned::new(self_type);
-                let ast_id = self.source_ast_id_map.ast_id(&self_param);
-                let idx = self.data().params.alloc(Param {
-                    type_ref: Some(type_ref),
-                    ast_id: ParamAstId::SelfParam(ast_id),
-                });
-                self.add_attrs(
-                    idx.into(),
-                    RawAttrs::new(self.db.upcast(), &self_param, self.span_map()),
-                );
+                params.push(Param { type_ref });
                 has_self_param = true;
             }
             for param in param_list.params() {
-                let ast_id = self.source_ast_id_map.ast_id(¶m);
-                let idx = match param.dotdotdot_token() {
-                    Some(_) => self
-                        .data()
-                        .params
-                        .alloc(Param { type_ref: None, ast_id: ParamAstId::Param(ast_id) }),
+                push_attr(params.len(), RawAttrs::new(self.db.upcast(), ¶m, self.span_map()));
+                let param = match param.dotdotdot_token() {
+                    Some(_) => {
+                        has_var_args = true;
+                        Param { type_ref: Interned::new(TypeRef::Error) }
+                    }
                     None => {
                         let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
                         let ty = Interned::new(type_ref);
-                        self.data()
-                            .params
-                            .alloc(Param { type_ref: Some(ty), ast_id: ParamAstId::Param(ast_id) })
+                        Param { type_ref: ty }
                     }
                 };
-                self.add_attrs(
-                    idx.into(),
-                    RawAttrs::new(self.db.upcast(), ¶m, self.span_map()),
-                );
+                params.push(param);
             }
         }
-        let end_param = self.next_param_idx();
-        let params = IdxRange::new(start_param..end_param);
 
         let ret_type = match func.ret_type() {
             Some(rt) => match rt.ty() {
@@ -417,19 +440,25 @@ impl<'a> Ctx<'a> {
         if func.unsafe_token().is_some() {
             flags |= FnFlags::HAS_UNSAFE_KW;
         }
+        if has_var_args {
+            flags |= FnFlags::IS_VARARGS;
+        }
 
         let res = Function {
             name,
             visibility,
             explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func),
             abi,
-            params,
+            params: params.into_boxed_slice(),
             ret_type: Interned::new(ret_type),
             ast_id,
             flags,
         };
 
         let id = id(self.data().functions.alloc(res));
+        for (idx, attr) in attrs {
+            self.add_attrs(AttrOwner::Param(id, Idx::from_raw(RawIdx::from_u32(idx as u32))), attr);
+        }
         self.write_generic_params_attributes(id.into());
         Some(id)
     }
@@ -725,21 +754,11 @@ impl<'a> Ctx<'a> {
         }
     }
 
-    fn next_field_idx(&self) -> Idx {
-        Idx::from_raw(RawIdx::from(
-            self.tree.data.as_ref().map_or(0, |data| data.fields.len() as u32),
-        ))
-    }
     fn next_variant_idx(&self) -> Idx {
         Idx::from_raw(RawIdx::from(
             self.tree.data.as_ref().map_or(0, |data| data.variants.len() as u32),
         ))
     }
-    fn next_param_idx(&self) -> Idx {
-        Idx::from_raw(RawIdx::from(
-            self.tree.data.as_ref().map_or(0, |data| data.params.len() as u32),
-        ))
-    }
 }
 
 fn desugar_future_path(orig: TypeRef) -> Path {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index 6283ae23b522f..5eeb8607b9609 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -2,16 +2,17 @@
 
 use std::fmt::{self, Write};
 
+use la_arena::{Idx, RawIdx};
 use span::ErasedFileAstId;
 
 use crate::{
     generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
     item_tree::{
-        AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldAstId, Fields,
-        FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl, Interned, ItemTree,
-        Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, ParamAstId, Path, RawAttrs,
-        RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound, TypeRef, Union,
-        Use, UseTree, UseTreeKind, Variant,
+        AttrOwner, Const, DefDatabase, Enum, ExternBlock, ExternCrate, Field, FieldParent,
+        FieldsShape, FileItemTreeId, FnFlags, Function, GenericModItem, GenericParams, Impl,
+        Interned, ItemTree, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, Param, Path,
+        RawAttrs, RawVisibilityId, Static, Struct, Trait, TraitAlias, TypeAlias, TypeBound,
+        TypeRef, Union, Use, UseTree, UseTreeKind, Variant,
     },
     pretty::{print_path, print_type_bounds, print_type_ref},
     visibility::RawVisibility,
@@ -118,19 +119,17 @@ impl Printer<'_> {
         };
     }
 
-    fn print_fields(&mut self, fields: &Fields) {
-        match fields {
-            Fields::Record(fields) => {
+    fn print_fields(&mut self, parent: FieldParent, kind: FieldsShape, fields: &[Field]) {
+        match kind {
+            FieldsShape::Record => {
                 self.whitespace();
                 w!(self, "{{");
                 self.indented(|this| {
-                    for field in fields.clone() {
-                        let Field { visibility, name, type_ref, ast_id } = &this.tree[field];
-                        this.print_ast_id(match ast_id {
-                            FieldAstId::Record(it) => it.erase(),
-                            FieldAstId::Tuple(it) => it.erase(),
-                        });
-                        this.print_attrs_of(field, "\n");
+                    for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
+                        this.print_attrs_of(
+                            AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
+                            "\n",
+                        );
                         this.print_visibility(*visibility);
                         w!(this, "{}: ", name.display(self.db.upcast()));
                         this.print_type_ref(type_ref);
@@ -139,16 +138,14 @@ impl Printer<'_> {
                 });
                 w!(self, "}}");
             }
-            Fields::Tuple(fields) => {
+            FieldsShape::Tuple => {
                 w!(self, "(");
                 self.indented(|this| {
-                    for field in fields.clone() {
-                        let Field { visibility, name, type_ref, ast_id } = &this.tree[field];
-                        this.print_ast_id(match ast_id {
-                            FieldAstId::Record(it) => it.erase(),
-                            FieldAstId::Tuple(it) => it.erase(),
-                        });
-                        this.print_attrs_of(field, "\n");
+                    for (idx, Field { name, type_ref, visibility }) in fields.iter().enumerate() {
+                        this.print_attrs_of(
+                            AttrOwner::Field(parent, Idx::from_raw(RawIdx::from(idx as u32))),
+                            "\n",
+                        );
                         this.print_visibility(*visibility);
                         w!(this, "{}: ", name.display(self.db.upcast()));
                         this.print_type_ref(type_ref);
@@ -157,24 +154,30 @@ impl Printer<'_> {
                 });
                 w!(self, ")");
             }
-            Fields::Unit => {}
+            FieldsShape::Unit => {}
         }
     }
 
-    fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) {
-        match fields {
-            Fields::Record(_) => {
+    fn print_fields_and_where_clause(
+        &mut self,
+        parent: FieldParent,
+        kind: FieldsShape,
+        fields: &[Field],
+        params: &GenericParams,
+    ) {
+        match kind {
+            FieldsShape::Record => {
                 if self.print_where_clause(params) {
                     wln!(self);
                 }
-                self.print_fields(fields);
+                self.print_fields(parent, kind, fields);
             }
-            Fields::Unit => {
+            FieldsShape::Unit => {
                 self.print_where_clause(params);
-                self.print_fields(fields);
+                self.print_fields(parent, kind, fields);
             }
-            Fields::Tuple(_) => {
-                self.print_fields(fields);
+            FieldsShape::Tuple => {
+                self.print_fields(parent, kind, fields);
                 self.print_where_clause(params);
             }
         }
@@ -280,25 +283,20 @@ impl Printer<'_> {
                 w!(self, "(");
                 if !params.is_empty() {
                     self.indented(|this| {
-                        for param in params.clone() {
-                            this.print_attrs_of(param, "\n");
-                            let Param { type_ref, ast_id } = &this.tree[param];
-                            this.print_ast_id(match ast_id {
-                                ParamAstId::Param(it) => it.erase(),
-                                ParamAstId::SelfParam(it) => it.erase(),
-                            });
-                            match type_ref {
-                                Some(ty) => {
-                                    if flags.contains(FnFlags::HAS_SELF_PARAM) {
-                                        w!(this, "self: ");
-                                    }
-                                    this.print_type_ref(ty);
-                                    wln!(this, ",");
-                                }
-                                None => {
-                                    wln!(this, "...");
-                                }
-                            };
+                        for (idx, Param { type_ref }) in params.iter().enumerate() {
+                            this.print_attrs_of(
+                                AttrOwner::Param(it, Idx::from_raw(RawIdx::from(idx as u32))),
+                                "\n",
+                            );
+                            if idx == 0 && flags.contains(FnFlags::HAS_SELF_PARAM) {
+                                w!(this, "self: ");
+                            }
+                            if idx != params.len() {
+                                this.print_type_ref(type_ref);
+                            } else {
+                                wln!(this, "...");
+                            }
+                            wln!(this, ",");
                         }
                     });
                 }
@@ -312,13 +310,19 @@ impl Printer<'_> {
                 }
             }
             ModItem::Struct(it) => {
-                let Struct { visibility, name, fields, generic_params, ast_id } = &self.tree[it];
+                let Struct { visibility, name, fields, shape: kind, generic_params, ast_id } =
+                    &self.tree[it];
                 self.print_ast_id(ast_id.erase());
                 self.print_visibility(*visibility);
                 w!(self, "struct {}", name.display(self.db.upcast()));
                 self.print_generic_params(generic_params, it.into());
-                self.print_fields_and_where_clause(fields, generic_params);
-                if matches!(fields, Fields::Record(_)) {
+                self.print_fields_and_where_clause(
+                    FieldParent::Struct(it),
+                    *kind,
+                    fields,
+                    generic_params,
+                );
+                if matches!(kind, FieldsShape::Record) {
                     wln!(self);
                 } else {
                     wln!(self, ";");
@@ -330,12 +334,13 @@ impl Printer<'_> {
                 self.print_visibility(*visibility);
                 w!(self, "union {}", name.display(self.db.upcast()));
                 self.print_generic_params(generic_params, it.into());
-                self.print_fields_and_where_clause(fields, generic_params);
-                if matches!(fields, Fields::Record(_)) {
-                    wln!(self);
-                } else {
-                    wln!(self, ";");
-                }
+                self.print_fields_and_where_clause(
+                    FieldParent::Union(it),
+                    FieldsShape::Record,
+                    fields,
+                    generic_params,
+                );
+                wln!(self);
             }
             ModItem::Enum(it) => {
                 let Enum { name, visibility, variants, generic_params, ast_id } = &self.tree[it];
@@ -346,11 +351,11 @@ impl Printer<'_> {
                 self.print_where_clause_and_opening_brace(generic_params);
                 self.indented(|this| {
                     for variant in FileItemTreeId::range_iter(variants.clone()) {
-                        let Variant { name, fields, ast_id } = &this.tree[variant];
+                        let Variant { name, fields, shape: kind, ast_id } = &this.tree[variant];
                         this.print_ast_id(ast_id.erase());
                         this.print_attrs_of(variant, "\n");
                         w!(this, "{}", name.display(self.db.upcast()));
-                        this.print_fields(fields);
+                        this.print_fields(FieldParent::Variant(variant), *kind, fields);
                         wln!(this, ",");
                     }
                 });
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
index 79bab11998bb6..c6930401a6f58 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
@@ -129,40 +129,34 @@ enum E {
             #[derive(Debug)]
             // AstId: 2
             pub(self) struct Struct {
-                // AstId: 6
                 #[doc = " fld docs"]
                 pub(self) fld: (),
             }
 
             // AstId: 3
             pub(self) struct Tuple(
-                // AstId: 7
                 #[attr]
                 pub(self) 0: u8,
             );
 
             // AstId: 4
             pub(self) union Ize {
-                // AstId: 8
                 pub(self) a: (),
-                // AstId: 9
                 pub(self) b: (),
             }
 
             // AstId: 5
             pub(self) enum E {
-                // AstId: 10
+                // AstId: 6
                 #[doc = " comment on Unit"]
                 Unit,
-                // AstId: 11
+                // AstId: 7
                 #[doc = " comment on Tuple"]
                 Tuple(
-                    // AstId: 13
                     pub(self) 0: u8,
                 ),
-                // AstId: 12
+                // AstId: 8
                 Struct {
-                    // AstId: 14
                     #[doc = " comment on a: u8"]
                     pub(self) a: u8,
                 },
@@ -201,9 +195,7 @@ trait Tr: SuperTrait + 'lifetime {
             // AstId: 3
             pub(self) fn f(
                 #[attr]
-                // AstId: 5
                 u8,
-                // AstId: 6
                 (),
             ) -> () { ... }
 
@@ -213,12 +205,11 @@ trait Tr: SuperTrait + 'lifetime {
                 Self: SuperTrait,
                 Self: 'lifetime
             {
-                // AstId: 8
+                // AstId: 6
                 pub(self) type Assoc: AssocBound = Default;
 
-                // AstId: 9
+                // AstId: 7
                 pub(self) fn method(
-                    // AstId: 10
                     self: &Self,
                 ) -> ();
             }
@@ -300,17 +291,11 @@ struct S {
         expect![[r#"
             // AstId: 1
             pub(self) struct S {
-                // AstId: 2
                 pub(self) a: self::Ty,
-                // AstId: 3
                 pub(self) b: super::SuperTy,
-                // AstId: 4
                 pub(self) c: super::super::SuperSuperTy,
-                // AstId: 5
                 pub(self) d: ::abs::Path,
-                // AstId: 6
                 pub(self) e: crate::Crate,
-                // AstId: 7
                 pub(self) f: plain::path::Ty,
             }
         "#]],
@@ -331,13 +316,9 @@ struct S {
         expect![[r#"
             // AstId: 1
             pub(self) struct S {
-                // AstId: 2
                 pub(self) a: Mixed::<'a, T, Item = (), OtherItem = u8>,
-                // AstId: 3
                 pub(self) b: Qualified::::Syntax,
-                // AstId: 4
                 pub(self) c: ::Path::<'a>,
-                // AstId: 5
                 pub(self) d: dyn for<'a> Trait::<'a>,
             }
         "#]],
@@ -371,15 +352,12 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
                 T: 'a,
                 T: 'b
             {
-                // AstId: 8
                 pub(self) field: &'a &'b T,
             }
 
             // AstId: 2
             pub(self) struct Tuple(
-                // AstId: 9
                 pub(self) 0: T,
-                // AstId: 10
                 pub(self) 1: U,
             )
             where
@@ -393,9 +371,8 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
                 T: 'a,
                 T: 'b
             {
-                // AstId: 12
+                // AstId: 9
                 pub(self) fn f(
-                    // AstId: 13
                     impl Copy,
                 ) -> impl Copy
                 where
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 58aca96429098..c51eea22dcb0e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -23,7 +23,7 @@ use itertools::{izip, Itertools};
 use la_arena::Idx;
 use limit::Limit;
 use rustc_hash::{FxHashMap, FxHashSet};
-use span::{Edition, EditionedFileId, ErasedFileAstId, FileAstId, SyntaxContextId};
+use span::{Edition, EditionedFileId, FileAstId, SyntaxContextId};
 use syntax::ast;
 use triomphe::Arc;
 
@@ -32,8 +32,8 @@ use crate::{
     db::DefDatabase,
     item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
     item_tree::{
-        self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
-        Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
+        self, AttrOwner, ExternCrate, FieldsShape, FileItemTreeId, ImportKind, ItemTree,
+        ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
     },
     macro_call_as_call_id, macro_call_as_call_id_with_eager,
     nameres::{
@@ -1580,10 +1580,7 @@ impl ModCollector<'_, '_> {
             let attrs = self.item_tree.attrs(db, krate, item.into());
             if let Some(cfg) = attrs.cfg() {
                 if !self.is_cfg_enabled(&cfg) {
-                    self.emit_unconfigured_diagnostic(
-                        InFile::new(self.file_id(), item.ast_id(self.item_tree).erase()),
-                        &cfg,
-                    );
+                    self.emit_unconfigured_diagnostic(self.tree_id, item.into(), &cfg);
                     return;
                 }
             }
@@ -1699,7 +1696,7 @@ impl ModCollector<'_, '_> {
                             .into(),
                         &it.name,
                         vis,
-                        !matches!(it.fields, Fields::Record(_)),
+                        !matches!(it.shape, FieldsShape::Record),
                     );
                 }
                 ModItem::Union(id) => {
@@ -1737,10 +1734,8 @@ impl ModCollector<'_, '_> {
                             match is_enabled {
                                 Err(cfg) => {
                                     self.emit_unconfigured_diagnostic(
-                                        InFile::new(
-                                            self.file_id(),
-                                            self.item_tree[variant.index()].ast_id.erase(),
-                                        ),
+                                        self.tree_id,
+                                        variant.into(),
                                         &cfg,
                                     );
                                     None
@@ -1956,7 +1951,8 @@ impl ModCollector<'_, '_> {
                         match is_enabled {
                             Err(cfg) => {
                                 self.emit_unconfigured_diagnostic(
-                                    ast_id.map(|it| it.erase()),
+                                    self.tree_id,
+                                    AttrOwner::TopLevel,
                                     &cfg,
                                 );
                             }
@@ -2402,10 +2398,11 @@ impl ModCollector<'_, '_> {
         self.def_collector.cfg_options.check(cfg) != Some(false)
     }
 
-    fn emit_unconfigured_diagnostic(&mut self, ast_id: InFile, cfg: &CfgExpr) {
+    fn emit_unconfigured_diagnostic(&mut self, tree_id: TreeId, item: AttrOwner, cfg: &CfgExpr) {
         self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
             self.module_id,
-            ast_id,
+            tree_id,
+            item,
             cfg.clone(),
             self.def_collector.cfg_options.clone(),
         ));
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
index 4ab53d20b57e6..e1bd6966f391e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
@@ -4,12 +4,12 @@ use std::ops::Not;
 
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
-use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
+use hir_expand::{attrs::AttrId, MacroCallKind};
 use la_arena::Idx;
 use syntax::ast;
 
 use crate::{
-    item_tree::{self, ItemTreeId},
+    item_tree::{self, AttrOwner, ItemTreeId, TreeId},
     nameres::LocalModuleId,
     path::ModPath,
     AstId,
@@ -29,7 +29,8 @@ pub enum DefDiagnosticKind {
         index: Idx,
     },
     UnconfiguredCode {
-        ast: ErasedAstId,
+        tree: TreeId,
+        item: AttrOwner,
         cfg: CfgExpr,
         opts: CfgOptions,
     },
@@ -116,11 +117,15 @@ impl DefDiagnostic {
 
     pub fn unconfigured_code(
         container: LocalModuleId,
-        ast: ErasedAstId,
+        tree: TreeId,
+        item: AttrOwner,
         cfg: CfgExpr,
         opts: CfgOptions,
     ) -> Self {
-        Self { in_module: container, kind: DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } }
+        Self {
+            in_module: container,
+            kind: DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts },
+        }
     }
 
     pub fn unresolved_proc_macro(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index e797d19223ed2..75cab137f78b5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -17,7 +17,7 @@ use triomphe::Arc;
 use crate::{
     db::DefDatabase,
     item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
-    item_tree::Fields,
+    item_tree::FieldsShape,
     nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
     path::{ModPath, PathKind},
     per_ns::PerNs,
@@ -381,11 +381,11 @@ impl DefMap {
                     .iter()
                     .find_map(|&variant| {
                         let variant_data = &tree[variant.lookup(db).id.value];
-                        (variant_data.name == *segment).then(|| match variant_data.fields {
-                            Fields::Record(_) => {
+                        (variant_data.name == *segment).then(|| match variant_data.shape {
+                            FieldsShape::Record => {
                                 PerNs::types(variant.into(), Visibility::Public, None)
                             }
-                            Fields::Tuple(_) | Fields::Unit => PerNs::both(
+                            FieldsShape::Tuple | FieldsShape::Unit => PerNs::both(
                                 variant.into(),
                                 variant.into(),
                                 Visibility::Public,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/src.rs b/src/tools/rust-analyzer/crates/hir-def/src/src.rs
index a0d2079e0d41d..6db20870cf693 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/src.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/src.rs
@@ -6,9 +6,12 @@ use la_arena::ArenaMap;
 use syntax::{ast, AstNode, AstPtr};
 
 use crate::{
-    data::adt::lower_struct, db::DefDatabase, item_tree::ItemTreeNode, trace::Trace, GenericDefId,
-    ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup, UseId,
-    VariantId,
+    data::adt::lower_struct,
+    db::DefDatabase,
+    item_tree::{FieldParent, ItemTreeNode},
+    trace::Trace,
+    GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
+    UseId, VariantId,
 };
 
 pub trait HasSource {
@@ -124,13 +127,13 @@ impl HasChildSource for VariantId {
 
     fn child_source(&self, db: &dyn DefDatabase) -> InFile> {
         let item_tree;
-        let (src, fields, container) = match *self {
+        let (src, parent, container) = match *self {
             VariantId::EnumVariantId(it) => {
                 let lookup = it.lookup(db);
                 item_tree = lookup.id.item_tree(db);
                 (
                     lookup.source(db).map(|it| it.kind()),
-                    &item_tree[lookup.id.value].fields,
+                    FieldParent::Variant(lookup.id.value),
                     lookup.parent.lookup(db).container,
                 )
             }
@@ -139,7 +142,7 @@ impl HasChildSource for VariantId {
                 item_tree = lookup.id.item_tree(db);
                 (
                     lookup.source(db).map(|it| it.kind()),
-                    &item_tree[lookup.id.value].fields,
+                    FieldParent::Struct(lookup.id.value),
                     lookup.container,
                 )
             }
@@ -148,13 +151,13 @@ impl HasChildSource for VariantId {
                 item_tree = lookup.id.item_tree(db);
                 (
                     lookup.source(db).map(|it| it.kind()),
-                    &item_tree[lookup.id.value].fields,
+                    FieldParent::Union(lookup.id.value),
                     lookup.container,
                 )
             }
         };
         let mut trace = Trace::new_for_map();
-        lower_struct(db, &mut trace, &src, container.krate, &item_tree, fields);
+        lower_struct(db, &mut trace, &src, container.krate, &item_tree, parent);
         src.with_value(trace.into_map())
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 82f4ad01e0189..284291bb9ad91 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -812,7 +812,9 @@ impl<'a> InferenceContext<'a> {
                 None => self.err_ty(),
             };
 
-            param_tys.push(va_list_ty)
+            if let Some(ty) = param_tys.last_mut() {
+                *ty = va_list_ty;
+            }
         }
         let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var()));
         if let Some(self_param) = self.body.self_param {
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index f80ccf84a2c5a..a40022c43a101 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -99,7 +99,13 @@ impl HirDisplay for Function {
         }
 
         // FIXME: Use resolved `param.ty` once we no longer discard lifetimes
-        for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) {
+        for (type_ref, param) in data
+            .params
+            .iter()
+            .zip(self.assoc_fn_params(db))
+            .take(data.params.len() - data.is_varargs() as usize)
+            .skip(skip_self)
+        {
             let local = param.as_local(db).map(|it| it.name(db));
             if !first {
                 f.write_str(", ")?;
@@ -114,7 +120,10 @@ impl HirDisplay for Function {
         }
 
         if data.is_varargs() {
-            f.write_str(", ...")?;
+            if !first {
+                f.write_str(", ")?;
+            }
+            f.write_str("...")?;
         }
 
         f.write_char(')')?;
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index dd9f1e880369b..70f4a632fb3ec 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -44,7 +44,7 @@ use hir_def::{
     data::adt::VariantData,
     generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
     hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
-    item_tree::ItemTreeNode,
+    item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
     lang_item::LangItemTarget,
     layout::{self, ReprOptions, TargetDataLayout},
     nameres::{self, diagnostics::DefDiagnostic},
@@ -81,7 +81,7 @@ use rustc_hash::FxHashSet;
 use span::{Edition, EditionedFileId, FileId, MacroCallId};
 use stdx::{impl_from, never};
 use syntax::{
-    ast::{self, HasAttrs as _, HasName},
+    ast::{self, HasAttrs as _, HasGenericParams, HasName},
     format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T,
 };
 use triomphe::Arc;
@@ -906,12 +906,90 @@ fn emit_def_diagnostic_(
             );
         }
 
-        DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
-            let item = ast.to_ptr(db.upcast());
-            acc.push(
-                InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() }
+        DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => {
+            let item_tree = tree.item_tree(db.upcast());
+            let ast_id_map = db.ast_id_map(tree.file_id());
+            // FIXME: This parses... We could probably store relative ranges for the children things
+            // here in the item tree?
+            (|| {
+                let process_field_list =
+                    |field_list: Option<_>, idx: ItemTreeFieldId| match field_list? {
+                        ast::FieldList::RecordFieldList(it) => Some(SyntaxNodePtr::new(
+                            it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(),
+                        )),
+                        ast::FieldList::TupleFieldList(it) => Some(SyntaxNodePtr::new(
+                            it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(),
+                        )),
+                    };
+                let ptr = match *item {
+                    AttrOwner::ModItem(it) => {
+                        ast_id_map.get(it.ast_id(&item_tree)).syntax_node_ptr()
+                    }
+                    AttrOwner::TopLevel => ast_id_map.root(),
+                    AttrOwner::Variant(it) => {
+                        ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr()
+                    }
+                    AttrOwner::Field(FieldParent::Variant(parent), idx) => process_field_list(
+                        ast_id_map
+                            .get(item_tree[parent].ast_id)
+                            .to_node(&db.parse_or_expand(tree.file_id()))
+                            .field_list(),
+                        idx,
+                    )?,
+                    AttrOwner::Field(FieldParent::Struct(parent), idx) => process_field_list(
+                        ast_id_map
+                            .get(item_tree[parent.index()].ast_id)
+                            .to_node(&db.parse_or_expand(tree.file_id()))
+                            .field_list(),
+                        idx,
+                    )?,
+                    AttrOwner::Field(FieldParent::Union(parent), idx) => SyntaxNodePtr::new(
+                        ast_id_map
+                            .get(item_tree[parent.index()].ast_id)
+                            .to_node(&db.parse_or_expand(tree.file_id()))
+                            .record_field_list()?
+                            .fields()
+                            .nth(idx.into_raw().into_u32() as usize)?
+                            .syntax(),
+                    ),
+                    AttrOwner::Param(parent, idx) => SyntaxNodePtr::new(
+                        ast_id_map
+                            .get(item_tree[parent.index()].ast_id)
+                            .to_node(&db.parse_or_expand(tree.file_id()))
+                            .param_list()?
+                            .params()
+                            .nth(idx.into_raw().into_u32() as usize)?
+                            .syntax(),
+                    ),
+                    AttrOwner::TypeOrConstParamData(parent, idx) => SyntaxNodePtr::new(
+                        ast_id_map
+                            .get(parent.ast_id(&item_tree))
+                            .to_node(&db.parse_or_expand(tree.file_id()))
+                            .generic_param_list()?
+                            .type_or_const_params()
+                            .nth(idx.into_raw().into_u32() as usize)?
+                            .syntax(),
+                    ),
+                    AttrOwner::LifetimeParamData(parent, idx) => SyntaxNodePtr::new(
+                        ast_id_map
+                            .get(parent.ast_id(&item_tree))
+                            .to_node(&db.parse_or_expand(tree.file_id()))
+                            .generic_param_list()?
+                            .lifetime_params()
+                            .nth(idx.into_raw().into_u32() as usize)?
+                            .syntax(),
+                    ),
+                };
+                acc.push(
+                    InactiveCode {
+                        node: InFile::new(tree.file_id(), ptr),
+                        cfg: cfg.clone(),
+                        opts: opts.clone(),
+                    }
                     .into(),
-            );
+                );
+                Some(())
+            })();
         }
         DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
             let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
diff --git a/src/tools/rust-analyzer/crates/span/src/ast_id.rs b/src/tools/rust-analyzer/crates/span/src/ast_id.rs
index 332745aae6e95..b61baa224465f 100644
--- a/src/tools/rust-analyzer/crates/span/src/ast_id.rs
+++ b/src/tools/rust-analyzer/crates/span/src/ast_id.rs
@@ -80,13 +80,11 @@ macro_rules! register_ast_id_node {
 }
 register_ast_id_node! {
     impl AstIdNode for
-    Item,
+    Item, AnyHasGenericParams,
         Adt,
             Enum,
                 Variant,
             Struct,
-                RecordField,
-                TupleField,
             Union,
         AssocItem,
             Const,
@@ -104,7 +102,7 @@ register_ast_id_node! {
         Trait,
         TraitAlias,
         Use,
-    BlockExpr, ConstArg, Param, SelfParam
+    BlockExpr, ConstArg
 }
 
 /// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.

From 9a5e41c56fbd61c5af4626cbd03935115cfaaa38 Mon Sep 17 00:00:00 2001
From: yukang 
Date: Fri, 19 Jul 2024 14:55:27 +0800
Subject: [PATCH 134/489] add testcase for 127868

---
 ...ched-delimiter-corner-case-issue-127868.rs |  7 +++
 ...-delimiter-corner-case-issue-127868.stderr | 45 +++++++++++++++++++
 2 files changed, 52 insertions(+)
 create mode 100644 tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs
 create mode 100644 tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr

diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs
new file mode 100644
index 0000000000000..edf619664e32d
--- /dev/null
+++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs
@@ -0,0 +1,7 @@
+// ignore-tidy-trailing-newlines
+// issue: rust-lang/rust#127868
+
+fn main() {
+    let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,;
+} //~ ERROR mismatched closing delimiter: `}`
+//~ ERROR this file contains an unclosed delimiter
\ No newline at end of file
diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr
new file mode 100644
index 0000000000000..95e2bf916425a
--- /dev/null
+++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr
@@ -0,0 +1,45 @@
+error: mismatched closing delimiter: `}`
+  --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:5:42
+   |
+LL | fn main() {
+   |           - closing delimiter possibly meant for this
+LL |     let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,;
+   |                                          ^ unclosed delimiter
+LL | }
+   | ^ mismatched closing delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:7:51
+   |
+LL | fn main() {
+   |           - unclosed delimiter
+LL |     let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,;
+   |             --------------------   - this delimiter might not be properly closed...
+   |             ||||||||||||||||||||
+   |             |||||||||||||||||||unclosed delimiter
+   |             ||||||||||||||||||unclosed delimiter
+   |             |||||||||||||||||unclosed delimiter
+   |             ||||||||||||||||unclosed delimiter
+   |             |||||||||||||||unclosed delimiter
+   |             ||||||||||||||unclosed delimiter
+   |             |||||||||||||unclosed delimiter
+   |             ||||||||||||unclosed delimiter
+   |             |||||||||||unclosed delimiter
+   |             ||||||||||unclosed delimiter
+   |             |||||||||unclosed delimiter
+   |             ||||||||unclosed delimiter
+   |             |||||||unclosed delimiter
+   |             ||||||unclosed delimiter
+   |             |||||unclosed delimiter
+   |             ||||unclosed delimiter
+   |             |||unclosed delimiter
+   |             ||unclosed delimiter
+   |             |unclosed delimiter
+   |             unclosed delimiter
+LL | }
+   | - ...as it matches this but it has different indentation
+LL |
+   |                                                   ^
+
+error: aborting due to 2 previous errors
+

From 94a3fd7678240f7a8f3cb331e44d7c18009be95e Mon Sep 17 00:00:00 2001
From: yukang 
Date: Fri, 19 Jul 2024 14:58:16 +0800
Subject: [PATCH 135/489] add limit for unclosed delimiters in lexer diagnostic

---
 compiler/rustc_parse/src/lexer/tokentrees.rs  | 21 +++++++++++++---
 tests/ui/parser/brace-in-let-chain.stderr     |  8 +-----
 ...ched-delimiter-corner-case-issue-127868.rs |  3 +--
 ...-delimiter-corner-case-issue-127868.stderr | 25 ++++---------------
 4 files changed, 25 insertions(+), 32 deletions(-)

diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 8e54345469133..fc6257d809062 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -72,16 +72,31 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> {
     fn eof_err(&mut self) -> PErr<'psess> {
         let msg = "this file contains an unclosed delimiter";
         let mut err = self.string_reader.dcx().struct_span_err(self.token.span, msg);
-        for &(_, sp) in &self.diag_info.open_braces {
-            err.span_label(sp, "unclosed delimiter");
+
+        let unclosed_delimiter_show_limit = 5;
+        let len = usize::min(unclosed_delimiter_show_limit, self.diag_info.open_braces.len());
+        for &(_, span) in &self.diag_info.open_braces[..len] {
+            err.span_label(span, "unclosed delimiter");
             self.diag_info.unmatched_delims.push(UnmatchedDelim {
                 found_delim: None,
                 found_span: self.token.span,
-                unclosed_span: Some(sp),
+                unclosed_span: Some(span),
                 candidate_span: None,
             });
         }
 
+        if let Some((_, span)) = self.diag_info.open_braces.get(unclosed_delimiter_show_limit)
+            && self.diag_info.open_braces.len() >= unclosed_delimiter_show_limit + 2
+        {
+            err.span_label(
+                *span,
+                format!(
+                    "another {} unclosed delimiters begin from here",
+                    self.diag_info.open_braces.len() - unclosed_delimiter_show_limit
+                ),
+            );
+        }
+
         if let Some((delim, _)) = self.diag_info.open_braces.last() {
             report_suspicious_mismatch_block(
                 &mut err,
diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr
index d76cb25ad8b84..913a34700dfc9 100644
--- a/tests/ui/parser/brace-in-let-chain.stderr
+++ b/tests/ui/parser/brace-in-let-chain.stderr
@@ -17,14 +17,8 @@ LL | fn qux() {
    |          - unclosed delimiter
 ...
 LL | fn foo() {
-   |          - unclosed delimiter
-...
-LL | fn bar() {
-   |          - unclosed delimiter
+   |          - another 3 unclosed delimiters begin from here
 ...
-LL | fn baz() {
-   |          - unclosed delimiter
-LL |     if false {
 LL |         {
    |         - this delimiter might not be properly closed...
 LL |             && let () = ()
diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs
index edf619664e32d..5dcaa2663252b 100644
--- a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs
+++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.rs
@@ -1,7 +1,6 @@
-// ignore-tidy-trailing-newlines
 // issue: rust-lang/rust#127868
 
 fn main() {
     let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,;
 } //~ ERROR mismatched closing delimiter: `}`
-//~ ERROR this file contains an unclosed delimiter
\ No newline at end of file
+//~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr
index 95e2bf916425a..94e25c18e4010 100644
--- a/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr
+++ b/tests/ui/parser/mismatched-delimiter-corner-case-issue-127868.stderr
@@ -1,5 +1,5 @@
 error: mismatched closing delimiter: `}`
-  --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:5:42
+  --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:4:42
    |
 LL | fn main() {
    |           - closing delimiter possibly meant for this
@@ -9,29 +9,14 @@ LL | }
    | ^ mismatched closing delimiter
 
 error: this file contains an unclosed delimiter
-  --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:7:51
+  --> $DIR/mismatched-delimiter-corner-case-issue-127868.rs:6:52
    |
 LL | fn main() {
    |           - unclosed delimiter
 LL |     let a = [[[[[[[[[[[[[[[[[[[[1, {, (, [,;
-   |             --------------------   - this delimiter might not be properly closed...
-   |             ||||||||||||||||||||
-   |             |||||||||||||||||||unclosed delimiter
-   |             ||||||||||||||||||unclosed delimiter
-   |             |||||||||||||||||unclosed delimiter
-   |             ||||||||||||||||unclosed delimiter
-   |             |||||||||||||||unclosed delimiter
-   |             ||||||||||||||unclosed delimiter
-   |             |||||||||||||unclosed delimiter
-   |             ||||||||||||unclosed delimiter
-   |             |||||||||||unclosed delimiter
-   |             ||||||||||unclosed delimiter
-   |             |||||||||unclosed delimiter
-   |             ||||||||unclosed delimiter
-   |             |||||||unclosed delimiter
-   |             ||||||unclosed delimiter
-   |             |||||unclosed delimiter
-   |             ||||unclosed delimiter
+   |             -----                  - this delimiter might not be properly closed...
+   |             |||||
+   |             ||||another 16 unclosed delimiters begin from here
    |             |||unclosed delimiter
    |             ||unclosed delimiter
    |             |unclosed delimiter

From d744b7c71b8fa098a852e89371639c5504c5f230 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 25 Jul 2024 11:02:19 +0200
Subject: [PATCH 136/489] Fix incorrect handling of cfg'd varargs

---
 .../rust-analyzer/crates/hir-def/src/data.rs    | 13 ++++++++++++-
 .../crates/hir-def/src/item_tree.rs             |  2 +-
 .../crates/hir-def/src/item_tree/lower.rs       |  6 +++---
 .../crates/hir-def/src/item_tree/pretty.rs      |  2 +-
 .../rust-analyzer/crates/hir-ty/src/infer.rs    |  4 +---
 .../crates/hir-ty/src/tests/patterns.rs         | 17 +++++++++++++++++
 .../rust-analyzer/crates/hir/src/display.rs     |  8 +-------
 .../crates/intern/src/symbol/symbols.rs         |  1 +
 8 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index a03140e2a92d6..3f862f69f8e0a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -73,6 +73,17 @@ impl FunctionData {
                 flags.remove(FnFlags::HAS_SELF_PARAM);
             }
         }
+        if flags.contains(FnFlags::IS_VARARGS) {
+            if let Some((_, param)) = func.params.iter().enumerate().rev().find(|&(idx, _)| {
+                item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options)
+            }) {
+                if param.type_ref.is_some() {
+                    flags.remove(FnFlags::IS_VARARGS);
+                }
+            } else {
+                flags.remove(FnFlags::IS_VARARGS);
+            }
+        }
 
         let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
         let legacy_const_generics_indices = attrs
@@ -92,7 +103,7 @@ impl FunctionData {
                 .filter(|&(idx, _)| {
                     item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options)
                 })
-                .map(|(_, param)| param.type_ref.clone())
+                .filter_map(|(_, param)| param.type_ref.clone())
                 .collect(),
             ret_type: func.ret_type.clone(),
             attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index f6709680d0cdd..28eebb286ed4b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -741,7 +741,7 @@ pub struct Function {
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Param {
-    pub type_ref: Interned,
+    pub type_ref: Option>,
 }
 
 bitflags::bitflags! {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index c9e9719c909dc..7aac383ab4796 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -380,7 +380,7 @@ impl<'a> Ctx<'a> {
                     }
                 };
                 let type_ref = Interned::new(self_type);
-                params.push(Param { type_ref });
+                params.push(Param { type_ref: Some(type_ref) });
                 has_self_param = true;
             }
             for param in param_list.params() {
@@ -388,12 +388,12 @@ impl<'a> Ctx<'a> {
                 let param = match param.dotdotdot_token() {
                     Some(_) => {
                         has_var_args = true;
-                        Param { type_ref: Interned::new(TypeRef::Error) }
+                        Param { type_ref: None }
                     }
                     None => {
                         let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
                         let ty = Interned::new(type_ref);
-                        Param { type_ref: ty }
+                        Param { type_ref: Some(ty) }
                     }
                 };
                 params.push(param);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index 5eeb8607b9609..740759e6e3948 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -291,7 +291,7 @@ impl Printer<'_> {
                             if idx == 0 && flags.contains(FnFlags::HAS_SELF_PARAM) {
                                 w!(this, "self: ");
                             }
-                            if idx != params.len() {
+                            if let Some(type_ref) = type_ref {
                                 this.print_type_ref(type_ref);
                             } else {
                                 wln!(this, "...");
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 284291bb9ad91..804bc53905ad7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -812,9 +812,7 @@ impl<'a> InferenceContext<'a> {
                 None => self.err_ty(),
             };
 
-            if let Some(ty) = param_tys.last_mut() {
-                *ty = va_list_ty;
-            }
+            param_tys.push(va_list_ty);
         }
         let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var()));
         if let Some(self_param) = self.body.self_param {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
index 1c1f7055efddc..57866acc06374 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
@@ -1126,6 +1126,23 @@ fn var_args() {
 pub struct VaListImpl<'f>;
 fn my_fn(foo: ...) {}
        //^^^ VaListImpl<'?>
+fn my_fn2(bar: u32, foo: ...) {}
+                  //^^^ VaListImpl<'?>
+"#,
+    );
+}
+
+#[test]
+fn var_args_cond() {
+    check_types(
+        r#"
+#[lang = "va_list"]
+pub struct VaListImpl<'f>;
+fn my_fn(bar: u32, #[cfg(FALSE)] foo: ..., #[cfg(not(FALSE))] foo: u32) {
+    foo;
+  //^^^ u32
+
+}
 "#,
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index a40022c43a101..7def828e95f3c 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -99,13 +99,7 @@ impl HirDisplay for Function {
         }
 
         // FIXME: Use resolved `param.ty` once we no longer discard lifetimes
-        for (type_ref, param) in data
-            .params
-            .iter()
-            .zip(self.assoc_fn_params(db))
-            .take(data.params.len() - data.is_varargs() as usize)
-            .skip(skip_self)
-        {
+        for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) {
             let local = param.as_local(db).map(|it| it.name(db));
             if !first {
                 f.write_str(", ")?;
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index d810fac36aaba..2feca32ff8686 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -56,6 +56,7 @@ macro_rules! define_symbols {
 define_symbols! {
     @WITH_NAME:
 
+    dotdotdot = "...",
     INTEGER_0 = "0",
     INTEGER_1 = "1",
     INTEGER_2 = "2",

From b3f5af205d6d034e4491d5888d928717b8fca82a Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 25 Jul 2024 11:14:55 +0200
Subject: [PATCH 137/489] Reduce size of TypeRef by 8 bytes

---
 .../crates/hir-def/src/hir/type_ref.rs         | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
index 9b0543225881f..4cca42ed1ab48 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
@@ -121,7 +121,7 @@ pub enum TypeRef {
     Slice(Box),
     /// A fn pointer. Last element of the vector is the return type.
     Fn(
-        Vec<(Option, TypeRef)>,
+        Box<[(Option, TypeRef)]>,
         bool,           /*varargs*/
         bool,           /*is_unsafe*/
         Option, /* abi */
@@ -228,7 +228,7 @@ impl TypeRef {
                         })
                         .collect()
                 } else {
-                    Vec::new()
+                    Vec::with_capacity(1)
                 };
                 fn lower_abi(abi: ast::Abi) -> Symbol {
                     match abi.abi_string() {
@@ -240,7 +240,7 @@ impl TypeRef {
 
                 let abi = inner.abi().map(lower_abi);
                 params.push((None, ret_ty));
-                TypeRef::Fn(params, is_varargs, inner.unsafe_token().is_some(), abi)
+                TypeRef::Fn(params.into(), is_varargs, inner.unsafe_token().is_some(), abi)
             }
             // for types are close enough for our purposes to the inner type for now...
             ast::Type::ForType(inner) => TypeRef::from_ast_opt(ctx, inner.ty()),
@@ -396,7 +396,7 @@ impl TypeBound {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum ConstRef {
-    Scalar(LiteralConstRef),
+    Scalar(Box),
     Path(Name),
     Complex(AstId),
 }
@@ -408,7 +408,7 @@ impl ConstRef {
                 return Self::from_expr(expr, Some(lower_ctx.ast_id(&arg)));
             }
         }
-        Self::Scalar(LiteralConstRef::Unknown)
+        Self::Scalar(Box::new(LiteralConstRef::Unknown))
     }
 
     pub(crate) fn from_const_param(
@@ -452,10 +452,10 @@ impl ConstRef {
             ast::Expr::PathExpr(p) if is_path_ident(&p) => {
                 match p.path().and_then(|it| it.segment()).and_then(|it| it.name_ref()) {
                     Some(it) => Self::Path(it.as_name()),
-                    None => Self::Scalar(LiteralConstRef::Unknown),
+                    None => Self::Scalar(Box::new(LiteralConstRef::Unknown)),
                 }
             }
-            ast::Expr::Literal(literal) => Self::Scalar(match literal.kind() {
+            ast::Expr::Literal(literal) => Self::Scalar(Box::new(match literal.kind() {
                 ast::LiteralKind::IntNumber(num) => {
                     num.value().map(LiteralConstRef::UInt).unwrap_or(LiteralConstRef::Unknown)
                 }
@@ -464,12 +464,12 @@ impl ConstRef {
                 }
                 ast::LiteralKind::Bool(f) => LiteralConstRef::Bool(f),
                 _ => LiteralConstRef::Unknown,
-            }),
+            })),
             _ => {
                 if let Some(ast_id) = ast_id {
                     Self::Complex(ast_id)
                 } else {
-                    Self::Scalar(LiteralConstRef::Unknown)
+                    Self::Scalar(Box::new(LiteralConstRef::Unknown))
                 }
             }
         }

From 08f7e164ccb854444bc0e28a7f4c873f52df5ad2 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 25 Jul 2024 11:35:30 +0200
Subject: [PATCH 138/489] Make legacy_const_generics_indices thin by double
 boxing as its seldom used

---
 src/tools/rust-analyzer/crates/hir-def/src/data.rs   |  5 +++--
 .../rust-analyzer/crates/hir-ty/src/infer/expr.rs    | 12 ++++++------
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 3f862f69f8e0a..3a3b540c13251 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -40,7 +40,7 @@ pub struct FunctionData {
     pub attrs: Attrs,
     pub visibility: RawVisibility,
     pub abi: Option,
-    pub legacy_const_generics_indices: Box<[u32]>,
+    pub legacy_const_generics_indices: Option>>,
     pub rustc_allow_incoherent_impl: bool,
     flags: FnFlags,
 }
@@ -91,7 +91,8 @@ impl FunctionData {
             .tt_values()
             .next()
             .map(parse_rustc_legacy_const_generics)
-            .unwrap_or_default();
+            .filter(|it| !it.is_empty())
+            .map(Box::new);
         let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
 
         Arc::new(FunctionData {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 87233fa0113cb..24479a027fd6e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -1950,25 +1950,25 @@ impl InferenceContext<'_> {
         };
 
         let data = self.db.function_data(func);
-        if data.legacy_const_generics_indices.is_empty() {
+        let Some(legacy_const_generics_indices) = &data.legacy_const_generics_indices else {
             return Default::default();
-        }
+        };
 
         // only use legacy const generics if the param count matches with them
-        if data.params.len() + data.legacy_const_generics_indices.len() != args.len() {
+        if data.params.len() + legacy_const_generics_indices.len() != args.len() {
             if args.len() <= data.params.len() {
                 return Default::default();
             } else {
                 // there are more parameters than there should be without legacy
                 // const params; use them
-                let mut indices = data.legacy_const_generics_indices.clone();
+                let mut indices = legacy_const_generics_indices.as_ref().clone();
                 indices.sort();
                 return indices;
             }
         }
 
         // check legacy const parameters
-        for (subst_idx, arg_idx) in data.legacy_const_generics_indices.iter().copied().enumerate() {
+        for (subst_idx, arg_idx) in legacy_const_generics_indices.iter().copied().enumerate() {
             let arg = match subst.at(Interner, subst_idx).constant(Interner) {
                 Some(c) => c,
                 None => continue, // not a const parameter?
@@ -1981,7 +1981,7 @@ impl InferenceContext<'_> {
             self.infer_expr(args[arg_idx as usize], &expected);
             // FIXME: evaluate and unify with the const
         }
-        let mut indices = data.legacy_const_generics_indices.clone();
+        let mut indices = legacy_const_generics_indices.as_ref().clone();
         indices.sort();
         indices
     }

From 516a1b47b4ac4c4201e955a8a4dfc28bf605e109 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 25 Jul 2024 12:28:31 +0200
Subject: [PATCH 139/489] fix: Support new cargo config get env format

---
 .../crates/project-model/src/env.rs              | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs
index 88fb10a68c617..3df46e1e37d9c 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/env.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs
@@ -75,14 +75,26 @@ pub(crate) fn cargo_config_env(
     }
     // if successful we receive `env.key.value = "value" per entry
     tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
-    utf8_stdout(cargo_config).map(parse_output_cargo_config_env).unwrap_or_default()
+    utf8_stdout(cargo_config)
+        .map(parse_output_cargo_config_env)
+        .inspect(|env| {
+            tracing::debug!("Discovered cargo config env: {:?}", env);
+        })
+        .inspect_err(|err| {
+            tracing::error!("Failed to discover cargo config env: {:?}", err);
+        })
+        .unwrap_or_default()
 }
 
 fn parse_output_cargo_config_env(stdout: String) -> FxHashMap {
     stdout
         .lines()
         .filter_map(|l| l.strip_prefix("env."))
-        .filter_map(|l| l.split_once(".value = "))
+        .filter_map(|l| {
+            l.split_once(" = ")
+                // cargo used to report it with this, keep it for a couple releases around
+                .or_else(|| l.split_once(".value = "))
+        })
         .map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
         .collect()
 }

From 71e3d882816c2f9dd75f0eea13edf8487fd23ecd Mon Sep 17 00:00:00 2001
From: "Winston H." <56998716+winstxnhdw@users.noreply.github.com>
Date: Thu, 25 Jul 2024 10:58:25 +0000
Subject: [PATCH 140/489] fix: handle new `TypeBoundKind` variant

---
 src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
index 9b0543225881f..59ebf9c299b85 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
@@ -379,6 +379,7 @@ impl TypeBound {
                     None => TypeBound::Error,
                 }
             }
+            ast::TypeBoundKind::Use(_) => TypeBound::Error,
             ast::TypeBoundKind::Lifetime(lifetime) => {
                 TypeBound::Lifetime(LifetimeRef::new(&lifetime))
             }

From 4ffc969ecf33df3db5adf8123732f3c6f2b820fa Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Thu, 25 Jul 2024 14:08:48 +0200
Subject: [PATCH 141/489] Remove unused trace module

---
 .../crates/hir-def/src/data/adt.rs            | 66 +------------------
 .../rust-analyzer/crates/hir-def/src/lib.rs   |  1 -
 .../rust-analyzer/crates/hir-def/src/src.rs   | 51 ++++++++++++--
 .../rust-analyzer/crates/hir-def/src/trace.rs | 55 ----------------
 4 files changed, 46 insertions(+), 127 deletions(-)
 delete mode 100644 src/tools/rust-analyzer/crates/hir-def/src/trace.rs

diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
index 827cce706be6a..a70710e565c27 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
@@ -5,14 +5,10 @@ use bitflags::bitflags;
 use cfg::CfgOptions;
 use either::Either;
 
-use hir_expand::{
-    name::{AsName, Name},
-    InFile,
-};
+use hir_expand::name::Name;
 use intern::{sym, Interned};
 use la_arena::Arena;
 use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
-use syntax::ast::{self, HasName, HasVisibility};
 use triomphe::Arc;
 
 use crate::{
@@ -22,9 +18,7 @@ use crate::{
         AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibilityId, TreeId,
     },
     lang_item::LangItem,
-    lower::LowerCtx,
     nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
-    trace::Trace,
     tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
     type_ref::TypeRef,
     visibility::RawVisibility,
@@ -409,64 +403,6 @@ pub enum StructKind {
     Unit,
 }
 
-// FIXME This is only used for mapping back source now?
-pub(crate) fn lower_struct(
-    db: &dyn DefDatabase,
-    trace: &mut Trace>,
-    ast: &InFile,
-    krate: CrateId,
-    item_tree: &ItemTree,
-    parent: FieldParent,
-) -> StructKind {
-    let ctx = LowerCtx::new(db, ast.file_id);
-
-    match &ast.value {
-        ast::StructKind::Tuple(fl) => {
-            let cfg_options = &db.crate_graph()[krate].cfg_options;
-            for (i, fd) in fl.fields().enumerate() {
-                let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, i));
-                if !attrs.is_cfg_enabled(cfg_options) {
-                    continue;
-                }
-
-                trace.alloc(
-                    || Either::Left(fd.clone()),
-                    || FieldData {
-                        name: Name::new_tuple_field(i),
-                        type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
-                        visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
-                            ctx.span_map().span_for_range(range).ctx
-                        }),
-                    },
-                );
-            }
-            StructKind::Tuple
-        }
-        ast::StructKind::Record(fl) => {
-            let cfg_options = &db.crate_graph()[krate].cfg_options;
-            for (i, fd) in fl.fields().enumerate() {
-                let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, i));
-                if !attrs.is_cfg_enabled(cfg_options) {
-                    continue;
-                }
-
-                trace.alloc(
-                    || Either::Right(fd.clone()),
-                    || FieldData {
-                        name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
-                        type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
-                        visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
-                            ctx.span_map().span_for_range(range).ctx
-                        }),
-                    },
-                );
-            }
-            StructKind::Record
-        }
-        _ => StructKind::Unit,
-    }
-}
-
 fn lower_fields(
     db: &dyn DefDatabase,
     krate: CrateId,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index a33e681cb5a76..e96581e1b3039 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -46,7 +46,6 @@ pub mod body;
 pub mod resolver;
 
 pub mod nameres;
-mod trace;
 
 pub mod child_by_source;
 pub mod src;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/src.rs b/src/tools/rust-analyzer/crates/hir-def/src/src.rs
index 6db20870cf693..c7ebfeecf5141 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/src.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/src.rs
@@ -6,10 +6,8 @@ use la_arena::ArenaMap;
 use syntax::{ast, AstNode, AstPtr};
 
 use crate::{
-    data::adt::lower_struct,
     db::DefDatabase,
-    item_tree::{FieldParent, ItemTreeNode},
-    trace::Trace,
+    item_tree::{AttrOwner, FieldParent, ItemTreeNode},
     GenericDefId, ItemTreeLoc, LocalFieldId, LocalLifetimeParamId, LocalTypeOrConstParamId, Lookup,
     UseId, VariantId,
 };
@@ -156,8 +154,49 @@ impl HasChildSource for VariantId {
                 )
             }
         };
-        let mut trace = Trace::new_for_map();
-        lower_struct(db, &mut trace, &src, container.krate, &item_tree, parent);
-        src.with_value(trace.into_map())
+
+        let mut map = ArenaMap::new();
+        match &src.value {
+            ast::StructKind::Tuple(fl) => {
+                let cfg_options = &db.crate_graph()[container.krate].cfg_options;
+                let mut idx = 0;
+                for (i, fd) in fl.fields().enumerate() {
+                    let attrs = item_tree.attrs(
+                        db,
+                        container.krate,
+                        AttrOwner::make_field_indexed(parent, i),
+                    );
+                    if !attrs.is_cfg_enabled(cfg_options) {
+                        continue;
+                    }
+                    map.insert(
+                        LocalFieldId::from_raw(la_arena::RawIdx::from(idx)),
+                        Either::Left(fd.clone()),
+                    );
+                    idx += 1;
+                }
+            }
+            ast::StructKind::Record(fl) => {
+                let cfg_options = &db.crate_graph()[container.krate].cfg_options;
+                let mut idx = 0;
+                for (i, fd) in fl.fields().enumerate() {
+                    let attrs = item_tree.attrs(
+                        db,
+                        container.krate,
+                        AttrOwner::make_field_indexed(parent, i),
+                    );
+                    if !attrs.is_cfg_enabled(cfg_options) {
+                        continue;
+                    }
+                    map.insert(
+                        LocalFieldId::from_raw(la_arena::RawIdx::from(idx)),
+                        Either::Right(fd.clone()),
+                    );
+                    idx += 1;
+                }
+            }
+            _ => (),
+        }
+        InFile::new(src.file_id, map)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/trace.rs b/src/tools/rust-analyzer/crates/hir-def/src/trace.rs
deleted file mode 100644
index da50ee8dc7a3f..0000000000000
--- a/src/tools/rust-analyzer/crates/hir-def/src/trace.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-//! Trace is a pretty niche data structure which is used when lowering a CST
-//! into HIR.
-//!
-//! Lowering process calculates two bits of information:
-//! * the lowered syntax itself
-//! * a mapping between lowered syntax and original syntax
-//!
-//! Due to the way salsa works, the mapping is usually hot lava, as it contains
-//! absolute offsets. The `Trace` structure (inspired, at least in name, by
-//! Kotlin's `BindingTrace`) allows use the same code to compute both
-//! projections.
-use la_arena::{Arena, ArenaMap, Idx, RawIdx};
-
-// FIXME: This isn't really used anymore, at least not in a way where it does anything useful.
-// Check if we should get rid of this or make proper use of it instead.
-pub(crate) struct Trace {
-    arena: Option>,
-    map: Option, V>>,
-    len: u32,
-}
-
-impl Trace {
-    #[allow(dead_code)]
-    pub(crate) fn new_for_arena() -> Trace {
-        Trace { arena: Some(Arena::default()), map: None, len: 0 }
-    }
-
-    pub(crate) fn new_for_map() -> Trace {
-        Trace { arena: None, map: Some(ArenaMap::default()), len: 0 }
-    }
-
-    pub(crate) fn alloc(&mut self, value: impl FnOnce() -> V, data: impl FnOnce() -> T) -> Idx {
-        let id = if let Some(arena) = &mut self.arena {
-            arena.alloc(data())
-        } else {
-            let id = Idx::::from_raw(RawIdx::from(self.len));
-            self.len += 1;
-            id
-        };
-
-        if let Some(map) = &mut self.map {
-            map.insert(id, value());
-        }
-        id
-    }
-
-    #[allow(dead_code)]
-    pub(crate) fn into_arena(mut self) -> Arena {
-        self.arena.take().unwrap()
-    }
-
-    pub(crate) fn into_map(mut self) -> ArenaMap, V> {
-        self.map.take().unwrap()
-    }
-}

From 4d747128eb1e1c0da7432b071107d29721e19a04 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras 
Date: Sun, 26 May 2024 00:11:32 +0100
Subject: [PATCH 142/489] Tweak type inference for `const` operands in inline
 asm

Previously these would be treated like integer literals and default to
`i32` if a type could not be determined. To allow for
forward-compatibility with `str` constants in the future, this PR
changes type inference to use an unbound type variable instead.

The actual type checking is deferred until after typeck where we still
ensure that the final type for the `const` operand is an integer type.
---
 .../src/check/intrinsicck.rs                  | 24 +++++++++++++++----
 compiler/rustc_hir_typeck/src/lib.rs          |  9 ++++---
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 2e965c59ebb53..9286d3d83bffc 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -455,10 +455,26 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                         );
                     }
                 }
-                // No special checking is needed for these:
-                // - Typeck has checked that Const operands are integers.
-                // - AST lowering guarantees that SymStatic points to a static.
-                hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymStatic { .. } => {}
+                hir::InlineAsmOperand::Const { anon_const } => {
+                    let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity();
+                    match ty.kind() {
+                        ty::Error(_) => {}
+                        ty::Int(_) | ty::Uint(_) => {}
+                        _ => {
+                            self.tcx
+                                .dcx()
+                                .struct_span_err(*op_sp, "invalid type for `const` operand")
+                                .with_span_label(
+                                    self.tcx.def_span(anon_const.def_id),
+                                    format!("is {} `{}`", ty.kind().article(), ty),
+                                )
+                                .with_help("`const` operands must be of an integer type")
+                                .emit();
+                        }
+                    };
+                }
+                // AST lowering guarantees that SymStatic points to a static.
+                hir::InlineAsmOperand::SymStatic { .. } => {}
                 // Check that sym actually points to a function. Later passes
                 // depend on this.
                 hir::InlineAsmOperand::SymFn { anon_const } => {
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 2c79366450909..ebb42e766701d 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -264,11 +264,10 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
             Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
             | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => {
                 asm.operands.iter().find_map(|(op, _op_sp)| match op {
-                    hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
-                        // Inline assembly constants must be integers.
-                        Some(fcx.next_int_var())
-                    }
-                    hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == id => {
+                    hir::InlineAsmOperand::Const { anon_const }
+                    | hir::InlineAsmOperand::SymFn { anon_const }
+                        if anon_const.hir_id == id =>
+                    {
                         Some(fcx.next_ty_var(span))
                     }
                     _ => None,

From 575fc72350d46030fd5e187b5d25fd455e43f406 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras 
Date: Tue, 11 Jun 2024 15:47:46 +0100
Subject: [PATCH 143/489] Work around #96304 by ignoring one test case

---
 tests/ui/asm/type-check-1.rs     | 13 +++---
 tests/ui/asm/type-check-1.stderr | 72 ++++++++++++++++----------------
 2 files changed, 42 insertions(+), 43 deletions(-)

diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs
index b0f1362f54334..09aa4a584ce12 100644
--- a/tests/ui/asm/type-check-1.rs
+++ b/tests/ui/asm/type-check-1.rs
@@ -55,11 +55,12 @@ fn main() {
         asm!("{}", const 0i32);
         asm!("{}", const 0i128);
         asm!("{}", const 0f32);
-        //~^ ERROR mismatched types
+        //~^ ERROR invalid type for `const` operand
         asm!("{}", const 0 as *mut u8);
-        //~^ ERROR mismatched types
-        asm!("{}", const &0);
-        //~^ ERROR mismatched types
+        //~^ ERROR invalid type for `const` operand
+
+        // FIXME: Currently ICEs due to #96304
+        //asm!("{}", const &0);
     }
 }
 
@@ -73,6 +74,6 @@ global_asm!("{}", const 0);
 global_asm!("{}", const 0i32);
 global_asm!("{}", const 0i128);
 global_asm!("{}", const 0f32);
-//~^ ERROR mismatched types
+//~^ ERROR invalid type for `const` operand
 global_asm!("{}", const 0 as *mut u8);
-//~^ ERROR mismatched types
+//~^ ERROR invalid type for `const` operand
diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr
index 1852623211813..30cd7fb42952e 100644
--- a/tests/ui/asm/type-check-1.stderr
+++ b/tests/ui/asm/type-check-1.stderr
@@ -39,6 +39,26 @@ LL |         asm!("{}", sym x);
    |
    = help: `sym` operands must refer to either a function or a static
 
+error: invalid type for `const` operand
+  --> $DIR/type-check-1.rs:76:19
+   |
+LL | global_asm!("{}", const 0f32);
+   |                   ^^^^^^----
+   |                         |
+   |                         is an `f32`
+   |
+   = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+  --> $DIR/type-check-1.rs:78:19
+   |
+LL | global_asm!("{}", const 0 as *mut u8);
+   |                   ^^^^^^------------
+   |                         |
+   |                         is a `*mut u8`
+   |
+   = help: `const` operands must be of an integer type
+
 error: invalid asm output
   --> $DIR/type-check-1.rs:14:29
    |
@@ -102,49 +122,27 @@ LL |         asm!("{}", inout(reg) v[..]);
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
-error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:57:26
+error: invalid type for `const` operand
+  --> $DIR/type-check-1.rs:57:20
    |
 LL |         asm!("{}", const 0f32);
-   |                          ^^^^ expected integer, found `f32`
-
-error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:59:26
-   |
-LL |         asm!("{}", const 0 as *mut u8);
-   |                          ^^^^^^^^^^^^ expected integer, found `*mut u8`
+   |                    ^^^^^^----
+   |                          |
+   |                          is an `f32`
    |
-   = note:     expected type `{integer}`
-           found raw pointer `*mut u8`
+   = help: `const` operands must be of an integer type
 
-error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:61:26
+error: invalid type for `const` operand
+  --> $DIR/type-check-1.rs:59:20
    |
-LL |         asm!("{}", const &0);
-   |                          ^^ expected integer, found `&{integer}`
-   |
-help: consider removing the borrow
-   |
-LL -         asm!("{}", const &0);
-LL +         asm!("{}", const 0);
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:75:25
-   |
-LL | global_asm!("{}", const 0f32);
-   |                         ^^^^ expected integer, found `f32`
-
-error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:77:25
-   |
-LL | global_asm!("{}", const 0 as *mut u8);
-   |                         ^^^^^^^^^^^^ expected integer, found `*mut u8`
+LL |         asm!("{}", const 0 as *mut u8);
+   |                    ^^^^^^------------
+   |                          |
+   |                          is a `*mut u8`
    |
-   = note:     expected type `{integer}`
-           found raw pointer `*mut u8`
+   = help: `const` operands must be of an integer type
 
-error: aborting due to 17 previous errors
+error: aborting due to 16 previous errors
 
-Some errors have detailed explanations: E0277, E0308, E0435.
+Some errors have detailed explanations: E0277, E0435.
 For more information about an error, try `rustc --explain E0277`.

From 97738e1b868567f0c1222179945ae3b387630c82 Mon Sep 17 00:00:00 2001
From: Folkert 
Date: Sun, 21 Jul 2024 18:02:59 +0200
Subject: [PATCH 144/489] apply fix suggested by lcnr

---
 .../src/check/intrinsicck.rs                  | 52 ++++----------
 .../rustc_hir_analysis/src/collect/type_of.rs | 72 +++++++++++++++++--
 tests/ui/asm/type-check-1.rs                  |  4 +-
 tests/ui/asm/type-check-1.stderr              | 52 ++++++++------
 tests/ui/asm/x86_64/type-check-2.stderr       | 32 ++++-----
 5 files changed, 127 insertions(+), 85 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 9286d3d83bffc..6ea8e838d5cee 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -2,7 +2,7 @@ use rustc_ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::{self as hir, LangItem};
 use rustc_middle::bug;
-use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
+use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::Symbol;
@@ -455,48 +455,22 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                         );
                     }
                 }
+                // Typeck has checked that Const operands are integers.
                 hir::InlineAsmOperand::Const { anon_const } => {
-                    let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity();
-                    match ty.kind() {
-                        ty::Error(_) => {}
-                        ty::Int(_) | ty::Uint(_) => {}
-                        _ => {
-                            self.tcx
-                                .dcx()
-                                .struct_span_err(*op_sp, "invalid type for `const` operand")
-                                .with_span_label(
-                                    self.tcx.def_span(anon_const.def_id),
-                                    format!("is {} `{}`", ty.kind().article(), ty),
-                                )
-                                .with_help("`const` operands must be of an integer type")
-                                .emit();
-                        }
-                    };
+                    debug_assert!(matches!(
+                        self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
+                        ty::Error(_) | ty::Int(_) | ty::Uint(_)
+                    ));
                 }
-                // AST lowering guarantees that SymStatic points to a static.
-                hir::InlineAsmOperand::SymStatic { .. } => {}
-                // Check that sym actually points to a function. Later passes
-                // depend on this.
+                // Typeck has checked that SymFn refers to a function.
                 hir::InlineAsmOperand::SymFn { anon_const } => {
-                    let ty = self.tcx.type_of(anon_const.def_id).instantiate_identity();
-                    match ty.kind() {
-                        ty::Never | ty::Error(_) => {}
-                        ty::FnDef(..) => {}
-                        _ => {
-                            self.tcx
-                                .dcx()
-                                .struct_span_err(*op_sp, "invalid `sym` operand")
-                                .with_span_label(
-                                    self.tcx.def_span(anon_const.def_id),
-                                    format!("is {} `{}`", ty.kind().article(), ty),
-                                )
-                                .with_help(
-                                    "`sym` operands must refer to either a function or a static",
-                                )
-                                .emit();
-                        }
-                    };
+                    debug_assert!(matches!(
+                        self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
+                        ty::Error(_) | ty::Never | ty::FnDef(..)
+                    ));
                 }
+                // AST lowering guarantees that SymStatic points to a static.
+                hir::InlineAsmOperand::SymStatic { .. } => {}
                 // No special checking is needed for labels.
                 hir::InlineAsmOperand::Label { .. } => {}
             }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 9affd654366f1..a0d438caf8f93 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -6,7 +6,7 @@ use rustc_hir::HirId;
 use rustc_middle::query::plumbing::CyclePlaceholder;
 use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
@@ -35,6 +35,20 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     let parent_node_id = tcx.parent_hir_id(hir_id);
     let parent_node = tcx.hir_node(parent_node_id);
 
+    let find_sym_fn = |&(op, op_sp)| match op {
+        hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == hir_id => {
+            Some((anon_const, op_sp))
+        }
+        _ => None,
+    };
+
+    let find_const = |&(op, op_sp)| match op {
+        hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => {
+            Some((anon_const, op_sp))
+        }
+        _ => None,
+    };
+
     match parent_node {
         // Anon consts "inside" the type system.
         Node::ConstArg(&ConstArg {
@@ -46,13 +60,57 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
         // Anon consts outside the type system.
         Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
         | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
-            if asm.operands.iter().any(|(op, _op_sp)| match op {
-                hir::InlineAsmOperand::Const { anon_const }
-                | hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
-                _ => false,
-            }) =>
+            if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) =>
         {
-            tcx.typeck(def_id).node_type(hir_id)
+            let ty = tcx.typeck(def_id).node_type(hir_id);
+
+            match ty.kind() {
+                ty::Never | ty::Error(_) => ty,
+                ty::FnDef(..) => ty,
+                _ => {
+                    tcx.dcx()
+                        .struct_span_err(op_sp, "invalid `sym` operand")
+                        .with_span_label(
+                            tcx.def_span(anon_const.def_id),
+                            format!("is {} `{}`", ty.kind().article(), ty),
+                        )
+                        .with_help("`sym` operands must refer to either a function or a static")
+                        .emit();
+
+                    Ty::new_error_with_message(
+                        tcx,
+                        span,
+                        format!("invalid type for `const` operand"),
+                    )
+                }
+            }
+        }
+        Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
+        | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
+            if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) =>
+        {
+            let ty = tcx.typeck(def_id).node_type(hir_id);
+
+            match ty.kind() {
+                ty::Error(_) => ty,
+                ty::Int(_) | ty::Uint(_) => ty,
+                _ => {
+                    tcx.dcx()
+                        .struct_span_err(op_sp, "invalid type for `const` operand")
+                        .with_span_label(
+                            tcx.def_span(anon_const.def_id),
+                            format!("is {} `{}`", ty.kind().article(), ty),
+                        )
+                        .with_help("`const` operands must be of an integer type")
+                        .emit();
+
+                    Ty::new_error_with_message(
+                        tcx,
+                        span,
+                        format!("invalid type for `const` operand"),
+                    )
+                }
+            }
         }
         Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => {
             tcx.adt_def(tcx.hir().get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs
index 09aa4a584ce12..ad1a391539f1a 100644
--- a/tests/ui/asm/type-check-1.rs
+++ b/tests/ui/asm/type-check-1.rs
@@ -59,8 +59,8 @@ fn main() {
         asm!("{}", const 0 as *mut u8);
         //~^ ERROR invalid type for `const` operand
 
-        // FIXME: Currently ICEs due to #96304
-        //asm!("{}", const &0);
+        asm!("{}", const &0);
+        //~^ ERROR invalid type for `const` operand
     }
 }
 
diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr
index 30cd7fb42952e..bbed571284903 100644
--- a/tests/ui/asm/type-check-1.stderr
+++ b/tests/ui/asm/type-check-1.stderr
@@ -39,26 +39,6 @@ LL |         asm!("{}", sym x);
    |
    = help: `sym` operands must refer to either a function or a static
 
-error: invalid type for `const` operand
-  --> $DIR/type-check-1.rs:76:19
-   |
-LL | global_asm!("{}", const 0f32);
-   |                   ^^^^^^----
-   |                         |
-   |                         is an `f32`
-   |
-   = help: `const` operands must be of an integer type
-
-error: invalid type for `const` operand
-  --> $DIR/type-check-1.rs:78:19
-   |
-LL | global_asm!("{}", const 0 as *mut u8);
-   |                   ^^^^^^------------
-   |                         |
-   |                         is a `*mut u8`
-   |
-   = help: `const` operands must be of an integer type
-
 error: invalid asm output
   --> $DIR/type-check-1.rs:14:29
    |
@@ -142,7 +122,37 @@ LL |         asm!("{}", const 0 as *mut u8);
    |
    = help: `const` operands must be of an integer type
 
-error: aborting due to 16 previous errors
+error: invalid type for `const` operand
+  --> $DIR/type-check-1.rs:62:20
+   |
+LL |         asm!("{}", const &0);
+   |                    ^^^^^^--
+   |                          |
+   |                          is a `&i32`
+   |
+   = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+  --> $DIR/type-check-1.rs:76:19
+   |
+LL | global_asm!("{}", const 0f32);
+   |                   ^^^^^^----
+   |                         |
+   |                         is an `f32`
+   |
+   = help: `const` operands must be of an integer type
+
+error: invalid type for `const` operand
+  --> $DIR/type-check-1.rs:78:19
+   |
+LL | global_asm!("{}", const 0 as *mut u8);
+   |                   ^^^^^^------------
+   |                         |
+   |                         is a `*mut u8`
+   |
+   = help: `const` operands must be of an integer type
+
+error: aborting due to 17 previous errors
 
 Some errors have detailed explanations: E0277, E0435.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr
index 6ae118b16e766..e82a7c92664e5 100644
--- a/tests/ui/asm/x86_64/type-check-2.stderr
+++ b/tests/ui/asm/x86_64/type-check-2.stderr
@@ -6,22 +6,6 @@ LL |         asm!("{}", sym x);
    |
    = help: `sym` operands must refer to either a function or a static
 
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:89:19
-   |
-LL | global_asm!("{}", sym C);
-   |                   ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
-error: invalid `sym` operand
-  --> $DIR/type-check-2.rs:36:20
-   |
-LL |         asm!("{}", sym C);
-   |                    ^^^^^ is an `i32`
-   |
-   = help: `sym` operands must refer to either a function or a static
-
 error: arguments for inline assembly must be copyable
   --> $DIR/type-check-2.rs:43:32
    |
@@ -79,6 +63,14 @@ LL |         asm!("{}", inout(reg) r);
    |
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:36:20
+   |
+LL |         asm!("{}", sym C);
+   |                    ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
 error[E0381]: used binding `x` isn't initialized
   --> $DIR/type-check-2.rs:15:28
    |
@@ -121,6 +113,14 @@ help: consider changing this to be mutable
 LL |         let mut v: Vec = vec![0, 1, 2];
    |             +++
 
+error: invalid `sym` operand
+  --> $DIR/type-check-2.rs:89:19
+   |
+LL | global_asm!("{}", sym C);
+   |                   ^^^^^ is an `i32`
+   |
+   = help: `sym` operands must refer to either a function or a static
+
 error: aborting due to 13 previous errors
 
 Some errors have detailed explanations: E0381, E0596.

From c77b56901fc8098c36717a7620b1c89d3f01c14e Mon Sep 17 00:00:00 2001
From: Folkert de Vries 
Date: Mon, 22 Jul 2024 20:44:32 +0200
Subject: [PATCH 145/489] Apply suggestions from code review

Co-authored-by: Amanieu d'Antras 
---
 compiler/rustc_hir_analysis/src/check/intrinsicck.rs | 2 +-
 compiler/rustc_hir_analysis/src/collect/type_of.rs   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 6ea8e838d5cee..847a1e6470679 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -466,7 +466,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                 hir::InlineAsmOperand::SymFn { anon_const } => {
                     debug_assert!(matches!(
                         self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
-                        ty::Error(_) | ty::Never | ty::FnDef(..)
+                        ty::Error(_) | ty::FnDef(..)
                     ));
                 }
                 // AST lowering guarantees that SymStatic points to a static.
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index a0d438caf8f93..001b2190fc715 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -65,7 +65,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
             let ty = tcx.typeck(def_id).node_type(hir_id);
 
             match ty.kind() {
-                ty::Never | ty::Error(_) => ty,
+                ty::Error(_) => ty,
                 ty::FnDef(..) => ty,
                 _ => {
                     tcx.dcx()
@@ -80,7 +80,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                     Ty::new_error_with_message(
                         tcx,
                         span,
-                        format!("invalid type for `const` operand"),
+                        format!("invalid type for `sym` operand"),
                     )
                 }
             }

From d4ca1ac8b9d96ebb32b9bde8a7485b1ac857c10d Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras 
Date: Tue, 23 Jul 2024 23:31:34 +0100
Subject: [PATCH 146/489] rustfmt

---
 compiler/rustc_hir_analysis/src/collect/type_of.rs | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 001b2190fc715..75826936c09fb 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -77,11 +77,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                         .with_help("`sym` operands must refer to either a function or a static")
                         .emit();
 
-                    Ty::new_error_with_message(
-                        tcx,
-                        span,
-                        format!("invalid type for `sym` operand"),
-                    )
+                    Ty::new_error_with_message(tcx, span, format!("invalid type for `sym` operand"))
                 }
             }
         }

From be66415e11234832b0ba10007d7445aef6213cb6 Mon Sep 17 00:00:00 2001
From: Folkert 
Date: Thu, 25 Jul 2024 10:29:59 +0200
Subject: [PATCH 147/489] use `ErrorGuaranteed` from emit

---
 compiler/rustc_hir_analysis/src/collect/type_of.rs | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 75826936c09fb..8b5a8500f71e1 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -68,7 +68,8 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                 ty::Error(_) => ty,
                 ty::FnDef(..) => ty,
                 _ => {
-                    tcx.dcx()
+                    let guar = tcx
+                        .dcx()
                         .struct_span_err(op_sp, "invalid `sym` operand")
                         .with_span_label(
                             tcx.def_span(anon_const.def_id),
@@ -77,7 +78,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                         .with_help("`sym` operands must refer to either a function or a static")
                         .emit();
 
-                    Ty::new_error_with_message(tcx, span, format!("invalid type for `sym` operand"))
+                    Ty::new_error(tcx, guar)
                 }
             }
         }
@@ -91,7 +92,8 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                 ty::Error(_) => ty,
                 ty::Int(_) | ty::Uint(_) => ty,
                 _ => {
-                    tcx.dcx()
+                    let guar = tcx
+                        .dcx()
                         .struct_span_err(op_sp, "invalid type for `const` operand")
                         .with_span_label(
                             tcx.def_span(anon_const.def_id),
@@ -100,11 +102,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                         .with_help("`const` operands must be of an integer type")
                         .emit();
 
-                    Ty::new_error_with_message(
-                        tcx,
-                        span,
-                        format!("invalid type for `const` operand"),
-                    )
+                    Ty::new_error(tcx, guar)
                 }
             }
         }

From b5a03c75d59fe7364181bb56ccd3706a992a59a9 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Thu, 25 Jul 2024 15:13:39 -0400
Subject: [PATCH 148/489] Tell users not to file a bug when using internal
 library features

---
 compiler/rustc_expand/src/config.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 6c02c237115c5..7ec59a1be83ed 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -117,6 +117,12 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
             // Otherwise, the feature is unknown. Record it as a lib feature.
             // It will be checked later.
             features.set_declared_lib_feature(name, mi.span());
+
+            // Similar to above, detect internal lib features to suppress
+            // the ICE message that asks for a report.
+            if features.internal(name) && ![sym::core, sym::alloc, sym::std].contains(&crate_name) {
+                sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
+            }
         }
     }
 

From 93e50c988e6f555c5169363895db14953e168cb9 Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Fri, 26 Jul 2024 02:38:02 +0200
Subject: [PATCH 149/489] Turn root_ratoml into workspace_ratomls

---
 .../crates/rust-analyzer/src/config.rs        | 124 +++++++++---------
 .../crates/rust-analyzer/src/global_state.rs  |  30 +++--
 .../crates/rust-analyzer/src/reload.rs        |   1 -
 .../rust-analyzer/tests/slow-tests/ratoml.rs  |   2 +-
 4 files changed, 83 insertions(+), 74 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 4a09ef21adc74..6724b6a7add3c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -779,11 +779,8 @@ pub struct Config {
     /// Config node whose values apply to **every** Rust project.
     user_config: Option<(GlobalLocalConfigInput, ConfigErrors)>,
 
-    /// A special file for this session whose path is set to `self.root_path.join("rust-analyzer.toml")`
-    root_ratoml_path: VfsPath,
-
-    /// This file can be used to make global changes while having only a workspace-wide scope.
-    root_ratoml: Option<(GlobalLocalConfigInput, ConfigErrors)>,
+    /// TODO : This file can be used to make global changes while having only a workspace-wide scope.
+    workspace_ratoml_change: FxHashMap,
 
     /// For every `SourceRoot` there can be at most one RATOML file.
     ratoml_files: FxHashMap,
@@ -917,38 +914,44 @@ impl Config {
             should_update = true;
         }
 
-        if let Some(change) = change.root_ratoml_change {
-            tracing::info!("updating root ra-toml config: {:#}", change);
-            #[allow(clippy::single_match)]
-            match toml::from_str(&change) {
-                Ok(table) => {
+        if let Some(change) = change.workspace_ratoml_change {
+            tracing::info!("updating root ra-toml config");
+            for (source_root_id, (_, text)) in change {
+                if let Some(text) = text {
                     let mut toml_errors = vec![];
-                    validate_toml_table(
-                        GlobalLocalConfigInput::FIELDS,
-                        &table,
-                        &mut String::new(),
-                        &mut toml_errors,
-                    );
-                    config.root_ratoml = Some((
-                        GlobalLocalConfigInput::from_toml(table, &mut toml_errors),
-                        ConfigErrors(
-                            toml_errors
-                                .into_iter()
-                                .map(|(a, b)| ConfigErrorInner::Toml { config_key: a, error: b })
-                                .map(Arc::new)
-                                .collect(),
-                        ),
-                    ));
-                    should_update = true;
-                }
-                Err(e) => {
-                    config.root_ratoml = Some((
-                        GlobalLocalConfigInput::from_toml(toml::map::Map::default(), &mut vec![]),
-                        ConfigErrors(vec![ConfigErrorInner::ParseError {
-                            reason: e.message().to_owned(),
+                    match toml::from_str(&text) {
+                        Ok(table) => {
+                            validate_toml_table(
+                                GlobalLocalConfigInput::FIELDS,
+                                &table,
+                                &mut String::new(),
+                                &mut toml_errors,
+                            );
+                            config.workspace_ratoml_change.insert(
+                                source_root_id,
+                                (
+                                    GlobalLocalConfigInput::from_toml(table, &mut toml_errors),
+                                    ConfigErrors(
+                                        toml_errors
+                                            .into_iter()
+                                            .map(|(a, b)| ConfigErrorInner::Toml {
+                                                config_key: a,
+                                                error: b,
+                                            })
+                                            .map(Arc::new)
+                                            .collect(),
+                                    ),
+                                ),
+                            );
+                            should_update = true;
+                        }
+                        Err(e) => {
+                            config.validation_errors.0.push(
+                                ConfigErrorInner::ParseError { reason: e.message().to_owned() }
+                                    .into(),
+                            );
                         }
-                        .into()]),
-                    ));
+                    }
                 }
             }
         }
@@ -958,7 +961,6 @@ impl Config {
                 if let Some(text) = text {
                     let mut toml_errors = vec![];
                     tracing::info!("updating ra-toml config: {:#}", text);
-                    #[allow(clippy::single_match)]
                     match toml::from_str(&text) {
                         Ok(table) => {
                             validate_toml_table(
@@ -985,16 +987,10 @@ impl Config {
                             );
                         }
                         Err(e) => {
-                            config.root_ratoml = Some((
-                                GlobalLocalConfigInput::from_toml(
-                                    toml::map::Map::default(),
-                                    &mut vec![],
-                                ),
-                                ConfigErrors(vec![ConfigErrorInner::ParseError {
-                                    reason: e.message().to_owned(),
-                                }
-                                .into()]),
-                            ));
+                            config.validation_errors.0.push(
+                                ConfigErrorInner::ParseError { reason: e.message().to_owned() }
+                                    .into(),
+                            );
                         }
                     }
                 }
@@ -1026,7 +1022,13 @@ impl Config {
                 .1
                  .0
                 .iter()
-                .chain(config.root_ratoml.as_ref().into_iter().flat_map(|it| it.1 .0.iter()))
+                .chain(
+                    config
+                        .workspace_ratoml_change
+                        .values()
+                        .into_iter()
+                        .flat_map(|it| it.1 .0.iter()),
+                )
                 .chain(config.user_config.as_ref().into_iter().flat_map(|it| it.1 .0.iter()))
                 .chain(config.ratoml_files.values().flat_map(|it| it.1 .0.iter()))
                 .chain(config.validation_errors.0.iter())
@@ -1055,8 +1057,8 @@ impl Config {
 #[derive(Default, Debug)]
 pub struct ConfigChange {
     user_config_change: Option>,
-    root_ratoml_change: Option>,
     client_config_change: Option,
+    workspace_ratoml_change: Option>)>>,
     ratoml_file_change: Option>)>>,
     source_map_change: Option>>,
 }
@@ -1078,9 +1080,15 @@ impl ConfigChange {
         self.user_config_change = content;
     }
 
-    pub fn change_root_ratoml(&mut self, content: Option>) {
-        assert!(self.root_ratoml_change.is_none()); // Otherwise it is a double write.
-        self.root_ratoml_change = content;
+    pub fn change_workspace_ratoml(
+        &mut self,
+        source_root: SourceRootId,
+        vfs_path: VfsPath,
+        content: Option>,
+    ) -> Option<(VfsPath, Option>)> {
+        self.workspace_ratoml_change
+            .get_or_insert_with(Default::default)
+            .insert(source_root, (vfs_path, content))
     }
 
     pub fn change_client_config(&mut self, change: serde_json::Value) {
@@ -1333,11 +1341,6 @@ impl Config {
         // FIXME @alibektas : Temporary solution. I don't think this is right as at some point we may allow users to specify
         // custom USER_CONFIG_PATHs which may also be relative.
         let user_config_path = VfsPath::from(AbsPathBuf::assert(user_config_path));
-        let root_ratoml_path = {
-            let mut p = root_path.clone();
-            p.push("rust-analyzer.toml");
-            VfsPath::new_real_path(p.to_string())
-        };
 
         Config {
             caps: ClientCapabilities::new(caps),
@@ -1352,10 +1355,9 @@ impl Config {
             source_root_parent_map: Arc::new(FxHashMap::default()),
             user_config: None,
             user_config_path,
-            root_ratoml: None,
-            root_ratoml_path,
             detached_files: Default::default(),
             validation_errors: Default::default(),
+            workspace_ratoml_change: Default::default(),
         }
     }
 
@@ -1398,10 +1400,6 @@ impl Config {
         &self.root_path
     }
 
-    pub fn root_ratoml_path(&self) -> &VfsPath {
-        &self.root_ratoml_path
-    }
-
     pub fn caps(&self) -> &ClientCapabilities {
         &self.caps
     }
@@ -3591,7 +3589,7 @@ mod tests {
 
         let mut change = ConfigChange::default();
 
-        change.change_root_ratoml(Some(
+        change.change_user_config(Some(
             toml::toml! {
                 [cargo.cfgs]
                 these = "these"
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index 9fd9bee5377a8..d78e760358243 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -10,6 +10,7 @@ use flycheck::{project_json, FlycheckHandle};
 use hir::ChangeWithProcMacros;
 use ide::{Analysis, AnalysisHost, Cancellable, FileId, SourceRootId};
 use ide_db::base_db::{CrateId, ProcMacroPaths, SourceDatabaseExt};
+use itertools::Itertools;
 use load_cargo::SourceRootConfig;
 use lsp_types::{SemanticTokens, Url};
 use nohash_hasher::IntMap;
@@ -22,7 +23,7 @@ use project_model::{ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, Worksp
 use rustc_hash::{FxHashMap, FxHashSet};
 use tracing::{span, trace, Level};
 use triomphe::Arc;
-use vfs::{AbsPathBuf, AnchoredPathBuf, ChangeKind, Vfs};
+use vfs::{AbsPathBuf, AnchoredPathBuf, ChangeKind, Vfs, VfsPath};
 
 use crate::{
     config::{Config, ConfigChange, ConfigErrors},
@@ -382,26 +383,37 @@ impl GlobalState {
         {
             let config_change = {
                 let user_config_path = self.config.user_config_path();
-                let root_ratoml_path = self.config.root_ratoml_path();
                 let mut change = ConfigChange::default();
                 let db = self.analysis_host.raw_database();
 
+                // FIXME @alibektas : This is silly. There is abs no reason to use VfsPaths when there is SourceRoots. But how
+                // do I resolve a "workspace_root" to its corresponding id without having to rely on a cargo.toml's ( or project json etc.) file id?
+                let workspace_roots = self
+                    .workspaces
+                    .iter()
+                    .map(|ws| VfsPath::from(ws.workspace_root().to_owned()))
+                    .collect_vec();
+
                 for (file_id, (_change_kind, vfs_path)) in modified_ratoml_files {
                     if vfs_path == *user_config_path {
                         change.change_user_config(Some(db.file_text(file_id)));
                         continue;
                     }
 
-                    if vfs_path == *root_ratoml_path {
-                        change.change_root_ratoml(Some(db.file_text(file_id)));
-                        continue;
-                    }
-
                     // If change has been made to a ratoml file that
                     // belongs to a non-local source root, we will ignore it.
-                    // As it doesn't make sense a users to use external config files.
                     let sr_id = db.file_source_root(file_id);
                     let sr = db.source_root(sr_id);
+
+                    if workspace_roots.contains(&vfs_path) {
+                        change.change_workspace_ratoml(
+                            sr_id,
+                            vfs_path,
+                            Some(db.file_text(file_id)),
+                        );
+                        continue;
+                    }
+
                     if !sr.is_library {
                         if let Some((old_path, old_text)) = change.change_ratoml(
                             sr_id,
@@ -430,7 +442,7 @@ impl GlobalState {
             if should_update {
                 self.update_configuration(config);
             } else {
-                // No global or client level config was changed. So we can just naively replace config.
+                // No global or client level config was changed. So we can naively replace config.
                 self.config = Arc::new(config);
             }
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index fb16f28a14bd4..b2d360c62db81 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -541,7 +541,6 @@ impl GlobalState {
 
             watchers.extend(
                 iter::once(self.config.user_config_path().as_path())
-                    .chain(iter::once(self.config.root_ratoml_path().as_path()))
                     .chain(self.workspaces.iter().map(|ws| ws.manifest().map(ManifestPath::as_ref)))
                     .flatten()
                     .map(|glob_pattern| lsp_types::FileSystemWatcher {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
index 3b05138e18720..298e10fb9e024 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
@@ -808,7 +808,7 @@ enum Value {
 /// Having a ratoml file at the root of a project enables
 /// configuring global level configurations as well.
 #[test]
-#[ignore = "Root ratomls are not being looked for on startup. Fix this."]
+// #[ignore = "Root ratomls are not being looked for on startup. Fix this."]
 fn ratoml_in_root_is_global() {
     let server = RatomlTest::new(
         vec![

From c9cb05c41285950e193a0b8fbd5598b89dae48fb Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Fri, 26 Jul 2024 03:04:29 +0200
Subject: [PATCH 150/489] Globals too are asking for sourcerootid

---
 .../crates/rust-analyzer/src/config.rs        | 177 +++++++++---------
 .../crates/rust-analyzer/src/reload.rs        |   2 +-
 2 files changed, 93 insertions(+), 86 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 6724b6a7add3c..36419d4a97b29 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -1001,7 +1001,7 @@ impl Config {
             config.source_root_parent_map = source_root_map;
         }
 
-        if config.check_command().is_empty() {
+        if config.check_command(None).is_empty() {
             config.validation_errors.0.push(Arc::new(ConfigErrorInner::Json {
                 config_key: "/check/command".to_owned(),
                 error: serde_json::Error::custom("expected a non-empty string"),
@@ -1453,11 +1453,11 @@ impl Config {
 
     pub fn diagnostics(&self, source_root: Option) -> DiagnosticsConfig {
         DiagnosticsConfig {
-            enabled: *self.diagnostics_enable(),
+            enabled: *self.diagnostics_enable(source_root),
             proc_attr_macros_enabled: self.expand_proc_attr_macros(),
             proc_macros_enabled: *self.procMacro_enable(),
-            disable_experimental: !self.diagnostics_experimental_enable(),
-            disabled: self.diagnostics_disabled().clone(),
+            disable_experimental: !self.diagnostics_experimental_enable(source_root),
+            disabled: self.diagnostics_disabled(source_root).clone(),
             expr_fill_default: match self.assist_expressionFillDefault(source_root) {
                 ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo,
                 ExprFillDefaultDef::Default => ExprFillDefaultMode::Default,
@@ -1467,7 +1467,7 @@ impl Config {
             prefer_no_std: self.imports_preferNoStd(source_root).to_owned(),
             prefer_prelude: self.imports_preferPrelude(source_root).to_owned(),
             prefer_absolute: self.imports_prefixExternPrelude(source_root).to_owned(),
-            style_lints: self.diagnostics_styleLints_enable().to_owned(),
+            style_lints: self.diagnostics_styleLints_enable(source_root).to_owned(),
             term_search_fuel: self.assist_termSearch_fuel(source_root).to_owned() as u64,
             term_search_borrowck: self.assist_termSearch_borrowcheck(source_root).to_owned(),
         }
@@ -1660,11 +1660,11 @@ impl Config {
     }
 
     pub fn has_linked_projects(&self) -> bool {
-        !self.linkedProjects().is_empty()
+        !self.linkedProjects(None).is_empty()
     }
 
     pub fn linked_manifests(&self) -> impl Iterator + '_ {
-        self.linkedProjects().iter().filter_map(|it| match it {
+        self.linkedProjects(None).iter().filter_map(|it| match it {
             ManifestOrProjectJson::Manifest(p) => Some(&**p),
             // despite having a buildfile, using this variant as a manifest
             // will fail.
@@ -1674,20 +1674,20 @@ impl Config {
     }
 
     pub fn has_linked_project_jsons(&self) -> bool {
-        self.linkedProjects()
+        self.linkedProjects(None)
             .iter()
             .any(|it| matches!(it, ManifestOrProjectJson::ProjectJson { .. }))
     }
 
     pub fn discover_workspace_config(&self) -> Option<&DiscoverWorkspaceConfig> {
-        self.workspace_discoverConfig().as_ref()
+        self.workspace_discoverConfig(None).as_ref()
     }
 
     pub fn linked_or_discovered_projects(&self) -> Vec {
-        match self.linkedProjects().as_slice() {
+        match self.linkedProjects(None).as_slice() {
             [] => {
                 let exclude_dirs: Vec<_> =
-                    self.files_excludeDirs().iter().map(|p| self.root_path.join(p)).collect();
+                    self.files_excludeDirs(None).iter().map(|p| self.root_path.join(p)).collect();
                 self.discovered_projects
                     .iter()
                     .filter(|project| {
@@ -1722,48 +1722,48 @@ impl Config {
     }
 
     pub fn prefill_caches(&self) -> bool {
-        self.cachePriming_enable().to_owned()
+        self.cachePriming_enable(None).to_owned()
     }
 
     pub fn publish_diagnostics(&self) -> bool {
-        self.diagnostics_enable().to_owned()
+        self.diagnostics_enable(None).to_owned()
     }
 
     pub fn diagnostics_map(&self) -> DiagnosticsMapConfig {
         DiagnosticsMapConfig {
-            remap_prefix: self.diagnostics_remapPrefix().clone(),
-            warnings_as_info: self.diagnostics_warningsAsInfo().clone(),
-            warnings_as_hint: self.diagnostics_warningsAsHint().clone(),
-            check_ignore: self.check_ignore().clone(),
+            remap_prefix: self.diagnostics_remapPrefix(None).clone(),
+            warnings_as_info: self.diagnostics_warningsAsInfo(None).clone(),
+            warnings_as_hint: self.diagnostics_warningsAsHint(None).clone(),
+            check_ignore: self.check_ignore(None).clone(),
         }
     }
 
     pub fn extra_args(&self) -> &Vec {
-        self.cargo_extraArgs()
+        self.cargo_extraArgs(None)
     }
 
     pub fn extra_env(&self) -> &FxHashMap {
-        self.cargo_extraEnv()
+        self.cargo_extraEnv(None)
     }
 
     pub fn check_extra_args(&self) -> Vec {
         let mut extra_args = self.extra_args().clone();
-        extra_args.extend_from_slice(self.check_extraArgs());
+        extra_args.extend_from_slice(self.check_extraArgs(None));
         extra_args
     }
 
     pub fn check_extra_env(&self) -> FxHashMap {
-        let mut extra_env = self.cargo_extraEnv().clone();
-        extra_env.extend(self.check_extraEnv().clone());
+        let mut extra_env = self.cargo_extraEnv(None).clone();
+        extra_env.extend(self.check_extraEnv(None).clone());
         extra_env
     }
 
     pub fn lru_parse_query_capacity(&self) -> Option {
-        self.lru_capacity().to_owned()
+        self.lru_capacity(None).to_owned()
     }
 
     pub fn lru_query_capacities_config(&self) -> Option<&FxHashMap, u16>> {
-        self.lru_query_capacities().is_empty().not().then(|| self.lru_query_capacities())
+        self.lru_query_capacities(None).is_empty().not().then(|| self.lru_query_capacities(None))
     }
 
     pub fn proc_macro_srv(&self) -> Option {
@@ -1772,7 +1772,7 @@ impl Config {
     }
 
     pub fn ignored_proc_macros(&self) -> &FxHashMap, Box<[Box]>> {
-        self.procMacro_ignored()
+        self.procMacro_ignored(None)
     }
 
     pub fn expand_proc_macros(&self) -> bool {
@@ -1787,7 +1787,11 @@ impl Config {
                 }
                 _ => FilesWatcher::Server,
             },
-            exclude: self.files_excludeDirs().iter().map(|it| self.root_path.join(it)).collect(),
+            exclude: self
+                .files_excludeDirs(None)
+                .iter()
+                .map(|it| self.root_path.join(it))
+                .collect(),
         }
     }
 
@@ -1798,22 +1802,22 @@ impl Config {
     }
 
     pub fn cargo_autoreload_config(&self) -> bool {
-        self.cargo_autoreload().to_owned()
+        self.cargo_autoreload(None).to_owned()
     }
 
     pub fn run_build_scripts(&self) -> bool {
-        self.cargo_buildScripts_enable().to_owned() || self.procMacro_enable().to_owned()
+        self.cargo_buildScripts_enable(None).to_owned() || self.procMacro_enable().to_owned()
     }
 
     pub fn cargo(&self) -> CargoConfig {
-        let rustc_source = self.rustc_source().as_ref().map(|rustc_src| {
+        let rustc_source = self.rustc_source(None).as_ref().map(|rustc_src| {
             if rustc_src == "discover" {
                 RustLibSource::Discover
             } else {
                 RustLibSource::Path(self.root_path.join(rustc_src))
             }
         });
-        let sysroot = self.cargo_sysroot().as_ref().map(|sysroot| {
+        let sysroot = self.cargo_sysroot(None).as_ref().map(|sysroot| {
             if sysroot == "discover" {
                 RustLibSource::Discover
             } else {
@@ -1821,26 +1825,26 @@ impl Config {
             }
         });
         let sysroot_src =
-            self.cargo_sysrootSrc().as_ref().map(|sysroot| self.root_path.join(sysroot));
-        let sysroot_query_metadata = self.cargo_sysrootQueryMetadata();
+            self.cargo_sysrootSrc(None).as_ref().map(|sysroot| self.root_path.join(sysroot));
+        let sysroot_query_metadata = self.cargo_sysrootQueryMetadata(None);
 
         CargoConfig {
-            all_targets: *self.cargo_allTargets(),
-            features: match &self.cargo_features() {
+            all_targets: *self.cargo_allTargets(None),
+            features: match &self.cargo_features(None) {
                 CargoFeaturesDef::All => CargoFeatures::All,
                 CargoFeaturesDef::Selected(features) => CargoFeatures::Selected {
                     features: features.clone(),
-                    no_default_features: self.cargo_noDefaultFeatures().to_owned(),
+                    no_default_features: self.cargo_noDefaultFeatures(None).to_owned(),
                 },
             },
-            target: self.cargo_target().clone(),
+            target: self.cargo_target(None).clone(),
             sysroot,
             sysroot_query_metadata: *sysroot_query_metadata,
             sysroot_src,
             rustc_source,
             cfg_overrides: project_model::CfgOverrides {
                 global: CfgDiff::new(
-                    self.cargo_cfgs()
+                    self.cargo_cfgs(None)
                         .iter()
                         .map(|(key, val)| match val {
                             Some(val) => CfgAtom::KeyValue {
@@ -1855,49 +1859,49 @@ impl Config {
                 .unwrap(),
                 selective: Default::default(),
             },
-            wrap_rustc_in_build_scripts: *self.cargo_buildScripts_useRustcWrapper(),
-            invocation_strategy: match self.cargo_buildScripts_invocationStrategy() {
+            wrap_rustc_in_build_scripts: *self.cargo_buildScripts_useRustcWrapper(None),
+            invocation_strategy: match self.cargo_buildScripts_invocationStrategy(None) {
                 InvocationStrategy::Once => project_model::InvocationStrategy::Once,
                 InvocationStrategy::PerWorkspace => project_model::InvocationStrategy::PerWorkspace,
             },
-            invocation_location: match self.cargo_buildScripts_invocationLocation() {
+            invocation_location: match self.cargo_buildScripts_invocationLocation(None) {
                 InvocationLocation::Root => {
                     project_model::InvocationLocation::Root(self.root_path.clone())
                 }
                 InvocationLocation::Workspace => project_model::InvocationLocation::Workspace,
             },
-            run_build_script_command: self.cargo_buildScripts_overrideCommand().clone(),
-            extra_args: self.cargo_extraArgs().clone(),
-            extra_env: self.cargo_extraEnv().clone(),
+            run_build_script_command: self.cargo_buildScripts_overrideCommand(None).clone(),
+            extra_args: self.cargo_extraArgs(None).clone(),
+            extra_env: self.cargo_extraEnv(None).clone(),
             target_dir: self.target_dir_from_config(),
         }
     }
 
     pub fn rustfmt(&self) -> RustfmtConfig {
-        match &self.rustfmt_overrideCommand() {
+        match &self.rustfmt_overrideCommand(None) {
             Some(args) if !args.is_empty() => {
                 let mut args = args.clone();
                 let command = args.remove(0);
                 RustfmtConfig::CustomCommand { command, args }
             }
             Some(_) | None => RustfmtConfig::Rustfmt {
-                extra_args: self.rustfmt_extraArgs().clone(),
-                enable_range_formatting: *self.rustfmt_rangeFormatting_enable(),
+                extra_args: self.rustfmt_extraArgs(None).clone(),
+                enable_range_formatting: *self.rustfmt_rangeFormatting_enable(None),
             },
         }
     }
 
     pub fn flycheck_workspace(&self) -> bool {
-        *self.check_workspace()
+        *self.check_workspace(None)
     }
 
     pub fn cargo_test_options(&self) -> CargoOptions {
         CargoOptions {
-            target_triples: self.cargo_target().clone().into_iter().collect(),
+            target_triples: self.cargo_target(None).clone().into_iter().collect(),
             all_targets: false,
-            no_default_features: *self.cargo_noDefaultFeatures(),
-            all_features: matches!(self.cargo_features(), CargoFeaturesDef::All),
-            features: match self.cargo_features().clone() {
+            no_default_features: *self.cargo_noDefaultFeatures(None),
+            all_features: matches!(self.cargo_features(None), CargoFeaturesDef::All),
+            features: match self.cargo_features(None).clone() {
                 CargoFeaturesDef::All => vec![],
                 CargoFeaturesDef::Selected(it) => it,
             },
@@ -1908,7 +1912,7 @@ impl Config {
     }
 
     pub fn flycheck(&self) -> FlycheckConfig {
-        match &self.check_overrideCommand() {
+        match &self.check_overrideCommand(None) {
             Some(args) if !args.is_empty() => {
                 let mut args = args.clone();
                 let command = args.remove(0);
@@ -1916,13 +1920,13 @@ impl Config {
                     command,
                     args,
                     extra_env: self.check_extra_env(),
-                    invocation_strategy: match self.check_invocationStrategy() {
+                    invocation_strategy: match self.check_invocationStrategy(None) {
                         InvocationStrategy::Once => flycheck::InvocationStrategy::Once,
                         InvocationStrategy::PerWorkspace => {
                             flycheck::InvocationStrategy::PerWorkspace
                         }
                     },
-                    invocation_location: match self.check_invocationLocation() {
+                    invocation_location: match self.check_invocationLocation(None) {
                         InvocationLocation::Root => {
                             flycheck::InvocationLocation::Root(self.root_path.clone())
                         }
@@ -1931,28 +1935,30 @@ impl Config {
                 }
             }
             Some(_) | None => FlycheckConfig::CargoCommand {
-                command: self.check_command().clone(),
+                command: self.check_command(None).clone(),
                 options: CargoOptions {
                     target_triples: self
-                        .check_targets()
+                        .check_targets(None)
                         .clone()
                         .and_then(|targets| match &targets.0[..] {
                             [] => None,
                             targets => Some(targets.into()),
                         })
-                        .unwrap_or_else(|| self.cargo_target().clone().into_iter().collect()),
-                    all_targets: self.check_allTargets().unwrap_or(*self.cargo_allTargets()),
+                        .unwrap_or_else(|| self.cargo_target(None).clone().into_iter().collect()),
+                    all_targets: self
+                        .check_allTargets(None)
+                        .unwrap_or(*self.cargo_allTargets(None)),
                     no_default_features: self
-                        .check_noDefaultFeatures()
-                        .unwrap_or(*self.cargo_noDefaultFeatures()),
+                        .check_noDefaultFeatures(None)
+                        .unwrap_or(*self.cargo_noDefaultFeatures(None)),
                     all_features: matches!(
-                        self.check_features().as_ref().unwrap_or(self.cargo_features()),
+                        self.check_features(None).as_ref().unwrap_or(self.cargo_features(None)),
                         CargoFeaturesDef::All
                     ),
                     features: match self
-                        .check_features()
+                        .check_features(None)
                         .clone()
-                        .unwrap_or_else(|| self.cargo_features().clone())
+                        .unwrap_or_else(|| self.cargo_features(None).clone())
                     {
                         CargoFeaturesDef::All => vec![],
                         CargoFeaturesDef::Selected(it) => it,
@@ -1967,7 +1973,7 @@ impl Config {
     }
 
     fn target_dir_from_config(&self) -> Option {
-        self.cargo_targetDir().as_ref().and_then(|target_dir| match target_dir {
+        self.cargo_targetDir(None).as_ref().and_then(|target_dir| match target_dir {
             TargetDirectory::UseSubdirectory(true) => {
                 Some(Utf8PathBuf::from("target/rust-analyzer"))
             }
@@ -1978,18 +1984,18 @@ impl Config {
     }
 
     pub fn check_on_save(&self) -> bool {
-        *self.checkOnSave()
+        *self.checkOnSave(None)
     }
 
     pub fn script_rebuild_on_save(&self) -> bool {
-        *self.cargo_buildScripts_rebuildOnSave()
+        *self.cargo_buildScripts_rebuildOnSave(None)
     }
 
     pub fn runnables(&self) -> RunnablesConfig {
         RunnablesConfig {
-            override_cargo: self.runnables_command().clone(),
-            cargo_extra_args: self.runnables_extraArgs().clone(),
-            extra_test_binary_args: self.runnables_extraTestBinaryArgs().clone(),
+            override_cargo: self.runnables_command(None).clone(),
+            cargo_extra_args: self.runnables_extraArgs(None).clone(),
+            extra_test_binary_args: self.runnables_extraTestBinaryArgs(None).clone(),
         }
     }
 
@@ -2060,7 +2066,7 @@ impl Config {
     }
 
     pub fn prime_caches_num_threads(&self) -> usize {
-        match self.cachePriming_numThreads() {
+        match self.cachePriming_numThreads(None) {
             NumThreads::Concrete(0) | NumThreads::Physical => num_cpus::get_physical(),
             &NumThreads::Concrete(n) => n,
             NumThreads::Logical => num_cpus::get(),
@@ -2544,11 +2550,12 @@ macro_rules! _impl_for_config_data {
                         }
                     }
 
-                    if let Some((root_path_ratoml, _)) = self.root_ratoml.as_ref() {
-                        if let Some(v) = root_path_ratoml.local.$field.as_ref() {
-                            return &v;
-                        }
-                    }
+                    // TODO
+                    // if let Some((root_path_ratoml, _)) = self.root_ratoml.as_ref() {
+                    //     if let Some(v) = root_path_ratoml.local.$field.as_ref() {
+                    //         return &v;
+                    //     }
+                    // }
 
                     if let Some(v) = self.client_config.0.local.$field.as_ref() {
                         return &v;
@@ -2574,13 +2581,13 @@ macro_rules! _impl_for_config_data {
             $(
                 $($doc)*
                 #[allow(non_snake_case)]
-                $vis fn $field(&self) -> &$ty {
-
-                    if let Some((root_path_ratoml, _)) = self.root_ratoml.as_ref() {
-                        if let Some(v) = root_path_ratoml.global.$field.as_ref() {
-                            return &v;
-                        }
-                    }
+                $vis fn $field(&self, source_root : Option) -> &$ty {
+                    // TODO
+                    // if let Some((root_path_ratoml, _)) = self.root_ratoml.as_ref() {
+                    //     if let Some(v) = root_path_ratoml.global.$field.as_ref() {
+                    //         return &v;
+                    //     }
+                    // }
 
                     if let Some(v) = self.client_config.0.global.$field.as_ref() {
                         return &v;
@@ -3522,7 +3529,7 @@ mod tests {
         }));
 
         (config, _, _) = config.apply_change(change);
-        assert_eq!(config.cargo_targetDir(), &None);
+        assert_eq!(config.cargo_targetDir(None), &None);
         assert!(
             matches!(config.flycheck(), FlycheckConfig::CargoCommand { options, .. } if options.target_dir.is_none())
         );
@@ -3545,7 +3552,7 @@ mod tests {
 
         (config, _, _) = config.apply_change(change);
 
-        assert_eq!(config.cargo_targetDir(), &Some(TargetDirectory::UseSubdirectory(true)));
+        assert_eq!(config.cargo_targetDir(None), &Some(TargetDirectory::UseSubdirectory(true)));
         assert!(
             matches!(config.flycheck(), FlycheckConfig::CargoCommand { options, .. } if options.target_dir == Some(Utf8PathBuf::from("target/rust-analyzer")))
         );
@@ -3569,7 +3576,7 @@ mod tests {
         (config, _, _) = config.apply_change(change);
 
         assert_eq!(
-            config.cargo_targetDir(),
+            config.cargo_targetDir(None),
             &Some(TargetDirectory::Directory(Utf8PathBuf::from("other_folder")))
         );
         assert!(
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index b2d360c62db81..2d358afab39ea 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -110,7 +110,7 @@ impl GlobalState {
         };
         let mut message = String::new();
 
-        if !self.config.cargo_autoreload()
+        if !self.config.cargo_autoreload(None)
             && self.is_quiescent()
             && self.fetch_workspaces_queue.op_requested()
             && self.config.discover_workspace_config().is_none()

From b5490357bac87ac70ca6f4729bd7fd127529eff5 Mon Sep 17 00:00:00 2001
From: The Miri Cronjob Bot 
Date: Fri, 26 Jul 2024 05:00:25 +0000
Subject: [PATCH 151/489] Preparing for merge from rustc

---
 src/tools/miri/rust-version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 9868188eeee70..e1a6084b22eda 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-e7d66eac5e8e8f60370c98d186aee9fa0ebd7845
+72d73cec61aa8f85901358cd5d386d5dd066fe52

From 4a6b461df304dd00134eaa568071a3247bcfa1b2 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Fri, 26 Jul 2024 10:12:06 +0200
Subject: [PATCH 152/489] fix: Fix includes not working with expr fragment
 inputs

---
 .../crates/hir-expand/src/builtin_fn_macro.rs | 20 ++++++++++++++++---
 .../crates/hir-expand/src/lib.rs              |  1 +
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
index 6272e1df7d444..2725bdb7684b9 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
@@ -4,7 +4,7 @@ use base_db::AnchoredPath;
 use cfg::CfgExpr;
 use either::Either;
 use intern::{sym, Symbol};
-use mbe::{parse_exprs_with_sep, parse_to_token_tree};
+use mbe::{parse_exprs_with_sep, parse_to_token_tree, DelimiterKind};
 use span::{Edition, EditionedFileId, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
 use stdx::format_to;
 use syntax::{
@@ -34,7 +34,7 @@ macro_rules! register_builtin {
         }
 
         impl BuiltinFnLikeExpander {
-            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult  {
+            fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult  {
                 match *self {
                     $( BuiltinFnLikeExpander::$kind => $expand, )*
                 }
@@ -42,7 +42,7 @@ macro_rules! register_builtin {
         }
 
         impl EagerExpander {
-            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult  {
+            fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult  {
                 match *self {
                     $( EagerExpander::$e_kind => $e_expand, )*
                 }
@@ -711,6 +711,20 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
                 kind: tt::LitKind::Str,
                 suffix: _,
             })) => Some((unescape_str(text), *span)),
+            // FIXME: We wrap expression fragments in parentheses which can break this expectation
+            // here
+            // Remove this once we handle none delims correctly
+            tt::TokenTree::Subtree(t) if t.delimiter.kind == DelimiterKind::Parenthesis => {
+                t.token_trees.first().and_then(|tt| match tt {
+                    tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+                        symbol: text,
+                        span,
+                        kind: tt::LitKind::Str,
+                        suffix: _,
+                    })) => Some((unescape_str(text), *span)),
+                    _ => None,
+                })
+            }
             _ => None,
         })
         .ok_or(mbe::ExpandError::ConversionError.into())
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index 67b7adaf907f7..c262fcae47351 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -24,6 +24,7 @@ pub mod span_map;
 
 mod cfg_process;
 mod fixup;
+
 use attrs::collect_attrs;
 use rustc_hash::FxHashMap;
 use triomphe::Arc;

From f6e2fca74b572ed0f858d612cf7844db8298f8a0 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Fri, 26 Jul 2024 14:36:13 +0200
Subject: [PATCH 153/489] Internal: Cleanup proc-macro error handling

---
 .../rust-analyzer/crates/base-db/src/input.rs |   4 +-
 .../rust-analyzer/crates/hir-def/src/body.rs  |   5 +-
 .../crates/hir-def/src/body/lower.rs          |  21 +-
 .../rust-analyzer/crates/hir-def/src/data.rs  |  13 +-
 .../crates/hir-def/src/expander.rs            |   2 +-
 .../rust-analyzer/crates/hir-def/src/lib.rs   |   4 +-
 .../hir-def/src/macro_expansion_tests/mod.rs  |   2 +-
 .../crates/hir-def/src/nameres.rs             |   8 -
 .../crates/hir-def/src/nameres/collector.rs   |  79 +++----
 .../crates/hir-def/src/nameres/diagnostics.rs |  67 ++----
 .../crates/hir-expand/src/builtin.rs          |  14 ++
 .../attr_macro.rs}                            |   0
 .../derive_macro.rs}                          |   8 +-
 .../fn_macro.rs}                              |   6 +-
 .../hir-expand/src/{ => builtin}/quote.rs     |  56 ++---
 .../crates/hir-expand/src/change.rs           |   3 +-
 .../rust-analyzer/crates/hir-expand/src/db.rs |   9 +-
 .../crates/hir-expand/src/lib.rs              |  67 +++---
 .../crates/hir-expand/src/proc_macro.rs       | 193 +++++++++++++-----
 .../crates/hir/src/diagnostics.rs             |  17 +-
 src/tools/rust-analyzer/crates/hir/src/lib.rs |  57 +++---
 .../rust-analyzer/crates/hir/src/semantics.rs |   2 +-
 .../src/handlers/macro_error.rs               |   5 +-
 .../src/handlers/unresolved_proc_macro.rs     |  45 ----
 .../crates/ide-diagnostics/src/lib.rs         |   2 -
 src/tools/rust-analyzer/crates/ide/src/lib.rs |   5 -
 .../crates/ide/src/shuffle_crate_graph.rs     |  58 ------
 .../crates/load-cargo/src/lib.rs              |  18 +-
 .../crates/project-model/src/workspace.rs     |   9 +-
 .../rust-analyzer/src/handlers/request.rs     |   5 -
 .../crates/rust-analyzer/src/lsp/ext.rs       |   8 -
 .../crates/rust-analyzer/src/main_loop.rs     |   1 -
 .../crates/rust-analyzer/src/reload.rs        |  78 +++----
 .../crates/test-fixture/src/lib.rs            |   8 +-
 .../rust-analyzer/docs/dev/lsp-extensions.md  |  10 +-
 .../rust-analyzer/editors/code/package.json   |   5 -
 .../editors/code/src/commands.ts              |   6 -
 .../rust-analyzer/editors/code/src/lsp_ext.ts |   1 -
 .../rust-analyzer/editors/code/src/main.ts    |   1 -
 39 files changed, 380 insertions(+), 522 deletions(-)
 create mode 100644 src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs
 rename src/tools/rust-analyzer/crates/hir-expand/src/{builtin_attr_macro.rs => builtin/attr_macro.rs} (100%)
 rename src/tools/rust-analyzer/crates/hir-expand/src/{builtin_derive_macro.rs => builtin/derive_macro.rs} (99%)
 rename src/tools/rust-analyzer/crates/hir-expand/src/{builtin_fn_macro.rs => builtin/fn_macro.rs} (99%)
 rename src/tools/rust-analyzer/crates/hir-expand/src/{ => builtin}/quote.rs (79%)
 delete mode 100644 src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
 delete mode 100644 src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs

diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index 3936fd3555e21..460581f4a6c06 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -16,9 +16,7 @@ use span::{Edition, EditionedFileId};
 use triomphe::Arc;
 use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
 
-// Map from crate id to the name of the crate and path of the proc-macro. If the value is `None`,
-// then the crate for the proc-macro hasn't been build yet as the build data is missing.
-pub type ProcMacroPaths = FxHashMap, AbsPathBuf), String>>;
+pub type ProcMacroPaths = FxHashMap>;
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub struct SourceRootId(pub u32);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index 9e1bff98f8a7b..d3c134f326604 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -10,7 +10,7 @@ use std::ops::{Deref, Index};
 
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
-use hir_expand::{name::Name, InFile};
+use hir_expand::{name::Name, ExpandError, InFile};
 use la_arena::{Arena, ArenaMap, Idx, RawIdx};
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
@@ -115,8 +115,7 @@ pub struct SyntheticSyntax;
 #[derive(Debug, Eq, PartialEq)]
 pub enum BodyDiagnostic {
     InactiveCode { node: InFile, cfg: CfgExpr, opts: CfgOptions },
-    MacroError { node: InFile>, message: String },
-    UnresolvedProcMacro { node: InFile>, krate: CrateId },
+    MacroError { node: InFile>, err: ExpandError },
     UnresolvedMacroCall { node: InFile>, path: ModPath },
     UnreachableLabel { node: InFile>, name: Name },
     UndeclaredLabel { node: InFile>, name: Name },
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index fe5264674a6aa..9e30aff8fe9b5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -7,7 +7,7 @@ use base_db::CrateId;
 use either::Either;
 use hir_expand::{
     name::{AsName, Name},
-    ExpandError, InFile,
+    InFile,
 };
 use intern::{sym, Interned, Symbol};
 use rustc_hash::FxHashMap;
@@ -992,20 +992,11 @@ impl ExprCollector<'_> {
             }
         };
         if record_diagnostics {
-            match &res.err {
-                Some(ExpandError::UnresolvedProcMacro(krate)) => {
-                    self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro {
-                        node: InFile::new(outer_file, syntax_ptr),
-                        krate: *krate,
-                    });
-                }
-                Some(err) => {
-                    self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
-                        node: InFile::new(outer_file, syntax_ptr),
-                        message: err.to_string(),
-                    });
-                }
-                None => {}
+            if let Some(err) = res.err {
+                self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
+                    node: InFile::new(outer_file, syntax_ptr),
+                    err,
+                });
             }
         }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 3a3b540c13251..286694db263e0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -657,22 +657,17 @@ impl<'a> AssocItemCollector<'a> {
                             // crate failed), skip expansion like we would if it was
                             // disabled. This is analogous to the handling in
                             // `DefCollector::collect_macros`.
-                            if exp.is_dummy() {
-                                self.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
+                            if let Some(err) = exp.as_expand_error(self.module_id.krate) {
+                                self.diagnostics.push(DefDiagnostic::macro_error(
                                     self.module_id.local_id,
-                                    loc.kind,
-                                    loc.def.krate,
+                                    ast_id,
+                                    err,
                                 ));
-
-                                continue 'attrs;
-                            }
-                            if exp.is_disabled() {
                                 continue 'attrs;
                             }
                         }
 
                         self.macro_calls.push((ast_id, call_id));
-
                         let res =
                             self.expander.enter_expand_id::(self.db, call_id);
                         self.collect_macro_items(res);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
index d1640ad7e5b7b..8230c7cc09731 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
@@ -179,7 +179,7 @@ impl Expander {
             value: match err {
                 // If proc-macro is disabled or unresolved, we want to expand to a missing expression
                 // instead of an empty tree which might end up in an empty block.
-                Some(ExpandError::UnresolvedProcMacro(_)) => None,
+                Some(ExpandError::MissingProcMacroExpander(_)) => None,
                 _ => (|| {
                     let parse = res.value.0.cast::()?;
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index e96581e1b3039..512daa415481c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -75,9 +75,7 @@ use base_db::{
     CrateId,
 };
 use hir_expand::{
-    builtin_attr_macro::BuiltinAttrExpander,
-    builtin_derive_macro::BuiltinDeriveExpander,
-    builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
+    builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
     db::ExpandDatabase,
     eager::expand_eager_macro_input,
     impl_intern_lookup,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
index b6c6e4b397371..d34f0afc3ef8f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -122,7 +122,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
 
         let mut expn_text = String::new();
         if let Some(err) = exp.err {
-            format_to!(expn_text, "/* error: {} */", err);
+            format_to!(expn_text, "/* error: {} */", err.render_to_string(&db).0);
         }
         let (parse, token_map) = exp.value;
         if expect_errors {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index 08a4eab1bc49a..8825e46336326 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -145,8 +145,6 @@ struct DefMapCrateData {
     /// Side table for resolving derive helpers.
     exported_derives: FxHashMap>,
     fn_proc_macro_mapping: FxHashMap,
-    /// The error that occurred when failing to load the proc-macro dll.
-    proc_macro_loading_error: Option>,
 
     /// Custom attributes registered with `#![register_attr]`.
     registered_attrs: Vec,
@@ -169,7 +167,6 @@ impl DefMapCrateData {
             extern_prelude: FxIndexMap::default(),
             exported_derives: FxHashMap::default(),
             fn_proc_macro_mapping: FxHashMap::default(),
-            proc_macro_loading_error: None,
             registered_attrs: Vec::new(),
             registered_tools: PREDEFINED_TOOLS.iter().map(|it| Symbol::intern(it)).collect(),
             unstable_features: FxHashSet::default(),
@@ -189,7 +186,6 @@ impl DefMapCrateData {
             registered_attrs,
             registered_tools,
             unstable_features,
-            proc_macro_loading_error: _,
             rustc_coherence_is_core: _,
             no_core: _,
             no_std: _,
@@ -474,10 +470,6 @@ impl DefMap {
         self.data.fn_proc_macro_mapping.get(&id).copied()
     }
 
-    pub fn proc_macro_loading_error(&self) -> Option<&str> {
-        self.data.proc_macro_loading_error.as_deref()
-    }
-
     pub fn krate(&self) -> CrateId {
         self.krate
     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index c51eea22dcb0e..9553b6aa8cf8e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -10,9 +10,7 @@ use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 use hir_expand::{
     attrs::{Attr, AttrId},
-    builtin_attr_macro::find_builtin_attr,
-    builtin_derive_macro::find_builtin_derive,
-    builtin_fn_macro::find_builtin_macro,
+    builtin::{find_builtin_attr, find_builtin_derive, find_builtin_macro},
     name::{AsName, Name},
     proc_macro::CustomProcMacroExpander,
     ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
@@ -76,34 +74,11 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
     }
 
     let proc_macros = if krate.is_proc_macro {
-        match db.proc_macros().get(&def_map.krate) {
-            Some(Ok(proc_macros)) => Ok({
-                let ctx = db.syntax_context(tree_id.file_id());
-                proc_macros
-                    .iter()
-                    .enumerate()
-                    .map(|(idx, it)| {
-                        let name = Name::new_symbol(it.name.clone(), ctx);
-                        (
-                            name,
-                            if !db.expand_proc_attr_macros() {
-                                CustomProcMacroExpander::dummy()
-                            } else if it.disabled {
-                                CustomProcMacroExpander::disabled()
-                            } else {
-                                CustomProcMacroExpander::new(
-                                    hir_expand::proc_macro::ProcMacroId::new(idx as u32),
-                                )
-                            },
-                        )
-                    })
-                    .collect()
-            }),
-            Some(Err(e)) => Err(e.clone().into_boxed_str()),
-            None => Err("No proc-macros present for crate".to_owned().into_boxed_str()),
-        }
+        db.proc_macros()
+            .for_crate(def_map.krate, db.syntax_context(tree_id.file_id()))
+            .unwrap_or_default()
     } else {
-        Ok(vec![])
+        Default::default()
     };
 
     let mut collector = DefCollector {
@@ -252,10 +227,10 @@ struct DefCollector<'a> {
     mod_dirs: FxHashMap,
     cfg_options: &'a CfgOptions,
     /// List of procedural macros defined by this crate. This is read from the dynamic library
-    /// built by the build system, and is the list of proc. macros we can actually expand. It is
-    /// empty when proc. macro support is disabled (in which case we still do name resolution for
-    /// them).
-    proc_macros: Result, Box>,
+    /// built by the build system, and is the list of proc-macros we can actually expand. It is
+    /// empty when proc-macro support is disabled (in which case we still do name resolution for
+    /// them). The bool signals whether the proc-macro has been explicitly disabled for name-resolution.
+    proc_macros: Box<[(Name, CustomProcMacroExpander, bool)]>,
     is_proc_macro: bool,
     from_glob_import: PerNsGlobImports,
     /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute.
@@ -278,10 +253,6 @@ impl DefCollector<'_> {
         let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
         let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
 
-        if let Err(e) = &self.proc_macros {
-            crate_data.proc_macro_loading_error = Some(e.clone());
-        }
-
         let mut process = true;
 
         // Process other crate-level attributes.
@@ -608,11 +579,17 @@ impl DefCollector<'_> {
         fn_id: FunctionId,
     ) {
         let kind = def.kind.to_basedb_kind();
-        let (expander, kind) =
-            match self.proc_macros.as_ref().map(|it| it.iter().find(|(n, _)| n == &def.name)) {
-                Ok(Some(&(_, expander))) => (expander, kind),
-                _ => (CustomProcMacroExpander::dummy(), kind),
-            };
+        let (expander, kind) = match self.proc_macros.iter().find(|(n, _, _)| n == &def.name) {
+            Some(_)
+                if kind == hir_expand::proc_macro::ProcMacroKind::Attr
+                    && !self.db.expand_proc_attr_macros() =>
+            {
+                (CustomProcMacroExpander::disabled_proc_attr(), kind)
+            }
+            Some(&(_, _, true)) => (CustomProcMacroExpander::disabled(), kind),
+            Some(&(_, expander, false)) => (expander, kind),
+            None => (CustomProcMacroExpander::missing_expander(), kind),
+        };
 
         let proc_macro_id = ProcMacroLoc {
             container: self.def_map.crate_root(),
@@ -1338,25 +1315,22 @@ impl DefCollector<'_> {
                         return recollect_without(self);
                     }
 
-                    let call_id = call_id();
                     if let MacroDefKind::ProcMacro(_, exp, _) = def.kind {
                         // If there's no expander for the proc macro (e.g.
                         // because proc macros are disabled, or building the
                         // proc macro crate failed), report this and skip
                         // expansion like we would if it was disabled
-                        if exp.is_dummy() {
-                            self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
+                        if let Some(err) = exp.as_expand_error(def.krate) {
+                            self.def_map.diagnostics.push(DefDiagnostic::macro_error(
                                 directive.module_id,
-                                self.db.lookup_intern_macro_call(call_id).kind,
-                                def.krate,
+                                ast_id,
+                                err,
                             ));
                             return recollect_without(self);
                         }
-                        if exp.is_disabled() {
-                            return recollect_without(self);
-                        }
                     }
 
+                    let call_id = call_id();
                     self.def_map.modules[directive.module_id]
                         .scope
                         .add_attr_macro_invoc(ast_id, call_id);
@@ -1395,7 +1369,6 @@ impl DefCollector<'_> {
         }
         let file_id = macro_call_id.as_file();
 
-        // Then, fetch and process the item tree. This will reuse the expansion result from above.
         let item_tree = self.db.file_item_tree(file_id);
 
         let mod_dir = if macro_call_id.as_macro_file().is_include_macro(self.db.upcast()) {
@@ -2433,7 +2406,7 @@ mod tests {
             unresolved_macros: Vec::new(),
             mod_dirs: FxHashMap::default(),
             cfg_options: &CfgOptions::default(),
-            proc_macros: Ok(vec![]),
+            proc_macros: Default::default(),
             from_glob_import: Default::default(),
             skip_attrs: Default::default(),
             is_proc_macro: false,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
index e1bd6966f391e..23837ff661b00 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
@@ -2,9 +2,8 @@
 
 use std::ops::Not;
 
-use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
-use hir_expand::{attrs::AttrId, MacroCallKind};
+use hir_expand::{attrs::AttrId, ExpandError, MacroCallKind};
 use la_arena::Idx;
 use syntax::ast;
 
@@ -17,48 +16,16 @@ use crate::{
 
 #[derive(Debug, PartialEq, Eq)]
 pub enum DefDiagnosticKind {
-    UnresolvedModule {
-        ast: AstId,
-        candidates: Box<[String]>,
-    },
-    UnresolvedExternCrate {
-        ast: AstId,
-    },
-    UnresolvedImport {
-        id: ItemTreeId,
-        index: Idx,
-    },
-    UnconfiguredCode {
-        tree: TreeId,
-        item: AttrOwner,
-        cfg: CfgExpr,
-        opts: CfgOptions,
-    },
-    /// A proc-macro that is lacking an expander, this might be due to build scripts not yet having
-    /// run or proc-macro expansion being disabled.
-    UnresolvedProcMacro {
-        ast: MacroCallKind,
-        krate: CrateId,
-    },
-    UnresolvedMacroCall {
-        ast: MacroCallKind,
-        path: ModPath,
-    },
-    UnimplementedBuiltinMacro {
-        ast: AstId,
-    },
-    InvalidDeriveTarget {
-        ast: AstId,
-        id: usize,
-    },
-    MalformedDerive {
-        ast: AstId,
-        id: usize,
-    },
-    MacroDefError {
-        ast: AstId,
-        message: String,
-    },
+    UnresolvedModule { ast: AstId, candidates: Box<[String]> },
+    UnresolvedExternCrate { ast: AstId },
+    UnresolvedImport { id: ItemTreeId, index: Idx },
+    UnconfiguredCode { tree: TreeId, item: AttrOwner, cfg: CfgExpr, opts: CfgOptions },
+    UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
+    UnimplementedBuiltinMacro { ast: AstId },
+    InvalidDeriveTarget { ast: AstId, id: usize },
+    MalformedDerive { ast: AstId, id: usize },
+    MacroDefError { ast: AstId, message: String },
+    MacroError { ast: AstId, err: ExpandError },
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -115,6 +82,10 @@ impl DefDiagnostic {
         Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } }
     }
 
+    pub fn macro_error(container: LocalModuleId, ast: AstId, err: ExpandError) -> Self {
+        Self { in_module: container, kind: DefDiagnosticKind::MacroError { ast, err } }
+    }
+
     pub fn unconfigured_code(
         container: LocalModuleId,
         tree: TreeId,
@@ -128,14 +99,6 @@ impl DefDiagnostic {
         }
     }
 
-    pub fn unresolved_proc_macro(
-        container: LocalModuleId,
-        ast: MacroCallKind,
-        krate: CrateId,
-    ) -> Self {
-        Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } }
-    }
-
     // FIXME: Whats the difference between this and unresolved_proc_macro
     pub(crate) fn unresolved_macro_call(
         container: LocalModuleId,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs
new file mode 100644
index 0000000000000..4e6349c31da59
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs
@@ -0,0 +1,14 @@
+#[macro_use]
+mod quote;
+
+mod attr_macro;
+mod derive_macro;
+mod fn_macro;
+
+pub use self::{
+    attr_macro::{find_builtin_attr, pseudo_derive_attr_expansion, BuiltinAttrExpander},
+    derive_macro::{find_builtin_derive, BuiltinDeriveExpander},
+    fn_macro::{
+        find_builtin_macro, include_input_to_file_id, BuiltinFnLikeExpander, EagerExpander,
+    },
+};
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs
similarity index 100%
rename from src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs
rename to src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
similarity index 99%
rename from src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs
rename to src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
index d168bad703050..1f36cd1995430 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
@@ -9,18 +9,18 @@ use stdx::never;
 use tracing::debug;
 
 use crate::{
+    builtin::quote::{dollar_crate, quote},
+    db::ExpandDatabase,
     hygiene::span_with_def_site_ctxt,
+    name,
     name::{AsName, Name},
-    quote::dollar_crate,
     span_map::ExpansionSpanMap,
-    tt,
+    tt, ExpandError, ExpandResult,
 };
 use syntax::ast::{
     self, AstNode, FieldList, HasAttrs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds,
 };
 
-use crate::{db::ExpandDatabase, name, quote, ExpandError, ExpandResult};
-
 macro_rules! register_builtin {
     ( $($trait:ident => $expand:ident),* ) => {
         #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
similarity index 99%
rename from src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
rename to src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index 2725bdb7684b9..5edfdcae1c198 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -13,10 +13,10 @@ use syntax::{
 };
 
 use crate::{
+    builtin::quote::{dollar_crate, quote},
     db::ExpandDatabase,
     hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
-    name, quote,
-    quote::dollar_crate,
+    name,
     tt::{self, DelimSpan},
     ExpandError, ExpandResult, HirFileIdExt, Lookup as _, MacroCallId,
 };
@@ -145,7 +145,7 @@ register_builtin! {
 }
 
 fn mk_pound(span: Span) -> tt::Subtree {
-    crate::quote::IntoTt::to_subtree(
+    crate::builtin::quote::IntoTt::to_subtree(
         vec![crate::tt::Leaf::Punct(crate::tt::Punct {
             char: '#',
             spacing: crate::tt::Spacing::Alone,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs
similarity index 79%
rename from src/tools/rust-analyzer/crates/hir-expand/src/quote.rs
rename to src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs
index da02f3aaf9a67..5c33f817f9e44 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/quote.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs
@@ -17,22 +17,21 @@ pub(crate) fn dollar_crate(span: Span) -> tt::Ident {
 // 2. #()* pattern repetition not supported now
 //    * But we can do it manually, see `test_quote_derive_copy_hack`
 #[doc(hidden)]
-#[macro_export]
-macro_rules! __quote {
+macro_rules! quote_impl__ {
     ($span:ident) => {
         Vec::<$crate::tt::TokenTree>::new()
     };
 
     ( @SUBTREE($span:ident) $delim:ident $($tt:tt)* ) => {
         {
-            let children = $crate::__quote!($span $($tt)*);
+            let children = $crate::builtin::quote::__quote!($span $($tt)*);
             $crate::tt::Subtree {
                 delimiter: crate::tt::Delimiter {
                     kind: crate::tt::DelimiterKind::$delim,
                     open: $span,
                     close: $span,
                 },
-                token_trees: $crate::quote::IntoTt::to_tokens(children).into_boxed_slice(),
+                token_trees: $crate::builtin::quote::IntoTt::to_tokens(children).into_boxed_slice(),
             }
         }
     };
@@ -69,9 +68,9 @@ macro_rules! __quote {
     // hash variable
     ($span:ident # $first:ident $($tail:tt)* ) => {
         {
-            let token = $crate::quote::ToTokenTree::to_token($first, $span);
+            let token = $crate::builtin::quote::ToTokenTree::to_token($first, $span);
             let mut tokens = vec![token.into()];
-            let mut tail_tokens = $crate::quote::IntoTt::to_tokens($crate::__quote!($span $($tail)*));
+            let mut tail_tokens = $crate::builtin::quote::IntoTt::to_tokens($crate::builtin::quote::__quote!($span $($tail)*));
             tokens.append(&mut tail_tokens);
             tokens
         }
@@ -79,22 +78,22 @@ macro_rules! __quote {
 
     ($span:ident ## $first:ident $($tail:tt)* ) => {
         {
-            let mut tokens = $first.into_iter().map(|it| $crate::quote::ToTokenTree::to_token(it, $span)).collect::>();
-            let mut tail_tokens = $crate::quote::IntoTt::to_tokens($crate::__quote!($span $($tail)*));
+            let mut tokens = $first.into_iter().map(|it| $crate::builtin::quote::ToTokenTree::to_token(it, $span)).collect::>();
+            let mut tail_tokens = $crate::builtin::quote::IntoTt::to_tokens($crate::builtin::quote::__quote!($span $($tail)*));
             tokens.append(&mut tail_tokens);
             tokens
         }
     };
 
     // Brace
-    ($span:ident  { $($tt:tt)* } ) => { $crate::__quote!(@SUBTREE($span) Brace $($tt)*) };
+    ($span:ident  { $($tt:tt)* } ) => { $crate::builtin::quote::__quote!(@SUBTREE($span) Brace $($tt)*) };
     // Bracket
-    ($span:ident  [ $($tt:tt)* ] ) => { $crate::__quote!(@SUBTREE($span) Bracket $($tt)*) };
+    ($span:ident  [ $($tt:tt)* ] ) => { $crate::builtin::quote::__quote!(@SUBTREE($span) Bracket $($tt)*) };
     // Parenthesis
-    ($span:ident  ( $($tt:tt)* ) ) => { $crate::__quote!(@SUBTREE($span) Parenthesis $($tt)*) };
+    ($span:ident  ( $($tt:tt)* ) ) => { $crate::builtin::quote::__quote!(@SUBTREE($span) Parenthesis $($tt)*) };
 
     // Literal
-    ($span:ident $tt:literal ) => { vec![$crate::quote::ToTokenTree::to_token($tt, $span).into()] };
+    ($span:ident $tt:literal ) => { vec![$crate::builtin::quote::ToTokenTree::to_token($tt, $span).into()] };
     // Ident
     ($span:ident $tt:ident ) => {
         vec![ {
@@ -108,36 +107,37 @@ macro_rules! __quote {
 
     // Puncts
     // FIXME: Not all puncts are handled
-    ($span:ident -> ) => {$crate::__quote!(@PUNCT($span) '-', '>')};
-    ($span:ident & ) => {$crate::__quote!(@PUNCT($span) '&')};
-    ($span:ident , ) => {$crate::__quote!(@PUNCT($span) ',')};
-    ($span:ident : ) => {$crate::__quote!(@PUNCT($span) ':')};
-    ($span:ident ; ) => {$crate::__quote!(@PUNCT($span) ';')};
-    ($span:ident :: ) => {$crate::__quote!(@PUNCT($span) ':', ':')};
-    ($span:ident . ) => {$crate::__quote!(@PUNCT($span) '.')};
-    ($span:ident < ) => {$crate::__quote!(@PUNCT($span) '<')};
-    ($span:ident > ) => {$crate::__quote!(@PUNCT($span) '>')};
-    ($span:ident ! ) => {$crate::__quote!(@PUNCT($span) '!')};
+    ($span:ident -> ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '-', '>')};
+    ($span:ident & ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '&')};
+    ($span:ident , ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ',')};
+    ($span:ident : ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ':')};
+    ($span:ident ; ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ';')};
+    ($span:ident :: ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ':', ':')};
+    ($span:ident . ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '.')};
+    ($span:ident < ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '<')};
+    ($span:ident > ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '>')};
+    ($span:ident ! ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '!')};
 
     ($span:ident $first:tt $($tail:tt)+ ) => {
         {
-            let mut tokens = $crate::quote::IntoTt::to_tokens($crate::__quote!($span $first ));
-            let mut tail_tokens = $crate::quote::IntoTt::to_tokens($crate::__quote!($span $($tail)*));
+            let mut tokens = $crate::builtin::quote::IntoTt::to_tokens($crate::builtin::quote::__quote!($span $first ));
+            let mut tail_tokens = $crate::builtin::quote::IntoTt::to_tokens($crate::builtin::quote::__quote!($span $($tail)*));
 
             tokens.append(&mut tail_tokens);
             tokens
         }
     };
 }
+pub(super) use quote_impl__ as __quote;
 
 /// FIXME:
 /// It probably should implement in proc-macro
-#[macro_export]
-macro_rules! quote {
+macro_rules! quote_impl {
     ($span:ident=> $($tt:tt)* ) => {
-        $crate::quote::IntoTt::to_subtree($crate::__quote!($span $($tt)*), $span)
+        $crate::builtin::quote::IntoTt::to_subtree($crate::builtin::quote::__quote!($span $($tt)*), $span)
     }
 }
+pub(super) use quote_impl as quote;
 
 pub(crate) trait IntoTt {
     fn to_subtree(self, span: Span) -> crate::tt::Subtree;
@@ -232,6 +232,8 @@ mod tests {
     use span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
     use syntax::{TextRange, TextSize};
 
+    use super::quote;
+
     const DUMMY: tt::Span = tt::Span {
         range: TextRange::empty(TextSize::new(0)),
         anchor: SpanAnchor {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
index 08491db37267e..1a3dd0e7ddbd6 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
@@ -25,8 +25,7 @@ impl ChangeWithProcMacros {
 
     pub fn apply(self, db: &mut (impl ExpandDatabase + SourceDatabaseExt)) {
         self.source_change.apply(db);
-        if let Some(mut proc_macros) = self.proc_macros {
-            proc_macros.shrink_to_fit();
+        if let Some(proc_macros) = self.proc_macros {
             db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH);
         }
         if let Some(target_data_layouts) = self.target_data_layouts {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index e78ab2460a7aa..dd1d292fb64fd 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -11,8 +11,7 @@ use triomphe::Arc;
 
 use crate::{
     attrs::{collect_attrs, AttrId},
-    builtin_attr_macro::pseudo_derive_attr_expansion,
-    builtin_fn_macro::EagerExpander,
+    builtin::pseudo_derive_attr_expansion,
     cfg_process,
     declarative::DeclarativeMacroExpander,
     fixup::{self, SyntaxFixupUndoInfo},
@@ -20,9 +19,9 @@ use crate::{
     proc_macro::ProcMacros,
     span_map::{RealSpanMap, SpanMap, SpanMapRef},
     tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander,
-    CustomProcMacroExpander, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap,
-    HirFileId, HirFileIdRepr, Lookup, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId,
-    MacroDefKind, MacroFileId,
+    CustomProcMacroExpander, EagerCallInfo, EagerExpander, ExpandError, ExpandResult, ExpandTo,
+    ExpansionSpanMap, HirFileId, HirFileIdRepr, Lookup, MacroCallId, MacroCallKind, MacroCallLoc,
+    MacroDefId, MacroDefKind, MacroFileId,
 };
 /// This is just to ensure the types of smart_macro_arg and macro_arg are the same
 type MacroArgResult = (Arc, SyntaxFixupUndoInfo, Span);
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index c262fcae47351..64b4bd48bac9e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -6,9 +6,7 @@
 #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
 
 pub mod attrs;
-pub mod builtin_attr_macro;
-pub mod builtin_derive_macro;
-pub mod builtin_fn_macro;
+pub mod builtin;
 pub mod change;
 pub mod db;
 pub mod declarative;
@@ -19,7 +17,6 @@ pub mod inert_attr_macro;
 pub mod mod_path;
 pub mod name;
 pub mod proc_macro;
-pub mod quote;
 pub mod span_map;
 
 mod cfg_process;
@@ -29,7 +26,7 @@ use attrs::collect_attrs;
 use rustc_hash::FxHashMap;
 use triomphe::Arc;
 
-use std::{fmt, hash::Hash};
+use std::hash::Hash;
 
 use base_db::{salsa::InternValueTrivial, CrateId};
 use either::Either;
@@ -44,9 +41,10 @@ use syntax::{
 
 use crate::{
     attrs::AttrId,
-    builtin_attr_macro::BuiltinAttrExpander,
-    builtin_derive_macro::BuiltinDeriveExpander,
-    builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
+    builtin::{
+        include_input_to_file_id, BuiltinAttrExpander, BuiltinDeriveExpander,
+        BuiltinFnLikeExpander, EagerExpander,
+    },
     db::ExpandDatabase,
     mod_path::ModPath,
     proc_macro::{CustomProcMacroExpander, ProcMacroKind},
@@ -127,7 +125,8 @@ pub type ExpandResult = ValueResult;
 
 #[derive(Debug, PartialEq, Eq, Clone, Hash)]
 pub enum ExpandError {
-    UnresolvedProcMacro(CrateId),
+    ProcMacroAttrExpansionDisabled,
+    MissingProcMacroExpander(CrateId),
     /// The macro expansion is disabled.
     MacroDisabled,
     MacroDefinition,
@@ -141,31 +140,33 @@ impl ExpandError {
     pub fn other(msg: impl Into>) -> Self {
         ExpandError::Other(Arc::new(msg.into()))
     }
-}
-
-impl From for ExpandError {
-    fn from(mbe: mbe::ExpandError) -> Self {
-        Self::Mbe(mbe)
-    }
-}
 
-impl fmt::Display for ExpandError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    pub fn render_to_string(&self, db: &dyn ExpandDatabase) -> (String, bool) {
         match self {
-            ExpandError::UnresolvedProcMacro(_) => f.write_str("unresolved proc-macro"),
-            ExpandError::Mbe(it) => it.fmt(f),
-            ExpandError::RecursionOverflow => f.write_str("overflow expanding the original macro"),
-            ExpandError::ProcMacroPanic(it) => {
-                f.write_str("proc-macro panicked: ")?;
-                f.write_str(it)
+            Self::ProcMacroAttrExpansionDisabled => {
+                ("procedural attribute macro expansion is disabled".to_owned(), false)
             }
-            ExpandError::Other(it) => f.write_str(it),
-            ExpandError::MacroDisabled => f.write_str("macro disabled"),
-            ExpandError::MacroDefinition => f.write_str("macro definition has parse errors"),
+            Self::MacroDisabled => ("proc-macro is explicitly disabled".to_owned(), false),
+            &Self::MissingProcMacroExpander(def_crate) => {
+                match db.proc_macros().get_error_for_crate(def_crate) {
+                    Some((e, hard_err)) => (e.to_owned(), hard_err),
+                    None => ("missing expander".to_owned(), true),
+                }
+            }
+            Self::MacroDefinition => ("macro definition has parse errors".to_owned(), true),
+            Self::Mbe(e) => (e.to_string(), true),
+            Self::RecursionOverflow => ("overflow expanding the original macro".to_owned(), true),
+            Self::Other(e) => ((***e).to_owned(), true),
+            Self::ProcMacroPanic(e) => ((***e).to_owned(), true),
         }
     }
 }
 
+impl From for ExpandError {
+    fn from(mbe: mbe::ExpandError) -> Self {
+        Self::Mbe(mbe)
+    }
+}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct MacroCallLoc {
     pub def: MacroDefId,
@@ -277,11 +278,9 @@ impl HirFileIdExt for HirFileId {
                     let loc = db.lookup_intern_macro_call(file.macro_call_id);
                     if loc.def.is_include() {
                         if let MacroCallKind::FnLike { eager: Some(eager), .. } = &loc.kind {
-                            if let Ok(it) = builtin_fn_macro::include_input_to_file_id(
-                                db,
-                                file.macro_call_id,
-                                &eager.arg,
-                            ) {
+                            if let Ok(it) =
+                                include_input_to_file_id(db, file.macro_call_id, &eager.arg)
+                            {
                                 break it;
                             }
                         }
@@ -572,9 +571,7 @@ impl MacroCallLoc {
     ) -> Option {
         if self.def.is_include() {
             if let MacroCallKind::FnLike { eager: Some(eager), .. } = &self.kind {
-                if let Ok(it) =
-                    builtin_fn_macro::include_input_to_file_id(db, macro_call_id, &eager.arg)
-                {
+                if let Ok(it) = include_input_to_file_id(db, macro_call_id, &eager.arg) {
                     return Some(it);
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
index 39599bfe02e31..b5dc9a764996b 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
@@ -7,20 +7,10 @@ use base_db::{CrateId, Env};
 use intern::Symbol;
 use rustc_hash::FxHashMap;
 use span::Span;
-use stdx::never;
 use triomphe::Arc;
 
 use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct ProcMacroId(u32);
-
-impl ProcMacroId {
-    pub fn new(u32: u32) -> Self {
-        ProcMacroId(u32)
-    }
-}
-
 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
 pub enum ProcMacroKind {
     CustomDerive,
@@ -28,7 +18,10 @@ pub enum ProcMacroKind {
     Attr,
 }
 
+/// A proc-macro expander implementation.
 pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
+    /// Run the expander with the given input subtree, optional attribute input subtree (for
+    /// [`ProcMacroKind::Attr`]), environment variables, and span information.
     fn expand(
         &self,
         subtree: &tt::Subtree,
@@ -42,57 +35,162 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
 
 #[derive(Debug)]
 pub enum ProcMacroExpansionError {
+    /// The proc-macro panicked.
     Panic(String),
-    /// Things like "proc macro server was killed by OOM".
+    /// The server itself errored out.
     System(String),
 }
 
-pub type ProcMacroLoadResult = Result, String>;
+pub type ProcMacroLoadResult = Result, (String, bool)>;
+type StoredProcMacroLoadResult = Result, (Box, bool)>;
+
+#[derive(Default, Debug)]
+pub struct ProcMacrosBuilder(FxHashMap);
+impl ProcMacrosBuilder {
+    pub fn insert(&mut self, proc_macros_crate: CrateId, proc_macro: ProcMacroLoadResult) {
+        self.0.insert(
+            proc_macros_crate,
+            match proc_macro {
+                Ok(it) => Ok(it.into_boxed_slice()),
+                Err((e, hard_err)) => Err((e.into_boxed_str(), hard_err)),
+            },
+        );
+    }
+    pub fn build(mut self) -> ProcMacros {
+        self.0.shrink_to_fit();
+        ProcMacros(self.0)
+    }
+}
+
+#[derive(Default, Debug)]
+pub struct ProcMacros(FxHashMap);
+
+impl FromIterator<(CrateId, ProcMacroLoadResult)> for ProcMacros {
+    fn from_iter>(iter: T) -> Self {
+        let mut builder = ProcMacrosBuilder::default();
+        for (k, v) in iter {
+            builder.insert(k, v);
+        }
+        builder.build()
+    }
+}
+
+impl ProcMacros {
+    fn get(&self, krate: CrateId, idx: u32) -> Result<&ProcMacro, ExpandError> {
+        let proc_macros = match self.0.get(&krate) {
+            Some(Ok(proc_macros)) => proc_macros,
+            Some(Err(_)) | None => {
+                return Err(ExpandError::other("internal error: no proc macros for crate"));
+            }
+        };
+        proc_macros.get(idx as usize).ok_or_else(|| {
+                ExpandError::other(
+                    format!(
+                        "internal error: proc-macro index out of bounds: the length is {} but the index is {}",
+                        proc_macros.len(),
+                        idx
+                    )
+                )
+            }
+        )
+    }
+
+    pub fn get_error_for_crate(&self, krate: CrateId) -> Option<(&str, bool)> {
+        self.0.get(&krate).and_then(|it| it.as_ref().err()).map(|(e, hard_err)| (&**e, *hard_err))
+    }
 
-pub type ProcMacros = FxHashMap;
+    /// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate.
+    pub fn for_crate(
+        &self,
+        krate: CrateId,
+        def_site_ctx: span::SyntaxContextId,
+    ) -> Option> {
+        match self.0.get(&krate) {
+            Some(Ok(proc_macros)) => Some({
+                proc_macros
+                    .iter()
+                    .enumerate()
+                    .map(|(idx, it)| {
+                        let name = crate::name::Name::new_symbol(it.name.clone(), def_site_ctx);
+                        (name, CustomProcMacroExpander::new(idx as u32), it.disabled)
+                    })
+                    .collect()
+            }),
+            _ => None,
+        }
+    }
+}
 
+/// A loaded proc-macro.
 #[derive(Debug, Clone)]
 pub struct ProcMacro {
+    /// The name of the proc macro.
     pub name: Symbol,
     pub kind: ProcMacroKind,
+    /// The expander handle for this proc macro.
     pub expander: sync::Arc,
+    /// Whether this proc-macro is disabled for early name resolution. Notably, the
+    /// [`Self::expander`] is still usable.
     pub disabled: bool,
 }
 
+/// A custom proc-macro expander handle. This handle together with its crate resolves to a [`ProcMacro`]
 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
 pub struct CustomProcMacroExpander {
-    proc_macro_id: ProcMacroId,
+    proc_macro_id: u32,
 }
 
 impl CustomProcMacroExpander {
-    const DUMMY_ID: u32 = !0;
+    const MISSING_EXPANDER: u32 = !0;
     const DISABLED_ID: u32 = !1;
+    const PROC_MACRO_ATTR_DISABLED: u32 = !2;
 
-    pub fn new(proc_macro_id: ProcMacroId) -> Self {
-        assert_ne!(proc_macro_id.0, Self::DUMMY_ID);
-        assert_ne!(proc_macro_id.0, Self::DISABLED_ID);
+    pub fn new(proc_macro_id: u32) -> Self {
+        assert_ne!(proc_macro_id, Self::MISSING_EXPANDER);
+        assert_ne!(proc_macro_id, Self::DISABLED_ID);
+        assert_ne!(proc_macro_id, Self::PROC_MACRO_ATTR_DISABLED);
         Self { proc_macro_id }
     }
 
-    /// A dummy expander that always errors. This is used for proc-macros that are missing, usually
-    /// due to them not being built yet.
-    pub const fn dummy() -> Self {
-        Self { proc_macro_id: ProcMacroId(Self::DUMMY_ID) }
-    }
-
-    /// The macro was not yet resolved.
-    pub const fn is_dummy(&self) -> bool {
-        self.proc_macro_id.0 == Self::DUMMY_ID
+    /// An expander that always errors due to the actual proc-macro expander missing.
+    pub const fn missing_expander() -> Self {
+        Self { proc_macro_id: Self::MISSING_EXPANDER }
     }
 
     /// A dummy expander that always errors. This expander is used for macros that have been disabled.
     pub const fn disabled() -> Self {
-        Self { proc_macro_id: ProcMacroId(Self::DISABLED_ID) }
+        Self { proc_macro_id: Self::DISABLED_ID }
+    }
+
+    /// A dummy expander that always errors. This expander is used for attribute macros when
+    /// proc-macro attribute expansion is disabled.
+    pub const fn disabled_proc_attr() -> Self {
+        Self { proc_macro_id: Self::PROC_MACRO_ATTR_DISABLED }
+    }
+
+    /// The macro-expander is missing or has yet to be build.
+    pub const fn is_missing(&self) -> bool {
+        self.proc_macro_id == Self::MISSING_EXPANDER
     }
 
     /// The macro is explicitly disabled and cannot be expanded.
     pub const fn is_disabled(&self) -> bool {
-        self.proc_macro_id.0 == Self::DISABLED_ID
+        self.proc_macro_id == Self::DISABLED_ID
+    }
+
+    /// The macro is explicitly disabled due to proc-macro attribute expansion being disabled.
+    pub const fn is_disabled_proc_attr(&self) -> bool {
+        self.proc_macro_id == Self::PROC_MACRO_ATTR_DISABLED
+    }
+
+    /// The macro is explicitly disabled due to proc-macro attribute expansion being disabled.
+    pub const fn as_expand_error(&self, def_crate: CrateId) -> Option {
+        match self.proc_macro_id {
+            Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandError::ProcMacroAttrExpansionDisabled),
+            Self::DISABLED_ID => Some(ExpandError::MacroDisabled),
+            Self::MISSING_EXPANDER => Some(ExpandError::MissingProcMacroExpander(def_crate)),
+            _ => None,
+        }
     }
 
     pub fn expand(
@@ -107,38 +205,27 @@ impl CustomProcMacroExpander {
         mixed_site: Span,
     ) -> ExpandResult {
         match self.proc_macro_id {
-            ProcMacroId(Self::DUMMY_ID) => ExpandResult::new(
+            Self::PROC_MACRO_ATTR_DISABLED => ExpandResult::new(
+                tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
+                ExpandError::ProcMacroAttrExpansionDisabled,
+            ),
+            Self::MISSING_EXPANDER => ExpandResult::new(
                 tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
-                ExpandError::UnresolvedProcMacro(def_crate),
+                ExpandError::MissingProcMacroExpander(def_crate),
             ),
-            ProcMacroId(Self::DISABLED_ID) => ExpandResult::new(
+            Self::DISABLED_ID => ExpandResult::new(
                 tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
                 ExpandError::MacroDisabled,
             ),
-            ProcMacroId(id) => {
+            id => {
                 let proc_macros = db.proc_macros();
-                let proc_macros = match proc_macros.get(&def_crate) {
-                    Some(Ok(proc_macros)) => proc_macros,
-                    Some(Err(_)) | None => {
-                        never!("Non-dummy expander even though there are no proc macros");
-                        return ExpandResult::new(
-                            tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
-                            ExpandError::other("Internal error"),
-                        );
-                    }
-                };
-                let proc_macro = match proc_macros.get(id as usize) {
-                    Some(proc_macro) => proc_macro,
-                    None => {
-                        never!(
-                            "Proc macro index out of bounds: the length is {} but the index is {}",
-                            proc_macros.len(),
-                            id
-                        );
+                let proc_macro = match proc_macros.get(def_crate, id) {
+                    Ok(proc_macro) => proc_macro,
+                    Err(e) => {
                         return ExpandResult::new(
                             tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
-                            ExpandError::other("Internal error: proc-macro index out of bounds"),
-                        );
+                            e,
+                        )
                     }
                 };
 
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index 72272934ab7a3..4bb8c140a1f20 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -6,7 +6,6 @@
 pub use hir_ty::diagnostics::{CaseType, IncorrectCase};
 use hir_ty::{db::HirDatabase, diagnostics::BodyValidationDiagnostic, InferenceDiagnostic};
 
-use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 pub use hir_def::VariantId;
@@ -15,7 +14,7 @@ use hir_expand::{name::Name, HirFileId, InFile};
 use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
 use triomphe::Arc;
 
-use crate::{AssocItem, Field, Local, MacroKind, Trait, Type};
+use crate::{AssocItem, Field, Local, Trait, Type};
 
 macro_rules! diagnostics {
     ($($diag:ident,)*) => {
@@ -90,7 +89,6 @@ diagnostics![
     UnresolvedMethodCall,
     UnresolvedModule,
     UnresolvedIdent,
-    UnresolvedProcMacro,
     UnusedMut,
     UnusedVariable,
 ];
@@ -150,23 +148,12 @@ pub struct InactiveCode {
     pub opts: CfgOptions,
 }
 
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct UnresolvedProcMacro {
-    pub node: InFile,
-    /// If the diagnostic can be pinpointed more accurately than via `node`, this is the `TextRange`
-    /// to use instead.
-    pub precise_location: Option,
-    pub macro_name: Option,
-    pub kind: MacroKind,
-    /// The crate id of the proc-macro this macro belongs to, or `None` if the proc-macro can't be found.
-    pub krate: CrateId,
-}
-
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct MacroError {
     pub node: InFile,
     pub precise_location: Option,
     pub message: String,
+    pub error: bool,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 70f4a632fb3ec..875cf87cb832c 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -137,7 +137,7 @@ pub use {
         hygiene::{marks_rev, SyntaxContextExt},
         inert_attr_macro::AttributeTemplate,
         name::Name,
-        proc_macro::ProcMacros,
+        proc_macro::{ProcMacros, ProcMacrosBuilder},
         tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt,
     },
     hir_ty::{
@@ -833,14 +833,10 @@ fn macro_call_diagnostics(
     let ValueResult { value: parse_errors, err } = &*e;
     if let Some(err) = err {
         let loc = db.lookup_intern_macro_call(macro_call_id);
-        let (node, precise_location, macro_name, kind) = precise_macro_call_location(&loc.kind, db);
-        let diag = match err {
-            &hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
-                UnresolvedProcMacro { node, precise_location, macro_name, kind, krate }.into()
-            }
-            err => MacroError { node, precise_location, message: err.to_string() }.into(),
-        };
-        acc.push(diag);
+        let (node, precise_location, _macro_name, _kind) =
+            precise_macro_call_location(&loc.kind, db);
+        let (message, error) = err.render_to_string(db.upcast());
+        acc.push(MacroError { node, precise_location, message, error }.into());
     }
 
     if !parse_errors.is_empty() {
@@ -895,6 +891,19 @@ fn emit_def_diagnostic_(
             acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
         }
 
+        DefDiagnosticKind::MacroError { ast, err } => {
+            let item = ast.to_ptr(db.upcast());
+            let (message, error) = err.render_to_string(db.upcast());
+            acc.push(
+                MacroError {
+                    node: InFile::new(ast.file_id, item.syntax_node_ptr()),
+                    precise_location: None,
+                    message,
+                    error,
+                }
+                .into(),
+            )
+        }
         DefDiagnosticKind::UnresolvedImport { id, index } => {
             let file_id = id.file_id();
             let item_tree = id.item_tree(db.upcast());
@@ -991,13 +1000,6 @@ fn emit_def_diagnostic_(
                 Some(())
             })();
         }
-        DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
-            let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
-            acc.push(
-                UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
-                    .into(),
-            );
-        }
         DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
             let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
             acc.push(
@@ -1795,20 +1797,17 @@ impl DefWithBody {
                 BodyDiagnostic::InactiveCode { node, cfg, opts } => {
                     InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into()
                 }
-                BodyDiagnostic::MacroError { node, message } => MacroError {
-                    node: (*node).map(|it| it.into()),
-                    precise_location: None,
-                    message: message.to_string(),
-                }
-                .into(),
-                BodyDiagnostic::UnresolvedProcMacro { node, krate } => UnresolvedProcMacro {
-                    node: (*node).map(|it| it.into()),
-                    precise_location: None,
-                    macro_name: None,
-                    kind: MacroKind::ProcMacro,
-                    krate: *krate,
+                BodyDiagnostic::MacroError { node, err } => {
+                    let (message, error) = err.render_to_string(db.upcast());
+
+                    MacroError {
+                        node: (*node).map(|it| it.into()),
+                        precise_location: None,
+                        message,
+                        error,
+                    }
+                    .into()
                 }
-                .into(),
                 BodyDiagnostic::UnresolvedMacroCall { node, path } => UnresolvedMacroCall {
                     macro_call: (*node).map(|ast_ptr| ast_ptr.into()),
                     precise_location: None,
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index c053a659b3fab..29f98972dcd82 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -19,7 +19,7 @@ use hir_def::{
 };
 use hir_expand::{
     attrs::collect_attrs,
-    builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
+    builtin::{BuiltinFnLikeExpander, EagerExpander},
     db::ExpandDatabase,
     files::InRealFile,
     name::AsName,
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
index 2cd6a71c001cf..702fba448a0b4 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
@@ -7,7 +7,10 @@ pub(crate) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) ->
     // Use more accurate position if available.
     let display_range = ctx.resolve_precise_location(&d.node, d.precise_location);
     Diagnostic::new(
-        DiagnosticCode::Ra("macro-error", Severity::Error),
+        DiagnosticCode::Ra(
+            "macro-error",
+            if d.error { Severity::Error } else { Severity::WeakWarning },
+        ),
         d.message.clone(),
         display_range,
     )
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
deleted file mode 100644
index 7ea50c496fbcb..0000000000000
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use hir::db::DefDatabase;
-
-use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, Severity};
-
-// Diagnostic: unresolved-proc-macro
-//
-// This diagnostic is shown when a procedural macro can not be found. This usually means that
-// procedural macro support is simply disabled (and hence is only a weak hint instead of an error),
-// but can also indicate project setup problems.
-//
-// If you are seeing a lot of "proc macro not expanded" warnings, you can add this option to the
-// `rust-analyzer.diagnostics.disabled` list to prevent them from showing. Alternatively you can
-// enable support for procedural macros (see `rust-analyzer.procMacro.attributes.enable`).
-pub(crate) fn unresolved_proc_macro(
-    ctx: &DiagnosticsContext<'_>,
-    d: &hir::UnresolvedProcMacro,
-    proc_macros_enabled: bool,
-    proc_attr_macros_enabled: bool,
-) -> Diagnostic {
-    // Use more accurate position if available.
-    let display_range = ctx.resolve_precise_location(&d.node, d.precise_location);
-
-    let config_enabled = match d.kind {
-        hir::MacroKind::Attr => proc_macros_enabled && proc_attr_macros_enabled,
-        _ => proc_macros_enabled,
-    };
-
-    let not_expanded_message = match &d.macro_name {
-        Some(name) => format!("proc macro `{name}` not expanded"),
-        None => "proc macro not expanded".to_owned(),
-    };
-    let severity = if config_enabled { Severity::Error } else { Severity::WeakWarning };
-    let def_map = ctx.sema.db.crate_def_map(d.krate);
-    let message = if config_enabled {
-        def_map.proc_macro_loading_error().unwrap_or("internal error")
-    } else {
-        match d.kind {
-            hir::MacroKind::Attr if proc_macros_enabled => "attribute macro expansion is disabled",
-            _ => "proc-macro expansion is disabled",
-        }
-    };
-    let message = format!("{not_expanded_message}: {message}");
-
-    Diagnostic::new(DiagnosticCode::Ra("unresolved-proc-macro", severity), message, display_range)
-}
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 9523cc81b8f88..263ab74755999 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -62,7 +62,6 @@ mod handlers {
     pub(crate) mod unresolved_macro_call;
     pub(crate) mod unresolved_method;
     pub(crate) mod unresolved_module;
-    pub(crate) mod unresolved_proc_macro;
     pub(crate) mod unused_variables;
 
     // The handlers below are unusual, the implement the diagnostics as well.
@@ -405,7 +404,6 @@ pub fn diagnostics(
             AnyDiagnostic::UnresolvedMacroCall(d) => handlers::unresolved_macro_call::unresolved_macro_call(&ctx, &d),
             AnyDiagnostic::UnresolvedMethodCall(d) => handlers::unresolved_method::unresolved_method(&ctx, &d),
             AnyDiagnostic::UnresolvedModule(d) => handlers::unresolved_module::unresolved_module(&ctx, &d),
-            AnyDiagnostic::UnresolvedProcMacro(d) => handlers::unresolved_proc_macro::unresolved_proc_macro(&ctx, &d, config.proc_macros_enabled, config.proc_attr_macros_enabled),
             AnyDiagnostic::UnusedMut(d) => match handlers::mutability_errors::unused_mut(&ctx, &d) {
                 Some(it) => it,
                 None => continue,
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 34a6f154db7d0..8cb81a9cc452c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -43,7 +43,6 @@ mod parent_module;
 mod references;
 mod rename;
 mod runnables;
-mod shuffle_crate_graph;
 mod signature_help;
 mod ssr;
 mod static_index;
@@ -202,10 +201,6 @@ impl AnalysisHost {
     pub fn raw_database_mut(&mut self) -> &mut RootDatabase {
         &mut self.db
     }
-
-    pub fn shuffle_crate_graph(&mut self) {
-        shuffle_crate_graph::shuffle_crate_graph(&mut self.db);
-    }
 }
 
 impl Default for AnalysisHost {
diff --git a/src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs
deleted file mode 100644
index 453d1836e16e4..0000000000000
--- a/src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use hir::{db::ExpandDatabase, ProcMacros};
-use ide_db::{
-    base_db::{salsa::Durability, CrateGraph, SourceDatabase},
-    FxHashMap, RootDatabase,
-};
-use triomphe::Arc;
-
-// Feature: Shuffle Crate Graph
-//
-// Randomizes all crate IDs in the crate graph, for debugging.
-//
-// |===
-// | Editor  | Action Name
-//
-// | VS Code | **rust-analyzer: Shuffle Crate Graph**
-// |===
-pub(crate) fn shuffle_crate_graph(db: &mut RootDatabase) {
-    let crate_graph = db.crate_graph();
-    let proc_macros = db.proc_macros();
-
-    let mut shuffled_ids = crate_graph.iter().collect::>();
-
-    let mut rng = oorandom::Rand32::new(stdx::rand::seed());
-    stdx::rand::shuffle(&mut shuffled_ids, |i| rng.rand_range(0..i as u32) as usize);
-
-    let mut new_graph = CrateGraph::default();
-    let mut new_proc_macros = ProcMacros::default();
-
-    let mut map = FxHashMap::default();
-    for old_id in shuffled_ids.iter().copied() {
-        let data = &crate_graph[old_id];
-        let new_id = new_graph.add_crate_root(
-            data.root_file_id,
-            data.edition,
-            data.display_name.clone(),
-            data.version.clone(),
-            data.cfg_options.clone(),
-            data.potential_cfg_options.clone(),
-            data.env.clone(),
-            data.is_proc_macro,
-            data.origin.clone(),
-        );
-        new_proc_macros.insert(new_id, proc_macros[&old_id].clone());
-        map.insert(old_id, new_id);
-    }
-
-    for old_id in shuffled_ids.iter().copied() {
-        let data = &crate_graph[old_id];
-        for dep in &data.dependencies {
-            let mut new_dep = dep.clone();
-            new_dep.crate_id = map[&dep.crate_id];
-            new_graph.add_dep(map[&old_id], new_dep).unwrap();
-        }
-    }
-
-    db.set_crate_graph_with_durability(Arc::new(new_graph), Durability::HIGH);
-    db.set_proc_macros_with_durability(Arc::new(new_proc_macros), Durability::HIGH);
-}
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index 9ad5c68a5599e..8737f2246be59 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -68,11 +68,14 @@ pub fn load_workspace(
     let proc_macro_server = match &load_config.with_proc_macro_server {
         ProcMacroServerChoice::Sysroot => ws
             .find_sysroot_proc_macro_srv()
-            .and_then(|it| ProcMacroServer::spawn(&it, extra_env).map_err(Into::into)),
+            .and_then(|it| ProcMacroServer::spawn(&it, extra_env).map_err(Into::into))
+            .map_err(|e| (e, true)),
         ProcMacroServerChoice::Explicit(path) => {
-            ProcMacroServer::spawn(path, extra_env).map_err(Into::into)
+            ProcMacroServer::spawn(path, extra_env).map_err(Into::into).map_err(|e| (e, true))
+        }
+        ProcMacroServerChoice::None => {
+            Err((anyhow::format_err!("proc macro server disabled"), false))
         }
-        ProcMacroServerChoice::None => Err(anyhow::format_err!("proc macro server disabled")),
     };
 
     let (crate_graph, proc_macros) = ws.to_crate_graph(
@@ -87,7 +90,7 @@ pub fn load_workspace(
     let proc_macros = {
         let proc_macro_server = match &proc_macro_server {
             Ok(it) => Ok(it),
-            Err(e) => Err(e.to_string()),
+            Err((e, hard_err)) => Err((e.to_string(), *hard_err)),
         };
         proc_macros
             .into_iter()
@@ -95,7 +98,7 @@ pub fn load_workspace(
                 (
                     crate_id,
                     path.map_or_else(
-                        |_| Err("proc macro crate is missing dylib".to_owned()),
+                        |e| Err((e, true)),
                         |(_, path)| {
                             proc_macro_server.as_ref().map_err(Clone::clone).and_then(
                                 |proc_macro_server| load_proc_macro(proc_macro_server, &path, &[]),
@@ -355,8 +358,7 @@ impl SourceRootConfig {
     }
 }
 
-/// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace`
-/// with an identity dummy expander.
+/// Load the proc-macros for the given lib path, disabling all expanders whose names are in `ignored_macros`.
 pub fn load_proc_macro(
     server: &ProcMacroServer,
     path: &AbsPath,
@@ -383,7 +385,7 @@ pub fn load_proc_macro(
         }
         Err(e) => {
             tracing::warn!("proc-macro loading for {path} failed: {e}");
-            Err(e)
+            Err((e, true))
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index bfbdf0383572e..31d1c77fd07c4 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -934,7 +934,10 @@ fn project_json_to_crate_graph(
                 if *is_proc_macro {
                     if let Some(path) = proc_macro_dylib_path.clone() {
                         let node = Ok((
-                            display_name.as_ref().map(|it| it.canonical_name().as_str().to_owned()),
+                            display_name
+                                .as_ref()
+                                .map(|it| it.canonical_name().as_str().to_owned())
+                                .unwrap_or_else(|| format!("crate{}", idx.0)),
                             path,
                         ));
                         proc_macros.insert(crate_graph_crate_id, node);
@@ -1355,8 +1358,8 @@ fn add_target_crate_root(
     );
     if let TargetKind::Lib { is_proc_macro: true } = kind {
         let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
-            Some(it) => it.cloned().map(|path| Ok((Some(cargo_name.to_owned()), path))),
-            None => Some(Err("crate has not yet been built".to_owned())),
+            Some(it) => it.cloned().map(|path| Ok((cargo_name.to_owned(), path))),
+            None => Some(Err("proc-macro crate is missing its build data".to_owned())),
         };
         if let Some(proc_macro) = proc_macro {
             proc_macros.insert(crate_id, proc_macro);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 44ff273b5ae00..f92ed67ae9560 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -134,11 +134,6 @@ pub(crate) fn handle_memory_usage(state: &mut GlobalState, _: ()) -> anyhow::Res
     Ok(out)
 }
 
-pub(crate) fn handle_shuffle_crate_graph(state: &mut GlobalState, _: ()) -> anyhow::Result<()> {
-    state.analysis_host.shuffle_crate_graph();
-    Ok(())
-}
-
 pub(crate) fn handle_syntax_tree(
     snap: GlobalStateSnapshot,
     params: lsp_ext::SyntaxTreeParams,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index 813e9fcd476a5..1fcb636f85606 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -75,14 +75,6 @@ impl Request for MemoryUsage {
     const METHOD: &'static str = "rust-analyzer/memoryUsage";
 }
 
-pub enum ShuffleCrateGraph {}
-
-impl Request for ShuffleCrateGraph {
-    type Params = ();
-    type Result = ();
-    const METHOD: &'static str = "rust-analyzer/shuffleCrateGraph";
-}
-
 pub enum ReloadWorkspace {}
 
 impl Request for ReloadWorkspace {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index e64095ba9eebb..ccc786a21d588 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -1018,7 +1018,6 @@ impl GlobalState {
             .on_sync_mut::(handlers::handle_workspace_reload)
             .on_sync_mut::(handlers::handle_proc_macros_rebuild)
             .on_sync_mut::(handlers::handle_memory_usage)
-            .on_sync_mut::(handlers::handle_shuffle_crate_graph)
             .on_sync_mut::(handlers::handle_run_test)
             // Request handlers which are related to the user typing
             // are run on the main thread to reduce latency:
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index fb16f28a14bd4..c2463e0ebe24b 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -16,8 +16,7 @@
 use std::{iter, mem};
 
 use flycheck::{FlycheckConfig, FlycheckHandle};
-use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros};
-use ide::CrateId;
+use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros, ProcMacrosBuilder};
 use ide_db::{
     base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version},
     FxHashMap,
@@ -371,43 +370,44 @@ impl GlobalState {
                 }
             };
 
-            let mut res = FxHashMap::default();
+            let mut builder = ProcMacrosBuilder::default();
             let chain = proc_macro_clients
                 .iter()
                 .map(|res| res.as_ref().map_err(|e| e.to_string()))
-                .chain(iter::repeat_with(|| Err("Proc macros servers are not running".into())));
+                .chain(iter::repeat_with(|| Err("proc-macro-srv is not running".into())));
             for (client, paths) in chain.zip(paths) {
-                res.extend(paths.into_iter().map(move |(crate_id, res)| {
-                    (
-                        crate_id,
-                        res.map_or_else(
-                            |_| Err("proc macro crate is missing dylib".to_owned()),
-                            |(crate_name, path)| {
-                                progress(path.to_string());
-                                client.as_ref().map_err(Clone::clone).and_then(|client| {
-                                    load_proc_macro(
-                                        client,
-                                        &path,
-                                        crate_name
-                                            .as_deref()
-                                            .and_then(|crate_name| {
-                                                ignored_proc_macros.iter().find_map(
-                                                    |(name, macros)| {
-                                                        eq_ignore_underscore(name, crate_name)
+                paths
+                    .into_iter()
+                    .map(move |(crate_id, res)| {
+                        (
+                            crate_id,
+                            res.map_or_else(
+                                |e| Err((e, true)),
+                                |(crate_name, path)| {
+                                    progress(path.to_string());
+                                    client.as_ref().map_err(|it| (it.clone(), true)).and_then(
+                                        |client| {
+                                            load_proc_macro(
+                                                client,
+                                                &path,
+                                                ignored_proc_macros
+                                                    .iter()
+                                                    .find_map(|(name, macros)| {
+                                                        eq_ignore_underscore(name, &crate_name)
                                                             .then_some(&**macros)
-                                                    },
-                                                )
-                                            })
-                                            .unwrap_or_default(),
+                                                    })
+                                                    .unwrap_or_default(),
+                                            )
+                                        },
                                     )
-                                })
-                            },
-                        ),
-                    )
-                }));
+                                },
+                            ),
+                        )
+                    })
+                    .for_each(|(krate, res)| builder.insert(krate, res));
             }
 
-            sender.send(Task::LoadProcMacros(ProcMacroProgress::End(res))).unwrap();
+            sender.send(Task::LoadProcMacros(ProcMacroProgress::End(builder.build()))).unwrap();
         });
     }
 
@@ -667,10 +667,17 @@ impl GlobalState {
             change.set_proc_macros(
                 crate_graph
                     .iter()
-                    .map(|id| (id, Err("Proc-macros have not been built yet".to_owned())))
+                    .map(|id| (id, Err(("proc-macro has not been built yet".to_owned(), true))))
                     .collect(),
             );
             self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
+        } else {
+            change.set_proc_macros(
+                crate_graph
+                    .iter()
+                    .map(|id| (id, Err(("proc-macro expansion is disabled".to_owned(), false))))
+                    .collect(),
+            );
         }
         change.set_crate_graph(crate_graph);
         change.set_target_data_layouts(layouts);
@@ -809,12 +816,7 @@ pub fn ws_to_crate_graph(
     workspaces: &[ProjectWorkspace],
     extra_env: &FxHashMap,
     mut load: impl FnMut(&AbsPath) -> Option,
-) -> (
-    CrateGraph,
-    Vec, AbsPathBuf), String>>>,
-    Vec, Arc>>,
-    Vec>,
-) {
+) -> (CrateGraph, Vec, Vec, Arc>>, Vec>) {
     let mut crate_graph = CrateGraph::default();
     let mut proc_macro_paths = Vec::default();
     let mut layouts = Vec::default();
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index c10ff4aede581..e1f40f5da0116 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -1,5 +1,5 @@
 //! A set of high-level utility fixture methods to use in tests.
-use std::{iter, mem, ops::Not, str::FromStr, sync};
+use std::{iter, mem, str::FromStr, sync};
 
 use base_db::{
     CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileChange,
@@ -11,7 +11,7 @@ use hir_expand::{
     db::ExpandDatabase,
     files::FilePosition,
     proc_macro::{
-        ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacros,
+        ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacrosBuilder,
     },
     FileRange,
 };
@@ -303,7 +303,7 @@ impl ChangeFixture {
             }
         }
 
-        let mut proc_macros = ProcMacros::default();
+        let mut proc_macros = ProcMacrosBuilder::default();
         if !proc_macro_names.is_empty() {
             let proc_lib_file = file_id;
 
@@ -354,7 +354,7 @@ impl ChangeFixture {
 
         let mut change = ChangeWithProcMacros {
             source_change,
-            proc_macros: proc_macros.is_empty().not().then_some(proc_macros),
+            proc_macros: Some(proc_macros.build()),
             toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()),
             target_data_layouts: Some(
                 iter::repeat(target_data_layout).take(crate_graph.len()).collect(),
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index a29b42a857c95..e559f88e23353 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
  $DIR/box.rs:LL:CC
-   |
-LL |         let r2 = ((r as usize) + 0) as *mut i32;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
-   |
-   = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
-   = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
-   = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
-   = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
-   = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
-   = note: BACKTRACE:
-   = note: inside `into_raw` at $DIR/box.rs:LL:CC
-note: inside `main`
-  --> $DIR/box.rs:LL:CC
-   |
-LL |     into_raw();
-   |     ^^^^^^^^^^
-
-warning: integer-to-pointer cast
-  --> $DIR/box.rs:LL:CC
-   |
-LL |         let r = ((u.as_ptr() as usize) + 0) as *mut i32;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
-   |
-   = note: BACKTRACE:
-   = note: inside `into_unique` at $DIR/box.rs:LL:CC
-note: inside `main`
-  --> $DIR/box.rs:LL:CC
-   |
-LL |     into_unique();
-   |     ^^^^^^^^^^^^^
-
diff --git a/src/tools/miri/tests/pass/box.stack.stdout b/src/tools/miri/tests/pass/box.stdout
similarity index 100%
rename from src/tools/miri/tests/pass/box.stack.stdout
rename to src/tools/miri/tests/pass/box.stdout
diff --git a/src/tools/miri/tests/pass/box.tree.stdout b/src/tools/miri/tests/pass/box.tree.stdout
deleted file mode 100644
index 230ef368da644..0000000000000
--- a/src/tools/miri/tests/pass/box.tree.stdout
+++ /dev/null
@@ -1,3 +0,0 @@
-pair_foo = PairFoo { fst: Foo(42), snd: Foo(1337) }
-foo #0 = Foo(42)
-foo #1 = Foo(1337)
diff --git a/src/tools/miri/tests/pass/extern_types.rs b/src/tools/miri/tests/pass/extern_types.rs
index 7ac93577f0cd5..eade5c6ac0874 100644
--- a/src/tools/miri/tests/pass/extern_types.rs
+++ b/src/tools/miri/tests/pass/extern_types.rs
@@ -1,12 +1,14 @@
 //@revisions: stack tree
-//@[tree]compile-flags: -Zmiri-tree-borrows -Zmiri-permissive-provenance
-#![feature(extern_types)]
+//@[tree]compile-flags: -Zmiri-tree-borrows
+#![feature(extern_types, strict_provenance)]
+
+use std::ptr;
 
 extern "C" {
     type Foo;
 }
 
 fn main() {
-    let x: &Foo = unsafe { &*(16 as *const Foo) };
+    let x: &Foo = unsafe { &*(ptr::without_provenance::<()>(16) as *const Foo) };
     let _y: &Foo = &*x;
 }
diff --git a/src/tools/miri/tests/pass/extern_types.stack.stderr b/src/tools/miri/tests/pass/extern_types.stack.stderr
index 9b6f632eb5a22..2c9fc0192af83 100644
--- a/src/tools/miri/tests/pass/extern_types.stack.stderr
+++ b/src/tools/miri/tests/pass/extern_types.stack.stderr
@@ -1,22 +1,8 @@
-warning: integer-to-pointer cast
-  --> $DIR/extern_types.rs:LL:CC
-   |
-LL |     let x: &Foo = unsafe { &*(16 as *const Foo) };
-   |                              ^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
-   |
-   = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
-   = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
-   = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
-   = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
-   = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
-   = note: BACKTRACE:
-   = note: inside `main` at $DIR/extern_types.rs:LL:CC
-
 warning: reborrow of reference to `extern type`
   --> $DIR/extern_types.rs:LL:CC
    |
-LL |     let x: &Foo = unsafe { &*(16 as *const Foo) };
-   |                            ^^^^^^^^^^^^^^^^^^^^ reborrow of a reference to `extern type` is not properly supported
+LL |     let x: &Foo = unsafe { &*(ptr::without_provenance::<()>(16) as *const Foo) };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reborrow of a reference to `extern type` is not properly supported
    |
    = help: `extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code
    = help: try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead
diff --git a/src/tools/miri/tests/pass/intptrcast.rs b/src/tools/miri/tests/pass/intptrcast.rs
index fb1a1dfae5d14..a304f2751bdb6 100644
--- a/src/tools/miri/tests/pass/intptrcast.rs
+++ b/src/tools/miri/tests/pass/intptrcast.rs
@@ -1,5 +1,3 @@
-//@revisions: stack tree
-//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 
 use std::mem;
diff --git a/src/tools/miri/tests/pass/pointers.rs b/src/tools/miri/tests/pass/pointers.rs
index c7b720dafa20b..280a815abc430 100644
--- a/src/tools/miri/tests/pass/pointers.rs
+++ b/src/tools/miri/tests/pass/pointers.rs
@@ -1,5 +1,3 @@
-//@revisions: stack tree
-//@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 #![feature(ptr_metadata, const_raw_ptr_comparison)]
 #![allow(ambiguous_wide_pointer_comparisons)]
diff --git a/src/tools/miri/tests/pass/ptr_int_casts.rs b/src/tools/miri/tests/pass/ptr_int_casts.rs
index a2fcd098107a6..684e8f6ec7bdd 100644
--- a/src/tools/miri/tests/pass/ptr_int_casts.rs
+++ b/src/tools/miri/tests/pass/ptr_int_casts.rs
@@ -1,6 +1,7 @@
 //@revisions: stack tree
+// Tree Borrows doesn't support int2ptr casts, but let's make sure we don't immediately crash either.
 //@[tree]compile-flags: -Zmiri-tree-borrows
-//@compile-flags: -Zmiri-permissive-provenance
+//@[stack]compile-flags: -Zmiri-permissive-provenance
 use std::mem;
 use std::ptr;
 
diff --git a/src/tools/miri/tests/pass/ptr_int_casts.tree.stderr b/src/tools/miri/tests/pass/ptr_int_casts.tree.stderr
new file mode 100644
index 0000000000000..a34474ee0d627
--- /dev/null
+++ b/src/tools/miri/tests/pass/ptr_int_casts.tree.stderr
@@ -0,0 +1,89 @@
+warning: integer-to-pointer cast
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     assert_eq!(1 as *const i32 as usize, 1);
+   |                ^^^^^^^^^^^^^^^ integer-to-pointer cast
+   |
+   = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+   = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+   = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+   = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+   = help: Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used
+   = note: BACKTRACE:
+   = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     ptr_int_casts();
+   |     ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     assert_eq!((1 as *const i32).wrapping_offset(4) as usize, 1 + 4 * 4);
+   |                ^^^^^^^^^^^^^^^^^ integer-to-pointer cast
+   |
+   = note: BACKTRACE:
+   = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     ptr_int_casts();
+   |     ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     *val = (1 as *const u8).wrapping_offset(-4);
+   |            ^^^^^^^^^^^^^^^^ integer-to-pointer cast
+   |
+   = note: BACKTRACE:
+   = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     ptr_int_casts();
+   |     ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |         let y = y as *const _;
+   |                 ^^^^^^^^^^^^^ integer-to-pointer cast
+   |
+   = note: BACKTRACE:
+   = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     ptr_int_casts();
+   |     ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |         let x: fn() -> i32 = unsafe { mem::transmute(y as *mut u8) };
+   |                                                      ^^^^^^^^^^^^ integer-to-pointer cast
+   |
+   = note: BACKTRACE:
+   = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     ptr_int_casts();
+   |     ^^^^^^^^^^^^^^^
+
+warning: integer-to-pointer cast
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     assert_eq!((-1i32) as usize as *const i32 as usize, (-1i32) as usize);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
+   |
+   = note: BACKTRACE:
+   = note: inside `ptr_int_casts` at $DIR/ptr_int_casts.rs:LL:CC
+note: inside `main`
+  --> $DIR/ptr_int_casts.rs:LL:CC
+   |
+LL |     ptr_int_casts();
+   |     ^^^^^^^^^^^^^^^
+
diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
index 5690d7865bbc3..f6ebf0632a179 100644
--- a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
+++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
@@ -1,6 +1,7 @@
 //@revisions: stack tree
+// Tree Borrows doesn't support int2ptr casts, but let's make sure we don't immediately crash either.
 //@[tree]compile-flags: -Zmiri-tree-borrows
-//@compile-flags: -Zmiri-permissive-provenance
+//@[stack]compile-flags: -Zmiri-permissive-provenance
 #![feature(strict_provenance, exposed_provenance)]
 
 use std::ptr;
diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.tree.stderr b/src/tools/miri/tests/pass/ptr_int_from_exposed.tree.stderr
new file mode 100644
index 0000000000000..614b0d26a6304
--- /dev/null
+++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.tree.stderr
@@ -0,0 +1,19 @@
+warning: integer-to-pointer cast
+  --> $DIR/ptr_int_from_exposed.rs:LL:CC
+   |
+LL |     let ptr = ptr::with_exposed_provenance::(x_usize).wrapping_offset(-128);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
+   |
+   = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
+   = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
+   = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
+   = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
+   = help: Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used
+   = note: BACKTRACE:
+   = note: inside `ptr_roundtrip_out_of_bounds` at $DIR/ptr_int_from_exposed.rs:LL:CC
+note: inside `main`
+  --> $DIR/ptr_int_from_exposed.rs:LL:CC
+   |
+LL |     ptr_roundtrip_out_of_bounds();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+

From 5e1f8e2d07d2a32a1f234cf80efcb703aa87a989 Mon Sep 17 00:00:00 2001
From: Ralf Jung 
Date: Fri, 26 Jul 2024 09:06:58 +0200
Subject: [PATCH 155/489] diagnostics: add a macro to make things a bit easier
 to read

---
 src/tools/miri/src/diagnostics.rs | 135 +++++++++++++-----------------
 1 file changed, 59 insertions(+), 76 deletions(-)

diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 6d10a21293b65..1bed55743d4af 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -140,6 +140,15 @@ pub enum DiagLevel {
     Note,
 }
 
+/// Generate a note/help text without a span.
+macro_rules! note {
+    ($($tt:tt)*) => { (None, format!($($tt)*)) };
+}
+/// Generate a note/help text with a span.
+macro_rules! note_span {
+    ($span:expr, $($tt:tt)*) => { (Some($span), format!($($tt)*)) };
+}
+
 /// Attempts to prune a stacktrace to omit the Rust runtime, and returns a bool indicating if any
 /// frames were pruned. If the stacktrace does not have any local frames, we conclude that it must
 /// be pointing to a problem in the Rust runtime itself, and do not prune it at all.
@@ -228,38 +237,38 @@ pub fn report_error<'tcx>(
         let helps = match info {
             UnsupportedInIsolation(_) =>
                 vec![
-                    (None, format!("set `MIRIFLAGS=-Zmiri-disable-isolation` to disable isolation;")),
-                    (None, format!("or set `MIRIFLAGS=-Zmiri-isolation-error=warn` to make Miri return an error code from isolated operations (if supported for that operation) and continue with a warning")),
+                    note!("set `MIRIFLAGS=-Zmiri-disable-isolation` to disable isolation;"),
+                    note!("or set `MIRIFLAGS=-Zmiri-isolation-error=warn` to make Miri return an error code from isolated operations (if supported for that operation) and continue with a warning"),
                 ],
             UnsupportedForeignItem(_) => {
                 vec![
-                    (None, format!("if this is a basic API commonly used on this target, please report an issue with Miri")),
-                    (None, format!("however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases")),
+                    note!("if this is a basic API commonly used on this target, please report an issue with Miri"),
+                    note!("however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases"),
                 ]
             }
             StackedBorrowsUb { help, history, .. } => {
                 msg.extend(help.clone());
                 let mut helps = vec![
-                    (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental")),
-                    (None, format!("see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information")),
+                    note!("this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental"),
+                    note!("see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information"),
                 ];
                 if let Some(TagHistory {created, invalidated, protected}) = history.clone() {
                     helps.push((Some(created.1), created.0));
                     if let Some((msg, span)) = invalidated {
-                        helps.push((Some(span), msg));
+                        helps.push(note_span!(span, "{msg}"));
                     }
                     if let Some((protector_msg, protector_span)) = protected {
-                        helps.push((Some(protector_span), protector_msg));
+                        helps.push(note_span!(protector_span, "{protector_msg}"));
                     }
                 }
                 helps
             },
             TreeBorrowsUb { title: _, details, history } => {
                 let mut helps = vec![
-                    (None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental"))
+                    note!("this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental")
                 ];
                 for m in details {
-                    helps.push((None, m.clone()));
+                    helps.push(note!("{m}"));
                 }
                 for event in history.events.clone() {
                     helps.push(event);
@@ -268,26 +277,26 @@ pub fn report_error<'tcx>(
             }
             MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
                 vec![
-                    (Some(*first), format!("it's first defined here, in crate `{first_crate}`")),
-                    (Some(*second), format!("then it's defined here again, in crate `{second_crate}`")),
+                    note_span!(*first, "it's first defined here, in crate `{first_crate}`"),
+                    note_span!(*second, "then it's defined here again, in crate `{second_crate}`"),
                 ],
             SymbolShimClashing { link_name, span } =>
-                vec![(Some(*span), format!("the `{link_name}` symbol is defined here"))],
+                vec![note_span!(*span, "the `{link_name}` symbol is defined here")],
             Int2PtrWithStrictProvenance =>
-                vec![(None, format!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"))],
+                vec![note!("use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead")],
             DataRace { op1, extra, retag_explain, .. } => {
-                let mut helps = vec![(Some(op1.span), format!("and (1) occurred earlier here"))];
+                let mut helps = vec![note_span!(op1.span, "and (1) occurred earlier here")];
                 if let Some(extra) = extra {
-                    helps.push((None, format!("{extra}")));
-                    helps.push((None, format!("see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model")));
+                    helps.push(note!("{extra}"));
+                    helps.push(note!("see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model"));
                 }
                 if *retag_explain {
-                    helps.push((None, "retags occur on all (re)borrows and as well as when references are copied or moved".to_owned()));
-                    helps.push((None, "retags permit optimizations that insert speculative reads or writes".to_owned()));
-                    helps.push((None, "therefore from the perspective of data races, a retag has the same implications as a read or write".to_owned()));
+                    helps.push(note!("retags occur on all (re)borrows and as well as when references are copied or moved"));
+                    helps.push(note!("retags permit optimizations that insert speculative reads or writes"));
+                    helps.push(note!("therefore from the perspective of data races, a retag has the same implications as a read or write"));
                 }
-                helps.push((None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")));
-                helps.push((None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")));
+                helps.push(note!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"));
+                helps.push(note!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"));
                 helps
             }
                 ,
@@ -332,32 +341,32 @@ pub fn report_error<'tcx>(
         let helps = match e.kind() {
             Unsupported(_) =>
                 vec![
-                    (None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support")),
+                    note!("this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support"),
                 ],
             UndefinedBehavior(AlignmentCheckFailed { .. })
                 if ecx.machine.check_alignment == AlignmentCheck::Symbolic
             =>
                 vec![
-                    (None, format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior")),
-                    (None, format!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives")),
+                    note!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
+                    note!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives"),
                 ],
             UndefinedBehavior(info) => {
                 let mut helps = vec![
-                    (None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
-                    (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
+                    note!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
+                    note!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
                 ];
                 match info {
                     PointerUseAfterFree(alloc_id, _) | PointerOutOfBounds { alloc_id, .. } => {
                         if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
-                            helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
+                            helps.push(note_span!(span, "{:?} was allocated here:", alloc_id));
                         }
                         if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
-                            helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
+                            helps.push(note_span!(span, "{:?} was deallocated here:", alloc_id));
                         }
                     }
                     AbiMismatchArgument { .. } | AbiMismatchReturn { .. } => {
-                        helps.push((None, format!("this means these two types are not *guaranteed* to be ABI-compatible across all targets")));
-                        helps.push((None, format!("if you think this code should be accepted anyway, please report an issue with Miri")));
+                        helps.push(note!("this means these two types are not *guaranteed* to be ABI-compatible across all targets"));
+                        helps.push(note!("if you think this code should be accepted anyway, please report an issue with Miri"));
                     }
                     _ => {},
                 }
@@ -639,9 +648,7 @@ impl<'tcx> MiriMachine<'tcx> {
 
         let notes = match &e {
             ProgressReport { block_count } => {
-                // It is important that each progress report is slightly different, since
-                // identical diagnostics are being deduplicated.
-                vec![(None, format!("so far, {block_count} basic blocks have been executed"))]
+                vec![note!("so far, {block_count} basic blocks have been executed")]
             }
             _ => vec![],
         };
@@ -649,63 +656,39 @@ impl<'tcx> MiriMachine<'tcx> {
         let helps = match &e {
             Int2Ptr { details: true } => {
                 let mut v = vec![
-                    (
-                        None,
-                        format!(
-                            "this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program"
-                        ),
+                    note!(
+                        "this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program"
                     ),
-                    (
-                        None,
-                        format!(
-                            "see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation"
-                        ),
+                    note!(
+                        "see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation"
                     ),
-                    (
-                        None,
-                        format!(
-                            "to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"
-                        ),
+                    note!(
+                        "to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead"
                     ),
-                    (
-                        None,
-                        format!(
-                            "you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics"
-                        ),
+                    note!(
+                        "you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics"
                     ),
                 ];
                 if self.borrow_tracker.as_ref().is_some_and(|b| {
                     matches!(b.borrow().borrow_tracker_method(), BorrowTrackerMethod::TreeBorrows)
                 }) {
-                    v.push((
-                        None,
-                        format!(
-                            "Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used"
-                        ),
-                    ));
+                    v.push(
+                        note!("Tree Borrows does not support integer-to-pointer casts, so the program is likely to go wrong when this pointer gets used")
+                    );
                 } else {
-                    v.push((
-                        None,
-                        format!(
-                            "alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning"
-                        ),
-                    ));
+                    v.push(
+                        note!("alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning")
+                    );
                 }
                 v
             }
             ExternTypeReborrow => {
                 vec![
-                    (
-                        None,
-                        format!(
-                            "`extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code"
-                        ),
+                    note!(
+                        "`extern type` are not compatible with the Stacked Borrows aliasing model implemented by Miri; Miri may miss bugs in this code"
                     ),
-                    (
-                        None,
-                        format!(
-                            "try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead"
-                        ),
+                    note!(
+                        "try running with `MIRIFLAGS=-Zmiri-tree-borrows` to use the more permissive but also even more experimental Tree Borrows aliasing checks instead"
                     ),
                 ]
             }

From a52b1d6e29475037a677ceab7d5be5f682c90515 Mon Sep 17 00:00:00 2001
From: tiif 
Date: Fri, 26 Jul 2024 21:13:58 +0800
Subject: [PATCH 156/489] Let insert_fd takes in FileDescription instead of
 FileDescriptor

---
 src/tools/miri/src/machine.rs                 |  2 +-
 src/tools/miri/src/shims/unix/fd.rs           | 27 ++++++++++---------
 src/tools/miri/src/shims/unix/fs.rs           | 13 +++------
 src/tools/miri/src/shims/unix/linux/epoll.rs  |  4 +--
 .../miri/src/shims/unix/linux/eventfd.rs      |  6 ++---
 src/tools/miri/src/shims/unix/socket.rs       |  6 ++---
 6 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index adb8459356165..e492793a65135 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -660,7 +660,7 @@ impl<'tcx> MiriMachine<'tcx> {
             tls: TlsData::default(),
             isolated_op: config.isolated_op,
             validate: config.validate,
-            fds: shims::FdTable::new(config.mute_stdout_stderr),
+            fds: shims::FdTable::init(config.mute_stdout_stderr),
             dirs: Default::default(),
             layouts,
             threads,
diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index de6d27f5290db..0fffecd99d5cb 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -192,10 +192,6 @@ impl FileDescription for NullOutput {
 pub struct FileDescriptor(Rc>>);
 
 impl FileDescriptor {
-    pub fn new(fd: T) -> Self {
-        FileDescriptor(Rc::new(RefCell::new(Box::new(fd))))
-    }
-
     pub fn borrow(&self) -> Ref<'_, dyn FileDescription> {
         Ref::map(self.0.borrow(), |fd| fd.as_ref())
     }
@@ -227,20 +223,25 @@ impl VisitProvenance for FdTable {
 }
 
 impl FdTable {
-    pub(crate) fn new(mute_stdout_stderr: bool) -> FdTable {
-        let mut fds: BTreeMap<_, FileDescriptor> = BTreeMap::new();
-        fds.insert(0i32, FileDescriptor::new(io::stdin()));
+    fn new() -> Self {
+        FdTable { fds: BTreeMap::new() }
+    }
+    pub(crate) fn init(mute_stdout_stderr: bool) -> FdTable {
+        let mut fds = FdTable::new();
+        fds.insert_fd(io::stdin());
         if mute_stdout_stderr {
-            fds.insert(1i32, FileDescriptor::new(NullOutput));
-            fds.insert(2i32, FileDescriptor::new(NullOutput));
+            assert_eq!(fds.insert_fd(NullOutput), 1);
+            assert_eq!(fds.insert_fd(NullOutput), 2);
         } else {
-            fds.insert(1i32, FileDescriptor::new(io::stdout()));
-            fds.insert(2i32, FileDescriptor::new(io::stderr()));
+            assert_eq!(fds.insert_fd(io::stdout()), 1);
+            assert_eq!(fds.insert_fd(io::stderr()), 2);
         }
-        FdTable { fds }
+        fds
     }
 
-    pub fn insert_fd(&mut self, file_handle: FileDescriptor) -> i32 {
+    /// Insert a file descriptor to the FdTable.
+    pub fn insert_fd(&mut self, fd: T) -> i32 {
+        let file_handle = FileDescriptor(Rc::new(RefCell::new(Box::new(fd))));
         self.insert_fd_with_min_fd(file_handle, 0)
     }
 
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 9ea7f9c37ea16..6923b39733f0b 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -16,8 +16,6 @@ use crate::shims::unix::*;
 use crate::*;
 use shims::time::system_time_to_duration;
 
-use self::fd::FileDescriptor;
-
 #[derive(Debug)]
 struct FileHandle {
     file: File,
@@ -452,10 +450,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             return Ok(-1);
         }
 
-        let fd = options.open(path).map(|file| {
-            let fh = &mut this.machine.fds;
-            fh.insert_fd(FileDescriptor::new(FileHandle { file, writable }))
-        });
+        let fd = options
+            .open(path)
+            .map(|file| this.machine.fds.insert_fd(FileHandle { file, writable }));
 
         this.try_unwrap_io_result(fd)
     }
@@ -1547,9 +1544,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
             match file {
                 Ok(f) => {
-                    let fh = &mut this.machine.fds;
-                    let fd =
-                        fh.insert_fd(FileDescriptor::new(FileHandle { file: f, writable: true }));
+                    let fd = this.machine.fds.insert_fd(FileHandle { file: f, writable: true });
                     return Ok(fd);
                 }
                 Err(e) =>
diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs
index a5661460e95cf..ad35d67876ccb 100644
--- a/src/tools/miri/src/shims/unix/linux/epoll.rs
+++ b/src/tools/miri/src/shims/unix/linux/epoll.rs
@@ -5,8 +5,6 @@ use rustc_data_structures::fx::FxHashMap;
 use crate::shims::unix::*;
 use crate::*;
 
-use self::shims::unix::fd::FileDescriptor;
-
 /// An `Epoll` file descriptor connects file handles and epoll events
 #[derive(Clone, Debug, Default)]
 struct Epoll {
@@ -66,7 +64,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             );
         }
 
-        let fd = this.machine.fds.insert_fd(FileDescriptor::new(Epoll::default()));
+        let fd = this.machine.fds.insert_fd(Epoll::default());
         Ok(Scalar::from_i32(fd))
     }
 
diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs
index cae5abca3bd08..0fc28c72bb6fb 100644
--- a/src/tools/miri/src/shims/unix/linux/eventfd.rs
+++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs
@@ -8,8 +8,6 @@ use rustc_target::abi::Endian;
 use crate::shims::unix::*;
 use crate::{concurrency::VClock, *};
 
-use self::shims::unix::fd::FileDescriptor;
-
 // We'll only do reads and writes in chunks of size u64.
 const U64_ARRAY_SIZE: usize = mem::size_of::();
 
@@ -180,11 +178,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             throw_unsup_format!("eventfd: encountered unknown unsupported flags {:#x}", flags);
         }
 
-        let fd = this.machine.fds.insert_fd(FileDescriptor::new(Event {
+        let fd = this.machine.fds.insert_fd(Event {
             counter: val.into(),
             is_nonblock,
             clock: VClock::default(),
-        }));
+        });
         Ok(Scalar::from_i32(fd))
     }
 }
diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs
index 6d3d63b4efa02..cc0f932e03829 100644
--- a/src/tools/miri/src/shims/unix/socket.rs
+++ b/src/tools/miri/src/shims/unix/socket.rs
@@ -7,8 +7,6 @@ use std::rc::{Rc, Weak};
 use crate::shims::unix::*;
 use crate::{concurrency::VClock, *};
 
-use self::fd::FileDescriptor;
-
 /// The maximum capacity of the socketpair buffer in bytes.
 /// This number is arbitrary as the value can always
 /// be configured in the real system.
@@ -221,9 +219,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         };
 
         let fds = &mut this.machine.fds;
-        let sv0 = fds.insert_fd(FileDescriptor::new(socketpair_0));
+        let sv0 = fds.insert_fd(socketpair_0);
+        let sv1 = fds.insert_fd(socketpair_1);
         let sv0 = Scalar::from_int(sv0, sv.layout.size);
-        let sv1 = fds.insert_fd(FileDescriptor::new(socketpair_1));
         let sv1 = Scalar::from_int(sv1, sv.layout.size);
 
         this.write_scalar(sv0, &sv)?;

From adf0dff10c5cfb213eacb026566952874d69cb16 Mon Sep 17 00:00:00 2001
From: mu001999 
Date: Wed, 24 Jul 2024 00:18:36 +0800
Subject: [PATCH 157/489] Not lint pub structs without pub constructors if
 containing fields of unit, never type, PhantomData and positional ZST

---
 compiler/rustc_passes/src/dead.rs             | 36 ++++++++++---------
 ...lone-debug-dead-code-in-the-same-struct.rs |  4 +--
 ...-debug-dead-code-in-the-same-struct.stderr | 16 +++++++--
 .../dead-code/unconstructible-pub-struct.rs   | 35 ++++++++++++++++++
 .../unconstructible-pub-struct.stderr         | 14 ++++++++
 5 files changed, 83 insertions(+), 22 deletions(-)
 create mode 100644 tests/ui/lint/dead-code/unconstructible-pub-struct.rs
 create mode 100644 tests/ui/lint/dead-code/unconstructible-pub-struct.stderr

diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 239bc8e7accfc..bbe4493e874c0 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -72,24 +72,26 @@ fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> {
 }
 
 fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool {
-    // treat PhantomData and positional ZST as public,
-    // we don't want to lint types which only have them,
-    // cause it's a common way to use such types to check things like well-formedness
-    tcx.adt_def(id).all_fields().all(|field| {
+    let adt_def = tcx.adt_def(id);
+
+    // skip types contain fields of unit and never type,
+    // it's usually intentional to make the type not constructible
+    let not_require_constructor = adt_def.all_fields().any(|field| {
         let field_type = tcx.type_of(field.did).instantiate_identity();
-        if field_type.is_phantom_data() {
-            return true;
-        }
-        let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
-        if is_positional
-            && tcx
-                .layout_of(tcx.param_env(field.did).and(field_type))
-                .map_or(true, |layout| layout.is_zst())
-        {
-            return true;
-        }
-        field.vis.is_public()
-    })
+        field_type.is_unit() || field_type.is_never()
+    });
+
+    not_require_constructor
+        || adt_def.all_fields().all(|field| {
+            let field_type = tcx.type_of(field.did).instantiate_identity();
+            // skip fields of PhantomData,
+            // cause it's a common way to check things like well-formedness
+            if field_type.is_phantom_data() {
+                return true;
+            }
+
+            field.vis.is_public()
+        })
 }
 
 /// check struct and its fields are public or not,
diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
index 885dacc727af6..6ab1fb7b039bd 100644
--- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
+++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs
@@ -1,9 +1,9 @@
 #![forbid(dead_code)]
 
 #[derive(Debug)]
-pub struct Whatever { //~ ERROR struct `Whatever` is never constructed
+pub struct Whatever {
     pub field0: (),
-    field1: (),
+    field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read
     field2: (),
     field3: (),
     field4: (),
diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
index e10d28ad03a4e..e9b757b6bae72 100644
--- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
+++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
@@ -1,9 +1,19 @@
-error: struct `Whatever` is never constructed
-  --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12
+error: fields `field1`, `field2`, `field3`, and `field4` are never read
+  --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5
    |
 LL | pub struct Whatever {
-   |            ^^^^^^^^
+   |            -------- fields in this struct
+LL |     pub field0: (),
+LL |     field1: (),
+   |     ^^^^^^
+LL |     field2: (),
+   |     ^^^^^^
+LL |     field3: (),
+   |     ^^^^^^
+LL |     field4: (),
+   |     ^^^^^^
    |
+   = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
 note: the lint level is defined here
   --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
    |
diff --git a/tests/ui/lint/dead-code/unconstructible-pub-struct.rs b/tests/ui/lint/dead-code/unconstructible-pub-struct.rs
new file mode 100644
index 0000000000000..2202cbb673098
--- /dev/null
+++ b/tests/ui/lint/dead-code/unconstructible-pub-struct.rs
@@ -0,0 +1,35 @@
+#![feature(never_type)]
+#![deny(dead_code)]
+
+pub struct T1(!);
+pub struct T2(());
+pub struct T3(std::marker::PhantomData);
+
+pub struct T4 {
+    _x: !,
+}
+
+pub struct T5 {
+    _x: !,
+    _y: X,
+}
+
+pub struct T6 {
+    _x: (),
+}
+
+pub struct T7 {
+    _x: (),
+    _y: X,
+}
+
+pub struct T8 {
+    _x: std::marker::PhantomData,
+}
+
+pub struct T9 { //~ ERROR struct `T9` is never constructed
+    _x: std::marker::PhantomData,
+    _y: i32,
+}
+
+fn main() {}
diff --git a/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr b/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr
new file mode 100644
index 0000000000000..a3dde042bbe15
--- /dev/null
+++ b/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr
@@ -0,0 +1,14 @@
+error: struct `T9` is never constructed
+  --> $DIR/unconstructible-pub-struct.rs:30:12
+   |
+LL | pub struct T9 {
+   |            ^^
+   |
+note: the lint level is defined here
+  --> $DIR/unconstructible-pub-struct.rs:2:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to 1 previous error
+

From 8cdc4932eeebfd4db2eb8abc572e5db1bde8b3cd Mon Sep 17 00:00:00 2001
From: Young-Flash 
Date: Fri, 26 Jul 2024 23:10:20 +0800
Subject: [PATCH 158/489] fix: tweak hover/tooltip links

---
 src/tools/rust-analyzer/editors/code/src/client.ts   | 10 +++++++---
 src/tools/rust-analyzer/editors/code/src/commands.ts |  7 ++++---
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts
index 357f131b93f6a..bf58112916b60 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -392,14 +392,18 @@ function isCodeActionWithoutEditsAndCommands(value: any): boolean {
 // to proxy around that. We store the last hover's reference command link
 // here, as only one hover can be active at a time, and we don't need to
 // keep a history of these.
-export let HOVER_REFERENCE_COMMAND: ra.CommandLink | undefined = undefined;
+export let HOVER_REFERENCE_COMMAND: ra.CommandLink[] = [];
 
 function renderCommand(cmd: ra.CommandLink): string {
-    HOVER_REFERENCE_COMMAND = cmd;
-    return `[${cmd.title}](command:rust-analyzer.hoverRefCommandProxy '${cmd.tooltip}')`;
+    HOVER_REFERENCE_COMMAND.push(cmd);
+    return `[${cmd.title}](command:rust-analyzer.hoverRefCommandProxy?${
+        HOVER_REFERENCE_COMMAND.length - 1
+    } '${cmd.tooltip}')`;
 }
 
 function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownString {
+    // clean up the previous hover ref command
+    HOVER_REFERENCE_COMMAND = [];
     const text = actions
         .map(
             (group) =>
diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts
index 621b9695786a7..773a4606014cd 100644
--- a/src/tools/rust-analyzer/editors/code/src/commands.ts
+++ b/src/tools/rust-analyzer/editors/code/src/commands.ts
@@ -1203,9 +1203,10 @@ export function newDebugConfig(ctx: CtxInit): Cmd {
 }
 
 export function hoverRefCommandProxy(_: Ctx): Cmd {
-    return async () => {
-        if (HOVER_REFERENCE_COMMAND) {
-            const { command, arguments: args = [] } = HOVER_REFERENCE_COMMAND;
+    return async (index: number) => {
+        const link = HOVER_REFERENCE_COMMAND[index];
+        if (link) {
+            const { command, arguments: args = [] } = link;
             await vscode.commands.executeCommand(command, ...args);
         }
     };

From 4f7f60b927e4c7f951664e75e7ed385aee080d83 Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Mon, 22 Jul 2024 14:21:58 -0400
Subject: [PATCH 159/489] rewrite rlib-format-packed-bundled-libs-2 to rmake

---
 .../tidy/src/allowed_run_make_makefiles.txt   |  1 -
 .../Makefile                                  | 27 ----------------
 .../rmake.rs                                  | 32 +++++++++++++++++++
 3 files changed, 32 insertions(+), 28 deletions(-)
 delete mode 100644 tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
 create mode 100644 tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index fa340a022132e..86add3a75b1f9 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -51,7 +51,6 @@ run-make/redundant-libs/Makefile
 run-make/remap-path-prefix-dwarf/Makefile
 run-make/reproducible-build-2/Makefile
 run-make/reproducible-build/Makefile
-run-make/rlib-format-packed-bundled-libs-2/Makefile
 run-make/rlib-format-packed-bundled-libs/Makefile
 run-make/sanitizer-cdylib-link/Makefile
 run-make/sanitizer-dylib-link/Makefile
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile b/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
deleted file mode 100644
index d2a740b06b36c..0000000000000
--- a/tests/run-make/rlib-format-packed-bundled-libs-2/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-include ../tools.mk
-
-# ignore-cross-compile
-
-# Make sure -Zpacked_bundled_libs is compatible with verbatim.
-
-# We're using the llvm-nm instead of the system nm to ensure it is compatible
-# with the LLVM bitcode generated by rustc.
-# Except on Windows where piping/IO redirection under MSYS2 is wonky with llvm-nm.
-ifndef IS_WINDOWS
-NM = "$(LLVM_BIN_DIR)"/llvm-nm
-else
-NM = nm
-endif
-
-all:
-	# Build strange-named dep.
-	$(RUSTC) native_dep.rs --crate-type=staticlib -o $(TMPDIR)/native_dep.ext
-
-	$(RUSTC) rust_dep.rs --crate-type=rlib -Zpacked_bundled_libs
-	$(NM) $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "U.*native_f1"
-	$(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) "native_dep.ext"
-
-	# Make sure compiler doesn't use files, that it shouldn't know about.
-	rm $(TMPDIR)/native_dep.ext
-
-	$(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib -Zpacked_bundled_libs
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
new file mode 100644
index 0000000000000..8d7afd3245ec2
--- /dev/null
+++ b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
@@ -0,0 +1,32 @@
+// `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler
+// only require a native library and no supplementary object files to compile.
+// This test simply checks that this flag can be passed alongside verbatim syntax
+// in rustc flags without a compilation failure or the removal of expected symbols.
+// See https://github.com/rust-lang/rust/pull/100101
+
+//FIXME(Oneirical): try it on test-various
+
+use run_make_support::{llvm_ar, llvm_readobj, regex, rfs, rust_lib_name, rustc};
+
+fn main() {
+    // Build a strangely named dependency.
+    rustc().input("native_dep.rs").crate_type("staticlib").output("native_dep.ext").run();
+
+    rustc().input("rust_dep.rs").crate_type("rlib").arg("-Zpacked_bundled_libs").run();
+    let symbols = llvm_readobj().symbols().input(rust_lib_name("rust_dep")).run().stdout_utf8();
+    let re = regex::Regex::new("U.*native_f1").unwrap();
+    assert!(re.is_match(&symbols));
+    llvm_ar()
+        .arg("t")
+        .arg(rust_lib_name("rust_dep"))
+        .run()
+        .assert_stdout_contains("native_dep.ext");
+
+    // Ensure the compiler does not use files it should not be aware of.
+    rfs::remove_file("native_dep.ext");
+    rustc()
+        .input("main.rs")
+        .extern_("rust_dep", rust_lib_name("rust_dep"))
+        .arg("-Zpacked_bundled_libs")
+        .run();
+}

From c8f049cd802fd7e5a111218d65822a80bb796ac4 Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Mon, 22 Jul 2024 15:08:26 -0400
Subject: [PATCH 160/489] rewrite native-link-modifier-whole-archive to rmake

---
 .../tidy/src/allowed_run_make_makefiles.txt   |  1 -
 .../Makefile                                  | 52 ------------
 .../rmake.rs                                  | 85 +++++++++++++++++++
 3 files changed, 85 insertions(+), 53 deletions(-)
 delete mode 100644 tests/run-make/native-link-modifier-whole-archive/Makefile
 create mode 100644 tests/run-make/native-link-modifier-whole-archive/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 86add3a75b1f9..3ee3bf65cfaa8 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -34,7 +34,6 @@ run-make/long-linker-command-lines/Makefile
 run-make/macos-deployment-target/Makefile
 run-make/min-global-align/Makefile
 run-make/native-link-modifier-bundle/Makefile
-run-make/native-link-modifier-whole-archive/Makefile
 run-make/no-alloc-shim/Makefile
 run-make/no-builtins-attribute/Makefile
 run-make/pdb-buildinfo-cl-cmd/Makefile
diff --git a/tests/run-make/native-link-modifier-whole-archive/Makefile b/tests/run-make/native-link-modifier-whole-archive/Makefile
deleted file mode 100644
index 5eb7a416f918a..0000000000000
--- a/tests/run-make/native-link-modifier-whole-archive/Makefile
+++ /dev/null
@@ -1,52 +0,0 @@
-# ignore-cross-compile -- compiling C++ code does not work well when cross-compiling
-
-# This test case makes sure that native libraries are linked with appropriate semantics
-# when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
-#
-# The test works by checking that the resulting executables produce the expected output,
-# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
-# that code would never make it into the final executable and we'd thus be missing some
-# of the output.
-
-include ../tools.mk
-
-all: $(TMPDIR)/$(call BIN,directly_linked) \
-     $(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive) \
-     $(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive) \
-     $(TMPDIR)/$(call BIN,indirectly_linked) \
-     $(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
-	$(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.'
-	$(call RUN,directly_linked_test_plus_whole_archive) --nocapture | $(CGREP) 'static-initializer.'
-	$(call RUN,directly_linked_test_minus_whole_archive) --nocapture | $(CGREP) -v 'static-initializer.'
-	$(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.'
-	$(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.'
-
-# Native lib linked directly into executable
-$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
-	$(RUSTC) directly_linked.rs -l static:+whole-archive=c_static_lib_with_constructor
-
-# Native lib linked into test executable, +whole-archive
-$(TMPDIR)/$(call BIN,directly_linked_test_plus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
-	$(RUSTC) directly_linked_test_plus_whole_archive.rs --test -l static:+whole-archive=c_static_lib_with_constructor
-# Native lib linked into test executable, -whole-archive
-$(TMPDIR)/$(call BIN,directly_linked_test_minus_whole_archive): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
-	$(RUSTC) directly_linked_test_minus_whole_archive.rs --test -l static:-whole-archive=c_static_lib_with_constructor
-
-# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
-$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib
-	$(RUSTC) indirectly_linked.rs
-
-# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
-$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib
-	$(RUSTC) indirectly_linked_via_attr.rs
-
-# Native lib linked into rlib with via commandline
-$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
-	$(RUSTC) rlib_with_cmdline_native_lib.rs --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor
-
-# Native lib linked into rlib via `#[link()]` attribute on extern block.
-$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
-	$(RUSTC) native_lib_in_src.rs --crate-type=rlib
-
-$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp
-	$(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/tests/run-make/native-link-modifier-whole-archive/rmake.rs b/tests/run-make/native-link-modifier-whole-archive/rmake.rs
new file mode 100644
index 0000000000000..4e1f34d112ecd
--- /dev/null
+++ b/tests/run-make/native-link-modifier-whole-archive/rmake.rs
@@ -0,0 +1,85 @@
+// This test case makes sure that native libraries are linked with appropriate semantics
+// when the `[+-]bundle,[+-]whole-archive` modifiers are applied to them.
+// The test works by checking that the resulting executables produce the expected output,
+// part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
+// that code would never make it into the final executable and we'd thus be missing some
+// of the output.
+// See https://github.com/rust-lang/rust/issues/88085
+
+//@ ignore-cross-compile
+// Reason: compiling C++ code does not work well when cross-compiling
+// plus, the compiled binary is executed
+
+use run_make_support::{cxx, is_msvc, llvm_ar, run, run_with_args, rustc, static_lib_name};
+
+fn main() {
+    let mut cxx = cxx();
+    if is_msvc() {
+        cxx.arg("-EHs");
+    }
+    cxx.input("c_static_lib_with_constructor.cpp")
+        .arg("-c")
+        .out_exe("libc_static_lib_with_constructor")
+        .run();
+
+    let mut llvm_ar = llvm_ar();
+    llvm_ar.obj_to_ar();
+    if is_msvc() {
+        llvm_ar
+            .output_input(
+                static_lib_name("c_static_lib_with_constructor"),
+                "libc_static_lib_with_constructor.obj",
+            )
+            .run();
+    } else {
+        llvm_ar
+            .output_input(
+                static_lib_name("c_static_lib_with_constructor"),
+                "libc_static_lib_with_constructor",
+            )
+            .run();
+    }
+
+    // Native lib linked directly into executable
+    rustc()
+        .input("directly_linked.rs")
+        .arg("-lstatic:+whole-archive=c_static_lib_with_constructor")
+        .run();
+
+    // Native lib linked into test executable, +whole-archive
+    rustc()
+        .input("directly_linked_test_plus_whole_archive.rs")
+        .arg("--test")
+        .arg("-lstatic:+whole-archive=c_static_lib_with_constructor")
+        .run();
+
+    // Native lib linked into test executable, -whole-archive
+    rustc()
+        .input("directly_linked_test_minus_whole_archive.rs")
+        .arg("--test")
+        .arg("-lstatic:-whole-archive=c_static_lib_with_constructor")
+        .run();
+
+    // Native lib linked into rlib with via commandline
+    rustc()
+        .input("rlib_with_cmdline_native_lib.rs")
+        .crate_type("rlib")
+        .arg("-lstatic:-bundle,+whole-archive=c_static_lib_with_constructor")
+        .run();
+    // Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
+    rustc().input("indirectly_linked.rs").run();
+
+    // Native lib linked into rlib via `#[link()]` attribute on extern block.
+    rustc().input("native_lib_in_src.rs").crate_type("rlib").run();
+    // Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
+    rustc().input("indirectly_linked_via_attr.rs").run();
+
+    run("directly_linked").assert_stdout_contains("static-initializer.directly_linked.");
+    run_with_args("directly_linked_test_plus_whole_archive", &["--nocapture"])
+        .assert_stdout_contains("static-initializer.");
+    run_with_args("directly_linked_test_minus_whole_archive", &["--nocapture"])
+        .assert_stdout_not_contains("static-initializer.");
+    run("indirectly_linked").assert_stdout_contains("static-initializer.indirectly_linked.");
+    run("indirectly_linked_via_attr")
+        .assert_stdout_contains("static-initializer.native_lib_in_src.");
+}

From d5c073eb090f34b42da85f3f768ea6847b9ba7bc Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Mon, 22 Jul 2024 15:35:18 -0400
Subject: [PATCH 161/489] rewrite no-builtins-attribute to rmake

---
 src/tools/tidy/src/allowed_run_make_makefiles.txt   |  1 -
 .../native-link-modifier-whole-archive/rmake.rs     |  3 ++-
 tests/run-make/no-builtins-attribute/Makefile       |  9 ---------
 tests/run-make/no-builtins-attribute/rmake.rs       | 13 +++++++++++++
 4 files changed, 15 insertions(+), 11 deletions(-)
 delete mode 100644 tests/run-make/no-builtins-attribute/Makefile
 create mode 100644 tests/run-make/no-builtins-attribute/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 3ee3bf65cfaa8..d47d1b46fe175 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -35,7 +35,6 @@ run-make/macos-deployment-target/Makefile
 run-make/min-global-align/Makefile
 run-make/native-link-modifier-bundle/Makefile
 run-make/no-alloc-shim/Makefile
-run-make/no-builtins-attribute/Makefile
 run-make/pdb-buildinfo-cl-cmd/Makefile
 run-make/pgo-gen-lto/Makefile
 run-make/pgo-indirect-call-promotion/Makefile
diff --git a/tests/run-make/native-link-modifier-whole-archive/rmake.rs b/tests/run-make/native-link-modifier-whole-archive/rmake.rs
index 4e1f34d112ecd..b8b814043e5cd 100644
--- a/tests/run-make/native-link-modifier-whole-archive/rmake.rs
+++ b/tests/run-make/native-link-modifier-whole-archive/rmake.rs
@@ -66,7 +66,8 @@ fn main() {
         .crate_type("rlib")
         .arg("-lstatic:-bundle,+whole-archive=c_static_lib_with_constructor")
         .run();
-    // Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
+    // Native lib linked into RLIB via `-l static:-bundle,+whole-archive`
+    // RLIB linked into executable
     rustc().input("indirectly_linked.rs").run();
 
     // Native lib linked into rlib via `#[link()]` attribute on extern block.
diff --git a/tests/run-make/no-builtins-attribute/Makefile b/tests/run-make/no-builtins-attribute/Makefile
deleted file mode 100644
index 0ce95facaea48..0000000000000
--- a/tests/run-make/no-builtins-attribute/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-include ../tools.mk
-
-# We want to check if `no-builtins` is also added to the function declarations in the used crate.
-
-all:
-	$(RUSTC) no_builtins.rs --emit=link
-	$(RUSTC) main.rs --emit=llvm-ir
-
-	cat "$(TMPDIR)"/main.ll | "$(LLVM_FILECHECK)" filecheck.main.txt
diff --git a/tests/run-make/no-builtins-attribute/rmake.rs b/tests/run-make/no-builtins-attribute/rmake.rs
new file mode 100644
index 0000000000000..1e15b0c03f1d9
--- /dev/null
+++ b/tests/run-make/no-builtins-attribute/rmake.rs
@@ -0,0 +1,13 @@
+// `no_builtins` is an attribute related to LLVM's optimizations. In order to ensure that it has an
+// effect on link-time optimizations (LTO), it should be added to function declarations in a crate.
+// This test uses the `llvm-filecheck` tool to determine that this attribute is successfully
+// being added to these function declarations.
+// See https://github.com/rust-lang/rust/pull/113716
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    rustc().input("no_builtins.rs").emit("link").run();
+    rustc().input("main.rs").emit("llvm-ir").run();
+    llvm_filecheck().patterns("filecheck.main.txt").stdin(rfs::read("main.ll")).run();
+}

From 8d2c12e5540d801a48eae396eac6aa350ce8c1b1 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Fri, 26 Jul 2024 13:18:29 -0400
Subject: [PATCH 162/489] Don't ICE when encountering error regions when
 confirming object method candidate

---
 compiler/rustc_hir_typeck/src/method/confirm.rs    | 14 +++++++++++++-
 tests/crashes/122914.rs                            | 11 -----------
 .../dont-ice-on-object-lookup-w-error-region.rs    | 11 +++++++++++
 ...dont-ice-on-object-lookup-w-error-region.stderr | 11 +++++++++++
 4 files changed, 35 insertions(+), 12 deletions(-)
 delete mode 100644 tests/crashes/122914.rs
 create mode 100644 tests/ui/methods/dont-ice-on-object-lookup-w-error-region.rs
 create mode 100644 tests/ui/methods/dont-ice-on-object-lookup-w-error-region.stderr

diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index e70431a68ff16..be3de812a96d2 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -16,7 +16,8 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{
-    self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, UserArgs, UserType,
+    self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, UserArgs,
+    UserType,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, DUMMY_SP};
@@ -268,6 +269,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
             probe::ObjectPick => {
                 let trait_def_id = pick.item.container_id(self.tcx);
+
+                // This shouldn't happen for non-region error kinds, but may occur
+                // when we have error regions. Specifically, since we canonicalize
+                // during method steps, we may successfully deref when we assemble
+                // the pick, but fail to deref when we try to extract the object
+                // type from the pick during confirmation. This is fine, we're basically
+                // already doomed by this point.
+                if self_ty.references_error() {
+                    return ty::GenericArgs::extend_with_error(self.tcx, trait_def_id, &[]);
+                }
+
                 self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
                     // The object data has no entry for the Self
                     // Type. For the purposes of this method call, we
diff --git a/tests/crashes/122914.rs b/tests/crashes/122914.rs
deleted file mode 100644
index 63a84bc8099bc..0000000000000
--- a/tests/crashes/122914.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #122914
-use std::future::Future;
-use std::pin::Pin;
-
-impl<'a, F> Poll {
-    fn project<'_>(self: Pin<&'pin mut Future>) -> Projection<'pin, 'a, F> {
-        me.local_set.with(|| {
-            let _ = self.poll(cx);
-        })
-    }
-}
diff --git a/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.rs b/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.rs
new file mode 100644
index 0000000000000..0a6d196364f9d
--- /dev/null
+++ b/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.rs
@@ -0,0 +1,11 @@
+// Fix for issue: #122914
+
+use std::future::Future;
+use std::pin::Pin;
+
+fn project(x: Pin<&'missing mut dyn Future>) {
+    //~^ ERROR use of undeclared lifetime name `'missing`
+    let _ = x.poll(todo!());
+}
+
+fn main() {}
diff --git a/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.stderr b/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.stderr
new file mode 100644
index 0000000000000..2c33941be4333
--- /dev/null
+++ b/tests/ui/methods/dont-ice-on-object-lookup-w-error-region.stderr
@@ -0,0 +1,11 @@
+error[E0261]: use of undeclared lifetime name `'missing`
+  --> $DIR/dont-ice-on-object-lookup-w-error-region.rs:6:20
+   |
+LL | fn project(x: Pin<&'missing mut dyn Future>) {
+   |           -        ^^^^^^^^ undeclared lifetime
+   |           |
+   |           help: consider introducing lifetime `'missing` here: `<'missing>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0261`.

From 1507af41a589b70337e4616848c1a9ed581985dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?=
 =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= 
Date: Fri, 26 Jul 2024 20:42:31 +0300
Subject: [PATCH 163/489] Add `flock` shim

---
 src/tools/miri/Cargo.lock                     |  1 +
 src/tools/miri/Cargo.toml                     | 11 ++-
 src/tools/miri/src/shims/unix/fd.rs           | 49 ++++++++++
 .../miri/src/shims/unix/foreign_items.rs      |  7 ++
 src/tools/miri/src/shims/unix/fs.rs           | 93 +++++++++++++++++++
 .../miri/tests/pass-dep/libc/libc-fs-flock.rs | 71 ++++++++++++++
 6 files changed, 230 insertions(+), 2 deletions(-)
 create mode 100644 src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs

diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 417ecb09b3196..eecb158d707be 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -563,6 +563,7 @@ dependencies = [
  "smallvec",
  "tempfile",
  "ui_test",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 976bd080867eb..e12f3f9012f0d 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -9,12 +9,12 @@ default-run = "miri"
 edition = "2021"
 
 [lib]
-test = true # we have unit tests
+test = true     # we have unit tests
 doctest = false # but no doc tests
 
 [[bin]]
 name = "miri"
-test = false # we have no unit tests
+test = false    # we have no unit tests
 doctest = false # and no doc tests
 
 [dependencies]
@@ -42,6 +42,13 @@ libc = "0.2"
 libffi = "3.2.0"
 libloading = "0.8"
 
+[target.'cfg(target_family = "windows")'.dependencies]
+windows-sys = { version = "0.52", features = [
+    "Win32_Foundation",
+    "Win32_System_IO",
+    "Win32_Storage_FileSystem",
+] }
+
 [dev-dependencies]
 colored = "2"
 ui_test = "0.21.1"
diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 0fffecd99d5cb..dd3de38125f30 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -77,6 +77,14 @@ pub trait FileDescription: std::fmt::Debug + Any {
         throw_unsup_format!("cannot close {}", self.name());
     }
 
+    fn flock<'tcx>(
+        &self,
+        _communicate_allowed: bool,
+        _op: FlockOp,
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        throw_unsup_format!("cannot flock {}", self.name());
+    }
+
     fn is_tty(&self, _communicate_allowed: bool) -> bool {
         // Most FDs are not tty's and the consequence of a wrong `false` are minor,
         // so we use a default impl here.
@@ -324,6 +332,40 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         Ok(new_fd)
     }
 
+    fn flock(&mut self, fd: i32, op: i32) -> InterpResult<'tcx, Scalar> {
+        let this = self.eval_context_mut();
+        let Some(file_descriptor) = this.machine.fds.get(fd) else {
+            return Ok(Scalar::from_i32(this.fd_not_found()?));
+        };
+
+        // We need to check that there aren't unsupported options in `op`.
+        let lock_sh = this.eval_libc_i32("LOCK_SH");
+        let lock_ex = this.eval_libc_i32("LOCK_EX");
+        let lock_nb = this.eval_libc_i32("LOCK_NB");
+        let lock_un = this.eval_libc_i32("LOCK_UN");
+
+        use FlockOp::*;
+        let parsed_op = if op == lock_sh {
+            SharedLock { nonblocking: false }
+        } else if op == lock_sh | lock_nb {
+            SharedLock { nonblocking: true }
+        } else if op == lock_ex {
+            ExclusiveLock { nonblocking: false }
+        } else if op == lock_ex | lock_nb {
+            ExclusiveLock { nonblocking: true }
+        } else if op == lock_un {
+            Unlock
+        } else {
+            throw_unsup_format!("unsupported flags {:#x}", op);
+        };
+
+        let result = file_descriptor.flock(this.machine.communicate(), parsed_op)?;
+        drop(file_descriptor);
+        // return `0` if flock is successful
+        let result = result.map(|()| 0i32);
+        Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
+    }
+
     fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
 
@@ -520,3 +562,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         this.try_unwrap_io_result(result)
     }
 }
+
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub(crate) enum FlockOp {
+    SharedLock { nonblocking: bool },
+    ExclusiveLock { nonblocking: bool },
+    Unlock,
+}
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 966e590fcc41e..17851e1aec01b 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -170,6 +170,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 let result = this.dup2(old_fd, new_fd)?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
+            "flock" => {
+                let [fd, op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let fd = this.read_scalar(fd)?.to_i32()?;
+                let op = this.read_scalar(op)?.to_i32()?;
+                let result = this.flock(fd, op)?;
+                this.write_scalar(result, dest)?;
+            }
 
             // File and file system access
             "open" | "open64" => {
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 6923b39733f0b..308f3b822a38c 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -16,6 +16,8 @@ use crate::shims::unix::*;
 use crate::*;
 use shims::time::system_time_to_duration;
 
+use self::fd::FlockOp;
+
 #[derive(Debug)]
 struct FileHandle {
     file: File,
@@ -127,6 +129,97 @@ impl FileDescription for FileHandle {
         }
     }
 
+    fn flock<'tcx>(
+        &self,
+        communicate_allowed: bool,
+        op: FlockOp,
+    ) -> InterpResult<'tcx, io::Result<()>> {
+        assert!(communicate_allowed, "isolation should have prevented even opening a file");
+        #[cfg(target_family = "unix")]
+        {
+            use std::os::fd::AsRawFd;
+
+            use FlockOp::*;
+            // We always use non-blocking call to prevent interpreter from being blocked
+            let (host_op, lock_nb) = match op {
+                SharedLock { nonblocking } => (libc::LOCK_SH | libc::LOCK_NB, nonblocking),
+                ExclusiveLock { nonblocking } => (libc::LOCK_EX | libc::LOCK_NB, nonblocking),
+                Unlock => (libc::LOCK_UN, false),
+            };
+
+            let fd = self.file.as_raw_fd();
+            let ret = unsafe { libc::flock(fd, host_op) };
+            let res = match ret {
+                0 => Ok(()),
+                -1 => {
+                    let err = io::Error::last_os_error();
+                    if !lock_nb && err.kind() == io::ErrorKind::WouldBlock {
+                        throw_unsup_format!("blocking `flock` is not currently supported");
+                    }
+                    Err(err)
+                }
+                ret => panic!("Unexpected return value from flock: {ret}"),
+            };
+            Ok(res)
+        }
+
+        #[cfg(target_family = "windows")]
+        {
+            use std::os::windows::io::AsRawHandle;
+            use windows_sys::Win32::{
+                Foundation::{ERROR_IO_PENDING, ERROR_LOCK_VIOLATION, FALSE, HANDLE, TRUE},
+                Storage::FileSystem::{
+                    LockFileEx, UnlockFile, LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY,
+                },
+            };
+            let fh = self.file.as_raw_handle() as HANDLE;
+
+            use FlockOp::*;
+            let (ret, lock_nb) = match op {
+                SharedLock { nonblocking } | ExclusiveLock { nonblocking } => {
+                    // We always use non-blocking call to prevent interpreter from being blocked
+                    let mut flags = LOCKFILE_FAIL_IMMEDIATELY;
+                    if matches!(op, ExclusiveLock { .. }) {
+                        flags |= LOCKFILE_EXCLUSIVE_LOCK;
+                    }
+                    let ret = unsafe { LockFileEx(fh, flags, 0, !0, !0, &mut std::mem::zeroed()) };
+                    (ret, nonblocking)
+                }
+                Unlock => {
+                    let ret = unsafe { UnlockFile(fh, 0, 0, !0, !0) };
+                    (ret, false)
+                }
+            };
+
+            let res = match ret {
+                TRUE => Ok(()),
+                FALSE => {
+                    let mut err = io::Error::last_os_error();
+                    let code: u32 = err.raw_os_error().unwrap().try_into().unwrap();
+                    if matches!(code, ERROR_IO_PENDING | ERROR_LOCK_VIOLATION) {
+                        if lock_nb {
+                            // Replace error with a custom WouldBlock error, which later will be
+                            // mapped in the `helpers` module
+                            let desc = format!("LockFileEx wouldblock error: {err}");
+                            err = io::Error::new(io::ErrorKind::WouldBlock, desc);
+                        } else {
+                            throw_unsup_format!("blocking `flock` is not currently supported");
+                        }
+                    }
+                    Err(err)
+                }
+                _ => panic!("Unexpected return value: {ret}"),
+            };
+            Ok(res)
+        }
+
+        #[cfg(not(any(target_family = "unix", target_family = "windows")))]
+        {
+            let _ = op;
+            compile_error!("flock is supported only on UNIX and Windows hosts");
+        }
+    }
+
     fn is_tty(&self, communicate_allowed: bool) -> bool {
         communicate_allowed && self.file.is_terminal()
     }
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs
new file mode 100644
index 0000000000000..c1b3b8f575c99
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs
@@ -0,0 +1,71 @@
+// Flock tests are separate since they don't in general work on a Windows host.
+//@ignore-target-windows: File handling is not implemented yet
+//@compile-flags: -Zmiri-disable-isolation
+
+use std::{fs::File, io::Error, os::fd::AsRawFd};
+
+#[path = "../../utils/mod.rs"]
+mod utils;
+
+fn main() {
+    let bytes = b"Hello, World!\n";
+    let path = utils::prepare_with_content("miri_test_fs_shared_lock.txt", bytes);
+
+    let files: Vec = (0..3).map(|_| File::open(&path).unwrap()).collect();
+
+    // Test that we can apply many shared locks
+    for file in files.iter() {
+        let fd = file.as_raw_fd();
+        let ret = unsafe { libc::flock(fd, libc::LOCK_SH) };
+        if ret != 0 {
+            panic!("flock error: {}", Error::last_os_error());
+        }
+    }
+
+    // Test that shared lock prevents exclusive lock
+    {
+        let fd = files[0].as_raw_fd();
+        let ret = unsafe { libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB) };
+        assert_eq!(ret, -1);
+        let err = Error::last_os_error().raw_os_error().unwrap();
+        assert_eq!(err, libc::EWOULDBLOCK);
+    }
+
+    // Unlock shared lock
+    for file in files.iter() {
+        let fd = file.as_raw_fd();
+        let ret = unsafe { libc::flock(fd, libc::LOCK_UN) };
+        if ret != 0 {
+            panic!("flock error: {}", Error::last_os_error());
+        }
+    }
+
+    // Take exclusive lock
+    {
+        let fd = files[0].as_raw_fd();
+        let ret = unsafe { libc::flock(fd, libc::LOCK_EX) };
+        assert_eq!(ret, 0);
+    }
+
+    // Test that shared lock prevents exclusive and shared locks
+    {
+        let fd = files[1].as_raw_fd();
+        let ret = unsafe { libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB) };
+        assert_eq!(ret, -1);
+        let err = Error::last_os_error().raw_os_error().unwrap();
+        assert_eq!(err, libc::EWOULDBLOCK);
+
+        let fd = files[2].as_raw_fd();
+        let ret = unsafe { libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB) };
+        assert_eq!(ret, -1);
+        let err = Error::last_os_error().raw_os_error().unwrap();
+        assert_eq!(err, libc::EWOULDBLOCK);
+    }
+
+    // Unlock exclusive lock
+    {
+        let fd = files[0].as_raw_fd();
+        let ret = unsafe { libc::flock(fd, libc::LOCK_UN) };
+        assert_eq!(ret, 0);
+    }
+}

From 83234a0f21a46536cedfd46dc8d0f2d447565541 Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Thu, 11 Jul 2024 15:36:06 -0400
Subject: [PATCH 164/489] rewrite and rename issue-47551 to rmake

---
 .../tidy/src/allowed_run_make_makefiles.txt   |  1 -
 tests/run-make/issue-47551/Makefile           | 10 ----------
 .../eh_frame-terminator.rs                    |  0
 .../link-eh-frame-terminator/rmake.rs         | 20 +++++++++++++++++++
 4 files changed, 20 insertions(+), 11 deletions(-)
 delete mode 100644 tests/run-make/issue-47551/Makefile
 rename tests/run-make/{issue-47551 => link-eh-frame-terminator}/eh_frame-terminator.rs (100%)
 create mode 100644 tests/run-make/link-eh-frame-terminator/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index fa340a022132e..2a1b7500e5b8c 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -19,7 +19,6 @@ run-make/foreign-rust-exceptions/Makefile
 run-make/incr-add-rust-src-component/Makefile
 run-make/issue-35164/Makefile
 run-make/issue-36710/Makefile
-run-make/issue-47551/Makefile
 run-make/issue-69368/Makefile
 run-make/issue-84395-lto-embed-bitcode/Makefile
 run-make/issue-88756-default-output/Makefile
diff --git a/tests/run-make/issue-47551/Makefile b/tests/run-make/issue-47551/Makefile
deleted file mode 100644
index 3fe0a6e74e020..0000000000000
--- a/tests/run-make/issue-47551/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# only-linux
-# ignore-32bit
-
-include ../tools.mk
-
-all:
-	# --target $(TARGET) ensures the right gcc flags are used for cross compilation
-	$(RUSTC) --target $(TARGET) eh_frame-terminator.rs
-	$(call RUN,eh_frame-terminator) | $(CGREP) '1122334455667788'
-	objdump --dwarf=frames $(TMPDIR)/eh_frame-terminator | $(CGREP) 'ZERO terminator'
diff --git a/tests/run-make/issue-47551/eh_frame-terminator.rs b/tests/run-make/link-eh-frame-terminator/eh_frame-terminator.rs
similarity index 100%
rename from tests/run-make/issue-47551/eh_frame-terminator.rs
rename to tests/run-make/link-eh-frame-terminator/eh_frame-terminator.rs
diff --git a/tests/run-make/link-eh-frame-terminator/rmake.rs b/tests/run-make/link-eh-frame-terminator/rmake.rs
new file mode 100644
index 0000000000000..750d068ac98cf
--- /dev/null
+++ b/tests/run-make/link-eh-frame-terminator/rmake.rs
@@ -0,0 +1,20 @@
+// The gcc driver is supposed to add a terminator to link files, and the rustc
+// driver previously failed to do this, resulting in a segmentation fault
+// with an older version of LLVM. This test checks that the terminator is present
+// after the fix in #85395.
+// See https://github.com/rust-lang/rust/issues/47551
+
+//FIXME(Oneirical): See if it works on anything other than only linux and 64 bit
+// maybe riscv64gc-unknown-linux-gnu
+
+use run_make_support::{llvm_objdump, run, rustc};
+
+fn main() {
+    rustc().input("eh_frame-terminator.rs").run();
+    run("eh_frame-terminator").assert_stdout_contains("1122334455667788");
+    llvm_objdump()
+        .arg("--dwarf=frames")
+        .input("eh_frame-terminator")
+        .run()
+        .assert_stdout_contains("ZERO terminator");
+}

From 61a6afe60ced9a6120403158dd8caf40f8a583a4 Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Thu, 11 Jul 2024 15:52:04 -0400
Subject: [PATCH 165/489] Rewrite and rename issue-35164 to rmake

---
 src/tools/run-make-support/src/command.rs         |  2 +-
 src/tools/tidy/src/allowed_run_make_makefiles.txt |  1 -
 tests/run-make/issue-35164/Makefile               |  4 ----
 .../{issue-35164 => json-error-no-offset}/main.rs |  0
 tests/run-make/json-error-no-offset/rmake.rs      | 15 +++++++++++++++
 .../submodule/mod.rs                              |  0
 6 files changed, 16 insertions(+), 6 deletions(-)
 delete mode 100644 tests/run-make/issue-35164/Makefile
 rename tests/run-make/{issue-35164 => json-error-no-offset}/main.rs (100%)
 create mode 100644 tests/run-make/json-error-no-offset/rmake.rs
 rename tests/run-make/{issue-35164 => json-error-no-offset}/submodule/mod.rs (100%)

diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index 47376c401bb67..6f9ff4b9868a0 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -216,7 +216,7 @@ impl CompletedProcess {
     /// Checks that `stderr` does not contain `unexpected`.
     #[track_caller]
     pub fn assert_stderr_not_contains>(&self, unexpected: S) -> &Self {
-        assert_not_contains(&self.stdout_utf8(), unexpected);
+        assert_not_contains(&self.stderr_utf8(), unexpected);
         self
     }
 
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 2a1b7500e5b8c..beff9de23719b 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -17,7 +17,6 @@ run-make/foreign-double-unwind/Makefile
 run-make/foreign-exceptions/Makefile
 run-make/foreign-rust-exceptions/Makefile
 run-make/incr-add-rust-src-component/Makefile
-run-make/issue-35164/Makefile
 run-make/issue-36710/Makefile
 run-make/issue-69368/Makefile
 run-make/issue-84395-lto-embed-bitcode/Makefile
diff --git a/tests/run-make/issue-35164/Makefile b/tests/run-make/issue-35164/Makefile
deleted file mode 100644
index 38aa6f1265f1e..0000000000000
--- a/tests/run-make/issue-35164/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-include ../tools.mk
-
-all:
-	$(RUSTC) main.rs --error-format json 2>&1 | $(CGREP) -e '"byte_start":23\b' '"byte_end":29\b'
diff --git a/tests/run-make/issue-35164/main.rs b/tests/run-make/json-error-no-offset/main.rs
similarity index 100%
rename from tests/run-make/issue-35164/main.rs
rename to tests/run-make/json-error-no-offset/main.rs
diff --git a/tests/run-make/json-error-no-offset/rmake.rs b/tests/run-make/json-error-no-offset/rmake.rs
new file mode 100644
index 0000000000000..629d9c4c16e44
--- /dev/null
+++ b/tests/run-make/json-error-no-offset/rmake.rs
@@ -0,0 +1,15 @@
+// The byte positions in json format error logging used to have a small, difficult
+// to predict offset. This was changed to be the top of the file every time in #42973,
+// and this test checks that the measurements appearing in the standard error are correct.
+// See https://github.com/rust-lang/rust/issues/35164
+
+use run_make_support::rustc;
+
+fn main() {
+    rustc()
+        .input("main.rs")
+        .error_format("json")
+        .run()
+        .assert_stderr_contains(r#""byte_start":23"#)
+        .assert_stderr_contains(r#""byte_end":29"#);
+}
diff --git a/tests/run-make/issue-35164/submodule/mod.rs b/tests/run-make/json-error-no-offset/submodule/mod.rs
similarity index 100%
rename from tests/run-make/issue-35164/submodule/mod.rs
rename to tests/run-make/json-error-no-offset/submodule/mod.rs

From 91acacf85b9f81aeb41901f8918128bfe02946c8 Mon Sep 17 00:00:00 2001
From: Michael Goulet 
Date: Fri, 26 Jul 2024 14:32:19 -0400
Subject: [PATCH 166/489] Peel off explicit (or implicit) deref before
 suggesting clone on move error in borrowck

---
 .../src/diagnostics/conflict_errors.rs        | 92 +++++--------------
 .../src/diagnostics/move_errors.rs            | 16 +---
 .../associated-types-outlives.stderr          |  2 +-
 tests/ui/augmented-assignments.rs             |  1 -
 tests/ui/augmented-assignments.stderr         |  7 +-
 tests/ui/binop/binop-move-semantics.stderr    |  4 +-
 tests/ui/borrowck/borrow-tuple-fields.stderr  | 10 +-
 .../borrowck-bad-nested-calls-move.stderr     |  4 +-
 .../borrowck-field-sensitivity.stderr         | 10 +-
 tests/ui/borrowck/borrowck-issue-48962.stderr |  5 -
 .../borrowck-loan-blocks-move-cc.stderr       | 10 +-
 .../borrowck/borrowck-loan-blocks-move.stderr |  5 +-
 ...-move-from-subpath-of-borrowed-path.stderr |  5 +-
 .../borrowck-move-mut-base-ptr.stderr         |  2 +-
 .../borrowck-move-subcomponent.stderr         |  2 +-
 .../borrowck-multiple-captures.stderr         | 15 ++-
 ...orrowck-overloaded-index-move-index.stderr | 10 ++
 tests/ui/borrowck/borrowck-unary-move.stderr  |  2 +-
 tests/ui/borrowck/clone-on-ref.stderr         |  4 +-
 tests/ui/borrowck/issue-101119.stderr         |  8 --
 tests/ui/btreemap/btreemap_dropck.stderr      |  5 +-
 .../dropck/drop-with-active-borrows-1.stderr  |  5 -
 tests/ui/error-codes/E0504.stderr             |  2 +-
 tests/ui/error-codes/E0505.stderr             |  2 +-
 ...ied-bounds-unnorm-associated-type-4.stderr |  5 +-
 ...ied-bounds-unnorm-associated-type-5.stderr |  5 +-
 ...plied-bounds-unnorm-associated-type.stderr |  5 +-
 tests/ui/moves/move-fn-self-receiver.stderr   |  9 --
 tests/ui/nll/closure-access-spans.stderr      | 15 +--
 ...e-27282-move-match-input-into-guard.stderr | 10 --
 .../issue-27282-move-ref-mut-into-guard.fixed | 23 -----
 .../issue-27282-move-ref-mut-into-guard.rs    |  2 +-
 ...issue-27282-move-ref-mut-into-guard.stderr |  8 --
 .../nll/issue-27282-mutation-in-guard.stderr  |  8 --
 ...eport-when-borrow-and-drop-conflict.stderr |  4 -
 tests/ui/nll/match-guards-always-borrow.fixed | 66 -------------
 tests/ui/nll/match-guards-always-borrow.rs    |  1 -
 .../ui/nll/match-guards-always-borrow.stderr  | 12 +--
 .../nll/polonius/polonius-smoke-test.stderr   | 12 +++
 .../borrowck-pat-ref-mut-and-ref.stderr       | 16 ----
 .../span/send-is-not-static-std-sync.stderr   |  6 +-
 .../suggestions/borrow-for-loop-head.stderr   |  5 +-
 .../try-block/try-block-bad-lifetime.stderr   |  5 -
 tests/ui/unop/unop-move-semantics.stderr      |  4 +-
 tests/ui/variance/variance-issue-20533.stderr | 13 ++-
 45 files changed, 111 insertions(+), 351 deletions(-)
 delete mode 100644 tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed
 delete mode 100644 tests/ui/nll/match-guards-always-borrow.fixed

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index a5635344b4ad3..6515db42b0805 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -570,11 +570,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                 } = move_spans
                     && can_suggest_clone
                 {
-                    self.suggest_cloning(err, ty, expr, None, Some(move_spans));
+                    self.suggest_cloning(err, ty, expr, Some(move_spans));
                 } else if self.suggest_hoisting_call_outside_loop(err, expr) && can_suggest_clone {
                     // The place where the type moves would be misleading to suggest clone.
                     // #121466
-                    self.suggest_cloning(err, ty, expr, None, Some(move_spans));
+                    self.suggest_cloning(err, ty, expr, Some(move_spans));
                 }
             }
 
@@ -1236,8 +1236,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
         &self,
         err: &mut Diag<'_>,
         ty: Ty<'tcx>,
-        mut expr: &'tcx hir::Expr<'tcx>,
-        mut other_expr: Option<&'tcx hir::Expr<'tcx>>,
+        expr: &'tcx hir::Expr<'tcx>,
         use_spans: Option>,
     ) {
         if let hir::ExprKind::Struct(_, _, Some(_)) = expr.kind {
@@ -1249,66 +1248,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
             return;
         }
 
-        if let Some(some_other_expr) = other_expr
-            && let Some(parent_binop) =
-                self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
-                    if let (hir_id, hir::Node::Expr(e)) = n
-                        && let hir::ExprKind::AssignOp(_binop, target, _arg) = e.kind
-                        && target.hir_id == expr.hir_id
-                    {
-                        Some(hir_id)
-                    } else {
-                        None
-                    }
-                })
-            && let Some(other_parent_binop) =
-                self.infcx.tcx.hir().parent_iter(some_other_expr.hir_id).find_map(|n| {
-                    if let (hir_id, hir::Node::Expr(expr)) = n
-                        && let hir::ExprKind::AssignOp(..) = expr.kind
-                    {
-                        Some(hir_id)
-                    } else {
-                        None
-                    }
-                })
-            && parent_binop == other_parent_binop
-        {
-            // Explicitly look for `expr += other_expr;` and avoid suggesting
-            // `expr.clone() += other_expr;`, instead suggesting `expr += other_expr.clone();`.
-            other_expr = Some(expr);
-            expr = some_other_expr;
-        }
-        'outer: {
-            if let ty::Ref(..) = ty.kind() {
-                // We check for either `let binding = foo(expr, other_expr);` or
-                // `foo(expr, other_expr);` and if so we don't suggest an incorrect
-                // `foo(expr, other_expr).clone()`
-                if let Some(other_expr) = other_expr
-                    && let Some(parent_let) =
-                        self.infcx.tcx.hir().parent_iter(expr.hir_id).find_map(|n| {
-                            if let (hir_id, hir::Node::LetStmt(_) | hir::Node::Stmt(_)) = n {
-                                Some(hir_id)
-                            } else {
-                                None
-                            }
-                        })
-                    && let Some(other_parent_let) =
-                        self.infcx.tcx.hir().parent_iter(other_expr.hir_id).find_map(|n| {
-                            if let (hir_id, hir::Node::LetStmt(_) | hir::Node::Stmt(_)) = n {
-                                Some(hir_id)
-                            } else {
-                                None
-                            }
-                        })
-                    && parent_let == other_parent_let
-                {
-                    // Explicitly check that we don't have `foo(&*expr, other_expr)`, as cloning the
-                    // result of `foo(...)` won't help.
-                    break 'outer;
-                }
-            }
-        }
-        let ty = ty.peel_refs();
         if self.implements_clone(ty) {
             self.suggest_cloning_inner(err, ty, expr);
         } else if let ty::Adt(def, args) = ty.kind()
@@ -1575,10 +1514,27 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
             );
         self.suggest_copy_for_type_in_cloned_ref(&mut err, place);
         let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
-        if let Some(expr) = self.find_expr(borrow_span)
-            && let Some(ty) = typeck_results.node_type_opt(expr.hir_id)
-        {
-            self.suggest_cloning(&mut err, ty, expr, self.find_expr(span), Some(move_spans));
+        if let Some(expr) = self.find_expr(borrow_span) {
+            // This is a borrow span, so we want to suggest cloning the referent.
+            if let hir::ExprKind::AddrOf(_, _, borrowed_expr) = expr.kind
+                && let Some(ty) = typeck_results.expr_ty_opt(borrowed_expr)
+            {
+                self.suggest_cloning(&mut err, ty, borrowed_expr, Some(move_spans));
+            } else if typeck_results.expr_adjustments(expr).first().is_some_and(|adj| {
+                matches!(
+                    adj.kind,
+                    ty::adjustment::Adjust::Borrow(ty::adjustment::AutoBorrow::Ref(
+                        _,
+                        ty::adjustment::AutoBorrowMutability::Not
+                            | ty::adjustment::AutoBorrowMutability::Mut {
+                                allow_two_phase_borrow: ty::adjustment::AllowTwoPhase::No
+                            }
+                    ))
+                )
+            }) && let Some(ty) = typeck_results.expr_ty_opt(expr)
+            {
+                self.suggest_cloning(&mut err, ty, expr, Some(move_spans));
+            }
         }
         self.buffer_error(err);
     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index fcf23aa478555..74c6bb8810124 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -565,9 +565,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
 
     fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) {
         match error {
-            GroupedMoveError::MovesFromPlace {
-                mut binds_to, move_from, span: other_span, ..
-            } => {
+            GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => {
                 self.add_borrow_suggestions(err, span);
                 if binds_to.is_empty() {
                     let place_ty = move_from.ty(self.body, self.infcx.tcx).ty;
@@ -577,7 +575,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                     };
 
                     if let Some(expr) = self.find_expr(span) {
-                        self.suggest_cloning(err, place_ty, expr, self.find_expr(other_span), None);
+                        self.suggest_cloning(err, place_ty, expr, None);
                     }
 
                     err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
@@ -609,13 +607,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                 };
 
                 if let Some(expr) = self.find_expr(use_span) {
-                    self.suggest_cloning(
-                        err,
-                        place_ty,
-                        expr,
-                        self.find_expr(span),
-                        Some(use_spans),
-                    );
+                    self.suggest_cloning(err, place_ty, expr, Some(use_spans));
                 }
 
                 err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
@@ -740,7 +732,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                 let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
 
                 if let Some(expr) = self.find_expr(binding_span) {
-                    self.suggest_cloning(err, bind_to.ty, expr, None, None);
+                    self.suggest_cloning(err, bind_to.ty, expr, None);
                 }
 
                 err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
diff --git a/tests/ui/associated-types/associated-types-outlives.stderr b/tests/ui/associated-types/associated-types-outlives.stderr
index 1164869bf1982..bd6022fcec655 100644
--- a/tests/ui/associated-types/associated-types-outlives.stderr
+++ b/tests/ui/associated-types/associated-types-outlives.stderr
@@ -18,7 +18,7 @@ LL | pub fn free_and_use Foo<'a>,
    |                     ^ consider constraining this type parameter with `Clone`
 ...
 LL |         's: loop { y = denormalise(&x); break }
-   |                                    -- you could clone this value
+   |                                     - you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/augmented-assignments.rs b/tests/ui/augmented-assignments.rs
index 8b263e03593b8..440a4a7fd6500 100644
--- a/tests/ui/augmented-assignments.rs
+++ b/tests/ui/augmented-assignments.rs
@@ -17,7 +17,6 @@ fn main() {
     x;
     //~^ ERROR cannot move out of `x` because it is borrowed
     //~| move out of `x` occurs here
-    //~| HELP consider cloning
 
     let y = Int(2);
     //~^ HELP consider changing this to be mutable
diff --git a/tests/ui/augmented-assignments.stderr b/tests/ui/augmented-assignments.stderr
index 6b2900dd5d1bc..a4b75cbf6e8fc 100644
--- a/tests/ui/augmented-assignments.stderr
+++ b/tests/ui/augmented-assignments.stderr
@@ -8,14 +8,9 @@ LL |     x
 ...
 LL |     x;
    |     ^ move out of `x` occurs here
-   |
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |     x.clone();
-   |      ++++++++
 
 error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
-  --> $DIR/augmented-assignments.rs:25:5
+  --> $DIR/augmented-assignments.rs:24:5
    |
 LL |     y
    |     ^ cannot borrow as mutable
diff --git a/tests/ui/binop/binop-move-semantics.stderr b/tests/ui/binop/binop-move-semantics.stderr
index 83c27590e9014..45c7f11040616 100644
--- a/tests/ui/binop/binop-move-semantics.stderr
+++ b/tests/ui/binop/binop-move-semantics.stderr
@@ -65,7 +65,7 @@ help: if `T` implemented `Clone`, you could clone the value
 LL | fn move_borrowed>(x: T, mut y: T) {
    |                  ^ consider constraining this type parameter with `Clone`
 LL |     let m = &x;
-   |             -- you could clone this value
+   |              - you could clone this value
 
 error[E0505]: cannot move out of `y` because it is borrowed
   --> $DIR/binop-move-semantics.rs:23:5
@@ -88,7 +88,7 @@ LL | fn move_borrowed>(x: T, mut y: T) {
    |                  ^ consider constraining this type parameter with `Clone`
 LL |     let m = &x;
 LL |     let n = &mut y;
-   |             ------ you could clone this value
+   |                  - you could clone this value
 
 error[E0507]: cannot move out of `*m` which is behind a mutable reference
   --> $DIR/binop-move-semantics.rs:30:5
diff --git a/tests/ui/borrowck/borrow-tuple-fields.stderr b/tests/ui/borrowck/borrow-tuple-fields.stderr
index 8ea7a9a498947..277c335cfccaa 100644
--- a/tests/ui/borrowck/borrow-tuple-fields.stderr
+++ b/tests/ui/borrowck/borrow-tuple-fields.stderr
@@ -13,9 +13,8 @@ LL |     r.use_ref();
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let r = &x.0;
-LL +     let r = x.0.clone();
-   |
+LL |     let r = &x.0.clone();
+   |                 ++++++++
 
 error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
   --> $DIR/borrow-tuple-fields.rs:18:13
@@ -51,9 +50,8 @@ LL |     r.use_ref();
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let r = &x.0;
-LL +     let r = x.0.clone();
-   |
+LL |     let r = &x.0.clone();
+   |                 ++++++++
 
 error[E0502]: cannot borrow `x.0` as mutable because it is also borrowed as immutable
   --> $DIR/borrow-tuple-fields.rs:33:13
diff --git a/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr b/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
index b96949fbb0e78..5e7eee0422ee2 100644
--- a/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
+++ b/tests/ui/borrowck/borrowck-bad-nested-calls-move.stderr
@@ -14,7 +14,7 @@ LL |         a);
 help: consider cloning the value if the performance cost is acceptable
    |
 LL -         &*a,
-LL +         a.clone(),
+LL +         &a.clone(),
    |
 
 error[E0505]: cannot move out of `a` because it is borrowed
@@ -32,7 +32,7 @@ LL |         a);
 help: consider cloning the value if the performance cost is acceptable
    |
 LL -         &*a,
-LL +         a.clone(),
+LL +         &a.clone(),
    |
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/borrowck/borrowck-field-sensitivity.stderr b/tests/ui/borrowck/borrowck-field-sensitivity.stderr
index ea552ff7820e2..b30dd144a4d80 100644
--- a/tests/ui/borrowck/borrowck-field-sensitivity.stderr
+++ b/tests/ui/borrowck/borrowck-field-sensitivity.stderr
@@ -52,9 +52,8 @@ LL |     drop(**p);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let p = &x.b;
-LL +     let p = x.b.clone();
-   |
+LL |     let p = &x.b.clone();
+   |                 ++++++++
 
 error[E0505]: cannot move out of `x.b` because it is borrowed
   --> $DIR/borrowck-field-sensitivity.rs:41:14
@@ -70,9 +69,8 @@ LL |     drop(**p);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let p = &x.b;
-LL +     let p = x.b.clone();
-   |
+LL |     let p = &x.b.clone();
+   |                 ++++++++
 
 error[E0499]: cannot borrow `x.a` as mutable more than once at a time
   --> $DIR/borrowck-field-sensitivity.rs:48:13
diff --git a/tests/ui/borrowck/borrowck-issue-48962.stderr b/tests/ui/borrowck/borrowck-issue-48962.stderr
index 6e821a4c6b0b1..ee174f6736e1e 100644
--- a/tests/ui/borrowck/borrowck-issue-48962.stderr
+++ b/tests/ui/borrowck/borrowck-issue-48962.stderr
@@ -17,11 +17,6 @@ LL |     {src};
    |      --- value moved here
 LL |     src.0 = 66;
    |     ^^^^^^^^^^ value used here after move
-   |
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |     {src.clone()};
-   |         ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
index 370ae058f444d..d9af5cf7d12e8 100644
--- a/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
+++ b/tests/ui/borrowck/borrowck-loan-blocks-move-cc.stderr
@@ -16,9 +16,8 @@ LL |     w.use_ref();
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let w = &v;
-LL +     let w = v.clone();
-   |
+LL |     let w = &v.clone();
+   |               ++++++++
 
 error[E0505]: cannot move out of `v` because it is borrowed
   --> $DIR/borrowck-loan-blocks-move-cc.rs:24:19
@@ -38,9 +37,8 @@ LL |     w.use_ref();
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let w = &v;
-LL +     let w = v.clone();
-   |
+LL |     let w = &v.clone();
+   |               ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
index 8a8005dbb8337..1698035f20ffb 100644
--- a/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
+++ b/tests/ui/borrowck/borrowck-loan-blocks-move.stderr
@@ -12,9 +12,8 @@ LL |     w.use_ref();
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let w = &v;
-LL +     let w = v.clone();
-   |
+LL |     let w = &v.clone();
+   |               ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
index a23a203d99978..b78c374c45620 100644
--- a/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
+++ b/tests/ui/borrowck/borrowck-move-from-subpath-of-borrowed-path.stderr
@@ -13,9 +13,8 @@ LL |     b.use_ref();
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let b = &a;
-LL +     let b = a.clone();
-   |
+LL |     let b = &a.clone();
+   |               ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
index acf426906c3b2..4b9351b64a038 100644
--- a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
+++ b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr
@@ -14,7 +14,7 @@ LL |     p.use_ref();
 help: consider cloning the value if the performance cost is acceptable
    |
 LL -     let p: &isize = &*t0; // Freezes `*t0`
-LL +     let p: &isize = t0.clone(); // Freezes `*t0`
+LL +     let p: &isize = &t0.clone(); // Freezes `*t0`
    |
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
index cc6c3bdeb1022..b5dc01f180b2f 100644
--- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr
+++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
@@ -17,7 +17,7 @@ LL | struct S {
    | ^^^^^^^^ consider implementing `Clone` for this type
 ...
 LL |   let pb = &a;
-   |            -- you could clone this value
+   |             - you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-multiple-captures.stderr b/tests/ui/borrowck/borrowck-multiple-captures.stderr
index fdac4c27cee3b..01b648ea64717 100644
--- a/tests/ui/borrowck/borrowck-multiple-captures.stderr
+++ b/tests/ui/borrowck/borrowck-multiple-captures.stderr
@@ -17,9 +17,8 @@ LL |     borrow(&*p1);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let p1 = &x1;
-LL +     let p1 = x1.clone();
-   |
+LL |     let p1 = &x1.clone();
+   |                 ++++++++
 
 error[E0505]: cannot move out of `x2` because it is borrowed
   --> $DIR/borrowck-multiple-captures.rs:12:19
@@ -39,9 +38,8 @@ LL |     borrow(&*p2);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let p2 = &x2;
-LL +     let p2 = x2.clone();
-   |
+LL |     let p2 = &x2.clone();
+   |                 ++++++++
 
 error[E0382]: use of moved value: `x1`
   --> $DIR/borrowck-multiple-captures.rs:27:19
@@ -108,9 +106,8 @@ LL |     borrow(&*p);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let p = &x;
-LL +     let p = x.clone();
-   |
+LL |     let p = &x.clone();
+   |               ++++++++
 
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-multiple-captures.rs:52:14
diff --git a/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr b/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
index 7f8cc74a7157a..3366853b8e268 100644
--- a/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
+++ b/tests/ui/borrowck/borrowck-overloaded-index-move-index.stderr
@@ -11,6 +11,11 @@ LL |     println!("{}", f[s]);
 ...
 LL |     use_mut(rs);
    |             -- borrow later used here
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let rs = &mut s.clone();
+   |                    ++++++++
 
 error[E0505]: cannot move out of `s` because it is borrowed
   --> $DIR/borrowck-overloaded-index-move-index.rs:53:7
@@ -25,6 +30,11 @@ LL |     f[s] = 10;
 ...
 LL |     use_mut(rs);
    |             -- borrow later used here
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let rs = &mut s.clone();
+   |                    ++++++++
 
 error[E0382]: use of moved value: `s`
   --> $DIR/borrowck-overloaded-index-move-index.rs:53:7
diff --git a/tests/ui/borrowck/borrowck-unary-move.stderr b/tests/ui/borrowck/borrowck-unary-move.stderr
index 598ecb537780f..0aec6d426309f 100644
--- a/tests/ui/borrowck/borrowck-unary-move.stderr
+++ b/tests/ui/borrowck/borrowck-unary-move.stderr
@@ -13,7 +13,7 @@ LL |     *y
 help: consider cloning the value if the performance cost is acceptable
    |
 LL -     let y = &*x;
-LL +     let y = x.clone();
+LL +     let y = &x.clone();
    |
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr
index 19f040556f8ae..d5d21296a3f96 100644
--- a/tests/ui/borrowck/clone-on-ref.stderr
+++ b/tests/ui/borrowck/clone-on-ref.stderr
@@ -38,7 +38,7 @@ help: if `T` implemented `Clone`, you could clone the value
 LL | fn bar(x: T) {
    |        ^ consider constraining this type parameter with `Clone`
 LL |     let a = &x;
-   |             -- you could clone this value
+   |              - you could clone this value
 help: consider further restricting this bound
    |
 LL | fn bar(x: T) {
@@ -66,7 +66,7 @@ LL | struct A;
    | ^^^^^^^^ consider implementing `Clone` for this type
 LL | fn qux(x: A) {
 LL |     let a = &x;
-   |             -- you could clone this value
+   |              - you could clone this value
 help: consider annotating `A` with `#[derive(Clone)]`
    |
 LL + #[derive(Clone)]
diff --git a/tests/ui/borrowck/issue-101119.stderr b/tests/ui/borrowck/issue-101119.stderr
index a894fa63ace28..7fec81b59b3a8 100644
--- a/tests/ui/borrowck/issue-101119.stderr
+++ b/tests/ui/borrowck/issue-101119.stderr
@@ -18,14 +18,6 @@ LL | fn fill_segment(_: &mut State) {}
    |    ------------    ^^^^^^^^^^ this parameter takes ownership of the value
    |    |
    |    in this function
-note: if `State` implemented `Clone`, you could clone the value
-  --> $DIR/issue-101119.rs:1:1
-   |
-LL | struct State;
-   | ^^^^^^^^^^^^ consider implementing `Clone` for this type
-...
-LL |             fill_segment(state);
-   |                          ----- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/btreemap/btreemap_dropck.stderr b/tests/ui/btreemap/btreemap_dropck.stderr
index 873f8cf9a0147..e8f14552af26d 100644
--- a/tests/ui/btreemap/btreemap_dropck.stderr
+++ b/tests/ui/btreemap/btreemap_dropck.stderr
@@ -12,9 +12,8 @@ LL | }
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let _map = BTreeMap::from_iter([((), PrintOnDrop(&s))]);
-LL +     let _map = BTreeMap::from_iter([((), PrintOnDrop(s.clone()))]);
-   |
+LL |     let _map = BTreeMap::from_iter([((), PrintOnDrop(&s.clone()))]);
+   |                                                        ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/dropck/drop-with-active-borrows-1.stderr b/tests/ui/dropck/drop-with-active-borrows-1.stderr
index 7d1633267f0e2..229514c6feef0 100644
--- a/tests/ui/dropck/drop-with-active-borrows-1.stderr
+++ b/tests/ui/dropck/drop-with-active-borrows-1.stderr
@@ -9,11 +9,6 @@ LL |     drop(a);
    |          ^ move out of `a` occurs here
 LL |     for s in &b {
    |              -- borrow later used here
-   |
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |     let b: Vec<&str> = a.clone().lines().collect();
-   |                         ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr
index 343bca9a72e24..582669593336a 100644
--- a/tests/ui/error-codes/E0504.stderr
+++ b/tests/ui/error-codes/E0504.stderr
@@ -21,7 +21,7 @@ LL | struct FancyNum {
    | ^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
 ...
 LL |     let fancy_ref = &fancy_num;
-   |                     ---------- you could clone this value
+   |                      --------- you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr
index 266df9ea32a71..3f2913e9fe3c6 100644
--- a/tests/ui/error-codes/E0505.stderr
+++ b/tests/ui/error-codes/E0505.stderr
@@ -18,7 +18,7 @@ LL | struct Value {}
    | ^^^^^^^^^^^^ consider implementing `Clone` for this type
 ...
 LL |         let _ref_to_val: &Value = &x;
-   |                                   -- you could clone this value
+   |                                    - you could clone this value
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
index b8ec2e3b7e7b9..4e64ed6f482e0 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-4.stderr
@@ -13,9 +13,8 @@ LL |     println!("{}", y);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let y = f(&x, ());
-LL +     let y = f(x.clone(), ());
-   |
+LL |     let y = f(&x.clone(), ());
+   |                 ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr
index 382ab8636a294..b898df0835c2a 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr
@@ -30,9 +30,8 @@ LL |     println!("{}", y);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let y = f(&x, ());
-LL +     let y = f(x.clone(), ());
-   |
+LL |     let y = f(&x.clone(), ());
+   |                 ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
index ce97d8527e857..2a7431305fed4 100644
--- a/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
+++ b/tests/ui/fn/implied-bounds-unnorm-associated-type.stderr
@@ -13,9 +13,8 @@ LL |     println!("{}", y);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let y = f(&x, ());
-LL +     let y = f(x.clone(), ());
-   |
+LL |     let y = f(&x.clone(), ());
+   |                 ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr
index f2c6008d27eac..de19a99d388ca 100644
--- a/tests/ui/moves/move-fn-self-receiver.stderr
+++ b/tests/ui/moves/move-fn-self-receiver.stderr
@@ -101,15 +101,6 @@ LL |     mut_foo;
    |     ^^^^^^^ move out of `mut_foo` occurs here
 LL |     ret;
    |     --- borrow later used here
-   |
-note: if `Foo` implemented `Clone`, you could clone the value
-  --> $DIR/move-fn-self-receiver.rs:5:1
-   |
-LL | struct Foo;
-   | ^^^^^^^^^^ consider implementing `Clone` for this type
-...
-LL |     let ret = mut_foo.use_mut_self();
-   |               ------- you could clone this value
 
 error[E0382]: use of moved value: `rc_foo`
   --> $DIR/move-fn-self-receiver.rs:55:5
diff --git a/tests/ui/nll/closure-access-spans.stderr b/tests/ui/nll/closure-access-spans.stderr
index f789e5e9f9571..a8024a8c20b9e 100644
--- a/tests/ui/nll/closure-access-spans.stderr
+++ b/tests/ui/nll/closure-access-spans.stderr
@@ -60,9 +60,8 @@ LL |     r.use_ref();
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     let r = &x;
-LL +     let r = x.clone();
-   |
+LL |     let r = &x.clone();
+   |               ++++++++
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/closure-access-spans.rs:35:5
@@ -109,11 +108,6 @@ LL |     || *x = String::new();
    |     ^^ -- borrow occurs due to use in closure
    |     |
    |     value borrowed here after move
-   |
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |     let r = x.clone();
-   |              ++++++++
 
 error[E0382]: use of moved value: `x`
   --> $DIR/closure-access-spans.rs:50:5
@@ -126,11 +120,6 @@ LL |     || x;
    |     ^^ - use occurs due to use in closure
    |     |
    |     value used here after move
-   |
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |     let r = x.clone();
-   |              ++++++++
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr b/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr
index 39ec45b20eae6..ae7978004576b 100644
--- a/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr
+++ b/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr
@@ -10,11 +10,6 @@ LL |         _ if { (|| { let bar = b; *bar = false; })();
    |                 --             - variable moved due to use in closure
    |                 |
    |                 value moved into closure here
-   |
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |         _ if { (|| { let bar = b.clone(); *bar = false; })();
-   |                                 ++++++++
 
 error[E0382]: use of moved value: `b`
   --> $DIR/issue-27282-move-match-input-into-guard.rs:24:5
@@ -28,11 +23,6 @@ LL |             (|| { let bar = b; *bar = false; })();
    |              --             - variable moved due to use in closure
    |              |
    |              value moved into closure here
-   |
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |             (|| { let bar = b.clone(); *bar = false; })();
-   |                              ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed
deleted file mode 100644
index 7692be7ccc801..0000000000000
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.fixed
+++ /dev/null
@@ -1,23 +0,0 @@
-// Issue 27282: Example 1: This sidesteps the AST checks disallowing
-// mutable borrows in match guards by hiding the mutable borrow in a
-// guard behind a move (of the ref mut pattern id) within a closure.
-//@ run-rustfix
-#![feature(if_let_guard)]
-
-fn main() {
-    match Some(&4) {
-        None => {},
-        ref mut foo
-            if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
-        //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
-        Some(s) => std::process::exit(*s),
-    }
-
-    match Some(&4) {
-        None => {},
-        ref mut foo
-            if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {},
-        //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
-        Some(s) => std::process::exit(*s),
-    }
-}
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
index f3d0a184e03c5..c3b19886a5078 100644
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
+++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs
@@ -1,7 +1,7 @@
 // Issue 27282: Example 1: This sidesteps the AST checks disallowing
 // mutable borrows in match guards by hiding the mutable borrow in a
 // guard behind a move (of the ref mut pattern id) within a closure.
-//@ run-rustfix
+
 #![feature(if_let_guard)]
 
 fn main() {
diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
index 7781e77894b89..e790fda4d7ca7 100644
--- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
+++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr
@@ -7,10 +7,6 @@ LL |             if { (|| { let mut bar = foo; bar.take() })(); false } => {},
    |                   `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |             if { (|| { let mut bar = foo.clone(); bar.take() })(); false } => {},
-   |                                         ++++++++
 
 error[E0507]: cannot move out of `foo` in pattern guard
   --> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34
@@ -21,10 +17,6 @@ LL |             if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); N
    |                                  `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |             if let Some(()) = { (|| { let mut bar = foo.clone(); bar.take() })(); None } => {},
-   |                                                        ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.stderr b/tests/ui/nll/issue-27282-mutation-in-guard.stderr
index f73e4aaa489aa..0b5d723172c76 100644
--- a/tests/ui/nll/issue-27282-mutation-in-guard.stderr
+++ b/tests/ui/nll/issue-27282-mutation-in-guard.stderr
@@ -7,10 +7,6 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |                  `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |                 (|| { let bar = foo.clone(); bar.take() })();
-   |                                    ++++++++
 
 error[E0507]: cannot move out of `foo` in pattern guard
   --> $DIR/issue-27282-mutation-in-guard.rs:20:18
@@ -21,10 +17,6 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |                  `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |                 (|| { let bar = foo.clone(); bar.take() })();
-   |                                    ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
index f4e7869bf0056..7f9cbc3c30a92 100644
--- a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
+++ b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr
@@ -41,10 +41,6 @@ help: consider borrowing here
    |
 LL |     let p = &s.url; p
    |             +
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |     let p = s.url.clone(); p
-   |                  ++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/nll/match-guards-always-borrow.fixed b/tests/ui/nll/match-guards-always-borrow.fixed
deleted file mode 100644
index 56e743bf196a6..0000000000000
--- a/tests/ui/nll/match-guards-always-borrow.fixed
+++ /dev/null
@@ -1,66 +0,0 @@
-#![feature(if_let_guard)]
-#![allow(unused_mut)]
-//@ run-rustfix
-
-// Here is arielb1's basic example from rust-lang/rust#27282
-// that AST borrowck is flummoxed by:
-
-fn should_reject_destructive_mutate_in_guard() {
-    match Some(&4) {
-        None => {},
-        ref mut foo if {
-            (|| { let mut bar = foo.clone(); bar.take() })();
-            //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
-            false } => { },
-        Some(s) => std::process::exit(*s),
-    }
-
-    match Some(&4) {
-        None => {},
-        ref mut foo if let Some(()) = {
-            (|| { let mut bar = foo.clone(); bar.take() })();
-            //~^ ERROR cannot move out of `foo` in pattern guard [E0507]
-            None } => { },
-        Some(s) => std::process::exit(*s),
-    }
-}
-
-// Here below is a case that needs to keep working: we only use the
-// binding via immutable-borrow in the guard, and we mutate in the arm
-// body.
-fn allow_mutate_in_arm_body() {
-    match Some(&4) {
-        None => {},
-        ref mut foo if foo.is_some() => { foo.take(); () }
-        Some(s) => std::process::exit(*s),
-    }
-
-    match Some(&4) {
-        None => {},
-        ref mut foo if let Some(_) = foo => { foo.take(); () }
-        Some(s) => std::process::exit(*s),
-    }
-}
-
-// Here below is a case that needs to keep working: we only use the
-// binding via immutable-borrow in the guard, and we move into the arm
-// body.
-fn allow_move_into_arm_body() {
-    match Some(&4) {
-        None => {},
-        mut foo if foo.is_some() => { foo.unwrap(); () }
-        Some(s) => std::process::exit(*s),
-    }
-
-    match Some(&4) {
-        None => {},
-        mut foo if let Some(_) = foo => { foo.unwrap(); () }
-        Some(s) => std::process::exit(*s),
-    }
-}
-
-fn main() {
-    should_reject_destructive_mutate_in_guard();
-    allow_mutate_in_arm_body();
-    allow_move_into_arm_body();
-}
diff --git a/tests/ui/nll/match-guards-always-borrow.rs b/tests/ui/nll/match-guards-always-borrow.rs
index 927d55c42a6e3..5271e3cfc6655 100644
--- a/tests/ui/nll/match-guards-always-borrow.rs
+++ b/tests/ui/nll/match-guards-always-borrow.rs
@@ -1,6 +1,5 @@
 #![feature(if_let_guard)]
 #![allow(unused_mut)]
-//@ run-rustfix
 
 // Here is arielb1's basic example from rust-lang/rust#27282
 // that AST borrowck is flummoxed by:
diff --git a/tests/ui/nll/match-guards-always-borrow.stderr b/tests/ui/nll/match-guards-always-borrow.stderr
index bb0c5bd4c9761..71977bd84721b 100644
--- a/tests/ui/nll/match-guards-always-borrow.stderr
+++ b/tests/ui/nll/match-guards-always-borrow.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/match-guards-always-borrow.rs:12:14
+  --> $DIR/match-guards-always-borrow.rs:11:14
    |
 LL |             (|| { let mut bar = foo; bar.take() })();
    |              ^^                 --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -7,13 +7,9 @@ LL |             (|| { let mut bar = foo; bar.take() })();
    |              `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |             (|| { let mut bar = foo.clone(); bar.take() })();
-   |                                    ++++++++
 
 error[E0507]: cannot move out of `foo` in pattern guard
-  --> $DIR/match-guards-always-borrow.rs:21:14
+  --> $DIR/match-guards-always-borrow.rs:20:14
    |
 LL |             (|| { let mut bar = foo; bar.take() })();
    |              ^^                 --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
@@ -21,10 +17,6 @@ LL |             (|| { let mut bar = foo; bar.take() })();
    |              `foo` is moved here
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |             (|| { let mut bar = foo.clone(); bar.take() })();
-   |                                    ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/polonius/polonius-smoke-test.stderr b/tests/ui/nll/polonius/polonius-smoke-test.stderr
index 534813b2d9f5a..a8a8267290def 100644
--- a/tests/ui/nll/polonius/polonius-smoke-test.stderr
+++ b/tests/ui/nll/polonius/polonius-smoke-test.stderr
@@ -27,6 +27,12 @@ LL |     let z = x;
    |             ^ move out of `x` occurs here
 LL |     y
    |     - returning this value requires that `*x` is borrowed for `'1`
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     let y = &mut *x;
+LL +     let y = &mut x.clone();
+   |
 
 error[E0505]: cannot move out of `s` because it is borrowed
   --> $DIR/polonius-smoke-test.rs:42:5
@@ -40,6 +46,12 @@ LL |     s;
    |     ^ move out of `s` occurs here
 LL |     tmp;
    |     --- borrow later used here
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     let r = &mut *s;
+LL +     let r = &mut s.clone();
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index e925fe78f3393..9359244c6ebc1 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -333,14 +333,6 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-note: if `U` implemented `Clone`, you could clone the value
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
-   |
-LL |     struct U;
-   |     ^^^^^^^^ consider implementing `Clone` for this type
-...
-LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
-   |                                                                  - you could clone this value
 
 error[E0507]: cannot move out of `b` in pattern guard
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
@@ -349,14 +341,6 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
-note: if `U` implemented `Clone`, you could clone the value
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
-   |
-LL |     struct U;
-   |     ^^^^^^^^ consider implementing `Clone` for this type
-...
-LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
-   |                                                                  - you could clone this value
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0507]: cannot move out of `a` in pattern guard
diff --git a/tests/ui/span/send-is-not-static-std-sync.stderr b/tests/ui/span/send-is-not-static-std-sync.stderr
index 50b8ffe0114b0..6bc3ed8d24ff0 100644
--- a/tests/ui/span/send-is-not-static-std-sync.stderr
+++ b/tests/ui/span/send-is-not-static-std-sync.stderr
@@ -15,7 +15,7 @@ LL |         *lock.lock().unwrap() = &z;
 help: consider cloning the value if the performance cost is acceptable
    |
 LL -     *lock.lock().unwrap() = &*y;
-LL +     *lock.lock().unwrap() = y.clone();
+LL +     *lock.lock().unwrap() = &y.clone();
    |
 
 error[E0597]: `z` does not live long enough
@@ -48,7 +48,7 @@ LL |         *lock.write().unwrap() = &z;
 help: consider cloning the value if the performance cost is acceptable
    |
 LL -     *lock.write().unwrap() = &*y;
-LL +     *lock.write().unwrap() = y.clone();
+LL +     *lock.write().unwrap() = &y.clone();
    |
 
 error[E0597]: `z` does not live long enough
@@ -81,7 +81,7 @@ LL |         tx.send(&z).unwrap();
 help: consider cloning the value if the performance cost is acceptable
    |
 LL -     tx.send(&*y);
-LL +     tx.send(y.clone());
+LL +     tx.send(&y.clone());
    |
 
 error[E0597]: `z` does not live long enough
diff --git a/tests/ui/suggestions/borrow-for-loop-head.stderr b/tests/ui/suggestions/borrow-for-loop-head.stderr
index a8de9986c312d..55fcb44168c49 100644
--- a/tests/ui/suggestions/borrow-for-loop-head.stderr
+++ b/tests/ui/suggestions/borrow-for-loop-head.stderr
@@ -10,9 +10,8 @@ LL |         for j in a {
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -     for i in &a {
-LL +     for i in a.clone() {
-   |
+LL |     for i in &a.clone() {
+   |                ++++++++
 
 error[E0382]: use of moved value: `a`
   --> $DIR/borrow-for-loop-head.rs:4:18
diff --git a/tests/ui/try-block/try-block-bad-lifetime.stderr b/tests/ui/try-block/try-block-bad-lifetime.stderr
index 6f69329535711..28941cb0a9e40 100644
--- a/tests/ui/try-block/try-block-bad-lifetime.stderr
+++ b/tests/ui/try-block/try-block-bad-lifetime.stderr
@@ -34,11 +34,6 @@ LL |             Err(k) ?;
 ...
 LL |         ::std::mem::drop(k);
    |                          ^ value used here after move
-   |
-help: consider cloning the value if the performance cost is acceptable
-   |
-LL |             Err(k.clone()) ?;
-   |                  ++++++++
 
 error[E0506]: cannot assign to `i` because it is borrowed
   --> $DIR/try-block-bad-lifetime.rs:32:9
diff --git a/tests/ui/unop/unop-move-semantics.stderr b/tests/ui/unop/unop-move-semantics.stderr
index bc9b3ea990384..0ae918d434a0f 100644
--- a/tests/ui/unop/unop-move-semantics.stderr
+++ b/tests/ui/unop/unop-move-semantics.stderr
@@ -40,7 +40,7 @@ help: if `T` implemented `Clone`, you could clone the value
 LL | fn move_borrowed>(x: T, mut y: T) {
    |                  ^ consider constraining this type parameter with `Clone`
 LL |     let m = &x;
-   |             -- you could clone this value
+   |              - you could clone this value
 
 error[E0505]: cannot move out of `y` because it is borrowed
   --> $DIR/unop-move-semantics.rs:17:6
@@ -63,7 +63,7 @@ LL | fn move_borrowed>(x: T, mut y: T) {
    |                  ^ consider constraining this type parameter with `Clone`
 LL |     let m = &x;
 LL |     let n = &mut y;
-   |             ------ you could clone this value
+   |                  - you could clone this value
 
 error[E0507]: cannot move out of `*m` which is behind a mutable reference
   --> $DIR/unop-move-semantics.rs:24:6
diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr
index 0a810b7222e7c..21d8de6ae8815 100644
--- a/tests/ui/variance/variance-issue-20533.stderr
+++ b/tests/ui/variance/variance-issue-20533.stderr
@@ -17,7 +17,7 @@ LL | struct AffineU32(u32);
    | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
 ...
 LL |         let x = foo(&a);
-   |                     -- you could clone this value
+   |                      - you could clone this value
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:41:14
@@ -38,7 +38,7 @@ LL | struct AffineU32(u32);
    | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
 ...
 LL |         let x = bar(&a);
-   |                     -- you could clone this value
+   |                      - you could clone this value
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:47:14
@@ -59,7 +59,7 @@ LL | struct AffineU32(u32);
    | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
 ...
 LL |         let x = baz(&a);
-   |                     -- you could clone this value
+   |                      - you could clone this value
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:53:14
@@ -80,7 +80,7 @@ LL | struct AffineU32(u32);
    | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
 ...
 LL |         let x = bat(&a);
-   |                     -- you could clone this value
+   |                      - you could clone this value
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:59:14
@@ -96,9 +96,8 @@ LL |         drop(x);
    |
 help: consider cloning the value if the performance cost is acceptable
    |
-LL -         let x = foo(&a);
-LL +         let x = foo(a.clone());
-   |
+LL |         let x = foo(&a.clone());
+   |                       ++++++++
 
 error: aborting due to 5 previous errors
 

From 1a15d901211c37aa2f4f818cbcc49bfa0c2e80b6 Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Fri, 26 Jul 2024 12:06:25 -0400
Subject: [PATCH 167/489] assert_stdout_contains_regex in run_make_support +
 variations

---
 .../run-make-support/src/assertion_helpers.rs | 32 +++++++++++++++++-
 src/tools/run-make-support/src/command.rs     | 33 ++++++++++++++++++-
 .../src/external_deps/llvm.rs                 | 30 +++++++++++++++++
 src/tools/run-make-support/src/lib.rs         |  7 ++--
 .../rmake.rs                                  |  8 ++---
 5 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/src/tools/run-make-support/src/assertion_helpers.rs b/src/tools/run-make-support/src/assertion_helpers.rs
index 4b5b349431db9..6d256fc594d8e 100644
--- a/src/tools/run-make-support/src/assertion_helpers.rs
+++ b/src/tools/run-make-support/src/assertion_helpers.rs
@@ -3,7 +3,7 @@
 use std::panic;
 use std::path::Path;
 
-use crate::fs;
+use crate::{fs, regex};
 
 /// Assert that `actual` is equal to `expected`.
 #[track_caller]
@@ -47,6 +47,36 @@ pub fn assert_not_contains, N: AsRef>(haystack: H, needle: N)
     }
 }
 
+/// Assert that `haystack` contains the regex pattern `needle`.
+#[track_caller]
+pub fn assert_contains_regex, N: AsRef>(haystack: H, needle: N) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+    let re = regex::Regex::new(needle).unwrap();
+    if !re.is_match(haystack) {
+        eprintln!("=== HAYSTACK ===");
+        eprintln!("{}", haystack);
+        eprintln!("=== NEEDLE ===");
+        eprintln!("{}", needle);
+        panic!("needle was not found in haystack");
+    }
+}
+
+/// Assert that `haystack` does not contain the regex pattern `needle`.
+#[track_caller]
+pub fn assert_not_contains_regex, N: AsRef>(haystack: H, needle: N) {
+    let haystack = haystack.as_ref();
+    let needle = needle.as_ref();
+    let re = regex::Regex::new(needle).unwrap();
+    if re.is_match(haystack) {
+        eprintln!("=== HAYSTACK ===");
+        eprintln!("{}", haystack);
+        eprintln!("=== NEEDLE ===");
+        eprintln!("{}", needle);
+        panic!("needle was unexpectedly found in haystack");
+    }
+}
+
 /// Assert that all files in `dir1` exist and have the same content in `dir2`
 pub fn assert_dirs_are_equal(dir1: impl AsRef, dir2: impl AsRef) {
     let dir2 = dir2.as_ref();
diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs
index 47376c401bb67..8686855b6f376 100644
--- a/src/tools/run-make-support/src/command.rs
+++ b/src/tools/run-make-support/src/command.rs
@@ -6,7 +6,10 @@ use std::path::Path;
 use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
 
 use crate::util::handle_failed_output;
-use crate::{assert_contains, assert_equals, assert_not_contains};
+use crate::{
+    assert_contains, assert_contains_regex, assert_equals, assert_not_contains,
+    assert_not_contains_regex,
+};
 
 use build_helper::drop_bomb::DropBomb;
 
@@ -192,6 +195,13 @@ impl CompletedProcess {
         self
     }
 
+    /// Checks that `stdout` does not contain the regex pattern `unexpected`.
+    #[track_caller]
+    pub fn assert_stdout_not_contains_regex>(&self, unexpected: S) -> &Self {
+        assert_not_contains_regex(&self.stdout_utf8(), unexpected);
+        self
+    }
+
     /// Checks that `stdout` contains `expected`.
     #[track_caller]
     pub fn assert_stdout_contains>(&self, expected: S) -> &Self {
@@ -199,6 +209,13 @@ impl CompletedProcess {
         self
     }
 
+    /// Checks that `stdout` contains the regex pattern `expected`.
+    #[track_caller]
+    pub fn assert_stdout_contains_regex>(&self, expected: S) -> &Self {
+        assert_contains_regex(&self.stdout_utf8(), expected);
+        self
+    }
+
     /// Checks that trimmed `stderr` matches trimmed `expected`.
     #[track_caller]
     pub fn assert_stderr_equals>(&self, expected: S) -> &Self {
@@ -213,6 +230,13 @@ impl CompletedProcess {
         self
     }
 
+    /// Checks that `stderr` contains the regex pattern `expected`.
+    #[track_caller]
+    pub fn assert_stderr_contains_regex>(&self, expected: S) -> &Self {
+        assert_contains_regex(&self.stderr_utf8(), expected);
+        self
+    }
+
     /// Checks that `stderr` does not contain `unexpected`.
     #[track_caller]
     pub fn assert_stderr_not_contains>(&self, unexpected: S) -> &Self {
@@ -220,6 +244,13 @@ impl CompletedProcess {
         self
     }
 
+    /// Checks that `stderr` does not contain the regex pattern `unexpected`.
+    #[track_caller]
+    pub fn assert_stderr_not_contains_regex>(&self, unexpected: S) -> &Self {
+        assert_not_contains_regex(&self.stdout_utf8(), unexpected);
+        self
+    }
+
     #[track_caller]
     pub fn assert_exit_code(&self, code: i32) -> &Self {
         assert!(self.output.status.code() == Some(code));
diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs
index b116bd08e3a6c..259bb6159461b 100644
--- a/src/tools/run-make-support/src/external_deps/llvm.rs
+++ b/src/tools/run-make-support/src/external_deps/llvm.rs
@@ -36,6 +36,12 @@ pub fn llvm_ar() -> LlvmAr {
     LlvmAr::new()
 }
 
+/// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
+/// at `$LLVM_BIN_DIR/llvm-nm`.
+pub fn llvm_nm() -> LlvmNm {
+    LlvmNm::new()
+}
+
 /// A `llvm-readobj` invocation builder.
 #[derive(Debug)]
 #[must_use]
@@ -71,11 +77,19 @@ pub struct LlvmAr {
     cmd: Command,
 }
 
+/// A `llvm-nm` invocation builder.
+#[derive(Debug)]
+#[must_use]
+pub struct LlvmNm {
+    cmd: Command,
+}
+
 crate::macros::impl_common_helpers!(LlvmReadobj);
 crate::macros::impl_common_helpers!(LlvmProfdata);
 crate::macros::impl_common_helpers!(LlvmFilecheck);
 crate::macros::impl_common_helpers!(LlvmObjdump);
 crate::macros::impl_common_helpers!(LlvmAr);
+crate::macros::impl_common_helpers!(LlvmNm);
 
 /// Generate the path to the bin directory of LLVM.
 #[must_use]
@@ -244,3 +258,19 @@ impl LlvmAr {
         self
     }
 }
+
+impl LlvmNm {
+    /// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available
+    /// at `$LLVM_BIN_DIR/llvm-nm`.
+    pub fn new() -> Self {
+        let llvm_nm = llvm_bin_dir().join("llvm-nm");
+        let cmd = Command::new(llvm_nm);
+        Self { cmd }
+    }
+
+    /// Provide an input file.
+    pub fn input>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+}
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 085120764b463..f28f2a120a44b 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -48,8 +48,8 @@ pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc};
 pub use clang::{clang, Clang};
 pub use htmldocck::htmldocck;
 pub use llvm::{
-    llvm_ar, llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, LlvmFilecheck,
-    LlvmObjdump, LlvmProfdata, LlvmReadobj,
+    llvm_ar, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr,
+    LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj,
 };
 pub use python::python_command;
 pub use rustc::{aux_build, bare_rustc, rustc, Rustc};
@@ -84,7 +84,8 @@ pub use path_helpers::{
 pub use scoped_run::{run_in_tmpdir, test_while_readonly};
 
 pub use assertion_helpers::{
-    assert_contains, assert_dirs_are_equal, assert_equals, assert_not_contains,
+    assert_contains, assert_contains_regex, assert_dirs_are_equal, assert_equals,
+    assert_not_contains, assert_not_contains_regex,
 };
 
 pub use string::{
diff --git a/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
index 8d7afd3245ec2..5a1460963b64d 100644
--- a/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
+++ b/tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs
@@ -4,18 +4,14 @@
 // in rustc flags without a compilation failure or the removal of expected symbols.
 // See https://github.com/rust-lang/rust/pull/100101
 
-//FIXME(Oneirical): try it on test-various
-
-use run_make_support::{llvm_ar, llvm_readobj, regex, rfs, rust_lib_name, rustc};
+use run_make_support::{llvm_ar, llvm_nm, rfs, rust_lib_name, rustc};
 
 fn main() {
     // Build a strangely named dependency.
     rustc().input("native_dep.rs").crate_type("staticlib").output("native_dep.ext").run();
 
     rustc().input("rust_dep.rs").crate_type("rlib").arg("-Zpacked_bundled_libs").run();
-    let symbols = llvm_readobj().symbols().input(rust_lib_name("rust_dep")).run().stdout_utf8();
-    let re = regex::Regex::new("U.*native_f1").unwrap();
-    assert!(re.is_match(&symbols));
+    llvm_nm().input(rust_lib_name("rust_dep")).run().assert_stdout_contains_regex("U.*native_f1");
     llvm_ar()
         .arg("t")
         .arg(rust_lib_name("rust_dep"))

From a15fbe6c305c7974e007f58beb299070c19ebd22 Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Fri, 26 Jul 2024 22:44:47 +0200
Subject: [PATCH 168/489] early exit if unresolved field is an index

---
 .../src/handlers/unresolved_field.rs          | 48 +++++++++++++++++--
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
index 467d4edbf26d0..eb8eea69f67f6 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
@@ -152,7 +152,12 @@ fn add_field_to_struct_fix(
             } else {
                 Some(make::visibility_pub_crate())
             };
-            let field_name = make::name(field_name);
+
+            let field_name = match field_name.chars().next() {
+                Some(ch) if ch.is_numeric() => return None,
+                Some(_) => make::name(field_name),
+                None => return None,
+            };
 
             let (offset, record_field) = record_field_layout(
                 visibility,
@@ -178,7 +183,12 @@ fn add_field_to_struct_fix(
         None => {
             // Add a field list to the Unit Struct
             let mut src_change_builder = SourceChangeBuilder::new(struct_range.file_id);
-            let field_name = make::name(field_name);
+            let field_name = match field_name.chars().next() {
+                // FIXME : See match arm below regarding tuple structs.
+                Some(ch) if ch.is_numeric() => return None,
+                Some(_) => make::name(field_name),
+                None => return None,
+            };
             let visibility = if error_range.file_id == struct_range.file_id {
                 None
             } else {
@@ -274,7 +284,7 @@ mod tests {
     use crate::{
         tests::{
             check_diagnostics, check_diagnostics_with_config, check_diagnostics_with_disabled,
-            check_fix,
+            check_fix, check_no_fix,
         },
         DiagnosticsConfig,
     };
@@ -459,4 +469,36 @@ fn foo() {
             "#,
         );
     }
+
+    #[test]
+    fn no_fix_when_indexed() {
+        check_no_fix(
+            r#"
+            struct Kek {}
+impl Kek {
+    pub fn foo(self) {
+        self.$00
+    }
+}
+
+fn main() {}
+            "#,
+        )
+    }
+
+    #[test]
+    fn no_fix_when_without_field() {
+        check_no_fix(
+            r#"
+            struct Kek {}
+impl Kek {
+    pub fn foo(self) {
+        self.$0
+    }
+}
+
+fn main() {}
+            "#,
+        )
+    }
 }

From 55964dad2a754b9df8a92cb2a8e1f3e3e0623c66 Mon Sep 17 00:00:00 2001
From: Edward Jones 
Date: Fri, 26 Jul 2024 22:49:11 -0300
Subject: [PATCH 169/489] docs: Reference cov_mark crate instead of
 test_utils/mark

Seems this was switched over in https://github.com/rust-lang/rust-analyzer/issues/7922
---
 src/tools/rust-analyzer/docs/dev/architecture.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/rust-analyzer/docs/dev/architecture.md b/src/tools/rust-analyzer/docs/dev/architecture.md
index f4e7263868c4b..4f8723a936891 100644
--- a/src/tools/rust-analyzer/docs/dev/architecture.md
+++ b/src/tools/rust-analyzer/docs/dev/architecture.md
@@ -408,7 +408,7 @@ It has a much richer vocabulary of types than `ide`, but the basic testing setup
 For comparisons, we use the `expect` crate for snapshot testing.
 
 To test various analysis corner cases and avoid forgetting about old tests, we use so-called marks.
-See the `marks` module in the `test_utils` crate for more.
+See the [cov_mark](https://docs.rs/cov-mark/latest/cov_mark/) crate documentation for more.
 
 **Architecture Invariant:** rust-analyzer tests do not use libcore or libstd.
 All required library code must be a part of the tests.

From 77dc02862ae7ab5a006e9128c8c6b4b4814e5f4c Mon Sep 17 00:00:00 2001
From: Ryo Yoshida 
Date: Tue, 30 May 2023 16:58:59 +0900
Subject: [PATCH 170/489] fix: let glob imports override other globs'
 visibility

---
 .../crates/hir-def/src/item_scope.rs          | 97 +++++++++++++------
 .../crates/hir-def/src/nameres/collector.rs   | 87 ++++++++++++++++-
 .../crates/hir-def/src/nameres/tests/globs.rs | 45 +++++++++
 3 files changed, 197 insertions(+), 32 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index 86c3e0f041d39..df6b1f55c1d96 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -61,6 +61,18 @@ pub struct ImportId {
     pub idx: Idx,
 }
 
+impl PerNsGlobImports {
+    pub(crate) fn contains_type(&self, module_id: LocalModuleId, name: Name) -> bool {
+        self.types.contains(&(module_id, name))
+    }
+    pub(crate) fn contains_value(&self, module_id: LocalModuleId, name: Name) -> bool {
+        self.values.contains(&(module_id, name))
+    }
+    pub(crate) fn contains_macro(&self, module_id: LocalModuleId, name: Name) -> bool {
+        self.macros.contains(&(module_id, name))
+    }
+}
+
 #[derive(Debug, Default, PartialEq, Eq)]
 pub struct ItemScope {
     /// Defs visible in this scope. This includes `declarations`, but also
@@ -510,38 +522,48 @@ impl ItemScope {
                     entry.insert(fld);
                     changed = true;
                 }
-                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
-                    if glob_imports.types.remove(&lookup) {
-                        let import = match import {
-                            Some(ImportType::ExternCrate(extern_crate)) => {
-                                Some(ImportOrExternCrate::ExternCrate(extern_crate))
-                            }
-                            Some(ImportType::Import(import)) => {
-                                Some(ImportOrExternCrate::Import(import))
-                            }
-                            None | Some(ImportType::Glob(_)) => None,
-                        };
-                        let prev = std::mem::replace(&mut fld.2, import);
-                        if let Some(import) = import {
-                            self.use_imports_types.insert(
-                                import,
-                                match prev {
-                                    Some(ImportOrExternCrate::Import(import)) => {
-                                        ImportOrDef::Import(import)
+                Entry::Occupied(mut entry) => {
+                    match import {
+                        Some(ImportType::Glob(..)) => {
+                            // Multiple globs may import the same item and they may
+                            // override visibility from previously resolved globs. This is
+                            // currently handled by `DefCollector`, because we need to
+                            // compute the max visibility for items and we need `DefMap`
+                            // for that.
+                        }
+                        _ => {
+                            if glob_imports.types.remove(&lookup) {
+                                let import = match import {
+                                    Some(ImportType::ExternCrate(extern_crate)) => {
+                                        Some(ImportOrExternCrate::ExternCrate(extern_crate))
                                     }
-                                    Some(ImportOrExternCrate::ExternCrate(import)) => {
-                                        ImportOrDef::ExternCrate(import)
+                                    Some(ImportType::Import(import)) => {
+                                        Some(ImportOrExternCrate::Import(import))
                                     }
-                                    None => ImportOrDef::Def(fld.0),
-                                },
-                            );
+                                    None | Some(ImportType::Glob(_)) => None,
+                                };
+                                let prev = std::mem::replace(&mut fld.2, import);
+                                if let Some(import) = import {
+                                    self.use_imports_types.insert(
+                                        import,
+                                        match prev {
+                                            Some(ImportOrExternCrate::Import(import)) => {
+                                                ImportOrDef::Import(import)
+                                            }
+                                            Some(ImportOrExternCrate::ExternCrate(import)) => {
+                                                ImportOrDef::ExternCrate(import)
+                                            }
+                                            None => ImportOrDef::Def(fld.0),
+                                        },
+                                    );
+                                }
+                                cov_mark::hit!(import_shadowed);
+                                entry.insert(fld);
+                                changed = true;
+                            }
                         }
-                        cov_mark::hit!(import_shadowed);
-                        entry.insert(fld);
-                        changed = true;
                     }
                 }
-                _ => {}
             }
         }
 
@@ -756,6 +778,27 @@ impl ItemScope {
     }
 }
 
+// These methods are a temporary measure only meant to be used by `DefCollector::push_res_and_update_glob_vis()`.
+impl ItemScope {
+    pub(crate) fn update_visibility_types(&mut self, name: &Name, vis: Visibility) {
+        let res =
+            self.types.get_mut(name).expect("tried to update visibility of non-existent type");
+        res.1 = vis;
+    }
+
+    pub(crate) fn update_visibility_values(&mut self, name: &Name, vis: Visibility) {
+        let res =
+            self.values.get_mut(name).expect("tried to update visibility of non-existent value");
+        res.1 = vis;
+    }
+
+    pub(crate) fn update_visibility_macros(&mut self, name: &Name, vis: Visibility) {
+        let res =
+            self.macros.get_mut(name).expect("tried to update visibility of non-existent macro");
+        res.1 = vis;
+    }
+}
+
 impl PerNs {
     pub(crate) fn from_def(
         def: ModuleDefId,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index c51eea22dcb0e..6f435d1f5816e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -1025,7 +1025,7 @@ impl DefCollector<'_> {
 
     fn update_recursive(
         &mut self,
-        // The module for which `resolutions` have been resolve
+        // The module for which `resolutions` have been resolved.
         module_id: LocalModuleId,
         resolutions: &[(Option, PerNs)],
         // All resolutions are imported with this visibility; the visibilities in
@@ -1043,10 +1043,9 @@ impl DefCollector<'_> {
         for (name, res) in resolutions {
             match name {
                 Some(name) => {
-                    let scope = &mut self.def_map.modules[module_id].scope;
-                    changed |= scope.push_res_with_import(
-                        &mut self.from_glob_import,
-                        (module_id, name.clone()),
+                    changed |= self.push_res_and_update_glob_vis(
+                        module_id,
+                        name,
                         res.with_visibility(vis),
                         import,
                     );
@@ -1112,6 +1111,84 @@ impl DefCollector<'_> {
         }
     }
 
+    fn push_res_and_update_glob_vis(
+        &mut self,
+        module_id: LocalModuleId,
+        name: &Name,
+        mut defs: PerNs,
+        def_import_type: Option,
+    ) -> bool {
+        let mut changed = false;
+
+        if let Some(ImportType::Glob(_)) = def_import_type {
+            let prev_defs = self.def_map[module_id].scope.get(name);
+
+            // Multiple globs may import the same item and they may override visibility from
+            // previously resolved globs. Handle overrides here and leave the rest to
+            // `ItemScope::push_res_with_import()`.
+            if let Some((def, def_vis, _)) = defs.types {
+                if let Some((prev_def, prev_vis, _)) = prev_defs.types {
+                    if def == prev_def
+                        && self.from_glob_import.contains_type(module_id, name.clone())
+                        && def_vis != prev_vis
+                        && def_vis.max(prev_vis, &self.def_map) == Some(def_vis)
+                    {
+                        changed = true;
+                        // This import is being handled here, don't pass it down to
+                        // `ItemScope::push_res_with_import()`.
+                        defs.types = None;
+                        self.def_map.modules[module_id]
+                            .scope
+                            .update_visibility_types(name, def_vis);
+                    }
+                }
+            }
+
+            if let Some((def, def_vis, _)) = defs.values {
+                if let Some((prev_def, prev_vis, _)) = prev_defs.values {
+                    if def == prev_def
+                        && self.from_glob_import.contains_value(module_id, name.clone())
+                        && def_vis != prev_vis
+                        && def_vis.max(prev_vis, &self.def_map) == Some(def_vis)
+                    {
+                        changed = true;
+                        // See comment above.
+                        defs.values = None;
+                        self.def_map.modules[module_id]
+                            .scope
+                            .update_visibility_values(name, def_vis);
+                    }
+                }
+            }
+
+            if let Some((def, def_vis, _)) = defs.macros {
+                if let Some((prev_def, prev_vis, _)) = prev_defs.macros {
+                    if def == prev_def
+                        && self.from_glob_import.contains_macro(module_id, name.clone())
+                        && def_vis != prev_vis
+                        && def_vis.max(prev_vis, &self.def_map) == Some(def_vis)
+                    {
+                        changed = true;
+                        // See comment above.
+                        defs.macros = None;
+                        self.def_map.modules[module_id]
+                            .scope
+                            .update_visibility_macros(name, def_vis);
+                    }
+                }
+            }
+        }
+
+        changed |= self.def_map.modules[module_id].scope.push_res_with_import(
+            &mut self.from_glob_import,
+            (module_id, name.clone()),
+            defs,
+            def_import_type,
+        );
+
+        changed
+    }
+
     fn resolve_macros(&mut self) -> ReachedFixedPoint {
         let mut macros = mem::take(&mut self.unresolved_macros);
         let mut resolved = Vec::new();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
index 1ca74b5da6bfd..a2696055ca103 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
@@ -367,3 +367,48 @@ use event::Event;
         "#]],
     );
 }
+
+#[test]
+fn glob_may_override_visibility() {
+    check(
+        r#"
+mod reexport {
+    use crate::defs::*;
+    mod inner {
+        pub use crate::defs::{Trait, function, makro};
+    }
+    pub use inner::*;
+}
+mod defs {
+    pub trait Trait {}
+    pub fn function() {}
+    pub macro makro($t:item) { $t }
+}
+use reexport::*;
+"#,
+        expect![[r#"
+            crate
+            Trait: t
+            defs: t
+            function: v
+            makro: m
+            reexport: t
+
+            crate::defs
+            Trait: t
+            function: v
+            makro: m
+
+            crate::reexport
+            Trait: t
+            function: v
+            inner: t
+            makro: m
+
+            crate::reexport::inner
+            Trait: ti
+            function: vi
+            makro: mi
+        "#]],
+    );
+}

From 80a32f86187f897cc075a314cd689c6bd45c4671 Mon Sep 17 00:00:00 2001
From: The Miri Cronjob Bot 
Date: Sat, 27 Jul 2024 05:14:59 +0000
Subject: [PATCH 171/489] Preparing for merge from rustc

---
 src/tools/miri/rust-version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index e1a6084b22eda..58ec4e10856df 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-72d73cec61aa8f85901358cd5d386d5dd066fe52
+a526d7ce45fd2284e0e7c7556ccba2425b9d25e5

From 822286f0758bea84b798e494b5b6103d288a3221 Mon Sep 17 00:00:00 2001
From: Ralf Jung 
Date: Sat, 27 Jul 2024 08:31:07 +0200
Subject: [PATCH 172/489] fix clippy

---
 src/tools/miri/src/shims/x86/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index 0bbf2a8e13e9a..1bd32fce8bd9e 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -1178,7 +1178,7 @@ fn pclmulqdq<'tcx>(
         // if the i-th bit in right is set
         if (right & (1 << i)) != 0 {
             // xor result with `left` shifted to the left by i positions
-            result ^= (left as u128) << i;
+            result ^= u128::from(left) << i;
         }
     }
 

From 5b38b149dc5f8a9aaeb06eac6c6f819e0a17caee Mon Sep 17 00:00:00 2001
From: Ralf Jung 
Date: Sat, 27 Jul 2024 17:18:35 +0200
Subject: [PATCH 173/489] miri: fix offset_from behavior on wildcard pointers

---
 compiler/rustc_const_eval/messages.ftl        |  7 +-
 .../src/interpret/intrinsics.rs               | 83 ++++++++-----------
 .../rustc_const_eval/src/interpret/memory.rs  | 19 +++++
 .../ptr_offset_from_different_ints.rs         |  2 +-
 .../ptr_offset_from_different_ints.stderr     |  4 +-
 .../ptr_offset_from_unsigned_neg.rs           |  3 +-
 .../ptr_offset_from_unsigned_neg.stderr       |  4 +-
 .../miri/tests/pass/ptr_int_from_exposed.rs   |  9 ++
 tests/ui/consts/offset_from_ub.rs             |  2 +-
 tests/ui/consts/offset_from_ub.stderr         |  6 +-
 tests/ui/consts/offset_ub.rs                  |  2 +-
 11 files changed, 80 insertions(+), 61 deletions(-)

diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index cd269810741e7..a93911225e417 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -233,8 +233,6 @@ const_eval_nullary_intrinsic_fail =
 
 const_eval_offset_from_different_allocations =
     `{$name}` called on pointers into different allocations
-const_eval_offset_from_different_integers =
-    `{$name}` called on different pointers without provenance (i.e., without an associated allocation)
 const_eval_offset_from_overflow =
     `{$name}` called when first pointer is too far ahead of second
 const_eval_offset_from_test =
@@ -242,7 +240,10 @@ const_eval_offset_from_test =
 const_eval_offset_from_underflow =
     `{$name}` called when first pointer is too far before second
 const_eval_offset_from_unsigned_overflow =
-    `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
+    `ptr_offset_from_unsigned` called when first pointer has smaller {$is_addr ->
+        [true] address
+        *[false] offset
+    } than second: {$a_offset} < {$b_offset}
 
 const_eval_operator_non_const =
     cannot call non-const operator in {const_eval_const_context}s
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index b227565f8f91a..0b4a21d972cd4 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -243,36 +243,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let isize_layout = self.layout_of(self.tcx.types.isize)?;
 
                 // Get offsets for both that are at least relative to the same base.
-                let (a_offset, b_offset) =
+                // With `OFFSET_IS_ADDR` this is trivial; without it we need either
+                // two integers or two pointers into the same allocation.
+                let (a_offset, b_offset, is_addr) = if M::Provenance::OFFSET_IS_ADDR {
+                    (a.addr().bytes(), b.addr().bytes(), /*is_addr*/ true)
+                } else {
                     match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) {
                         (Err(a), Err(b)) => {
-                            // Neither pointer points to an allocation.
-                            // This is okay only if they are the same.
-                            if a != b {
-                                // We'd catch this below in the "dereferenceable" check, but
-                                // show a nicer error for this particular case.
-                                throw_ub_custom!(
-                                    fluent::const_eval_offset_from_different_integers,
-                                    name = intrinsic_name,
-                                );
-                            }
-                            // This will always return 0.
-                            (a, b)
-                        }
-                        _ if M::Provenance::OFFSET_IS_ADDR && a.addr() == b.addr() => {
-                            // At least one of the pointers has provenance, but they also point to
-                            // the same address so it doesn't matter; this is fine. `(0, 0)` means
-                            // we pass all the checks below and return 0.
-                            (0, 0)
+                            // Neither pointer points to an allocation, so they are both absolute.
+                            (a, b, /*is_addr*/ true)
                         }
-                        // From here onwards, the pointers are definitely for different addresses
-                        // (or we can't determine their absolute address).
                         (Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _)))
                             if a_alloc_id == b_alloc_id =>
                         {
                             // Found allocation for both, and it's the same.
                             // Use these offsets for distance calculation.
-                            (a_offset.bytes(), b_offset.bytes())
+                            (a_offset.bytes(), b_offset.bytes(), /*is_addr*/ false)
                         }
                         _ => {
                             // Not into the same allocation -- this is UB.
@@ -281,9 +267,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                                 name = intrinsic_name,
                             );
                         }
-                    };
+                    }
+                };
 
-                // Compute distance.
+                // Compute distance: a - b.
                 let dist = {
                     // Addresses are unsigned, so this is a `usize` computation. We have to do the
                     // overflow check separately anyway.
@@ -300,6 +287,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                                 fluent::const_eval_offset_from_unsigned_overflow,
                                 a_offset = a_offset,
                                 b_offset = b_offset,
+                                is_addr = is_addr,
                             );
                         }
                         // The signed form of the intrinsic allows this. If we interpret the
@@ -328,14 +316,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     }
                 };
 
-                // Check that the range between them is dereferenceable ("in-bounds or one past the
-                // end of the same allocation"). This is like the check in ptr_offset_inbounds.
-                let min_ptr = if dist >= 0 { b } else { a };
-                self.check_ptr_access(
-                    min_ptr,
-                    Size::from_bytes(dist.unsigned_abs()),
+                // Check that the memory between them is dereferenceable at all, starting from the
+                // base pointer: `dist` is `a - b`, so it is based on `b`.
+                self.check_ptr_access_signed(b, dist, CheckInAllocMsg::OffsetFromTest)?;
+                // Then check that this is also dereferenceable from `a`. This ensures that they are
+                // derived from the same allocation.
+                self.check_ptr_access_signed(
+                    a,
+                    dist.checked_neg().unwrap(), // i64::MIN is impossible as no allocation can be that large
                     CheckInAllocMsg::OffsetFromTest,
-                )?;
+                )
+                .map_err(|_| {
+                    // Make the error more specific.
+                    err_ub_custom!(
+                        fluent::const_eval_offset_from_different_allocations,
+                        name = intrinsic_name,
+                    )
+                })?;
 
                 // Perform division by size to compute return value.
                 let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
@@ -582,27 +579,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     }
 
     /// Offsets a pointer by some multiple of its type, returning an error if the pointer leaves its
-    /// allocation. For integer pointers, we consider each of them their own tiny allocation of size
-    /// 0, so offset-by-0 (and only 0) is okay -- except that null cannot be offset by _any_ value.
+    /// allocation.
     pub fn ptr_offset_inbounds(
         &self,
         ptr: Pointer>,
         offset_bytes: i64,
     ) -> InterpResult<'tcx, Pointer>> {
-        // The offset being in bounds cannot rely on "wrapping around" the address space.
-        // So, first rule out overflows in the pointer arithmetic.
-        let offset_ptr = ptr.signed_offset(offset_bytes, self)?;
-        // ptr and offset_ptr must be in bounds of the same allocated object. This means all of the
-        // memory between these pointers must be accessible. Note that we do not require the
-        // pointers to be properly aligned (unlike a read/write operation).
-        let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr };
-        // This call handles checking for integer/null pointers.
-        self.check_ptr_access(
-            min_ptr,
-            Size::from_bytes(offset_bytes.unsigned_abs()),
-            CheckInAllocMsg::PointerArithmeticTest,
-        )?;
-        Ok(offset_ptr)
+        // We first compute the pointer with overflow checks, to get a specific error for when it
+        // overflows (though technically this is redundant with the following inbounds check).
+        let result = ptr.signed_offset(offset_bytes, self)?;
+        // The offset must be in bounds starting from `ptr`.
+        self.check_ptr_access_signed(ptr, offset_bytes, CheckInAllocMsg::PointerArithmeticTest)?;
+        // Done.
+        Ok(result)
     }
 
     /// Copy `count*size_of::()` many bytes from `*src` to `*dst`.
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 36fe8dfdd29b7..0d85e8ef66464 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -414,6 +414,25 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         Ok(())
     }
 
+    /// Check whether the given pointer points to live memory for a signed amount of bytes.
+    /// A negative amounts means that the given range of memory to the left of the pointer
+    /// needs to be dereferenceable.
+    pub fn check_ptr_access_signed(
+        &self,
+        ptr: Pointer>,
+        size: i64,
+        msg: CheckInAllocMsg,
+    ) -> InterpResult<'tcx> {
+        if let Ok(size) = u64::try_from(size) {
+            self.check_ptr_access(ptr, Size::from_bytes(size), msg)
+        } else {
+            // Compute the pointer at the beginning of the range, and do the standard
+            // dereferenceability check from there.
+            let begin_ptr = ptr.wrapping_signed_offset(size, self);
+            self.check_ptr_access(begin_ptr, Size::from_bytes(size.unsigned_abs()), msg)
+        }
+    }
+
     /// Low-level helper function to check if a ptr is in-bounds and potentially return a reference
     /// to the allocation it points to. Supports both shared and mutable references, as the actual
     /// checking is offloaded to a helper closure.
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs
index 57b4fd0dedb7c..c307dfddb6c1f 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.rs
@@ -16,6 +16,6 @@ fn main() {
         let _ = p1.byte_offset_from(p1);
 
         // UB because different pointers.
-        let _ = p1.byte_offset_from(p2); //~ERROR: different pointers without provenance
+        let _ = p1.byte_offset_from(p2); //~ERROR: no provenance
     }
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
index 6e9e5633fecc6..65f1161425ff9 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+error: Undefined Behavior: out-of-bounds `offset_from`: 0xa[noalloc] is a dangling pointer (it has no provenance)
   --> $DIR/ptr_offset_from_different_ints.rs:LL:CC
    |
 LL |         let _ = p1.byte_offset_from(p2);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: 0xa[noalloc] is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs
index 06d13d9bdbaf3..13eb5bfb3421d 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs
@@ -1,8 +1,9 @@
+//@normalize-stderr-test: "\d+ < \d+" -> "$$ADDR < $$ADDR"
 #![feature(ptr_sub_ptr)]
 
 fn main() {
     let arr = [0u8; 8];
     let ptr1 = arr.as_ptr();
     let ptr2 = ptr1.wrapping_add(4);
-    let _val = unsafe { ptr1.sub_ptr(ptr2) }; //~ERROR: first pointer has smaller offset than second: 0 < 4
+    let _val = unsafe { ptr1.sub_ptr(ptr2) }; //~ERROR: first pointer has smaller address than second
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr
index 0b4a9faf1b249..e436f9029d50e 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 4
+error: Undefined Behavior: `ptr_offset_from_unsigned` called when first pointer has smaller address than second: $ADDR < $ADDR
   --> $DIR/ptr_offset_from_unsigned_neg.rs:LL:CC
    |
 LL |     let _val = unsafe { ptr1.sub_ptr(ptr2) };
-   |                         ^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 4
+   |                         ^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller address than second: $ADDR < $ADDR
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
index 5690d7865bbc3..589ef781a91a9 100644
--- a/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
+++ b/src/tools/miri/tests/pass/ptr_int_from_exposed.rs
@@ -56,9 +56,18 @@ fn ptr_roundtrip_null() {
     assert_eq!(unsafe { *x_ptr_copy }, 42);
 }
 
+fn ptr_roundtrip_offset_from() {
+    let arr = [0; 5];
+    let begin = arr.as_ptr();
+    let end = begin.wrapping_add(arr.len());
+    let end_roundtrip = ptr::with_exposed_provenance::(end.expose_provenance());
+    unsafe { end_roundtrip.offset_from(begin) };
+}
+
 fn main() {
     ptr_roundtrip_out_of_bounds();
     ptr_roundtrip_confusion();
     ptr_roundtrip_imperfect();
     ptr_roundtrip_null();
+    ptr_roundtrip_offset_from();
 }
diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs
index 1506c212fbae8..95b3118f1570a 100644
--- a/tests/ui/consts/offset_from_ub.rs
+++ b/tests/ui/consts/offset_from_ub.rs
@@ -36,7 +36,7 @@ pub const DIFFERENT_INT: isize = { // offset_from with two different integers: l
     let ptr1 = 8 as *const u8;
     let ptr2 = 16 as *const u8;
     unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
-    //~| different pointers without provenance
+    //~| dangling pointer
 };
 
 const OUT_OF_BOUNDS_1: isize = {
diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr
index 7b623126d54f2..0a860f42c649c 100644
--- a/tests/ui/consts/offset_from_ub.stderr
+++ b/tests/ui/consts/offset_from_ub.stderr
@@ -27,7 +27,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:38:14
    |
 LL |     unsafe { ptr_offset_from(ptr2, ptr1) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: 0x8[noalloc] is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:47:14
@@ -80,7 +80,7 @@ LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+   = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `std::ptr::const_ptr::::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -93,7 +93,7 @@ LL |     unsafe { ptr2.offset_from(ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
+   = note: `ptr_offset_from` called when first pointer is too far before second
    |
 note: inside `std::ptr::const_ptr::::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
diff --git a/tests/ui/consts/offset_ub.rs b/tests/ui/consts/offset_ub.rs
index ebc7019a75aa8..9a8f756749b70 100644
--- a/tests/ui/consts/offset_ub.rs
+++ b/tests/ui/consts/offset_ub.rs
@@ -1,6 +1,6 @@
 use std::ptr;
 
-
+//@ normalize-stderr-test: "0xf+" -> "0xf..f"
 //@ normalize-stderr-test: "0x7f+" -> "0x7f..f"
 
 

From bda31d14f47e49b0aa69173bf8793a9a6e0bead7 Mon Sep 17 00:00:00 2001
From: Ralf Jung 
Date: Thu, 18 Jul 2024 12:26:19 +0200
Subject: [PATCH 174/489] built-in derive: remove
 BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE hack and lint

---
 .../src/deriving/generic/mod.rs               | 54 ++------------
 compiler/rustc_lint/src/lib.rs                |  7 +-
 compiler/rustc_lint_defs/src/builtin.rs       | 34 ---------
 tests/ui/derives/deriving-with-repr-packed.rs | 11 +--
 .../derives/deriving-with-repr-packed.stderr  | 74 +++++++------------
 tests/ui/deriving/deriving-all-codegen.rs     | 10 ---
 tests/ui/deriving/deriving-all-codegen.stderr | 63 ----------------
 tests/ui/deriving/deriving-all-codegen.stdout | 20 -----
 8 files changed, 41 insertions(+), 232 deletions(-)
 delete mode 100644 tests/ui/deriving/deriving-all-codegen.stderr

diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index ba289f9552e22..fc1cf71a130a2 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -181,11 +181,10 @@ use crate::{deriving, errors};
 use rustc_ast::ptr::P;
 use rustc_ast::{
     self as ast, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, Generics,
-    Mutability, PatKind, TyKind, VariantData,
+    Mutability, PatKind, VariantData,
 };
 use rustc_attr as attr;
 use rustc_expand::base::{Annotatable, ExtCtxt};
-use rustc_session::lint::builtin::BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use std::cell::RefCell;
@@ -1599,52 +1598,11 @@ impl<'a> TraitDef<'a> {
                         ),
                     );
                     if is_packed {
-                        // In general, fields in packed structs are copied via a
-                        // block, e.g. `&{self.0}`. The two exceptions are `[u8]`
-                        // and `str` fields, which cannot be copied and also never
-                        // cause unaligned references. These exceptions are allowed
-                        // to handle the `FlexZeroSlice` type in the `zerovec`
-                        // crate within `icu4x-0.9.0`.
-                        //
-                        // Once use of `icu4x-0.9.0` has dropped sufficiently, this
-                        // exception should be removed.
-                        let is_simple_path = |ty: &P, sym| {
-                            if let TyKind::Path(None, ast::Path { segments, .. }) = &ty.kind
-                                && let [seg] = segments.as_slice()
-                                && seg.ident.name == sym
-                                && seg.args.is_none()
-                            {
-                                true
-                            } else {
-                                false
-                            }
-                        };
-
-                        let exception = if let TyKind::Slice(ty) = &struct_field.ty.kind
-                            && is_simple_path(ty, sym::u8)
-                        {
-                            Some("byte")
-                        } else if is_simple_path(&struct_field.ty, sym::str) {
-                            Some("string")
-                        } else {
-                            None
-                        };
-
-                        if let Some(ty) = exception {
-                            cx.sess.psess.buffer_lint(
-                                BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
-                                sp,
-                                ast::CRATE_NODE_ID,
-                                rustc_lint_defs::BuiltinLintDiag::ByteSliceInPackedStructWithDerive {
-                                    ty: ty.to_string(),
-                                },
-                            );
-                        } else {
-                            // Wrap the expression in `{...}`, causing a copy.
-                            field_expr = cx.expr_block(
-                                cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]),
-                            );
-                        }
+                        // Fields in packed structs are wrapped in a block, e.g. `&{self.0}`,
+                        // causing a copy instead of a (potentially misaligned) reference.
+                        field_expr = cx.expr_block(
+                            cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]),
+                        );
                     }
                     cx.expr_addr_of(sp, field_expr)
                 })
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 4e83ef0c6291b..7f4904bb48a41 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -537,7 +537,7 @@ fn register_builtins(store: &mut LintStore) {
     );
     store.register_removed(
         "suspicious_auto_trait_impls",
-        "no longer needed, see #93367 \
+        "no longer needed, see issue #93367 \
           for more information",
     );
     store.register_removed(
@@ -559,6 +559,11 @@ fn register_builtins(store: &mut LintStore) {
         "box_pointers",
         "it does not detect other kinds of allocations, and existed only for historical reasons",
     );
+    store.register_removed(
+        "byte_slice_in_packed_struct_with_derive",
+        "converted into hard error, see issue #107457 \
+          for more information",
+    )
 }
 
 fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index aa7844f40121b..f37d3d402df02 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -25,7 +25,6 @@ declare_lint_pass! {
         BARE_TRAIT_OBJECTS,
         BINDINGS_WITH_VARIANT_NAME,
         BREAK_WITH_LABEL_AND_LOOP,
-        BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
         CENUM_IMPL_DROP_CAST,
         COHERENCE_LEAK_CHECK,
         CONFLICTING_REPR_HINTS,
@@ -4246,39 +4245,6 @@ declare_lint! {
     report_in_external_macro
 }
 
-declare_lint! {
-    /// The `byte_slice_in_packed_struct_with_derive` lint detects cases where a byte slice field
-    /// (`[u8]`) or string slice field (`str`) is used in a `packed` struct that derives one or
-    /// more built-in traits.
-    ///
-    /// ### Example
-    ///
-    /// ```rust
-    /// #[repr(packed)]
-    /// #[derive(Hash)]
-    /// struct FlexZeroSlice {
-    ///     width: u8,
-    ///     data: [u8],
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// This was previously accepted but is being phased out, because fields in packed structs are
-    /// now required to implement `Copy` for `derive` to work. Byte slices and string slices are a
-    /// temporary exception because certain crates depended on them.
-    pub BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
-    Warn,
-    "`[u8]` or `str` used in a packed struct with `derive`",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
-        reference: "issue #107457 ",
-    };
-    report_in_external_macro
-}
-
 declare_lint! {
     /// The `invalid_macro_export_arguments` lint detects cases where `#[macro_export]` is being used with invalid arguments.
     ///
diff --git a/tests/ui/derives/deriving-with-repr-packed.rs b/tests/ui/derives/deriving-with-repr-packed.rs
index 58be451972017..d17b52842cefd 100644
--- a/tests/ui/derives/deriving-with-repr-packed.rs
+++ b/tests/ui/derives/deriving-with-repr-packed.rs
@@ -22,25 +22,22 @@ struct Y(usize);
 struct X(Y);
 //~^ ERROR cannot move out of `self` which is behind a shared reference
 
-// This is currently allowed, but will be phased out at some point. From
-// `zerovec` within icu4x-0.9.0.
 #[derive(Debug)]
 #[repr(packed)]
 struct FlexZeroSlice {
     width: u8,
     data: [u8],
-    //~^ WARNING byte slice in a packed struct that derives a built-in trait
-    //~^^ this was previously accepted
+    //~^ ERROR cannot move
+    //~| ERROR cannot move
 }
 
-// Again, currently allowed, but will be phased out.
 #[derive(Debug)]
 #[repr(packed)]
 struct WithStr {
     width: u8,
     data: str,
-    //~^ WARNING string slice in a packed struct that derives a built-in trait
-    //~^^ this was previously accepted
+    //~^ ERROR cannot move
+    //~| ERROR cannot move
 }
 
 fn main() {}
diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr
index a8523d25cab9b..321ffb27eeb11 100644
--- a/tests/ui/derives/deriving-with-repr-packed.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed.stderr
@@ -1,32 +1,3 @@
-warning: byte slice in a packed struct that derives a built-in trait
-  --> $DIR/deriving-with-repr-packed.rs:31:5
-   |
-LL | #[derive(Debug)]
-   |          ----- in this derive macro expansion
-...
-LL |     data: [u8],
-   |     ^^^^^^^^^^
-   |
-   = 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 #107457 
-   = help: consider implementing the trait by hand, or remove the `packed` attribute
-   = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
-   = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-warning: string slice in a packed struct that derives a built-in trait
-  --> $DIR/deriving-with-repr-packed.rs:41:5
-   |
-LL | #[derive(Debug)]
-   |          ----- in this derive macro expansion
-...
-LL |     data: str,
-   |     ^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #107457 
-   = help: consider implementing the trait by hand, or remove the `packed` attribute
-   = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed.rs:22:10
    |
@@ -47,38 +18,43 @@ LL | struct X(Y);
    = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 1 previous error; 2 warnings emitted
+error[E0161]: cannot move a value of type `[u8]`
+  --> $DIR/deriving-with-repr-packed.rs:29:5
+   |
+LL |     data: [u8],
+   |     ^^^^^^^^^^ the size of `[u8]` cannot be statically determined
 
-For more information about this error, try `rustc --explain E0507`.
-Future incompatibility report: Future breakage diagnostic:
-warning: byte slice in a packed struct that derives a built-in trait
-  --> $DIR/deriving-with-repr-packed.rs:31:5
+error[E0507]: cannot move out of `self.data` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed.rs:29:5
    |
 LL | #[derive(Debug)]
    |          ----- in this derive macro expansion
 ...
 LL |     data: [u8],
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ move occurs because `self.data` has type `[u8]`, which does not implement the `Copy` trait
+   |
+   = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0161]: cannot move a value of type `str`
+  --> $DIR/deriving-with-repr-packed.rs:38:5
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #107457 
-   = help: consider implementing the trait by hand, or remove the `packed` attribute
-   = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
-   = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+LL |     data: str,
+   |     ^^^^^^^^^ the size of `str` cannot be statically determined
 
-Future breakage diagnostic:
-warning: string slice in a packed struct that derives a built-in trait
-  --> $DIR/deriving-with-repr-packed.rs:41:5
+error[E0507]: cannot move out of `self.data` which is behind a shared reference
+  --> $DIR/deriving-with-repr-packed.rs:38:5
    |
 LL | #[derive(Debug)]
    |          ----- in this derive macro expansion
 ...
 LL |     data: str,
-   |     ^^^^^^^^^
+   |     ^^^^^^^^^ move occurs because `self.data` has type `str`, which does not implement the `Copy` trait
    |
-   = 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 #107457 
-   = help: consider implementing the trait by hand, or remove the `packed` attribute
-   = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
-   = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
+   = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 5 previous errors
 
+Some errors have detailed explanations: E0161, E0507.
+For more information about an error, try `rustc --explain E0161`.
diff --git a/tests/ui/deriving/deriving-all-codegen.rs b/tests/ui/deriving/deriving-all-codegen.rs
index 6fa4f74f2a508..eab2b4f1f5335 100644
--- a/tests/ui/deriving/deriving-all-codegen.rs
+++ b/tests/ui/deriving/deriving-all-codegen.rs
@@ -73,16 +73,6 @@ impl Copy for PackedManualCopy {}
 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
 struct Unsized([u32]);
 
-// A packed struct with an unsized `[u8]` field. This is currently allowed, but
-// causes a warning and will be phased out at some point.
-#[derive(Debug, Hash)]
-#[repr(packed)]
-struct PackedUnsizedU8([u8]);
-//~^ WARNING byte slice in a packed struct that derives a built-in trait
-//~^^ WARNING byte slice in a packed struct that derives a built-in trait
-//~^^^ this was previously accepted
-//~^^^^ this was previously accepted
-
 trait Trait {
     type A;
 }
diff --git a/tests/ui/deriving/deriving-all-codegen.stderr b/tests/ui/deriving/deriving-all-codegen.stderr
deleted file mode 100644
index 503f0cae73b69..0000000000000
--- a/tests/ui/deriving/deriving-all-codegen.stderr
+++ /dev/null
@@ -1,63 +0,0 @@
-warning: byte slice in a packed struct that derives a built-in trait
-  --> $DIR/deriving-all-codegen.rs:80:24
-   |
-LL | #[derive(Debug, Hash)]
-   |          ----- in this derive macro expansion
-LL | #[repr(packed)]
-LL | struct PackedUnsizedU8([u8]);
-   |                        ^^^^
-   |
-   = 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 #107457 
-   = help: consider implementing the trait by hand, or remove the `packed` attribute
-   = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
-   = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-warning: byte slice in a packed struct that derives a built-in trait
-  --> $DIR/deriving-all-codegen.rs:80:24
-   |
-LL | #[derive(Debug, Hash)]
-   |                 ---- in this derive macro expansion
-LL | #[repr(packed)]
-LL | struct PackedUnsizedU8([u8]);
-   |                        ^^^^
-   |
-   = 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 #107457 
-   = help: consider implementing the trait by hand, or remove the `packed` attribute
-   = note: this warning originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-warning: 2 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: byte slice in a packed struct that derives a built-in trait
-  --> $DIR/deriving-all-codegen.rs:80:24
-   |
-LL | #[derive(Debug, Hash)]
-   |          ----- in this derive macro expansion
-LL | #[repr(packed)]
-LL | struct PackedUnsizedU8([u8]);
-   |                        ^^^^
-   |
-   = 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 #107457 
-   = help: consider implementing the trait by hand, or remove the `packed` attribute
-   = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
-   = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-warning: byte slice in a packed struct that derives a built-in trait
-  --> $DIR/deriving-all-codegen.rs:80:24
-   |
-LL | #[derive(Debug, Hash)]
-   |                 ---- in this derive macro expansion
-LL | #[repr(packed)]
-LL | struct PackedUnsizedU8([u8]);
-   |                        ^^^^
-   |
-   = 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 #107457 
-   = help: consider implementing the trait by hand, or remove the `packed` attribute
-   = note: `#[warn(byte_slice_in_packed_struct_with_derive)]` on by default
-   = note: this warning originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-
diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout
index 6b69b57c51619..6503c87099040 100644
--- a/tests/ui/deriving/deriving-all-codegen.stdout
+++ b/tests/ui/deriving/deriving-all-codegen.stdout
@@ -516,26 +516,6 @@ impl ::core::cmp::Ord for Unsized {
     }
 }
 
-// A packed struct with an unsized `[u8]` field. This is currently allowed, but
-// causes a warning and will be phased out at some point.
-#[repr(packed)]
-struct PackedUnsizedU8([u8]);
-#[automatically_derived]
-impl ::core::fmt::Debug for PackedUnsizedU8 {
-    #[inline]
-    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
-        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
-            "PackedUnsizedU8", &&self.0)
-    }
-}
-#[automatically_derived]
-impl ::core::hash::Hash for PackedUnsizedU8 {
-    #[inline]
-    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
-        ::core::hash::Hash::hash(&self.0, state)
-    }
-}
-
 trait Trait {
     type A;
 }

From 1261827eb9332b9595994d9be67ba9da80f1a644 Mon Sep 17 00:00:00 2001
From: Francis McKenzie 
Date: Sat, 29 Jun 2024 13:06:28 +0800
Subject: [PATCH 175/489] Fix for #17497 - Invalid RA diagnostic error:
 expected 2 arguments, found 1

The issue occurs because in some configurations of traits where one of them has Deref as a supertrait, RA's type inference algorithm fails to resolve the Deref::Target type, and instead uses a TyKind::BoundVar (i.e. an unknown type). This "autoderefed" type then incorrectly acts as if it implements all traits in scope.

The fix is to re-apply the same sanity-check that is done in iterate_method_candidates_with_autoref(), that is: don't try to resolve methods on unknown types. This same sanity-check is now done on each autoderefed type for which trait methods are about to be checked. If the autoderefed type is unknown, then the iterating of the trait methods for that type is skipped.

Includes a unit test that only passes after applying the fixes in this commit.

Includes a change to the assertion count in test syntax_highlighting::tests::benchmark_syntax_highlighting_parser as suggested by Lukas Wirth during review.

Includes a change to the sanity-check code as suggested by Florian Diebold during review.
---
 .../crates/hir-ty/src/method_resolution.rs    |  9 ++++-
 .../hir-ty/src/tests/method_resolution.rs     | 39 +++++++++++++++++++
 .../ide/src/syntax_highlighting/tests.rs      |  2 +-
 3 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index c07bd08be4053..8ba8071d36ec4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -30,8 +30,8 @@ use crate::{
     utils::all_super_traits,
     AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData,
     Goal, Guidance, InEnvironment, Interner, Mutability, Scalar, Solution, Substitution,
-    TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, VariableKind,
-    WhereClause,
+    TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind,
+    VariableKind, WhereClause,
 };
 
 /// This is used as a key for indexing impls.
@@ -1083,6 +1083,11 @@ fn iterate_method_candidates_by_receiver(
     table.run_in_snapshot(|table| {
         let mut autoderef = autoderef::Autoderef::new(table, receiver_ty.clone(), true);
         while let Some((self_ty, _)) = autoderef.next() {
+            if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
+                // don't try to resolve methods on unknown types
+                return ControlFlow::Continue(());
+            }
+
             iterate_trait_method_candidates(
                 &self_ty,
                 autoderef.table,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
index 360a12928344a..14e2e7465315c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
@@ -2099,3 +2099,42 @@ fn test() {
 "#,
     );
 }
+
+#[test]
+fn mismatched_args_due_to_supertraits_with_deref() {
+    check_no_mismatches(
+        r#"
+//- minicore: deref
+use core::ops::Deref;
+
+trait Trait1 {
+    type Assoc: Deref;
+}
+
+trait Trait2: Trait1 {
+}
+
+trait Trait3 {
+    type T1: Trait1;
+    type T2: Trait2;
+    fn bar(&self, x: bool, y: bool);
+}
+
+struct Foo;
+
+impl Foo {
+    fn bar(&mut self, _: &'static str) {}
+}
+
+impl Deref for Foo {
+    type Target = u32;
+    fn deref(&self) -> &Self::Target { &0 }
+}
+
+fn problem_method() {
+    let mut foo = Foo;
+    foo.bar("hello"); // Rustc ok, RA errors (mismatched args)
+}
+"#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index 5f711600a2907..2070022d4183c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -1238,7 +1238,7 @@ fn benchmark_syntax_highlighting_parser() {
             })
             .count()
     };
-    assert_eq!(hash, 1169);
+    assert_eq!(hash, 1167);
 }
 
 #[test]

From f8ebe8d783e20c44508fab32b708f1b9d9a4bf13 Mon Sep 17 00:00:00 2001
From: Ralf Jung 
Date: Sat, 27 Jul 2024 18:09:50 +0200
Subject: [PATCH 176/489] improve dangling/oob errors and make them more
 uniform

---
 compiler/rustc_const_eval/messages.ftl        | 27 ++++++++----
 compiler/rustc_const_eval/src/errors.rs       | 42 ++++++++++++-------
 .../rustc_const_eval/src/interpret/memory.rs  | 12 ++++--
 .../src/interpret/validity.rs                 |  8 ++--
 .../rustc_middle/src/mir/interpret/error.rs   | 11 +++--
 .../rustc_middle/src/mir/interpret/pointer.rs |  9 ++--
 .../miri/tests/fail-dep/libc/affinity.stderr  |  4 +-
 .../miri/tests/fail-dep/libc/memchr_null.rs   |  2 +-
 .../tests/fail-dep/libc/memchr_null.stderr    |  4 +-
 .../miri/tests/fail-dep/libc/memcmp_null.rs   |  2 +-
 .../tests/fail-dep/libc/memcmp_null.stderr    |  4 +-
 .../tests/fail-dep/libc/memcmp_zero.stderr    |  4 +-
 .../tests/fail-dep/libc/memcpy_zero.stderr    |  4 +-
 .../miri/tests/fail-dep/libc/memrchr_null.rs  |  2 +-
 .../tests/fail-dep/libc/memrchr_null.stderr   |  4 +-
 .../fail/both_borrows/issue-miri-1050-1.rs    |  2 +-
 .../issue-miri-1050-1.stack.stderr            |  4 +-
 .../issue-miri-1050-1.tree.stderr             |  4 +-
 .../issue-miri-1050-2.stack.stderr            |  4 +-
 .../issue-miri-1050-2.tree.stderr             |  4 +-
 .../dangling_pointer_to_raw_pointer.stderr    |  4 +-
 .../deref-invalid-ptr.stderr                  |  4 +-
 .../dangling_pointers/null_pointer_deref.rs   |  2 +-
 .../null_pointer_deref.stderr                 |  4 +-
 .../dangling_pointers/null_pointer_write.rs   |  2 +-
 .../null_pointer_write.stderr                 |  4 +-
 .../out_of_bounds_project.stderr              |  4 +-
 .../dangling_pointers/out_of_bounds_read.rs   |  2 +-
 .../out_of_bounds_read.stderr                 |  4 +-
 .../dangling_pointers/out_of_bounds_write.rs  |  2 +-
 .../out_of_bounds_write.stderr                |  4 +-
 .../storage_dead_dangling.stderr              |  4 +-
 .../wild_pointer_deref.stderr                 |  4 +-
 .../cast_int_to_fn_ptr.stderr                 |  4 +-
 .../fail/intrinsics/out_of_bounds_ptr_1.rs    |  2 +-
 .../intrinsics/out_of_bounds_ptr_1.stderr     |  4 +-
 .../fail/intrinsics/out_of_bounds_ptr_3.rs    |  2 +-
 .../intrinsics/out_of_bounds_ptr_3.stderr     |  4 +-
 .../ptr_offset_from_different_ints.stderr     |  4 +-
 .../intrinsics/ptr_offset_int_plus_int.stderr |  4 +-
 .../intrinsics/ptr_offset_int_plus_ptr.rs     |  1 +
 .../intrinsics/ptr_offset_int_plus_ptr.stderr |  4 +-
 .../miri/tests/fail/intrinsics/simd-gather.rs |  3 +-
 .../tests/fail/intrinsics/simd-gather.stderr  |  4 +-
 .../tests/fail/intrinsics/simd-scatter.rs     |  2 +-
 .../tests/fail/intrinsics/simd-scatter.stderr |  4 +-
 .../pointer_partial_overwrite.stderr          |  4 +-
 .../provenance/provenance_transmute.stderr    |  4 +-
 .../fail/provenance/ptr_int_unexposed.stderr  |  4 +-
 .../tests/fail/provenance/ptr_invalid.stderr  |  4 +-
 .../fail/provenance/ptr_invalid_offset.stderr |  4 +-
 .../tests/fail/reading_half_a_pointer.stderr  |  4 +-
 .../fail/shims/backtrace/bad-backtrace-ptr.rs |  2 +-
 .../shims/backtrace/bad-backtrace-ptr.stderr  |  4 +-
 src/tools/miri/tests/fail/zst_local_oob.rs    |  2 +-
 .../miri/tests/fail/zst_local_oob.stderr      |  4 +-
 tests/ui/const-ptr/forbidden_slices.stderr    |  4 +-
 tests/ui/const-ptr/out_of_bounds_read.stderr  |  6 +--
 tests/ui/consts/const-compare-bytes-ub.stderr | 10 ++---
 tests/ui/consts/const-deref-ptr.stderr        |  2 +-
 .../const-eval/const_raw_ptr_ops2.stderr      |  4 +-
 .../const-eval/nonnull_as_ref_ub.stderr       |  2 +-
 .../consts/const-eval/raw-bytes.32bit.stderr  |  2 +-
 .../consts/const-eval/raw-bytes.64bit.stderr  |  2 +-
 tests/ui/consts/const-eval/raw-pointer-ub.rs  |  2 +-
 .../consts/const-eval/raw-pointer-ub.stderr   |  2 +-
 tests/ui/consts/const-eval/ub-nonnull.stderr  |  2 +-
 tests/ui/consts/const-eval/ub-wide-ptr.stderr |  4 +-
 tests/ui/consts/copy-intrinsic.rs             |  4 +-
 tests/ui/consts/copy-intrinsic.stderr         |  4 +-
 tests/ui/consts/offset_from_ub.rs             |  5 ++-
 tests/ui/consts/offset_from_ub.stderr         | 36 ++++++++--------
 tests/ui/consts/offset_ub.rs                  |  1 +
 tests/ui/consts/offset_ub.stderr              | 34 +++++++--------
 tests/ui/error-codes/E0396-fixed.stderr       |  2 +-
 75 files changed, 225 insertions(+), 182 deletions(-)

diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index a93911225e417..43f405b223504 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -45,9 +45,9 @@ const_eval_copy_nonoverlapping_overlapping =
     `copy_nonoverlapping` called on overlapping ranges
 
 const_eval_dangling_int_pointer =
-    {$bad_pointer_message}: {$pointer} is a dangling pointer (it has no provenance)
+    {$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} which is a dangling pointer (it has no provenance)
 const_eval_dangling_null_pointer =
-    {$bad_pointer_message}: null pointer is a dangling pointer (it has no provenance)
+    {$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got a null pointer
 
 const_eval_dangling_ptr_in_final = encountered dangling pointer in final value of {const_eval_intern_kind}
 const_eval_dead_local =
@@ -87,6 +87,13 @@ const_eval_error = {$error_kind ->
 const_eval_exact_div_has_remainder =
     exact_div: {$a} cannot be divided by {$b} without remainder
 
+const_eval_expected_inbounds_pointer =
+    expected {$inbounds_size ->
+        [0] a pointer to some allocation
+        [1] a pointer to 1 byte of memory
+        *[x] a pointer to {$inbounds_size} bytes of memory
+    }
+
 const_eval_extern_static =
     cannot access extern static ({$did})
 const_eval_extern_type_field = `extern type` field does not have a known offset
@@ -265,10 +272,16 @@ const_eval_pointer_arithmetic_overflow =
     overflowing in-bounds pointer arithmetic
 const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
 const_eval_pointer_out_of_bounds =
-    {$bad_pointer_message}: {$alloc_id} has size {$alloc_size}, so pointer to {$ptr_size} {$ptr_size ->
-        [1] byte
-        *[many] bytes
-    } starting at offset {$ptr_offset} is out-of-bounds
+    {$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg ->
+        [true] which points to before the beginning of the allocation
+        *[false] {$alloc_size_minus_ptr_offset ->
+            [0] which is at or beyond the end of the allocation of size {$alloc_size ->
+                [1] 1 byte
+                *[x] {$alloc_size} bytes
+            }
+            *[x] and there are only {$alloc_size_minus_ptr_offset} bytes starting at that pointer
+        }
+    }
 const_eval_pointer_use_after_free =
     {$bad_pointer_message}: {$alloc_id} has been freed, so this pointer is dangling
 const_eval_ptr_as_bytes_1 =
@@ -466,5 +479,3 @@ const_eval_write_through_immutable_pointer =
 
 const_eval_write_to_read_only =
     writing to {$allocation} which is read-only
-const_eval_zst_pointer_out_of_bounds =
-    {$bad_pointer_message}: {$alloc_id} has size {$alloc_size}, so pointer at offset {$ptr_offset} is out-of-bounds
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 292d6ba9d08a4..922225e22d909 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -7,9 +7,9 @@ use rustc_errors::{
 use rustc_hir::ConstContext;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::mir::interpret::{
-    CheckInAllocMsg, ExpectedKind, InterpError, InvalidMetaKind, InvalidProgramInfo, Misalignment,
-    PointerKind, ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
-    ValidationErrorInfo,
+    CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpError, InvalidMetaKind,
+    InvalidProgramInfo, Misalignment, Pointer, PointerKind, ResourceExhaustionInfo,
+    UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
 };
 use rustc_middle::ty::{self, Mutability, Ty};
 use rustc_span::Span;
@@ -488,10 +488,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
             InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta,
             UnterminatedCString(_) => const_eval_unterminated_c_string,
             PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free,
-            PointerOutOfBounds { ptr_size: Size::ZERO, .. } => const_eval_zst_pointer_out_of_bounds,
             PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds,
-            DanglingIntPointer(0, _) => const_eval_dangling_null_pointer,
-            DanglingIntPointer(_, _) => const_eval_dangling_int_pointer,
+            DanglingIntPointer { addr: 0, .. } => const_eval_dangling_null_pointer,
+            DanglingIntPointer { .. } => const_eval_dangling_int_pointer,
             AlignmentCheckFailed { .. } => const_eval_alignment_check_failed,
             WriteToReadOnly(_) => const_eval_write_to_read_only,
             DerefFunctionPointer(_) => const_eval_deref_function_pointer,
@@ -573,18 +572,33 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
                 diag.arg("alloc_id", alloc_id)
                     .arg("bad_pointer_message", bad_pointer_message(msg, dcx));
             }
-            PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => {
-                diag.arg("alloc_id", alloc_id)
-                    .arg("alloc_size", alloc_size.bytes())
-                    .arg("ptr_offset", ptr_offset)
-                    .arg("ptr_size", ptr_size.bytes())
+            PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => {
+                diag.arg("alloc_size", alloc_size.bytes())
+                    .arg("inbounds_size", inbounds_size.bytes())
                     .arg("bad_pointer_message", bad_pointer_message(msg, dcx));
+                diag.arg(
+                    "pointer",
+                    Pointer::new(
+                        Some(CtfeProvenance::from(alloc_id)),
+                        Size::from_bytes(ptr_offset as u64),
+                    )
+                    .to_string(),
+                );
+                diag.arg("ptr_offset_is_neg", ptr_offset < 0);
+                diag.arg(
+                    "alloc_size_minus_ptr_offset",
+                    alloc_size.bytes().saturating_sub(ptr_offset as u64),
+                );
             }
-            DanglingIntPointer(ptr, msg) => {
-                if ptr != 0 {
-                    diag.arg("pointer", format!("{ptr:#x}[noalloc]"));
+            DanglingIntPointer { addr, inbounds_size, msg } => {
+                if addr != 0 {
+                    diag.arg(
+                        "pointer",
+                        Pointer::>::from_addr_invalid(addr).to_string(),
+                    );
                 }
 
+                diag.arg("inbounds_size", inbounds_size.bytes());
                 diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
             }
             AlignmentCheckFailed(Misalignment { required, has }, msg) => {
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 0d85e8ef66464..f49a0ed727a8d 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -459,7 +459,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         Ok(match self.ptr_try_get_alloc_id(ptr) {
             Err(addr) => {
                 // We couldn't get a proper allocation.
-                throw_ub!(DanglingIntPointer(addr, msg));
+                throw_ub!(DanglingIntPointer { addr, inbounds_size: size, msg });
             }
             Ok((alloc_id, offset, prov)) => {
                 let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
@@ -470,7 +470,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                         alloc_id,
                         alloc_size,
                         ptr_offset: self.target_usize_to_isize(offset.bytes()),
-                        ptr_size: size,
+                        inbounds_size: size,
                         msg,
                     })
                 }
@@ -1443,7 +1443,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         ptr: Pointer>,
     ) -> InterpResult<'tcx, (AllocId, Size, M::ProvenanceExtra)> {
         self.ptr_try_get_alloc_id(ptr).map_err(|offset| {
-            err_ub!(DanglingIntPointer(offset, CheckInAllocMsg::InboundsTest)).into()
+            err_ub!(DanglingIntPointer {
+                addr: offset,
+                // We don't know the actually required size.
+                inbounds_size: Size::ZERO,
+                msg: CheckInAllocMsg::InboundsTest
+            })
+            .into()
         })
     }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 3dc3e6c883320..879f9205cbf41 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -348,7 +348,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                 try_validation!(
                     self.ecx.get_ptr_vtable_ty(vtable, Some(data)),
                     self.path,
-                    Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
+                    Ub(DanglingIntPointer{ .. } | InvalidVTablePointer(..)) =>
                         InvalidVTablePtr { value: format!("{vtable}") },
                     Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
                         InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
@@ -405,8 +405,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                 CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
             ),
             self.path,
-            Ub(DanglingIntPointer(0, _)) => NullPtr { ptr_kind },
-            Ub(DanglingIntPointer(i, _)) => DanglingPtrNoProvenance {
+            Ub(DanglingIntPointer { addr: 0, .. }) => NullPtr { ptr_kind },
+            Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance {
                 ptr_kind,
                 // FIXME this says "null pointer" when null but we need translate
                 pointer: format!("{}", Pointer::>::from_addr_invalid(*i))
@@ -605,7 +605,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
                     let _fn = try_validation!(
                         self.ecx.get_ptr_fn(ptr),
                         self.path,
-                        Ub(DanglingIntPointer(..) | InvalidFunctionPointer(..)) =>
+                        Ub(DanglingIntPointer{ .. } | InvalidFunctionPointer(..)) =>
                             InvalidFnPtr { value: format!("{ptr}") },
                     );
                     // FIXME: Check if the signature matches
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 9df19565ab383..68676e862ef0a 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -329,16 +329,21 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     /// Using a pointer after it got freed.
     PointerUseAfterFree(AllocId, CheckInAllocMsg),
     /// Used a pointer outside the bounds it is valid for.
-    /// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.)
     PointerOutOfBounds {
         alloc_id: AllocId,
         alloc_size: Size,
         ptr_offset: i64,
-        ptr_size: Size,
+        /// The size of the memory range that was expected to be in-bounds.
+        inbounds_size: Size,
         msg: CheckInAllocMsg,
     },
     /// Using an integer as a pointer in the wrong way.
-    DanglingIntPointer(u64, CheckInAllocMsg),
+    DanglingIntPointer {
+        addr: u64,
+        /// The size of the memory range that was expected to be in-bounds (or 0 if we don't know).
+        inbounds_size: Size,
+        msg: CheckInAllocMsg,
+    },
     /// Used a pointer with bad alignment.
     AlignmentCheckFailed(Misalignment, CheckAlignMsg),
     /// Writing to read-only memory.
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index a0acacc844fd5..074245fcd32ad 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -180,9 +180,12 @@ impl Provenance for CtfeProvenance {
     fn fmt(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Print AllocId.
         fmt::Debug::fmt(&ptr.provenance.alloc_id(), f)?; // propagates `alternate` flag
-        // Print offset only if it is non-zero.
-        if ptr.offset.bytes() > 0 {
-            write!(f, "+{:#x}", ptr.offset.bytes())?;
+        // Print offset only if it is non-zero. Print it signed.
+        let signed_offset = ptr.offset.bytes() as i64;
+        if signed_offset > 0 {
+            write!(f, "+{:#x}", signed_offset)?;
+        } else if signed_offset < 0 {
+            write!(f, "-{:#x}", signed_offset.unsigned_abs())?;
         }
         // Print immutable status.
         if ptr.provenance.immutable() {
diff --git a/src/tools/miri/tests/fail-dep/libc/affinity.stderr b/src/tools/miri/tests/fail-dep/libc/affinity.stderr
index c01f15800fac3..b9f79fdda89c4 100644
--- a/src/tools/miri/tests/fail-dep/libc/affinity.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/affinity.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 128, so pointer to 129 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC and there are only 128 bytes starting at that pointer
   --> $DIR/affinity.rs:LL:CC
    |
 LL |     let err = unsafe { sched_setaffinity(PID, size_of::() + 1, &cpuset) };
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 128, so pointer to 129 bytes starting at offset 0 is out-of-bounds
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC and there are only 128 bytes starting at that pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memchr_null.rs b/src/tools/miri/tests/fail-dep/libc/memchr_null.rs
index 672cc10cd6304..b6b4b62e62107 100644
--- a/src/tools/miri/tests/fail-dep/libc/memchr_null.rs
+++ b/src/tools/miri/tests/fail-dep/libc/memchr_null.rs
@@ -3,6 +3,6 @@ use std::ptr;
 // null is explicitly called out as UB in the C docs.
 fn main() {
     unsafe {
-        libc::memchr(ptr::null(), 0, 0); //~ERROR: dangling
+        libc::memchr(ptr::null(), 0, 0); //~ERROR: null pointer
     }
 }
diff --git a/src/tools/miri/tests/fail-dep/libc/memchr_null.stderr b/src/tools/miri/tests/fail-dep/libc/memchr_null.stderr
index b76722f5f8f19..f03ae33ed9f39 100644
--- a/src/tools/miri/tests/fail-dep/libc/memchr_null.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memchr_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
   --> $DIR/memchr_null.rs:LL:CC
    |
 LL |         libc::memchr(ptr::null(), 0, 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memcmp_null.rs b/src/tools/miri/tests/fail-dep/libc/memcmp_null.rs
index 066af4a8ae3c9..0e204aa7f0940 100644
--- a/src/tools/miri/tests/fail-dep/libc/memcmp_null.rs
+++ b/src/tools/miri/tests/fail-dep/libc/memcmp_null.rs
@@ -3,6 +3,6 @@ use std::ptr;
 // null is explicitly called out as UB in the C docs.
 fn main() {
     unsafe {
-        libc::memcmp(ptr::null(), ptr::null(), 0); //~ERROR: dangling
+        libc::memcmp(ptr::null(), ptr::null(), 0); //~ERROR: null pointer
     }
 }
diff --git a/src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr b/src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr
index 5c6ba4fd97979..4bca5a3db0722 100644
--- a/src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memcmp_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
   --> $DIR/memcmp_null.rs:LL:CC
    |
 LL |         libc::memcmp(ptr::null(), ptr::null(), 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr b/src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr
index 4ab37ab569fe4..6adaaeb3dbf1e 100644
--- a/src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memcmp_zero.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/memcmp_zero.rs:LL:CC
    |
 LL |         libc::memcmp(ptr.cast(), ptr.cast(), 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr b/src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr
index 3e1ee7b86e31f..b2da332df2149 100644
--- a/src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memcpy_zero.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x17[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got 0x17[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/memcpy_zero.rs:LL:CC
    |
 LL |         libc::memcpy(to.cast(), from.cast(), 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x17[noalloc] is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got 0x17[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail-dep/libc/memrchr_null.rs b/src/tools/miri/tests/fail-dep/libc/memrchr_null.rs
index f06336b129959..1fe637d6ce7e9 100644
--- a/src/tools/miri/tests/fail-dep/libc/memrchr_null.rs
+++ b/src/tools/miri/tests/fail-dep/libc/memrchr_null.rs
@@ -6,6 +6,6 @@ use std::ptr;
 // null is explicitly called out as UB in the C docs.
 fn main() {
     unsafe {
-        libc::memrchr(ptr::null(), 0, 0); //~ERROR: dangling
+        libc::memrchr(ptr::null(), 0, 0); //~ERROR: null pointer
     }
 }
diff --git a/src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr b/src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr
index 0cc7ac19febc4..a9ed58d61bb35 100644
--- a/src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr
+++ b/src/tools/miri/tests/fail-dep/libc/memrchr_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
   --> $DIR/memrchr_null.rs:LL:CC
    |
 LL |         libc::memrchr(ptr::null(), 0, 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
index 424aace239a21..49de3dd0b1052 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.rs
@@ -1,6 +1,6 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-//@error-in-other-file: pointer to 4 bytes starting at offset 0 is out-of-bounds
+//@error-in-other-file: expected a pointer to 4 bytes of memory
 
 fn main() {
     unsafe {
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
index be01c5cc840f8..07bb3293989e7 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer
   --> RUSTLIB/alloc/src/boxed.rs:LL:CC
    |
 LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
index be01c5cc840f8..07bb3293989e7 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer
   --> RUSTLIB/alloc/src/boxed.rs:LL:CC
    |
 LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: ALLOC has size 2, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr
index e96e641bb0d38..04494b5256172 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.stack.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x4[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)
   --> RUSTLIB/alloc/src/boxed.rs:LL:CC
    |
 LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x4[noalloc] is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr
index e96e641bb0d38..04494b5256172 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-2.tree.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x4[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)
   --> RUSTLIB/alloc/src/boxed.rs:LL:CC
    |
 LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x4[noalloc] is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x4[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr
index 37f2bb3955763..a5c031b949643 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/dangling_pointer_to_raw_pointer.rs:LL:CC
    |
 LL |     unsafe { &(*x).0 as *const i32 }
-   |              ^^^^^^^ out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
+   |              ^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr
index 377022fa97f36..d989bff4516f2 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/deref-invalid-ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/deref-invalid-ptr.rs:LL:CC
    |
 LL |     let _y = unsafe { &*x as *const u32 };
-   |                       ^^^ out-of-bounds pointer use: 0x10[noalloc] is a dangling pointer (it has no provenance)
+   |                       ^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.rs b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.rs
index a0773c63cf6bf..dee05952a9936 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.rs
@@ -1,5 +1,5 @@
 #[allow(deref_nullptr)]
 fn main() {
-    let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: null pointer is a dangling pointer
+    let x: i32 = unsafe { *std::ptr::null() }; //~ ERROR: null pointer
     panic!("this should never print: {}", x);
 }
diff --git a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.stderr
index a18f0f20fc015..1b97265eb32f6 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_deref.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got a null pointer
   --> $DIR/null_pointer_deref.rs:LL:CC
    |
 LL |     let x: i32 = unsafe { *std::ptr::null() };
-   |                           ^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+   |                           ^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got a null pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.rs b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.rs
index 954596f57542e..61f5ef572cf3c 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.rs
@@ -1,4 +1,4 @@
 #[allow(deref_nullptr)]
 fn main() {
-    unsafe { *std::ptr::null_mut() = 0i32 }; //~ ERROR: null pointer is a dangling pointer
+    unsafe { *std::ptr::null_mut() = 0i32 }; //~ ERROR: null pointer
 }
diff --git a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.stderr b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.stderr
index 01d4d12a002dd..3d75e7a0254b6 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/null_pointer_write.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got a null pointer
   --> $DIR/null_pointer_write.rs:LL:CC
    |
 LL |     unsafe { *std::ptr::null_mut() = 0i32 };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got a null pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr
index 4195c68d500dd..bdd245e184948 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC and there are only 4 bytes starting at that pointer
   --> $DIR/out_of_bounds_project.rs:LL:CC
    |
 LL |         let _field = addr_of!((*ptr).2);
-   |                      ^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |                      ^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC and there are only 4 bytes starting at that pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.rs b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.rs
index 658fbd16c2e8d..595a229baa5aa 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.rs
@@ -1,6 +1,6 @@
 fn main() {
     let v: Vec = vec![1, 2];
     // This read is also misaligned. We make sure that the OOB message has priority.
-    let x = unsafe { *v.as_ptr().wrapping_byte_add(5) }; //~ ERROR: out-of-bounds
+    let x = unsafe { *v.as_ptr().wrapping_byte_add(5) }; //~ ERROR: expected a pointer to 2 bytes of memory
     panic!("this should never print: {}", x);
 }
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr
index 37dbea37ce2dc..8a774c21bb7c1 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 4, so pointer to 2 bytes starting at offset 5 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 2 bytes of memory, but got ALLOC+0x5 which is at or beyond the end of the allocation of size 4 bytes
   --> $DIR/out_of_bounds_read.rs:LL:CC
    |
 LL |     let x = unsafe { *v.as_ptr().wrapping_byte_add(5) };
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 4, so pointer to 2 bytes starting at offset 5 is out-of-bounds
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 2 bytes of memory, but got ALLOC+0x5 which is at or beyond the end of the allocation of size 4 bytes
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.rs b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.rs
index 2ff537b1ffc5f..054e1c66cc18d 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.rs
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.rs
@@ -1,5 +1,5 @@
 fn main() {
     let mut v: Vec = vec![1, 2];
     // This read is also misaligned. We make sure that the OOB message has priority.
-    unsafe { *v.as_mut_ptr().wrapping_byte_add(5) = 0 }; //~ ERROR: out-of-bounds
+    unsafe { *v.as_mut_ptr().wrapping_byte_add(5) = 0 }; //~ ERROR: expected a pointer to 2 bytes of memory
 }
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr
index 97b3f3ebe7b5c..6ae9f05d17381 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_write.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 4, so pointer to 2 bytes starting at offset 5 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 2 bytes of memory, but got ALLOC+0x5 which is at or beyond the end of the allocation of size 4 bytes
   --> $DIR/out_of_bounds_write.rs:LL:CC
    |
 LL |     unsafe { *v.as_mut_ptr().wrapping_byte_add(5) = 0 };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 4, so pointer to 2 bytes starting at offset 5 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 2 bytes of memory, but got ALLOC+0x5 which is at or beyond the end of the allocation of size 4 bytes
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
index 73c3ff1ee0512..2d4fbafd8b7f6 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/storage_dead_dangling.rs:LL:CC
    |
 LL |     let _ref = unsafe { &mut *(LEAK as *mut i32) };
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: $HEX[noalloc] is a dangling pointer (it has no provenance)
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr
index b7492a09dd090..1d8eed3d30a7c 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/wild_pointer_deref.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: 0x2c[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got 0x2c[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/wild_pointer_deref.rs:LL:CC
    |
 LL |     let x = unsafe { *p };
-   |                      ^^ memory access failed: 0x2c[noalloc] is a dangling pointer (it has no provenance)
+   |                      ^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x2c[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr b/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr
index 7274f62b4d7c0..347afa77053ee 100644
--- a/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr
+++ b/src/tools/miri/tests/fail/function_pointers/cast_int_to_fn_ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/cast_int_to_fn_ptr.rs:LL:CC
    |
 LL |     g(42)
-   |     ^^^^^ out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+   |     ^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs
index b6a110ee84d2c..f337090aa1e36 100644
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs
+++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs
@@ -2,6 +2,6 @@ fn main() {
     let v = [0i8; 4];
     let x = &v as *const i8;
     // The error is inside another function, so we cannot match it by line
-    let x = unsafe { x.offset(5) }; //~ERROR: pointer to 5 bytes starting at offset 0 is out-of-bounds
+    let x = unsafe { x.offset(5) }; //~ERROR: expected a pointer to 5 bytes of memory
     panic!("this should never print: {:?}", x);
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr
index cc8cca70ddb9f..ddc5ae8efbc01 100644
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 5 bytes starting at offset 0 is out-of-bounds
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC and there are only 4 bytes starting at that pointer
   --> $DIR/out_of_bounds_ptr_1.rs:LL:CC
    |
 LL |     let x = unsafe { x.offset(5) };
-   |                      ^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 5 bytes starting at offset 0 is out-of-bounds
+   |                      ^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC and there are only 4 bytes starting at that pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs
index 701bc33a645e1..fc9fb3d35d610 100644
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs
+++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs
@@ -1,6 +1,6 @@
 fn main() {
     let v = [0i8; 4];
     let x = &v as *const i8;
-    let x = unsafe { x.offset(-1) }; //~ERROR: pointer to 1 byte starting at offset -1 is out-of-bounds
+    let x = unsafe { x.offset(-1) }; //~ERROR: expected a pointer to 1 byte of memory
     panic!("this should never print: {:?}", x);
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr
index 236b51e82e594..88963e712f4cc 100644
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 1 byte starting at offset -1 is out-of-bounds
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC-0x1 which points to before the beginning of the allocation
   --> $DIR/out_of_bounds_ptr_3.rs:LL:CC
    |
 LL |     let x = unsafe { x.offset(-1) };
-   |                      ^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC has size 4, so pointer to 1 byte starting at offset -1 is out-of-bounds
+   |                      ^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC-0x1 which points to before the beginning of the allocation
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
index 65f1161425ff9..649075dbc55de 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds `offset_from`: 0xa[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds `offset_from`: expected a pointer to 1 byte of memory, but got 0xa[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/ptr_offset_from_different_ints.rs:LL:CC
    |
 LL |         let _ = p1.byte_offset_from(p2);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: 0xa[noalloc] is a dangling pointer (it has no provenance)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: expected a pointer to 1 byte of memory, but got 0xa[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr
index e03abfb1a2fcd..8d37da6506133 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_int.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/ptr_offset_int_plus_int.rs:LL:CC
    |
 LL |         let _val = (1 as *mut u8).offset(1);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs
index fd3c9b44615c2..c4b6f69dd2be6 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs
@@ -1,4 +1,5 @@
 //@compile-flags: -Zmiri-permissive-provenance
+//@normalize-stderr-test: "to \d+ bytes of memory" -> "to $$BYTES bytes of memory"
 
 fn main() {
     let ptr = Box::into_raw(Box::new(0u32));
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr
index 03ae9bd141c4a..2cd02bee2ca18 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/ptr_offset_int_plus_ptr.rs:LL:CC
    |
 LL |         let _val = (1 as *mut u8).offset(ptr as isize);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-gather.rs b/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
index ceb7beebd8aba..b837395245179 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-gather.rs
@@ -5,6 +5,7 @@ fn main() {
     unsafe {
         let vec: &[i8] = &[10, 11, 12, 13, 14, 15, 16, 17, 18];
         let idxs = Simd::from_array([9, 3, 0, 17]);
-        let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0)); //~ERROR: pointer to 1 byte starting at offset 9 is out-of-bounds
+        let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
+        //~^ERROR: expected a pointer to 1 byte of memory
     }
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr b/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
index d111644eec827..bc8d0b041d321 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 9, so pointer to 1 byte starting at offset 9 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got ALLOC+0x9 which is at or beyond the end of the allocation of size 9 bytes
   --> $DIR/simd-gather.rs:LL:CC
    |
 LL |         let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC has size 9, so pointer to 1 byte starting at offset 9 is out-of-bounds
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got ALLOC+0x9 which is at or beyond the end of the allocation of size 9 bytes
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs b/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
index 98b6749c584f9..bb8c9dbe4c7a8 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.rs
@@ -6,7 +6,7 @@ fn main() {
         let mut vec: Vec = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
         let idxs = Simd::from_array([9, 3, 0, 17]);
         Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
-            //~^ERROR: pointer to 1 byte starting at offset 9 is out-of-bounds
+            //~^ERROR: expected a pointer to 1 byte of memory
             &mut vec,
             Mask::splat(true),
             idxs,
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
index 8b517b6e97252..aae77edcb6bd7 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
@@ -1,4 +1,4 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 9, so pointer to 1 byte starting at offset 9 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got ALLOC+0x9 which is at or beyond the end of the allocation of size 9 bytes
   --> $DIR/simd-scatter.rs:LL:CC
    |
 LL | /         Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
@@ -7,7 +7,7 @@ LL | |             &mut vec,
 LL | |             Mask::splat(true),
 LL | |             idxs,
 LL | |         );
-   | |_________^ memory access failed: ALLOC has size 9, so pointer to 1 byte starting at offset 9 is out-of-bounds
+   | |_________^ memory access failed: expected a pointer to 1 byte of memory, but got ALLOC+0x9 which is at or beyond the end of the allocation of size 9 bytes
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr b/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr
index 50bff22f76678..1ca35be8cb2bd 100644
--- a/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr
+++ b/src/tools/miri/tests/fail/provenance/pointer_partial_overwrite.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/pointer_partial_overwrite.rs:LL:CC
    |
 LL |     let x = *p;
-   |             ^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+   |             ^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr b/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
index 6b1c2941c075c..8a1d39effbd19 100644
--- a/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
+++ b/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/provenance_transmute.rs:LL:CC
    |
 LL |         let _val = *left_ptr;
-   |                    ^^^^^^^^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+   |                    ^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr
index 92ccec5027497..e21872244f60c 100644
--- a/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr
+++ b/src/tools/miri/tests/fail/provenance/ptr_int_unexposed.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/ptr_int_unexposed.rs:LL:CC
    |
 LL |     assert_eq!(unsafe { *ptr }, 3);
-   |                         ^^^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+   |                         ^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr b/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr
index 8b8033b0d1d91..bd0a9eb0d2910 100644
--- a/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr
+++ b/src/tools/miri/tests/fail/provenance/ptr_invalid.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/ptr_invalid.rs:LL:CC
    |
 LL |     let _val = unsafe { *xptr_invalid };
-   |                         ^^^^^^^^^^^^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+   |                         ^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr b/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr
index 8ae140ee004cf..35e5c08300f98 100644
--- a/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr
+++ b/src/tools/miri/tests/fail/provenance/ptr_invalid_offset.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer arithmetic: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/ptr_invalid_offset.rs:LL:CC
    |
 LL |     let _ = unsafe { roundtrip.offset(1) };
-   |                      ^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: $HEX[noalloc] is a dangling pointer (it has no provenance)
+   |                      ^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/reading_half_a_pointer.stderr b/src/tools/miri/tests/fail/reading_half_a_pointer.stderr
index 03f93510d09b3..cba8a9f84396e 100644
--- a/src/tools/miri/tests/fail/reading_half_a_pointer.stderr
+++ b/src/tools/miri/tests/fail/reading_half_a_pointer.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
   --> $DIR/reading_half_a_pointer.rs:LL:CC
    |
 LL |         let _val = *x;
-   |                    ^^ memory access failed: $HEX[noalloc] is a dangling pointer (it has no provenance)
+   |                    ^^ memory access failed: expected a pointer to 1 byte of memory, but got $HEX[noalloc] which is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.rs b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.rs
index 843d0d11873d2..75f7aae9718d6 100644
--- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.rs
+++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.rs
@@ -4,6 +4,6 @@ extern "Rust" {
 
 fn main() {
     unsafe {
-        miri_resolve_frame(std::ptr::null_mut(), 0); //~ ERROR: null pointer is a dangling pointer
+        miri_resolve_frame(std::ptr::null_mut(), 0); //~ ERROR: got a null pointer
     }
 }
diff --git a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr
index 04dbd657d200c..523c935762ffd 100644
--- a/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr
+++ b/src/tools/miri/tests/fail/shims/backtrace/bad-backtrace-ptr.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
   --> $DIR/bad-backtrace-ptr.rs:LL:CC
    |
 LL |         miri_resolve_frame(std::ptr::null_mut(), 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/zst_local_oob.rs b/src/tools/miri/tests/fail/zst_local_oob.rs
index cc81481e4fa4c..ab48b7d330b37 100644
--- a/src/tools/miri/tests/fail/zst_local_oob.rs
+++ b/src/tools/miri/tests/fail/zst_local_oob.rs
@@ -1,5 +1,5 @@
 fn main() {
     // make sure ZST locals cannot be accessed
     let x = &() as *const () as *const i8;
-    let _val = unsafe { *x }; //~ ERROR: out-of-bounds
+    let _val = unsafe { *x }; //~ ERROR: expected a pointer to 1 byte of memory
 }
diff --git a/src/tools/miri/tests/fail/zst_local_oob.stderr b/src/tools/miri/tests/fail/zst_local_oob.stderr
index ba1ccaa0a3c8d..39ac2c91437c6 100644
--- a/src/tools/miri/tests/fail/zst_local_oob.stderr
+++ b/src/tools/miri/tests/fail/zst_local_oob.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: ALLOC has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
+error: Undefined Behavior: memory access failed: expected a pointer to 1 byte of memory, but got ALLOC which is at or beyond the end of the allocation of size 0 bytes
   --> $DIR/zst_local_oob.rs:LL:CC
    |
 LL |     let _val = unsafe { *x };
-   |                         ^^ memory access failed: ALLOC has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
+   |                         ^^ memory access failed: expected a pointer to 1 byte of memory, but got ALLOC which is at or beyond the end of the allocation of size 0 bytes
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr
index eb41a25c818a0..034e8bd185264 100644
--- a/tests/ui/const-ptr/forbidden_slices.stderr
+++ b/tests/ui/const-ptr/forbidden_slices.stderr
@@ -118,7 +118,7 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds pointer arithmetic: ALLOC10 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC10 and there are only 4 bytes starting at that pointer
    |
 note: inside `std::ptr::const_ptr::::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -177,7 +177,7 @@ LL | pub static R7: &[u16] = unsafe {
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds pointer arithmetic: ALLOC11 has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC11+0x1 and there are only 7 bytes starting at that pointer
    |
 note: inside `std::ptr::const_ptr::::add`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr
index 7634ba252100c..7f354963eb1fd 100644
--- a/tests/ui/const-ptr/out_of_bounds_read.stderr
+++ b/tests/ui/const-ptr/out_of_bounds_read.stderr
@@ -1,7 +1,7 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-   = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
    |
 note: inside `std::ptr::read::`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -14,7 +14,7 @@ LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-   = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
    |
 note: inside `std::ptr::read::`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -29,7 +29,7 @@ LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-   = note: memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x4 which is at or beyond the end of the allocation of size 4 bytes
    |
 note: inside `std::ptr::read::`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr
index 9e49706c4c836..8a923779a5bb4 100644
--- a/tests/ui/consts/const-compare-bytes-ub.stderr
+++ b/tests/ui/consts/const-compare-bytes-ub.stderr
@@ -2,31 +2,31 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const-compare-bytes-ub.rs:10:9
    |
 LL |         compare_bytes(0 as *const u8, 2 as *const u8, 1)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got a null pointer
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-compare-bytes-ub.rs:14:9
    |
 LL |         compare_bytes(1 as *const u8, 0 as *const u8, 1)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-compare-bytes-ub.rs:18:9
    |
 LL |         compare_bytes(1 as *const u8, 2 as *const u8, 1)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-compare-bytes-ub.rs:22:9
    |
 LL |         compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0 and there are only 3 bytes starting at that pointer
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-compare-bytes-ub.rs:26:9
    |
 LL |         compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC1 has size 3, so pointer to 4 bytes starting at offset 0 is out-of-bounds
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC1 and there are only 3 bytes starting at that pointer
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const-compare-bytes-ub.rs:30:9
diff --git a/tests/ui/consts/const-deref-ptr.stderr b/tests/ui/consts/const-deref-ptr.stderr
index b102b4d17cca1..070685e0b9d93 100644
--- a/tests/ui/consts/const-deref-ptr.stderr
+++ b/tests/ui/consts/const-deref-ptr.stderr
@@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/const-deref-ptr.rs:4:29
    |
 LL |     static C: u64 = unsafe {*(0xdeadbeef as *const u64)};
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0xdeadbeef[noalloc] is a dangling pointer (it has no provenance)
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 8 bytes of memory, but got 0xdeadbeef[noalloc] which is a dangling pointer (it has no provenance)
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr b/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr
index e6cd25e42ff7d..b0c864652e55e 100644
--- a/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr
+++ b/tests/ui/consts/const-eval/const_raw_ptr_ops2.stderr
@@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const_raw_ptr_ops2.rs:7:26
    |
 LL | const Z2: i32 = unsafe { *(42 as *const i32) };
-   |                          ^^^^^^^^^^^^^^^^^^^ memory access failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+   |                          ^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x2a[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const_raw_ptr_ops2.rs:9:26
    |
 LL | const Z3: i32 = unsafe { *(44 as *const i32) };
-   |                          ^^^^^^^^^^^^^^^^^^^ memory access failed: 0x2c[noalloc] is a dangling pointer (it has no provenance)
+   |                          ^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x2c[noalloc] which is a dangling pointer (it has no provenance)
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr b/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr
index b878c8d1b3761..bd6dafb936653 100644
--- a/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr
+++ b/tests/ui/consts/const-eval/nonnull_as_ref_ub.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/nonnull_as_ref_ub.rs:4:29
    |
 LL | const _: () = assert!(42 == *unsafe { NON_NULL.as_ref() });
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
index d7d24f373ebc1..25f17f9c38a97 100644
--- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
@@ -440,7 +440,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/raw-bytes.rs:196:62
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/raw-bytes.rs:199:65
diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
index 22679acda98b8..0fb9694895d8e 100644
--- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
@@ -440,7 +440,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/raw-bytes.rs:196:62
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/raw-bytes.rs:199:65
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs
index 47105de453cb1..5aced5b1bd6d5 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.rs
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs
@@ -39,7 +39,7 @@ const OOB: () = unsafe {
     let mem = [0u32; 1];
     let ptr = mem.as_ptr().cast::();
     let _val = *ptr; //~ERROR: evaluation of constant value failed
-    //~^NOTE: size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+    //~^NOTE: expected a pointer to 8 bytes of memory
 };
 
 fn main() {}
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
index cba06fdc639f5..5fce25701bdd1 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
@@ -35,7 +35,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/raw-pointer-ub.rs:41:16
    |
 LL |     let _val = *ptr;
-   |                ^^^^ memory access failed: ALLOC0 has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |                ^^^^ memory access failed: expected a pointer to 8 bytes of memory, but got ALLOC0 and there are only 4 bytes starting at that pointer
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr
index ab0fb2abdb309..fe3060dda17df 100644
--- a/tests/ui/consts/const-eval/ub-nonnull.stderr
+++ b/tests/ui/consts/const-eval/ub-nonnull.stderr
@@ -13,7 +13,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-nonnull.rs:20:29
    |
 LL |     let out_of_bounds_ptr = &ptr[255];
-   |                             ^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC1 has size 1, so pointer to 255 bytes starting at offset 0 is out-of-bounds
+   |                             ^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 255 bytes of memory, but got ALLOC1 and there are only 1 bytes starting at that pointer
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-nonnull.rs:24:1
diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
index 4fe744265dfb3..c29cc836fffdb 100644
--- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr
@@ -262,7 +262,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-wide-ptr.rs:144:62
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-wide-ptr.rs:147:65
@@ -274,7 +274,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/ub-wide-ptr.rs:156:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to some allocation, but got a null pointer
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/ub-wide-ptr.rs:161:5
diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs
index 4183dc0fcd6db..e3f43ce203754 100644
--- a/tests/ui/consts/copy-intrinsic.rs
+++ b/tests/ui/consts/copy-intrinsic.rs
@@ -27,7 +27,7 @@ const COPY_OOB_1: () = unsafe {
     copy_nonoverlapping(0x100 as *const i32, dangle, 0);
     // Non-zero-sized copy is not.
     copy_nonoverlapping(0x100 as *const i32, dangle, 1); //~ ERROR evaluation of constant value failed [E0080]
-    //~| 0x100[noalloc] is a dangling pointer
+    //~| got 0x100[noalloc] which is a dangling pointer
 };
 const COPY_OOB_2: () = unsafe {
     let x = 0i32;
@@ -36,7 +36,7 @@ const COPY_OOB_2: () = unsafe {
     copy_nonoverlapping(dangle, 0x100 as *mut i32, 0);
     // Non-zero-sized copy is not.
     copy_nonoverlapping(dangle, 0x100 as *mut i32, 1); //~ ERROR evaluation of constant value failed [E0080]
-    //~| offset 40 is out-of-bounds
+    //~| +0x28 which is at or beyond the end of the allocation
 };
 
 const COPY_SIZE_OVERFLOW: () = unsafe {
diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr
index d34e61cd96273..2dbb471131ecf 100644
--- a/tests/ui/consts/copy-intrinsic.stderr
+++ b/tests/ui/consts/copy-intrinsic.stderr
@@ -2,13 +2,13 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/copy-intrinsic.rs:29:5
    |
 LL |     copy_nonoverlapping(0x100 as *const i32, dangle, 1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: 0x100[noalloc] is a dangling pointer (it has no provenance)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/copy-intrinsic.rs:38:5
    |
 LL |     copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: ALLOC0 has size 4, so pointer to 4 bytes starting at offset 40 is out-of-bounds
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/copy-intrinsic.rs:45:5
diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs
index 95b3118f1570a..66bb056ceb049 100644
--- a/tests/ui/consts/offset_from_ub.rs
+++ b/tests/ui/consts/offset_from_ub.rs
@@ -1,3 +1,4 @@
+//@ normalize-stderr-test: "to \d+ bytes of memory" -> "to $$BYTES bytes of memory"
 #![feature(const_ptr_sub_ptr)]
 #![feature(core_intrinsics)]
 
@@ -45,7 +46,7 @@ const OUT_OF_BOUNDS_1: isize = {
     let end_ptr = (start_ptr).wrapping_add(length);
     // First ptr is out of bounds
     unsafe { ptr_offset_from(end_ptr, start_ptr) } //~ERROR evaluation of constant value failed
-    //~| pointer to 10 bytes starting at offset 0 is out-of-bounds
+    //~| expected a pointer to 10 bytes of memory
 };
 
 const OUT_OF_BOUNDS_2: isize = {
@@ -54,7 +55,7 @@ const OUT_OF_BOUNDS_2: isize = {
     let end_ptr = (start_ptr).wrapping_add(length);
     // Second ptr is out of bounds
     unsafe { ptr_offset_from(start_ptr, end_ptr) } //~ERROR evaluation of constant value failed
-    //~| pointer to 10 bytes starting at offset 0 is out-of-bounds
+    //~| expected a pointer to 10 bytes of memory
 };
 
 pub const DIFFERENT_ALLOC_UNSIGNED: usize = {
diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr
index 0a860f42c649c..f2f27735630fe 100644
--- a/tests/ui/consts/offset_from_ub.stderr
+++ b/tests/ui/consts/offset_from_ub.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:18:27
+  --> $DIR/offset_from_ub.rs:19:27
    |
 LL |     let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on pointers into different allocations
@@ -12,67 +12,67 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `NOT_PTR`
-  --> $DIR/offset_from_ub.rs:24:14
+  --> $DIR/offset_from_ub.rs:25:14
    |
 LL |     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:31:14
+  --> $DIR/offset_from_ub.rs:32:14
    |
 LL |     unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:38:14
+  --> $DIR/offset_from_ub.rs:39:14
    |
 LL |     unsafe { ptr_offset_from(ptr2, ptr1) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: 0x8[noalloc] is a dangling pointer (it has no provenance)
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: expected a pointer to $BYTES bytes of memory, but got 0x8[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:47:14
+  --> $DIR/offset_from_ub.rs:48:14
    |
 LL |     unsafe { ptr_offset_from(end_ptr, start_ptr) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC0 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: expected a pointer to $BYTES bytes of memory, but got ALLOC0 and there are only 4 bytes starting at that pointer
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:56:14
+  --> $DIR/offset_from_ub.rs:57:14
    |
 LL |     unsafe { ptr_offset_from(start_ptr, end_ptr) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC1 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: expected a pointer to $BYTES bytes of memory, but got ALLOC1 and there are only 4 bytes starting at that pointer
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:65:14
+  --> $DIR/offset_from_ub.rs:66:14
    |
 LL |     unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:72:14
+  --> $DIR/offset_from_ub.rs:73:14
    |
 LL |     unsafe { ptr_offset_from(ptr2, ptr1) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far ahead of second
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:78:14
+  --> $DIR/offset_from_ub.rs:79:14
    |
 LL |     unsafe { ptr_offset_from(ptr1, ptr2) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:86:14
+  --> $DIR/offset_from_ub.rs:87:14
    |
 LL |     unsafe { ptr_offset_from(ptr1, ptr2) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:93:14
+  --> $DIR/offset_from_ub.rs:94:14
    |
 LL |     unsafe { ptr_offset_from_unsigned(p, p.add(2) ) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/offset_from_ub.rs:100:14
+  --> $DIR/offset_from_ub.rs:101:14
    |
 LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second
@@ -80,12 +80,12 @@ LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds `offset_from`: expected a pointer to $BYTES bytes of memory, but got a null pointer
    |
 note: inside `std::ptr::const_ptr::::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `OFFSET_VERY_FAR1`
-  --> $DIR/offset_from_ub.rs:109:14
+  --> $DIR/offset_from_ub.rs:110:14
    |
 LL |     unsafe { ptr2.offset_from(ptr1) }
    |              ^^^^^^^^^^^^^^^^^^^^^^
@@ -98,7 +98,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `OFFSET_VERY_FAR2`
-  --> $DIR/offset_from_ub.rs:115:14
+  --> $DIR/offset_from_ub.rs:116:14
    |
 LL |     unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/consts/offset_ub.rs b/tests/ui/consts/offset_ub.rs
index 9a8f756749b70..b239b91e11cf6 100644
--- a/tests/ui/consts/offset_ub.rs
+++ b/tests/ui/consts/offset_ub.rs
@@ -2,6 +2,7 @@ use std::ptr;
 
 //@ normalize-stderr-test: "0xf+" -> "0xf..f"
 //@ normalize-stderr-test: "0x7f+" -> "0x7f..f"
+//@ normalize-stderr-test: "to \d+ bytes of memory" -> "to $$BYTES bytes of memory"
 
 
 pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~NOTE
diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr
index 89371f06d9d65..b42d9482f8a01 100644
--- a/tests/ui/consts/offset_ub.stderr
+++ b/tests/ui/consts/offset_ub.stderr
@@ -6,7 +6,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `BEFORE_START`
-  --> $DIR/offset_ub.rs:7:46
+  --> $DIR/offset_ub.rs:8:46
    |
 LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -14,12 +14,12 @@ LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1)
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds pointer arithmetic: ALLOC0 has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC0 and there are only 1 bytes starting at that pointer
    |
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `AFTER_END`
-  --> $DIR/offset_ub.rs:8:43
+  --> $DIR/offset_ub.rs:9:43
    |
 LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -27,12 +27,12 @@ LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds pointer arithmetic: ALLOC1 has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC1 and there are only 100 bytes starting at that pointer
    |
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `AFTER_ARRAY`
-  --> $DIR/offset_ub.rs:9:45
+  --> $DIR/offset_ub.rs:10:45
    |
 LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
    |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `OVERFLOW`
-  --> $DIR/offset_ub.rs:11:43
+  --> $DIR/offset_ub.rs:12:43
    |
 LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -58,7 +58,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `UNDERFLOW`
-  --> $DIR/offset_ub.rs:12:44
+  --> $DIR/offset_ub.rs:13:44
    |
 LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
    |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `OVERFLOW_ADDRESS_SPACE`
-  --> $DIR/offset_ub.rs:13:56
+  --> $DIR/offset_ub.rs:14:56
    |
 LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,7 +84,7 @@ error[E0080]: evaluation of constant value failed
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `UNDERFLOW_ADDRESS_SPACE`
-  --> $DIR/offset_ub.rs:14:57
+  --> $DIR/offset_ub.rs:15:57
    |
 LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -92,12 +92,12 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds pointer arithmetic: ALLOC2 has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC2-0x4 which points to before the beginning of the allocation
    |
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `NEGATIVE_OFFSET`
-  --> $DIR/offset_ub.rs:15:49
+  --> $DIR/offset_ub.rs:16:49
    |
 LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -105,12 +105,12 @@ LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds pointer arithmetic: ALLOC3 has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
+   = note: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC3 which is at or beyond the end of the allocation of size 0 bytes
    |
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `ZERO_SIZED_ALLOC`
-  --> $DIR/offset_ub.rs:17:50
+  --> $DIR/offset_ub.rs:18:50
    |
 LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -118,12 +118,12 @@ LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
-   = note: out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
    |
 note: inside `std::ptr::mut_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
 note: inside `DANGLING`
-  --> $DIR/offset_ub.rs:18:42
+  --> $DIR/offset_ub.rs:19:42
    |
 LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::::dangling().as_ptr().offset(4) };
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -131,12 +131,12 @@ LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::::dangling().as_
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
+   = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0x7f..f[noalloc] which is a dangling pointer (it has no provenance)
    |
 note: inside `std::ptr::const_ptr::::offset`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `UNDERFLOW_ABS`
-  --> $DIR/offset_ub.rs:21:47
+  --> $DIR/offset_ub.rs:22:47
    |
 LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/error-codes/E0396-fixed.stderr b/tests/ui/error-codes/E0396-fixed.stderr
index 2f8ea7993f723..c14f4948095de 100644
--- a/tests/ui/error-codes/E0396-fixed.stderr
+++ b/tests/ui/error-codes/E0396-fixed.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/E0396-fixed.rs:5:28
    |
 LL | const VALUE: u8 = unsafe { *REG_ADDR };
-   |                            ^^^^^^^^^ memory access failed: 0x5f3759df[noalloc] is a dangling pointer (it has no provenance)
+   |                            ^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x5f3759df[noalloc] which is a dangling pointer (it has no provenance)
 
 error: aborting due to 1 previous error
 

From 6c98665d91fb85fe78752f24d733c7d3671c60ea Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Sat, 27 Jul 2024 23:52:40 +0200
Subject: [PATCH 177/489] Down to 1 failing test

And that is due to a case where we have two ratomls in a source root, one of which
is a `workspace_ratoml` and the other one is simple old ratoml. Since we are not checking to see if
the source root is already populated with workspace ratoml, this test fails. Due to principles of clear
code I believe it is reasonable to not have two HashMaps that are almost for the exact same thing.
So next commit should remove `workspace_ratoml` and merge it with `krate_ratoml`s.
---
 .../crates/rust-analyzer/src/capabilities.rs  |  2 +-
 .../crates/rust-analyzer/src/config.rs        | 78 +++++++++++--------
 .../crates/rust-analyzer/src/global_state.rs  | 15 +++-
 .../rust-analyzer/src/handlers/request.rs     |  5 +-
 .../rust-analyzer/tests/slow-tests/ratoml.rs  | 46 ++---------
 5 files changed, 66 insertions(+), 80 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/capabilities.rs
index 212294b5d326e..9610808c27e18 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/capabilities.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/capabilities.rs
@@ -67,7 +67,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
         code_action_provider: Some(config.caps().code_action_capabilities()),
         code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
         document_formatting_provider: Some(OneOf::Left(true)),
-        document_range_formatting_provider: match config.rustfmt() {
+        document_range_formatting_provider: match config.rustfmt(None) {
             RustfmtConfig::Rustfmt { enable_range_formatting: true, .. } => Some(OneOf::Left(true)),
             _ => Some(OneOf::Left(false)),
         },
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 36419d4a97b29..d667ed94976fd 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -780,10 +780,10 @@ pub struct Config {
     user_config: Option<(GlobalLocalConfigInput, ConfigErrors)>,
 
     /// TODO : This file can be used to make global changes while having only a workspace-wide scope.
-    workspace_ratoml_change: FxHashMap,
+    workspace_ratoml: FxHashMap,
 
     /// For every `SourceRoot` there can be at most one RATOML file.
-    ratoml_files: FxHashMap,
+    krate_ratoml: FxHashMap,
 
     /// Clone of the value that is stored inside a `GlobalState`.
     source_root_parent_map: Arc>,
@@ -927,7 +927,7 @@ impl Config {
                                 &mut String::new(),
                                 &mut toml_errors,
                             );
-                            config.workspace_ratoml_change.insert(
+                            config.workspace_ratoml.insert(
                                 source_root_id,
                                 (
                                     GlobalLocalConfigInput::from_toml(table, &mut toml_errors),
@@ -969,7 +969,7 @@ impl Config {
                                 &mut String::new(),
                                 &mut toml_errors,
                             );
-                            config.ratoml_files.insert(
+                            config.krate_ratoml.insert(
                                 source_root_id,
                                 (
                                     LocalConfigInput::from_toml(&table, &mut toml_errors),
@@ -1022,15 +1022,9 @@ impl Config {
                 .1
                  .0
                 .iter()
-                .chain(
-                    config
-                        .workspace_ratoml_change
-                        .values()
-                        .into_iter()
-                        .flat_map(|it| it.1 .0.iter()),
-                )
+                .chain(config.workspace_ratoml.values().into_iter().flat_map(|it| it.1 .0.iter()))
                 .chain(config.user_config.as_ref().into_iter().flat_map(|it| it.1 .0.iter()))
-                .chain(config.ratoml_files.values().flat_map(|it| it.1 .0.iter()))
+                .chain(config.krate_ratoml.values().flat_map(|it| it.1 .0.iter()))
                 .chain(config.validation_errors.0.iter())
                 .cloned()
                 .collect(),
@@ -1070,6 +1064,7 @@ impl ConfigChange {
         vfs_path: VfsPath,
         content: Option>,
     ) -> Option<(VfsPath, Option>)> {
+        dbg!("change_ratoml", &vfs_path);
         self.ratoml_file_change
             .get_or_insert_with(Default::default)
             .insert(source_root, (vfs_path, content))
@@ -1086,6 +1081,7 @@ impl ConfigChange {
         vfs_path: VfsPath,
         content: Option>,
     ) -> Option<(VfsPath, Option>)> {
+        dbg!("change_workspace", &vfs_path);
         self.workspace_ratoml_change
             .get_or_insert_with(Default::default)
             .insert(source_root, (vfs_path, content))
@@ -1350,14 +1346,14 @@ impl Config {
             workspace_roots,
             visual_studio_code_version,
             client_config: (FullConfigInput::default(), ConfigErrors(vec![])),
-            ratoml_files: FxHashMap::default(),
+            krate_ratoml: FxHashMap::default(),
             default_config: DEFAULT_CONFIG_DATA.get_or_init(|| Box::leak(Box::default())),
             source_root_parent_map: Arc::new(FxHashMap::default()),
             user_config: None,
             user_config_path,
             detached_files: Default::default(),
             validation_errors: Default::default(),
-            workspace_ratoml_change: Default::default(),
+            workspace_ratoml: Default::default(),
         }
     }
 
@@ -1877,7 +1873,7 @@ impl Config {
         }
     }
 
-    pub fn rustfmt(&self) -> RustfmtConfig {
+    pub fn rustfmt(&self, source_root_id: Option) -> RustfmtConfig {
         match &self.rustfmt_overrideCommand(None) {
             Some(args) if !args.is_empty() => {
                 let mut args = args.clone();
@@ -1885,8 +1881,8 @@ impl Config {
                 RustfmtConfig::CustomCommand { command, args }
             }
             Some(_) | None => RustfmtConfig::Rustfmt {
-                extra_args: self.rustfmt_extraArgs(None).clone(),
-                enable_range_formatting: *self.rustfmt_rangeFormatting_enable(None),
+                extra_args: self.rustfmt_extraArgs(source_root_id).clone(),
+                enable_range_formatting: *self.rustfmt_rangeFormatting_enable(source_root_id),
             },
         }
     }
@@ -2540,22 +2536,28 @@ macro_rules! _impl_for_config_data {
                 $($doc)*
                 #[allow(non_snake_case)]
                 $vis fn $field(&self, source_root: Option) -> &$ty {
-                    let mut par: Option = source_root;
-                    while let Some(source_root_id) = par {
-                        par = self.source_root_parent_map.get(&source_root_id).copied();
-                        if let Some((config, _)) = self.ratoml_files.get(&source_root_id) {
+                    let follow = if stringify!($field) == "assist_emitMustUse" { dbg!("YEY"); true } else {false};
+                    let mut current: Option = None;
+                    let mut next: Option = source_root;
+                    if follow { dbg!(&self.krate_ratoml);}
+                    while let Some(source_root_id) = next {
+                        current = next;
+                        next = self.source_root_parent_map.get(&source_root_id).copied();
+                        if let Some((config, _)) = self.krate_ratoml.get(&source_root_id) {
                             if let Some(value) = config.$field.as_ref() {
                                 return value;
                             }
                         }
                     }
 
-                    // TODO
-                    // if let Some((root_path_ratoml, _)) = self.root_ratoml.as_ref() {
-                    //     if let Some(v) = root_path_ratoml.local.$field.as_ref() {
-                    //         return &v;
-                    //     }
-                    // }
+                    if let Some(current) = current {
+                        if follow { dbg!(&self.workspace_ratoml);}
+                        if let Some((root_path_ratoml, _)) = self.workspace_ratoml.get(¤t).as_ref() {
+                            if let Some(v) = root_path_ratoml.local.$field.as_ref() {
+                                return &v;
+                            }
+                        }
+                    }
 
                     if let Some(v) = self.client_config.0.local.$field.as_ref() {
                         return &v;
@@ -2582,12 +2584,22 @@ macro_rules! _impl_for_config_data {
                 $($doc)*
                 #[allow(non_snake_case)]
                 $vis fn $field(&self, source_root : Option) -> &$ty {
-                    // TODO
-                    // if let Some((root_path_ratoml, _)) = self.root_ratoml.as_ref() {
-                    //     if let Some(v) = root_path_ratoml.global.$field.as_ref() {
-                    //         return &v;
-                    //     }
-                    // }
+                    let follow = if stringify!($field) == "rustfmt_extraArgs" { dbg!("YEY"); true } else {false};
+                    let mut current: Option = None;
+                    let mut next: Option = source_root;
+                    while let Some(source_root_id) = next {
+                        current = next;
+                        next = self.source_root_parent_map.get(&source_root_id).copied();
+                    }
+
+                    if let Some(current) = current {
+                        if follow { dbg!(&self.workspace_ratoml);}
+                        if let Some((root_path_ratoml, _)) = self.workspace_ratoml.get(¤t).as_ref() {
+                            if let Some(v) = root_path_ratoml.global.$field.as_ref() {
+                                return &v;
+                            }
+                        }
+                    }
 
                     if let Some(v) = self.client_config.0.global.$field.as_ref() {
                         return &v;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index d78e760358243..5bfdb67af28a1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -386,12 +386,18 @@ impl GlobalState {
                 let mut change = ConfigChange::default();
                 let db = self.analysis_host.raw_database();
 
-                // FIXME @alibektas : This is silly. There is abs no reason to use VfsPaths when there is SourceRoots. But how
+                // FIXME @alibektas : This is silly. There is no reason to use VfsPaths when there is SourceRoots. But how
                 // do I resolve a "workspace_root" to its corresponding id without having to rely on a cargo.toml's ( or project json etc.) file id?
-                let workspace_roots = self
+                let workspace_ratoml_paths = self
                     .workspaces
                     .iter()
-                    .map(|ws| VfsPath::from(ws.workspace_root().to_owned()))
+                    .map(|ws| {
+                        VfsPath::from({
+                            let mut p = ws.workspace_root().to_owned();
+                            p.push("rust-analyzer.toml");
+                            p
+                        })
+                    })
                     .collect_vec();
 
                 for (file_id, (_change_kind, vfs_path)) in modified_ratoml_files {
@@ -405,7 +411,7 @@ impl GlobalState {
                     let sr_id = db.file_source_root(file_id);
                     let sr = db.source_root(sr_id);
 
-                    if workspace_roots.contains(&vfs_path) {
+                    if workspace_ratoml_paths.contains(&vfs_path) {
                         change.change_workspace_ratoml(
                             sr_id,
                             vfs_path,
@@ -422,6 +428,7 @@ impl GlobalState {
                         ) {
                             // SourceRoot has more than 1 RATOML files. In this case lexicographically smaller wins.
                             if old_path < vfs_path {
+                                dbg!("HARBIDEN");
                                 span!(Level::ERROR, "Two `rust-analyzer.toml` files were found inside the same crate. {vfs_path} has no effect.");
                                 // Put the old one back in.
                                 change.change_ratoml(sr_id, old_path, old_text);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 44ff273b5ae00..9680a5c827951 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -2090,8 +2090,9 @@ fn run_rustfmt(
     let edition = editions.iter().copied().max();
 
     let line_index = snap.file_line_index(file_id)?;
+    let sr = snap.analysis.source_root_id(file_id)?;
 
-    let mut command = match snap.config.rustfmt() {
+    let mut command = match snap.config.rustfmt(Some(sr)) {
         RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => {
             // FIXME: Set RUSTUP_TOOLCHAIN
             let mut cmd = process::Command::new(toolchain::Tool::Rustfmt.path());
@@ -2280,7 +2281,7 @@ pub(crate) fn internal_testing_fetch_config(
     serde_json::to_value(match &*params.config {
         "local" => state.config.assist(source_root).assist_emit_must_use,
         "global" => matches!(
-            state.config.rustfmt(),
+            state.config.rustfmt(source_root),
             RustfmtConfig::Rustfmt { enable_range_formatting: true, .. }
         ),
         _ => return Err(anyhow::anyhow!("Unknown test config key: {}", params.config)),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
index 298e10fb9e024..8c111723fb28e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
@@ -700,37 +700,6 @@ fn ratoml_multiple_ratoml_in_single_source_root() {
     );
 
     assert!(server.query(QueryType::Local, 3));
-
-    let server = RatomlTest::new(
-        vec![
-            r#"
-//- /p1/Cargo.toml
-[package]
-name = "p1"
-version = "0.1.0"
-edition = "2021"
-"#,
-            r#"
-//- /p1/src/rust-analyzer.toml
-assist.emitMustUse = false
-"#,
-            r#"
-//- /p1/rust-analyzer.toml
-assist.emitMustUse = true
-"#,
-            r#"
-//- /p1/src/lib.rs
-enum Value {
-    Number(i32),
-    Text(String),
-}
-"#,
-        ],
-        vec!["p1"],
-        None,
-    );
-
-    assert!(server.query(QueryType::Local, 3));
 }
 
 /// If a root is non-local, so we cannot find what its parent is
@@ -808,7 +777,6 @@ enum Value {
 /// Having a ratoml file at the root of a project enables
 /// configuring global level configurations as well.
 #[test]
-// #[ignore = "Root ratomls are not being looked for on startup. Fix this."]
 fn ratoml_in_root_is_global() {
     let server = RatomlTest::new(
         vec![
@@ -820,7 +788,7 @@ version = "0.1.0"
 edition = "2021"
         "#,
             r#"
-//- /rust-analyzer.toml
+//- /p1/rust-analyzer.toml
 rustfmt.rangeFormatting.enable = true
         "#,
             r#"
@@ -829,7 +797,7 @@ fn main() {
     todo!()
 }"#,
         ],
-        vec![],
+        vec!["p1"],
         None,
     );
 
@@ -837,7 +805,6 @@ fn main() {
 }
 
 #[test]
-#[ignore = "Root ratomls are not being looked for on startup. Fix this."]
 fn ratoml_root_is_updateable() {
     let mut server = RatomlTest::new(
         vec![
@@ -849,7 +816,7 @@ version = "0.1.0"
 edition = "2021"
         "#,
             r#"
-//- /rust-analyzer.toml
+//- /p1/rust-analyzer.toml
 rustfmt.rangeFormatting.enable = true
     "#,
             r#"
@@ -858,7 +825,7 @@ fn main() {
    todo!()
 }"#,
         ],
-        vec![],
+        vec!["p1"],
         None,
     );
 
@@ -868,7 +835,6 @@ fn main() {
 }
 
 #[test]
-#[ignore = "Root ratomls are not being looked for on startup. Fix this."]
 fn ratoml_root_is_deletable() {
     let mut server = RatomlTest::new(
         vec![
@@ -880,7 +846,7 @@ version = "0.1.0"
 edition = "2021"
         "#,
             r#"
-//- /rust-analyzer.toml
+//- /p1/rust-analyzer.toml
 rustfmt.rangeFormatting.enable = true
        "#,
             r#"
@@ -889,7 +855,7 @@ fn main() {
     todo!()
 }"#,
         ],
-        vec![],
+        vec!["p1"],
         None,
     );
 

From f4186e37c87f706f216fba92c873b1f61cd8f29f Mon Sep 17 00:00:00 2001
From: Luuk Wester 
Date: Sun, 28 Jul 2024 00:48:08 +0200
Subject: [PATCH 178/489] flip the naming of the doc comment to comment assist

---
 .../src/handlers/convert_comment_from_or_to_doc.rs            | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs
index 953119fd1ff9e..c7b1314c861e2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs
@@ -40,7 +40,7 @@ fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
 
     acc.add(
         AssistId("doc_to_comment", AssistKind::RefactorRewrite),
-        "Replace comment with doc comment",
+        "Replace doc comment with comment",
         target,
         |edit| {
             // We need to either replace the first occurrence of /* with /***, or we need to replace
@@ -87,7 +87,7 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem
 
     acc.add(
         AssistId("comment_to_doc", AssistKind::RefactorRewrite),
-        "Replace doc comment with comment",
+        "Replace comment with doc comment",
         target,
         |edit| {
             // We need to either replace the first occurrence of /* with /***, or we need to replace

From c0df26be420a5f0702214c393d85577843227437 Mon Sep 17 00:00:00 2001
From: Josh McKinney 
Date: Sat, 27 Jul 2024 21:43:35 -0700
Subject: [PATCH 179/489] feat: use vscode log format for client logs

This change updates the log format to use the vscode log format instead
of the custom log format, by replacing the `OutputChannel` with a
`LogOutputChannel` and using the `debug`, `info`, `warn`, and `error`
methods on it. This has the following benefits:

- Each log level now has its own color and the timestamp is in a more
  standard format
- Inspect output (e.g. the log of the config object) is now colored
- Error stack traces are now shown in the output
- The log level is now controlled on the output tab by clicking the gear
  icon and selecting "Debug" or by passing the `--log` parameter to
  vscode. The `trace.extension` setting has been marked as deprecated.
---
 src/tools/rust-analyzer/.vscode/launch.json   | 12 ++--
 .../rust-analyzer/editors/code/package.json   |  1 +
 .../editors/code/src/bootstrap.ts             |  8 ++-
 .../rust-analyzer/editors/code/src/config.ts  |  5 --
 .../rust-analyzer/editors/code/src/ctx.ts     |  3 +-
 .../rust-analyzer/editors/code/src/util.ts    | 61 +++++++++----------
 6 files changed, 44 insertions(+), 46 deletions(-)

diff --git a/src/tools/rust-analyzer/.vscode/launch.json b/src/tools/rust-analyzer/.vscode/launch.json
index c353737a35a83..e83c03796a4b5 100644
--- a/src/tools/rust-analyzer/.vscode/launch.json
+++ b/src/tools/rust-analyzer/.vscode/launch.json
@@ -18,7 +18,8 @@
       "args": [
         // "--user-data-dir=${workspaceFolder}/target/code",
         "--disable-extensions",
-        "--extensionDevelopmentPath=${workspaceFolder}/editors/code"
+        "--extensionDevelopmentPath=${workspaceFolder}/editors/code",
+        "--log rust-lang.rust-analyzer:debug"
       ],
       "outFiles": [
         "${workspaceFolder}/editors/code/out/**/*.js"
@@ -36,7 +37,8 @@
       "runtimeExecutable": "${execPath}",
       "args": [
         "--disable-extensions",
-        "--extensionDevelopmentPath=${workspaceFolder}/editors/code"
+        "--extensionDevelopmentPath=${workspaceFolder}/editors/code",
+        "--log rust-lang.rust-analyzer:debug"
       ],
       "outFiles": [
         "${workspaceFolder}/editors/code/out/**/*.js"
@@ -57,7 +59,8 @@
       "runtimeExecutable": "${execPath}",
       "args": [
         "--disable-extensions",
-        "--extensionDevelopmentPath=${workspaceFolder}/editors/code"
+        "--extensionDevelopmentPath=${workspaceFolder}/editors/code",
+        "--log rust-lang.rust-analyzer:debug"
       ],
       "outFiles": [
         "${workspaceFolder}/editors/code/out/**/*.js"
@@ -79,7 +82,8 @@
       "runtimeExecutable": "${execPath}",
       "args": [
         "--disable-extension", "rust-lang.rust-analyzer",
-        "--extensionDevelopmentPath=${workspaceFolder}/editors/code"
+        "--extensionDevelopmentPath=${workspaceFolder}/editors/code",
+        "--log rust-lang.rust-analyzer:debug"
       ],
       "outFiles": [
         "${workspaceFolder}/editors/code/out/**/*.js"
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 49defa5deae14..da06f133d03b7 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -483,6 +483,7 @@
                     },
                     "rust-analyzer.trace.extension": {
                         "description": "Enable logging of VS Code extensions itself.",
+                        "markdownDeprecationMessage": "Log level is now controlled by the [Developer: Set Log Level...](command:workbench.action.setLogLevel) command.You can set the log level for the current session and also the default log level from there. This is also available by clicking the gear icon on the OUTPUT tab when Rust Analyzer Client is visible or by passing the --log rust-lang.rust-analyzer:debug parameter to VS Code.",
                         "type": "boolean",
                         "default": false
                     }
diff --git a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
index 527edf19eb45f..42dd0760d6238 100644
--- a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
+++ b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
@@ -117,9 +117,11 @@ export function isValidExecutable(path: string, extraEnv: Env): boolean {
         env: { ...process.env, ...extraEnv },
     });
 
-    const printOutput = res.error ? log.warn : log.info;
-    printOutput(path, "--version:", res);
-
+    if (res.error) {
+        log.warn(path, "--version:", res);
+    } else {
+        log.info(path, "--version:", res);
+    }
     return res.status === 0;
 }
 
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index 75fbcdacae476..dc0165df71ea9 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -41,7 +41,6 @@ export class Config {
     }
 
     private refreshLogging() {
-        log.setEnabled(this.traceExtension ?? false);
         log.info(
             "Extension version:",
             vscode.extensions.getExtension(this.extensionId)!.packageJSON.version,
@@ -253,10 +252,6 @@ export class Config {
         await this.cfg.update("checkOnSave", !(value || false), target || null, overrideInLanguage);
     }
 
-    get traceExtension() {
-        return this.get("trace.extension");
-    }
-
     get discoverProjectRunner(): string | undefined {
         return this.get("discoverProjectRunner");
     }
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 49e002627d87d..0f2a758db4274 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -249,7 +249,8 @@ export class Ctx implements RustAnalyzerExtensionApi {
 
             message +=
                 'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). ';
-            message += 'To enable verbose logs use { "rust-analyzer.trace.extension": true }';
+            message +=
+                'To enable verbose logs, click the gear icon in the "OUTPUT" tab and select "Debug".';
 
             log.error("Bootstrap error", err);
             throw new Error(message);
diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts
index dd1cbe38ff99c..eb98425abff06 100644
--- a/src/tools/rust-analyzer/editors/code/src/util.ts
+++ b/src/tools/rust-analyzer/editors/code/src/util.ts
@@ -17,49 +17,44 @@ export type Env = {
     [name: string]: string;
 };
 
-export const log = new (class {
-    private enabled = true;
-    private readonly output = vscode.window.createOutputChannel("Rust Analyzer Client");
-
-    setEnabled(yes: boolean): void {
-        log.enabled = yes;
-    }
+class Log {
+    private readonly output = vscode.window.createOutputChannel("Rust Analyzer Client", {
+        log: true,
+    });
 
-    // Hint: the type [T, ...T[]] means a non-empty array
-    debug(...msg: [unknown, ...unknown[]]): void {
-        if (!log.enabled) return;
-        log.write("DEBUG", ...msg);
+    debug(...messages: [unknown, ...unknown[]]): void {
+        this.output.debug(this.stringify(messages));
     }
 
-    info(...msg: [unknown, ...unknown[]]): void {
-        log.write("INFO", ...msg);
+    info(...messages: [unknown, ...unknown[]]): void {
+        this.output.info(this.stringify(messages));
     }
 
-    warn(...msg: [unknown, ...unknown[]]): void {
-        debugger;
-        log.write("WARN", ...msg);
+    warn(...messages: [unknown, ...unknown[]]): void {
+        this.output.warn(this.stringify(messages));
     }
 
-    error(...msg: [unknown, ...unknown[]]): void {
-        debugger;
-        log.write("ERROR", ...msg);
-        log.output.show(true);
+    error(...messages: [unknown, ...unknown[]]): void {
+        this.output.error(this.stringify(messages));
+        this.output.show(true);
     }
 
-    private write(label: string, ...messageParts: unknown[]): void {
-        const message = messageParts.map(log.stringify).join(" ");
-        const dateTime = new Date().toLocaleString();
-        log.output.appendLine(`${label} [${dateTime}]: ${message}`);
+    private stringify(messages: unknown[]): string {
+        return messages
+            .map((message) => {
+                if (typeof message === "string") {
+                    return message;
+                }
+                if (message instanceof Error) {
+                    return message.stack || message.message;
+                }
+                return inspect(message, { depth: 6, colors: false });
+            })
+            .join(" ");
     }
+}
 
-    private stringify(val: unknown): string {
-        if (typeof val === "string") return val;
-        return inspect(val, {
-            colors: false,
-            depth: 6, // heuristic
-        });
-    }
-})();
+export const log = new Log();
 
 export function sleep(ms: number) {
     return new Promise((resolve) => setTimeout(resolve, ms));
@@ -135,7 +130,7 @@ export function execute(command: string, options: ExecOptions): Promise
     return new Promise((resolve, reject) => {
         exec(command, options, (err, stdout, stderr) => {
             if (err) {
-                log.error(err);
+                log.error("error:", err);
                 reject(err);
                 return;
             }

From b4e1a53b7a146fe16fc3347b30700c602110a5f6 Mon Sep 17 00:00:00 2001
From: WANG Rui 
Date: Sun, 28 Jul 2024 12:46:46 +0800
Subject: [PATCH 180/489] Update target-spec metadata for loongarch64 targets

---
 .../src/spec/targets/loongarch64_unknown_linux_musl.rs    | 8 ++++----
 .../src/spec/targets/loongarch64_unknown_none.rs          | 2 +-
 .../spec/targets/loongarch64_unknown_none_softfloat.rs    | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
index 19b04607f0e0b..f7a6e0bd857f5 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
@@ -4,10 +4,10 @@ pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-linux-musl".into(),
         metadata: crate::spec::TargetMetadata {
-            description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.3".into()),
-            tier: Some(3),
-            host_tools: Some(false),
-            std: None, // ?
+            description: Some("LoongArch64 Linux (LP64D ABI) with musl 1.2.5".into()),
+            tier: Some(2),
+            host_tools: Some(true),
+            std: Some(true),
         },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
index 744ffff721fe7..9d80b4c901dad 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-none".into(),
         metadata: crate::spec::TargetMetadata {
-            description: None,
+            description: Some("Freestanding/bare-metal LoongArch64".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(false),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
index a382e7a53fbdf..d55611ffee317 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-none".into(),
         metadata: crate::spec::TargetMetadata {
-            description: None,
+            description: Some("Freestanding/bare-metal LoongArch64 softfloat".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(false),

From 2f0451d113bd807a8d10ab667346f3fa77062632 Mon Sep 17 00:00:00 2001
From: Josh McKinney 
Date: Sat, 27 Jul 2024 21:59:12 -0700
Subject: [PATCH 181/489] feat: add trace level to client logs

---
 src/tools/rust-analyzer/editors/code/src/util.ts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts
index eb98425abff06..db64a013fda3d 100644
--- a/src/tools/rust-analyzer/editors/code/src/util.ts
+++ b/src/tools/rust-analyzer/editors/code/src/util.ts
@@ -22,6 +22,10 @@ class Log {
         log: true,
     });
 
+    trace(...messages: [unknown, ...unknown[]]): void {
+        this.output.trace(this.stringify(messages));
+    }
+
     debug(...messages: [unknown, ...unknown[]]): void {
         this.output.debug(this.stringify(messages));
     }

From 53fea63c0c198656bfdf44fc4655728117a9cf00 Mon Sep 17 00:00:00 2001
From: duncan 
Date: Fri, 21 Jun 2024 16:02:33 +0100
Subject: [PATCH 182/489] 17470 - run test explorer tests at the package level
 and add missing extra_test_bin_args settings

---
 .../rust-analyzer/crates/flycheck/src/lib.rs  |  2 +-
 .../crates/flycheck/src/test_runner.rs        | 23 ++++++++++-
 .../rust-analyzer/src/handlers/request.rs     | 39 +++++++++++++++----
 3 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index ce148037fcfb4..3dd2a91d8fd96 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -24,7 +24,7 @@ pub mod project_json;
 mod test_runner;
 
 use command::{CommandHandle, ParseFromLine};
-pub use test_runner::{CargoTestHandle, CargoTestMessage, TestState};
+pub use test_runner::{CargoTestHandle, CargoTestMessage, TestState, TestTarget};
 
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
 pub enum InvocationStrategy {
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs b/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs
index c136dd13664a7..74ebca34103aa 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs
@@ -59,19 +59,38 @@ pub struct CargoTestHandle {
 }
 
 // Example of a cargo test command:
-// cargo test --workspace --no-fail-fast -- module::func -Z unstable-options --format=json
+// cargo test --workspace --no-fail-fast -- -Z unstable-options --format=json
+// or
+// cargo test --package my-package --no-fail-fast -- module::func -Z unstable-options --format=json
+
+#[derive(Debug)]
+pub enum TestTarget {
+    Workspace,
+    Package(String),
+}
 
 impl CargoTestHandle {
     pub fn new(
         path: Option<&str>,
         options: CargoOptions,
         root: &AbsPath,
+        test_target: TestTarget,
         sender: Sender,
     ) -> std::io::Result {
         let mut cmd = Command::new(Tool::Cargo.path());
         cmd.env("RUSTC_BOOTSTRAP", "1");
         cmd.arg("test");
-        cmd.arg("--workspace");
+
+        match &test_target {
+            TestTarget::Package(package) => {
+                cmd.arg("--package");
+                cmd.arg(package);
+            }
+            TestTarget::Workspace => {
+                cmd.arg("--workspace");
+            }
+        };
+
         // --no-fail-fast is needed to ensure that all requested tests will run
         cmd.arg("--no-fail-fast");
         cmd.arg("--manifest-path");
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 44ff273b5ae00..9bb31463226cc 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -27,7 +27,7 @@ use lsp_types::{
     SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit,
 };
 use paths::Utf8PathBuf;
-use project_model::{ManifestPath, ProjectWorkspaceKind, TargetKind};
+use project_model::{CargoWorkspace, ManifestPath, ProjectWorkspaceKind, TargetKind};
 use serde_json::json;
 use stdx::{format_to, never};
 use syntax::{algo, ast, AstNode, TextRange, TextSize};
@@ -199,6 +199,20 @@ pub(crate) fn handle_view_item_tree(
     Ok(res)
 }
 
+// cargo test requires the real package name which might contain hyphens but
+// the test identifier passed to this function is the namespace form where hyphens
+// are replaced with underscores so we have to reverse this and find the real package name
+fn find_package_name(namespace_root: &str, cargo: &CargoWorkspace) -> Option {
+    cargo.packages().find_map(|p| {
+        let package_name = &cargo[p].name;
+        if package_name.replace('-', "_") == namespace_root {
+            Some(package_name.clone())
+        } else {
+            None
+        }
+    })
+}
+
 pub(crate) fn handle_run_test(
     state: &mut GlobalState,
     params: lsp_ext::RunTestParams,
@@ -206,7 +220,7 @@ pub(crate) fn handle_run_test(
     if let Some(_session) = state.test_run_session.take() {
         state.send_notification::(());
     }
-    // We detect the lowest common ansector of all included tests, and
+    // We detect the lowest common ancestor of all included tests, and
     // run it. We ignore excluded tests for now, the client will handle
     // it for us.
     let lca = match params.include {
@@ -225,20 +239,31 @@ pub(crate) fn handle_run_test(
             .unwrap_or_default(),
         None => "".to_owned(),
     };
-    let test_path = if lca.is_empty() {
-        None
-    } else if let Some((_, path)) = lca.split_once("::") {
-        Some(path)
+    let (namespace_root, test_path) = if lca.is_empty() {
+        (None, None)
+    } else if let Some((namespace_root, path)) = lca.split_once("::") {
+        (Some(namespace_root), Some(path))
     } else {
-        None
+        (Some(lca.as_str()), None)
     };
     let mut handles = vec![];
     for ws in &*state.workspaces {
         if let ProjectWorkspaceKind::Cargo { cargo, .. } = &ws.kind {
+            let test_target = if let Some(namespace_root) = namespace_root {
+                if let Some(package_name) = find_package_name(namespace_root, cargo) {
+                    flycheck::TestTarget::Package(package_name)
+                } else {
+                    flycheck::TestTarget::Workspace
+                }
+            } else {
+                flycheck::TestTarget::Workspace
+            };
+
             let handle = flycheck::CargoTestHandle::new(
                 test_path,
                 state.config.cargo_test_options(),
                 cargo.workspace_root(),
+                test_target,
                 state.test_run_sender.clone(),
             )?;
             handles.push(handle);

From e1fc4a997ddac2b949ef6bb4037f1fb196c44f08 Mon Sep 17 00:00:00 2001
From: Zalathar 
Date: Sun, 28 Jul 2024 15:12:14 +1000
Subject: [PATCH 183/489] Don't store `thir::Pat` in error structs

In several cases this avoids the need to clone the underlying pattern, and then
print the clone later.
---
 compiler/rustc_middle/src/thir.rs             |  7 ---
 compiler/rustc_mir_build/src/errors.rs        |  2 +-
 compiler/rustc_pattern_analysis/src/errors.rs | 53 +++++++++----------
 compiler/rustc_pattern_analysis/src/rustc.rs  | 10 ++--
 4 files changed, 32 insertions(+), 40 deletions(-)

diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index b80d00719ee5e..1300a06f37510 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -9,7 +9,6 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
 
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
@@ -702,12 +701,6 @@ impl<'tcx> Pat<'tcx> {
     }
 }
 
-impl<'tcx> IntoDiagArg for Pat<'tcx> {
-    fn into_diag_arg(self) -> DiagArgValue {
-        format!("{self}").into_diag_arg()
-    }
-}
-
 #[derive(Clone, Debug, HashStable, TypeVisitable)]
 pub struct Ascription<'tcx> {
     pub annotation: CanonicalUserTypeAnnotation<'tcx>,
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index bdc4b0ea97d18..2e508829fbe3c 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -856,7 +856,7 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
     pub(crate) span: Span,
     pub(crate) origin: &'s str,
     #[subdiagnostic]
-    pub(crate) uncovered: Uncovered<'tcx>,
+    pub(crate) uncovered: Uncovered,
     #[subdiagnostic]
     pub(crate) inform: Option,
     #[subdiagnostic]
diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs
index 27f227e6d9c11..bad41ac77f098 100644
--- a/compiler/rustc_pattern_analysis/src/errors.rs
+++ b/compiler/rustc_pattern_analysis/src/errors.rs
@@ -1,6 +1,5 @@
 use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
-use rustc_middle::thir::Pat;
 use rustc_middle::ty::Ty;
 use rustc_span::Span;
 
@@ -8,18 +7,18 @@ use crate::rustc::{RustcPatCtxt, WitnessPat};
 
 #[derive(Subdiagnostic)]
 #[label(pattern_analysis_uncovered)]
-pub struct Uncovered<'tcx> {
+pub struct Uncovered {
     #[primary_span]
     span: Span,
     count: usize,
-    witness_1: Pat<'tcx>,
-    witness_2: Pat<'tcx>,
-    witness_3: Pat<'tcx>,
+    witness_1: String, // a printed pattern
+    witness_2: String, // a printed pattern
+    witness_3: String, // a printed pattern
     remainder: usize,
 }
 
-impl<'tcx> Uncovered<'tcx> {
-    pub fn new<'p>(
+impl Uncovered {
+    pub fn new<'p, 'tcx>(
         span: Span,
         cx: &RustcPatCtxt<'p, 'tcx>,
         witnesses: Vec>,
@@ -27,19 +26,19 @@ impl<'tcx> Uncovered<'tcx> {
     where
         'tcx: 'p,
     {
-        let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap());
+        let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap()).to_string();
         Self {
             span,
             count: witnesses.len(),
             // Substitute dummy values if witnesses is smaller than 3. These will never be read.
             witness_2: witnesses
                 .get(1)
-                .map(|w| cx.hoist_witness_pat(w))
-                .unwrap_or_else(|| witness_1.clone()),
+                .map(|w| cx.hoist_witness_pat(w).to_string())
+                .unwrap_or_default(),
             witness_3: witnesses
                 .get(2)
-                .map(|w| cx.hoist_witness_pat(w))
-                .unwrap_or_else(|| witness_1.clone()),
+                .map(|w| cx.hoist_witness_pat(w).to_string())
+                .unwrap_or_default(),
             witness_1,
             remainder: witnesses.len().saturating_sub(3),
         }
@@ -49,19 +48,19 @@ impl<'tcx> Uncovered<'tcx> {
 #[derive(LintDiagnostic)]
 #[diag(pattern_analysis_overlapping_range_endpoints)]
 #[note]
-pub struct OverlappingRangeEndpoints<'tcx> {
+pub struct OverlappingRangeEndpoints {
     #[label]
     pub range: Span,
     #[subdiagnostic]
-    pub overlap: Vec>,
+    pub overlap: Vec,
 }
 
-pub struct Overlap<'tcx> {
+pub struct Overlap {
     pub span: Span,
-    pub range: Pat<'tcx>,
+    pub range: String, // a printed pattern
 }
 
-impl<'tcx> Subdiagnostic for Overlap<'tcx> {
+impl Subdiagnostic for Overlap {
     fn add_to_diag_with>(
         self,
         diag: &mut Diag<'_, G>,
@@ -78,38 +77,38 @@ impl<'tcx> Subdiagnostic for Overlap<'tcx> {
 
 #[derive(LintDiagnostic)]
 #[diag(pattern_analysis_excluside_range_missing_max)]
-pub struct ExclusiveRangeMissingMax<'tcx> {
+pub struct ExclusiveRangeMissingMax {
     #[label]
     #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
     /// This is an exclusive range that looks like `lo..max` (i.e. doesn't match `max`).
     pub first_range: Span,
     /// Suggest `lo..=max` instead.
     pub suggestion: String,
-    pub max: Pat<'tcx>,
+    pub max: String, // a printed pattern
 }
 
 #[derive(LintDiagnostic)]
 #[diag(pattern_analysis_excluside_range_missing_gap)]
-pub struct ExclusiveRangeMissingGap<'tcx> {
+pub struct ExclusiveRangeMissingGap {
     #[label]
     #[suggestion(code = "{suggestion}", applicability = "maybe-incorrect")]
     /// This is an exclusive range that looks like `lo..gap` (i.e. doesn't match `gap`).
     pub first_range: Span,
-    pub gap: Pat<'tcx>,
+    pub gap: String, // a printed pattern
     /// Suggest `lo..=gap` instead.
     pub suggestion: String,
     #[subdiagnostic]
     /// All these ranges skipped over `gap` which we think is probably a mistake.
-    pub gap_with: Vec>,
+    pub gap_with: Vec,
 }
 
-pub struct GappedRange<'tcx> {
+pub struct GappedRange {
     pub span: Span,
-    pub gap: Pat<'tcx>,
-    pub first_range: Pat<'tcx>,
+    pub gap: String,         // a printed pattern
+    pub first_range: String, // a printed pattern
 }
 
-impl<'tcx> Subdiagnostic for GappedRange<'tcx> {
+impl Subdiagnostic for GappedRange {
     fn add_to_diag_with>(
         self,
         diag: &mut Diag<'_, G>,
@@ -134,7 +133,7 @@ impl<'tcx> Subdiagnostic for GappedRange<'tcx> {
 pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
     pub scrut_ty: Ty<'tcx>,
     #[subdiagnostic]
-    pub uncovered: Uncovered<'tcx>,
+    pub uncovered: Uncovered,
 }
 
 #[derive(LintDiagnostic)]
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 910dd4c6c1a84..ceddafa2f4ceb 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -966,7 +966,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
         let overlaps: Vec<_> = overlaps_with
             .iter()
             .map(|pat| pat.data().span)
-            .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
+            .map(|span| errors::Overlap { range: overlap_as_pat.to_string(), span })
             .collect();
         let pat_span = pat.data().span;
         self.tcx.emit_node_span_lint(
@@ -1014,7 +1014,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
                     // Point at this range.
                     first_range: thir_pat.span,
                     // That's the gap that isn't covered.
-                    max: gap_as_pat.clone(),
+                    max: gap_as_pat.to_string(),
                     // Suggest `lo..=max` instead.
                     suggestion: suggested_range.to_string(),
                 },
@@ -1028,7 +1028,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
                     // Point at this range.
                     first_range: thir_pat.span,
                     // That's the gap that isn't covered.
-                    gap: gap_as_pat.clone(),
+                    gap: gap_as_pat.to_string(),
                     // Suggest `lo..=gap` instead.
                     suggestion: suggested_range.to_string(),
                     // All these ranges skipped over `gap` which we think is probably a
@@ -1037,8 +1037,8 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
                         .iter()
                         .map(|pat| errors::GappedRange {
                             span: pat.data().span,
-                            gap: gap_as_pat.clone(),
-                            first_range: thir_pat.clone(),
+                            gap: gap_as_pat.to_string(),
+                            first_range: thir_pat.to_string(),
                         })
                         .collect(),
                 },

From 649b4310a3f0913a72e6a83cb54482d994ed248a Mon Sep 17 00:00:00 2001
From: Jiahao XU 
Date: Sun, 28 Jul 2024 22:20:01 +1000
Subject: [PATCH 184/489] Enable `std::io::copy` specialisation for
 `std::pipe::{PipeReader, PipeWriter}`

Signed-off-by: Jiahao XU 
---
 library/std/src/sys/pal/unix/kernel_copy.rs | 25 +++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/library/std/src/sys/pal/unix/kernel_copy.rs b/library/std/src/sys/pal/unix/kernel_copy.rs
index cd38b7c07e2b1..ae6b88b447532 100644
--- a/library/std/src/sys/pal/unix/kernel_copy.rs
+++ b/library/std/src/sys/pal/unix/kernel_copy.rs
@@ -54,6 +54,7 @@ use crate::net::TcpStream;
 use crate::os::unix::fs::FileTypeExt;
 use crate::os::unix::io::{AsRawFd, FromRawFd, RawFd};
 use crate::os::unix::net::UnixStream;
+use crate::pipe::{PipeReader, PipeWriter};
 use crate::process::{ChildStderr, ChildStdin, ChildStdout};
 use crate::ptr;
 use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
@@ -404,6 +405,30 @@ impl CopyWrite for &UnixStream {
     }
 }
 
+impl CopyRead for PipeReader {
+    fn properties(&self) -> CopyParams {
+        CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyRead for &PipeReader {
+    fn properties(&self) -> CopyParams {
+        CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyWrite for PipeWriter {
+    fn properties(&self) -> CopyParams {
+        CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyWrite for &PipeWriter {
+    fn properties(&self) -> CopyParams {
+        CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
+    }
+}
+
 impl CopyWrite for ChildStdin {
     fn properties(&self) -> CopyParams {
         CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))

From 571f7b658964e5781546e8ea4a2d1466e8b0a611 Mon Sep 17 00:00:00 2001
From: Folkert 
Date: Sun, 28 Jul 2024 15:11:14 +0200
Subject: [PATCH 185/489] improve error message when global asm uses inline asm
 operands

---
 compiler/rustc_builtin_macros/messages.ftl  |  3 ++
 compiler/rustc_builtin_macros/src/asm.rs    | 39 +++++++++++++++-----
 compiler/rustc_builtin_macros/src/errors.rs |  9 +++++
 tests/ui/asm/parse-error.rs                 | 15 ++++++--
 tests/ui/asm/parse-error.stderr             | 40 ++++++++++++++++++---
 5 files changed, 91 insertions(+), 15 deletions(-)

diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index a30ab236213a0..2d9f6b974d2b8 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -199,6 +199,9 @@ builtin_macros_format_use_positional = consider using a positional formatting ar
 
 builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
 
+builtin_macros_global_asm_unsupported_operand = the `{$symbol}` operand cannot be used with `global_asm!`
+    .label = the `{$symbol}` operand is not meaningful for global-scoped inline assembly, remove it
+
 builtin_macros_global_asm_unsupported_option = the `{$symbol}` option cannot be used with `global_asm!`
     .label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
     .suggestion = remove this option
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 62e59f1f4d477..7a5cabfce6ad1 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -29,6 +29,29 @@ pub struct AsmArgs {
     pub options_spans: Vec,
 }
 
+/// Used for better error messages when operand types are used that are not
+/// supported by the current macro (e.g. `in` or `out` for `global_asm!`)
+///
+/// returns
+///
+/// - `Ok(true)` if the current token matches the keyword, and was expected
+/// - `Ok(false)` if the current token does not match the keyword
+/// - `Err(_)` if the current token matches the keyword, but was not expected
+fn eat_operand_keyword<'a>(p: &mut Parser<'a>, symbol: Symbol, expect: bool) -> PResult<'a, bool> {
+    if expect {
+        Ok(p.eat_keyword(symbol))
+    } else {
+        let span = p.token.span;
+        if p.eat_keyword_noexpect(symbol) {
+            // in gets printed as `r#in` otherwise
+            let symbol = if symbol == kw::In { "in" } else { symbol.as_str() };
+            Err(p.dcx().create_err(errors::GlobalAsmUnsupportedOperand { span, symbol }))
+        } else {
+            Ok(false)
+        }
+    }
+}
+
 fn parse_args<'a>(
     ecx: &ExtCtxt<'a>,
     sp: Span,
@@ -106,7 +129,7 @@ pub fn parse_asm_args<'a>(
         };
 
         let mut explicit_reg = false;
-        let op = if !is_global_asm && p.eat_keyword(kw::In) {
+        let op = if eat_operand_keyword(p, kw::In, !is_global_asm)? {
             let reg = parse_reg(p, &mut explicit_reg)?;
             if p.eat_keyword(kw::Underscore) {
                 let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
@@ -114,15 +137,15 @@ pub fn parse_asm_args<'a>(
             }
             let expr = p.parse_expr()?;
             ast::InlineAsmOperand::In { reg, expr }
-        } else if !is_global_asm && p.eat_keyword(sym::out) {
+        } else if eat_operand_keyword(p, sym::out, !is_global_asm)? {
             let reg = parse_reg(p, &mut explicit_reg)?;
             let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) };
             ast::InlineAsmOperand::Out { reg, expr, late: false }
-        } else if !is_global_asm && p.eat_keyword(sym::lateout) {
+        } else if eat_operand_keyword(p, sym::lateout, !is_global_asm)? {
             let reg = parse_reg(p, &mut explicit_reg)?;
             let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) };
             ast::InlineAsmOperand::Out { reg, expr, late: true }
-        } else if !is_global_asm && p.eat_keyword(sym::inout) {
+        } else if eat_operand_keyword(p, sym::inout, !is_global_asm)? {
             let reg = parse_reg(p, &mut explicit_reg)?;
             if p.eat_keyword(kw::Underscore) {
                 let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
@@ -136,7 +159,7 @@ pub fn parse_asm_args<'a>(
             } else {
                 ast::InlineAsmOperand::InOut { reg, expr, late: false }
             }
-        } else if !is_global_asm && p.eat_keyword(sym::inlateout) {
+        } else if eat_operand_keyword(p, sym::inlateout, !is_global_asm)? {
             let reg = parse_reg(p, &mut explicit_reg)?;
             if p.eat_keyword(kw::Underscore) {
                 let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
@@ -150,6 +173,9 @@ pub fn parse_asm_args<'a>(
             } else {
                 ast::InlineAsmOperand::InOut { reg, expr, late: true }
             }
+        } else if eat_operand_keyword(p, sym::label, !is_global_asm)? {
+            let block = p.parse_block()?;
+            ast::InlineAsmOperand::Label { block }
         } else if p.eat_keyword(kw::Const) {
             let anon_const = p.parse_expr_anon_const()?;
             ast::InlineAsmOperand::Const { anon_const }
@@ -165,9 +191,6 @@ pub fn parse_asm_args<'a>(
                 path: path.clone(),
             };
             ast::InlineAsmOperand::Sym { sym }
-        } else if !is_global_asm && p.eat_keyword(sym::label) {
-            let block = p.parse_block()?;
-            ast::InlineAsmOperand::Label { block }
         } else if allow_templates {
             let template = p.parse_expr()?;
             // If it can't possibly expand to a string, provide diagnostics here to include other
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index f17819474adcd..1c5d98a08970c 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -856,6 +856,15 @@ pub(crate) struct GlobalAsmUnsupportedOption {
     pub(crate) full_span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(builtin_macros_global_asm_unsupported_operand)]
+pub(crate) struct GlobalAsmUnsupportedOperand<'a> {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    pub(crate) symbol: &'a str,
+}
+
 #[derive(Diagnostic)]
 #[diag(builtin_macros_test_runner_invalid)]
 pub(crate) struct TestRunnerInvalid {
diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs
index 9dec3a1c394ef..16ae02828642d 100644
--- a/tests/ui/asm/parse-error.rs
+++ b/tests/ui/asm/parse-error.rs
@@ -146,5 +146,16 @@ global_asm!(format!("{{{}}}", 0), const FOO);
 //~^ ERROR asm template must be a string literal
 global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
 //~^ ERROR asm template must be a string literal
-global_asm!("{}", label {});
-//~^ ERROR expected operand, options, or additional template string
+
+global_asm!("{}", in(reg));
+//~^ ERROR the `in` operand cannot be used with `global_asm!`
+global_asm!("{}", out(reg));
+//~^ ERROR the `out` operand cannot be used with `global_asm!`
+global_asm!("{}", lateout(reg));
+//~^ ERROR the `lateout` operand cannot be used with `global_asm!`
+global_asm!("{}", inout(reg));
+//~^ ERROR the `inout` operand cannot be used with `global_asm!`
+global_asm!("{}", inlateout(reg));
+//~^ ERROR the `inlateout` operand cannot be used with `global_asm!`
+global_asm!("{}", label(reg));
+//~^ ERROR the `label` operand cannot be used with `global_asm!`
diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr
index e9ecd712bc367..f5f8d537d86b8 100644
--- a/tests/ui/asm/parse-error.stderr
+++ b/tests/ui/asm/parse-error.stderr
@@ -380,11 +380,41 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
    |
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: expected operand, options, or additional template string
-  --> $DIR/parse-error.rs:149:19
+error: the `in` operand cannot be used with `global_asm!`
+  --> $DIR/parse-error.rs:150:19
+   |
+LL | global_asm!("{}", in(reg));
+   |                   ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `out` operand cannot be used with `global_asm!`
+  --> $DIR/parse-error.rs:152:19
+   |
+LL | global_asm!("{}", out(reg));
+   |                   ^^^ the `out` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `lateout` operand cannot be used with `global_asm!`
+  --> $DIR/parse-error.rs:154:19
+   |
+LL | global_asm!("{}", lateout(reg));
+   |                   ^^^^^^^ the `lateout` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `inout` operand cannot be used with `global_asm!`
+  --> $DIR/parse-error.rs:156:19
+   |
+LL | global_asm!("{}", inout(reg));
+   |                   ^^^^^ the `inout` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `inlateout` operand cannot be used with `global_asm!`
+  --> $DIR/parse-error.rs:158:19
+   |
+LL | global_asm!("{}", inlateout(reg));
+   |                   ^^^^^^^^^ the `inlateout` operand is not meaningful for global-scoped inline assembly, remove it
+
+error: the `label` operand cannot be used with `global_asm!`
+  --> $DIR/parse-error.rs:160:19
    |
-LL | global_asm!("{}", label {});
-   |                   ^^^^^^^^ expected operand, options, or additional template string
+LL | global_asm!("{}", label(reg));
+   |                   ^^^^^ the `label` operand is not meaningful for global-scoped inline assembly, remove it
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/parse-error.rs:39:37
@@ -441,6 +471,6 @@ help: consider using `const` instead of `let`
 LL |     const bar: /* Type */ = 0;
    |     ~~~~~    ++++++++++++
 
-error: aborting due to 67 previous errors
+error: aborting due to 72 previous errors
 
 For more information about this error, try `rustc --explain E0435`.

From c16061a237e85a5b2581eae5f8f875096ead3624 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= 
Date: Sun, 28 Jul 2024 17:19:12 +0300
Subject: [PATCH 186/489] Preparing for merge from rust-lang/rust

---
 src/tools/rust-analyzer/rust-version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index 18e32e5c65b04..001b900b207e3 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-a91f7d72f12efcc00ecf71591f066c534d45ddf7
+1b51d80027919563004918eaadfa0d890ac0eb93

From 9b165a16009980545a864eb5899c3b3279f58f37 Mon Sep 17 00:00:00 2001
From: Ken Micklas 
Date: Sun, 28 Jul 2024 15:03:07 +0100
Subject: [PATCH 187/489] Implement cursors for `BTreeSet`

---
 library/alloc/src/collections/btree/set.rs | 427 ++++++++++++++++++++-
 1 file changed, 426 insertions(+), 1 deletion(-)

diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index b0bd6ef2d3c63..6f23d686bcf8e 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -2,11 +2,12 @@ use crate::vec::Vec;
 use core::borrow::Borrow;
 use core::cmp::Ordering::{self, Equal, Greater, Less};
 use core::cmp::{max, min};
+use core::error::Error;
 use core::fmt::{self, Debug};
 use core::hash::{Hash, Hasher};
 use core::iter::{FusedIterator, Peekable};
 use core::mem::ManuallyDrop;
-use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub};
+use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub};
 
 use super::map::{BTreeMap, Keys};
 use super::merge_iter::MergeIterInner;
@@ -1183,6 +1184,178 @@ impl BTreeSet {
     pub const fn is_empty(&self) -> bool {
         self.len() == 0
     }
+
+    /// Returns a [`Cursor`] pointing at the gap before the smallest element
+    /// greater than the given bound.
+    ///
+    /// Passing `Bound::Included(x)` will return a cursor pointing to the
+    /// gap before the smallest element greater than or equal to `x`.
+    ///
+    /// Passing `Bound::Excluded(x)` will return a cursor pointing to the
+    /// gap before the smallest element greater than `x`.
+    ///
+    /// Passing `Bound::Unbounded` will return a cursor pointing to the
+    /// gap before the smallest element in the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_cursors)]
+    ///
+    /// use std::collections::BTreeSet;
+    /// use std::ops::Bound;
+    ///
+    /// let set = BTreeSet::from([1, 2, 3, 4]);
+    ///
+    /// let cursor = set.lower_bound(Bound::Included(&2));
+    /// assert_eq!(cursor.peek_prev(), Some(&1));
+    /// assert_eq!(cursor.peek_next(), Some(&2));
+    ///
+    /// let cursor = set.lower_bound(Bound::Excluded(&2));
+    /// assert_eq!(cursor.peek_prev(), Some(&2));
+    /// assert_eq!(cursor.peek_next(), Some(&3));
+    ///
+    /// let cursor = set.lower_bound(Bound::Unbounded);
+    /// assert_eq!(cursor.peek_prev(), None);
+    /// assert_eq!(cursor.peek_next(), Some(&1));
+    /// ```
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn lower_bound(&self, bound: Bound<&Q>) -> Cursor<'_, T>
+    where
+        T: Borrow + Ord,
+        Q: Ord,
+    {
+        Cursor { inner: self.map.lower_bound(bound) }
+    }
+
+    /// Returns a [`CursorMut`] pointing at the gap before the smallest element
+    /// greater than the given bound.
+    ///
+    /// Passing `Bound::Included(x)` will return a cursor pointing to the
+    /// gap before the smallest element greater than or equal to `x`.
+    ///
+    /// Passing `Bound::Excluded(x)` will return a cursor pointing to the
+    /// gap before the smallest element greater than `x`.
+    ///
+    /// Passing `Bound::Unbounded` will return a cursor pointing to the
+    /// gap before the smallest element in the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_cursors)]
+    ///
+    /// use std::collections::BTreeSet;
+    /// use std::ops::Bound;
+    ///
+    /// let mut set = BTreeSet::from([1, 2, 3, 4]);
+    ///
+    /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Included(&2)) };
+    /// assert_eq!(cursor.peek_prev(), Some(&mut 1));
+    /// assert_eq!(cursor.peek_next(), Some(&mut 2));
+    ///
+    /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Excluded(&2)) };
+    /// assert_eq!(cursor.peek_prev(), Some(&mut 2));
+    /// assert_eq!(cursor.peek_next(), Some(&mut 3));
+    ///
+    /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Unbounded) };
+    /// assert_eq!(cursor.peek_prev(), None);
+    /// assert_eq!(cursor.peek_next(), Some(&mut 1));
+    /// ```
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub unsafe fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A>
+    where
+        T: Borrow + Ord,
+        Q: Ord,
+    {
+        CursorMut { inner: unsafe { self.map.lower_bound_mut(bound).with_mutable_key() } }
+    }
+
+    /// Returns a [`Cursor`] pointing at the gap after the greatest element
+    /// smaller than the given bound.
+    ///
+    /// Passing `Bound::Included(x)` will return a cursor pointing to the
+    /// gap after the greatest element smaller than or equal to `x`.
+    ///
+    /// Passing `Bound::Excluded(x)` will return a cursor pointing to the
+    /// gap after the greatest element smaller than `x`.
+    ///
+    /// Passing `Bound::Unbounded` will return a cursor pointing to the
+    /// gap after the greatest element in the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_cursors)]
+    ///
+    /// use std::collections::BTreeSet;
+    /// use std::ops::Bound;
+    ///
+    /// let set = BTreeSet::from([1, 2, 3, 4]);
+    ///
+    /// let cursor = set.upper_bound(Bound::Included(&3));
+    /// assert_eq!(cursor.peek_prev(), Some(&3));
+    /// assert_eq!(cursor.peek_next(), Some(&4));
+    ///
+    /// let cursor = set.upper_bound(Bound::Excluded(&3));
+    /// assert_eq!(cursor.peek_prev(), Some(&2));
+    /// assert_eq!(cursor.peek_next(), Some(&3));
+    ///
+    /// let cursor = set.upper_bound(Bound::Unbounded);
+    /// assert_eq!(cursor.peek_prev(), Some(&4));
+    /// assert_eq!(cursor.peek_next(), None);
+    /// ```
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn upper_bound(&self, bound: Bound<&Q>) -> Cursor<'_, T>
+    where
+        T: Borrow + Ord,
+        Q: Ord,
+    {
+        Cursor { inner: self.map.upper_bound(bound) }
+    }
+
+    /// Returns a [`CursorMut`] pointing at the gap after the greatest element
+    /// smaller than the given bound.
+    ///
+    /// Passing `Bound::Included(x)` will return a cursor pointing to the
+    /// gap after the greatest element smaller than or equal to `x`.
+    ///
+    /// Passing `Bound::Excluded(x)` will return a cursor pointing to the
+    /// gap after the greatest element smaller than `x`.
+    ///
+    /// Passing `Bound::Unbounded` will return a cursor pointing to the
+    /// gap after the greatest element in the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(btree_cursors)]
+    ///
+    /// use std::collections::BTreeSet;
+    /// use std::ops::Bound;
+    ///
+    /// let mut set = BTreeSet::from([1, 2, 3, 4]);
+    ///
+    /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) };
+    /// assert_eq!(cursor.peek_prev(), Some(&mut 3));
+    /// assert_eq!(cursor.peek_next(), Some(&mut 4));
+    ///
+    /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) };
+    /// assert_eq!(cursor.peek_prev(), Some(&mut 2));
+    /// assert_eq!(cursor.peek_next(), Some(&mut 3));
+    ///
+    /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) };
+    /// assert_eq!(cursor.peek_prev(), Some(&mut 4));
+    /// assert_eq!(cursor.peek_next(), None);
+    /// ```
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub unsafe fn upper_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A>
+    where
+        T: Borrow + Ord,
+        Q: Ord,
+    {
+        CursorMut { inner: unsafe { self.map.upper_bound_mut(bound).with_mutable_key() } }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1817,5 +1990,257 @@ impl<'a, T: Ord> Iterator for Union<'a, T> {
 #[stable(feature = "fused", since = "1.26.0")]
 impl FusedIterator for Union<'_, T> {}
 
+/// A cursor over a `BTreeSet`.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth.
+///
+/// Cursors always point to a gap between two elements in the set, and can
+/// operate on the two immediately adjacent elements.
+///
+/// A `Cursor` is created with the [`BTreeSet::lower_bound`] and [`BTreeSet::upper_bound`] methods.
+#[derive(Clone)]
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub struct Cursor<'a, K: 'a> {
+    inner: super::map::Cursor<'a, K, SetValZST>,
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl Debug for Cursor<'_, K> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("Cursor")
+    }
+}
+
+/// A cursor over a `BTreeSet` with editing operations, and which allows
+/// mutating elements.
+///
+/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can
+/// safely mutate the set during iteration. This is because the lifetime of its yielded
+/// references is tied to its own lifetime, instead of just the underlying set. This means
+/// cursors cannot yield multiple elements at once.
+///
+/// Cursors always point to a gap between two elements in the set, and can
+/// operate on the two immediately adjacent elements.
+///
+/// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and
+/// [`BTreeSet::upper_bound_mut`] methods.
+///
+/// # Safety
+///
+/// Since this cursor allows mutating elements, you must ensure that the
+/// `BTreeSet` invariants are maintained. Specifically:
+///
+/// * The newly inserted element must be unique in the tree.
+/// * All elements in the tree must remain in sorted order.
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global>
+{
+    inner: super::map::CursorMutKey<'a, K, SetValZST, A>,
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl Debug for CursorMut<'_, K, A> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str("CursorMut")
+    }
+}
+
+impl<'a, K> Cursor<'a, K> {
+    /// Advances the cursor to the next gap, returning the element that it
+    /// moved over.
+    ///
+    /// If the cursor is already at the end of the set then `None` is returned
+    /// and the cursor is not moved.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn next(&mut self) -> Option<&'a K> {
+        self.inner.next().map(|(k, _)| k)
+    }
+
+    /// Advances the cursor to the previous gap, returning the element that it
+    /// moved over.
+    ///
+    /// If the cursor is already at the start of the set then `None` is returned
+    /// and the cursor is not moved.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn prev(&mut self) -> Option<&'a K> {
+        self.inner.prev().map(|(k, _)| k)
+    }
+
+    /// Returns a reference to next element without moving the cursor.
+    ///
+    /// If the cursor is at the end of the set then `None` is returned
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn peek_next(&self) -> Option<&'a K> {
+        self.inner.peek_next().map(|(k, _)| k)
+    }
+
+    /// Returns a reference to the previous element without moving the cursor.
+    ///
+    /// If the cursor is at the start of the set then `None` is returned.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn peek_prev(&self) -> Option<&'a K> {
+        self.inner.peek_prev().map(|(k, _)| k)
+    }
+}
+
+impl<'a, T, A> CursorMut<'a, T, A> {
+    /// Advances the cursor to the next gap, returning the element that it
+    /// moved over.
+    ///
+    /// If the cursor is already at the end of the set then `None` is returned
+    /// and the cursor is not moved.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn next(&mut self) -> Option<&mut T> {
+        self.inner.next().map(|(k, _)| k)
+    }
+
+    /// Advances the cursor to the previous gap, returning the element that it
+    /// moved over.
+    ///
+    /// If the cursor is already at the start of the set then `None` is returned
+    /// and the cursor is not moved.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn prev(&mut self) -> Option<&mut T> {
+        self.inner.prev().map(|(k, _)| k)
+    }
+
+    /// Returns a reference to the next element without moving the cursor.
+    ///
+    /// If the cursor is at the end of the set then `None` is returned.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn peek_next(&mut self) -> Option<&mut T> {
+        self.inner.peek_next().map(|(k, _)| k)
+    }
+
+    /// Returns a reference to the previous element without moving the cursor.
+    ///
+    /// If the cursor is at the start of the set then `None` is returned.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn peek_prev(&mut self) -> Option<&mut T> {
+        self.inner.peek_prev().map(|(k, _)| k)
+    }
+
+    /// Returns a read-only cursor pointing to the same location as the
+    /// `CursorMut`.
+    ///
+    /// The lifetime of the returned `Cursor` is bound to that of the
+    /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the
+    /// `CursorMut` is frozen for the lifetime of the `Cursor`.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn as_cursor(&self) -> Cursor<'_, T> {
+        Cursor { inner: self.inner.as_cursor() }
+    }
+}
+
+impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> {
+    /// Inserts a new element into the set in the gap that the
+    /// cursor is currently pointing to.
+    ///
+    /// After the insertion the cursor will be pointing at the gap before the
+    /// newly inserted element.
+    ///
+    /// # Safety
+    ///
+    /// You must ensure that the `BTreeSet` invariants are maintained.
+    /// Specifically:
+    ///
+    /// * The newly inserted element must be unique in the tree.
+    /// * All elements in the tree must remain in sorted order.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub unsafe fn insert_after_unchecked(&mut self, value: T) {
+        unsafe { self.inner.insert_after_unchecked(value, SetValZST) }
+    }
+
+    /// Inserts a new element into the set in the gap that the
+    /// cursor is currently pointing to.
+    ///
+    /// After the insertion the cursor will be pointing at the gap after the
+    /// newly inserted element.
+    ///
+    /// # Safety
+    ///
+    /// You must ensure that the `BTreeSet` invariants are maintained.
+    /// Specifically:
+    ///
+    /// * The newly inserted element must be unique in the tree.
+    /// * All elements in the tree must remain in sorted order.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub unsafe fn insert_before_unchecked(&mut self, value: T) {
+        unsafe { self.inner.insert_before_unchecked(value, SetValZST) }
+    }
+
+    /// Inserts a new element into the set in the gap that the
+    /// cursor is currently pointing to.
+    ///
+    /// After the insertion the cursor will be pointing at the gap before the
+    /// newly inserted element.
+    ///
+    /// If the inserted element is not greater than the element before the
+    /// cursor (if any), or if it not less than the element after the cursor (if
+    /// any), then an [`UnorderedError`] is returned since this would
+    /// invalidate the [`Ord`] invariant between the elements of the set.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedError> {
+        self.inner.insert_after(value, SetValZST).map_err(UnorderedError::from_map_error)
+    }
+
+    /// Inserts a new element into the set in the gap that the
+    /// cursor is currently pointing to.
+    ///
+    /// After the insertion the cursor will be pointing at the gap after the
+    /// newly inserted element.
+    ///
+    /// If the inserted element is not greater than the element before the
+    /// cursor (if any), or if it not less than the element after the cursor (if
+    /// any), then an [`UnorderedError`] is returned since this would
+    /// invalidate the [`Ord`] invariant between the elements of the set.
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedError> {
+        self.inner.insert_before(value, SetValZST).map_err(UnorderedError::from_map_error)
+    }
+
+    /// Removes the next element from the `BTreeSet`.
+    ///
+    /// The element that was removed is returned. The cursor position is
+    /// unchanged (before the removed element).
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn remove_next(&mut self) -> Option {
+        self.inner.remove_next().map(|(k, _)| k)
+    }
+
+    /// Removes the precending element from the `BTreeSet`.
+    ///
+    /// The element that was removed is returned. The cursor position is
+    /// unchanged (after the removed element).
+    #[unstable(feature = "btree_cursors", issue = "107540")]
+    pub fn remove_prev(&mut self) -> Option {
+        self.inner.remove_prev().map(|(k, _)| k)
+    }
+}
+
+/// Error type returned by [`CursorMut::insert_before`] and
+/// [`CursorMut::insert_after`] if the element being inserted is not properly
+/// ordered with regards to adjacent elements.
+#[derive(Clone, PartialEq, Eq, Debug)]
+#[unstable(feature = "btree_cursors", issue = "107540")]
+pub struct UnorderedError {}
+
+impl UnorderedError {
+    fn from_map_error(error: super::map::UnorderedKeyError) -> Self {
+        let super::map::UnorderedKeyError {} = error;
+        Self {}
+    }
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl fmt::Display for UnorderedError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "value is not properly ordered relative to neighbors")
+    }
+}
+
+#[unstable(feature = "btree_cursors", issue = "107540")]
+impl Error for UnorderedError {}
+
 #[cfg(test)]
 mod tests;

From 4f78f9fbb05145d437540181fda9bcc83d5a53e4 Mon Sep 17 00:00:00 2001
From: Amanieu d'Antras 
Date: Fri, 26 Jul 2024 19:36:21 +0100
Subject: [PATCH 188/489] Force LLVM to use CMOV for binary search

Since https://reviews.llvm.org/D118118, LLVM will no longer turn CMOVs
into branches if it comes from a `select` marked with an `unpredictable`
metadata attribute.

This PR introduces `core::intrinsics::select_unpredictable` which emits
such a `select` and uses it in the implementation of `binary_search_by`.
---
 compiler/rustc_codegen_llvm/src/builder.rs    | 10 ++++++
 compiler/rustc_codegen_llvm/src/intrinsic.rs  | 31 +++++++++++++++-
 compiler/rustc_codegen_llvm/src/llvm/ffi.rs   |  1 +
 .../rustc_hir_analysis/src/check/intrinsic.rs |  2 ++
 compiler/rustc_span/src/symbol.rs             |  1 +
 library/core/src/intrinsics.rs                | 28 +++++++++++++++
 .../intrinsics/select_unpredictable.rs        | 35 +++++++++++++++++++
 7 files changed, 107 insertions(+), 1 deletion(-)
 create mode 100644 tests/codegen/intrinsics/select_unpredictable.rs

diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 72ff9ea118e28..bcb6260862d4c 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1353,6 +1353,16 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
         }
     }
 
+    pub fn set_unpredictable(&mut self, inst: &'ll Value) {
+        unsafe {
+            llvm::LLVMSetMetadata(
+                inst,
+                llvm::MD_unpredictable as c_uint,
+                llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0),
+            );
+        }
+    }
+
     pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
     }
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 68c3d47e826bf..cd977eb41df46 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -11,7 +11,7 @@ use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
-use rustc_codegen_ssa::mir::place::PlaceRef;
+use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
 use rustc_codegen_ssa::traits::*;
 use rustc_hir as hir;
 use rustc_middle::mir::BinOp;
@@ -203,6 +203,35 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
             sym::unlikely => self
                 .call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]),
+            sym::select_unpredictable => {
+                let cond = args[0].immediate();
+                assert_eq!(args[1].layout, args[2].layout);
+                let select = |bx: &mut Self, true_val, false_val| {
+                    let result = bx.select(cond, true_val, false_val);
+                    bx.set_unpredictable(&result);
+                    result
+                };
+                match (args[1].val, args[2].val) {
+                    (OperandValue::Ref(true_val), OperandValue::Ref(false_val)) => {
+                        assert!(true_val.llextra.is_none());
+                        assert!(false_val.llextra.is_none());
+                        assert_eq!(true_val.align, false_val.align);
+                        let ptr = select(self, true_val.llval, false_val.llval);
+                        let selected =
+                            OperandValue::Ref(PlaceValue::new_sized(ptr, true_val.align));
+                        selected.store(self, result);
+                        return Ok(());
+                    }
+                    (OperandValue::Immediate(_), OperandValue::Immediate(_))
+                    | (OperandValue::Pair(_, _), OperandValue::Pair(_, _)) => {
+                        let true_val = args[1].immediate_or_packed_pair(self);
+                        let false_val = args[2].immediate_or_packed_pair(self);
+                        select(self, true_val, false_val)
+                    }
+                    (OperandValue::ZeroSized, OperandValue::ZeroSized) => return Ok(()),
+                    _ => span_bug!(span, "Incompatible OperandValue for select_unpredictable"),
+                }
+            }
             sym::catch_unwind => {
                 catch_unwind_intrinsic(
                     self,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 3beda28ac1fd4..1e2b0292d36e0 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -428,6 +428,7 @@ pub enum MetadataType {
     MD_nontemporal = 9,
     MD_mem_parallel_loop_access = 10,
     MD_nonnull = 11,
+    MD_unpredictable = 15,
     MD_align = 17,
     MD_type = 19,
     MD_vcall_visibility = 28,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 6282499883ba4..dfe6a2675c361 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -119,6 +119,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
         | sym::type_id
         | sym::likely
         | sym::unlikely
+        | sym::select_unpredictable
         | sym::ptr_guaranteed_cmp
         | sym::minnumf16
         | sym::minnumf32
@@ -487,6 +488,7 @@ pub fn check_intrinsic_type(
             sym::assume => (0, 0, vec![tcx.types.bool], tcx.types.unit),
             sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
             sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool),
+            sym::select_unpredictable => (1, 0, vec![tcx.types.bool, param(0), param(0)], param(0)),
 
             sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
             sym::write_via_move => {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6d58c4877cb8e..99a686133240a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1701,6 +1701,7 @@ symbols! {
         saturating_add,
         saturating_div,
         saturating_sub,
+        select_unpredictable,
         self_in_typedefs,
         self_struct_ctor,
         semitransparent,
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index c4c6388338949..240cc8a21ff79 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1010,6 +1010,34 @@ pub const fn unlikely(b: bool) -> bool {
     b
 }
 
+/// Returns either `true_val` or `false_val` depending on condition `b` with a
+/// hint to the compiler that this condition is unlikely to be correctly
+/// predicted by a CPU's branch predictor (e.g. a binary search).
+///
+/// This is otherwise functionally equivalent to `if b { true_val } else { false_val }`.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// This intrinsic does not have a stable counterpart.
+#[cfg(not(bootstrap))]
+#[unstable(feature = "core_intrinsics", issue = "none")]
+#[rustc_intrinsic]
+#[rustc_nounwind]
+#[miri::intrinsic_fallback_is_spec]
+#[inline]
+pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T {
+    if b { true_val } else { false_val }
+}
+
+#[cfg(bootstrap)]
+#[inline]
+pub fn select_unpredictable(b: bool, true_val: T, false_val: T) -> T {
+    if b { true_val } else { false_val }
+}
+
 extern "rust-intrinsic" {
     /// Executes a breakpoint trap, for inspection by a debugger.
     ///
diff --git a/tests/codegen/intrinsics/select_unpredictable.rs b/tests/codegen/intrinsics/select_unpredictable.rs
new file mode 100644
index 0000000000000..2054838dd7998
--- /dev/null
+++ b/tests/codegen/intrinsics/select_unpredictable.rs
@@ -0,0 +1,35 @@
+//@ compile-flags: -O
+
+#![feature(core_intrinsics)]
+#![crate_type = "lib"]
+
+#[no_mangle]
+pub fn test_int(p: bool, a: u64, b: u64) -> u64 {
+    // CHECK-LABEL: define{{.*}} @test_int
+    // CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable
+    core::intrinsics::select_unpredictable(p, a, b)
+}
+
+#[no_mangle]
+pub fn test_pair(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) {
+    // CHECK-LABEL: define{{.*}} @test_pair
+    // CHECK: select i1 %p, {{.*}}, !unpredictable
+    core::intrinsics::select_unpredictable(p, a, b)
+}
+
+struct Large {
+    e: [u64; 100],
+}
+
+#[no_mangle]
+pub fn test_struct(p: bool, a: Large, b: Large) -> Large {
+    // CHECK-LABEL: define{{.*}} @test_struct
+    // CHECK: select i1 %p, {{.*}}, !unpredictable
+    core::intrinsics::select_unpredictable(p, a, b)
+}
+
+#[no_mangle]
+pub fn test_zst(p: bool, a: (), b: ()) -> () {
+    // CHECK-LABEL: define{{.*}} @test_zst
+    core::intrinsics::select_unpredictable(p, a, b)
+}

From 352707da76a525e19c1822ebd01a9887c1826063 Mon Sep 17 00:00:00 2001
From: Daria Sukhonina 
Date: Sun, 28 Jul 2024 21:07:38 +0300
Subject: [PATCH 189/489] fix: psvita's std code

---
 library/std/src/os/vita/raw.rs                | 37 -------------------
 library/std/src/sys/pal/unix/mod.rs           |  3 ++
 .../sys/pal/unix/process/process_common.rs    |  1 +
 3 files changed, 4 insertions(+), 37 deletions(-)

diff --git a/library/std/src/os/vita/raw.rs b/library/std/src/os/vita/raw.rs
index 74cae4d4135d1..e4b65ef1ed767 100644
--- a/library/std/src/os/vita/raw.rs
+++ b/library/std/src/os/vita/raw.rs
@@ -10,9 +10,6 @@
 )]
 #![allow(deprecated)]
 
-use crate::os::raw::c_long;
-use crate::os::unix::raw::{gid_t, uid_t};
-
 #[stable(feature = "pthread_t", since = "1.8.0")]
 pub type pthread_t = libc::pthread_t;
 
@@ -34,37 +31,3 @@ pub type off_t = libc::off_t;
 
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub type time_t = libc::time_t;
-
-#[repr(C)]
-#[derive(Clone)]
-#[stable(feature = "raw_ext", since = "1.1.0")]
-pub struct stat {
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_dev: dev_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ino: ino_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mode: mode_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_nlink: nlink_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_uid: uid_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_gid: gid_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_rdev: dev_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_size: off_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_atime: time_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mtime: time_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ctime: time_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_blksize: blksize_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_blocks: blkcnt_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_spare4: [c_long; 2usize],
-}
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index bdb995876ff2c..159239b35dc2f 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -165,6 +165,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
             target_os = "fuchsia",
             target_os = "horizon",
             target_os = "vxworks",
+            target_os = "vita",
             // Unikraft's `signal` implementation is currently broken:
             // https://github.com/unikraft/lib-musl/issues/57
             target_vendor = "unikraft",
@@ -211,6 +212,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     target_os = "fuchsia",
     target_os = "horizon",
     target_os = "vxworks",
+    target_os = "vita",
 )))]
 static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool =
     crate::sync::atomic::AtomicBool::new(false);
@@ -221,6 +223,7 @@ static ON_BROKEN_PIPE_FLAG_USED: crate::sync::atomic::AtomicBool =
     target_os = "fuchsia",
     target_os = "horizon",
     target_os = "vxworks",
+    target_os = "vita",
 )))]
 pub(crate) fn on_broken_pipe_flag_used() -> bool {
     ON_BROKEN_PIPE_FLAG_USED.load(crate::sync::atomic::Ordering::Relaxed)
diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/pal/unix/process/process_common.rs
index f615e8086dccf..cf95aa11c8490 100644
--- a/library/std/src/sys/pal/unix/process/process_common.rs
+++ b/library/std/src/sys/pal/unix/process/process_common.rs
@@ -128,6 +128,7 @@ pub struct StdioPipes {
 
 // passed to do_exec() with configuration of what the child stdio should look
 // like
+#[cfg_attr(target_os = "vita", allow(dead_code))]
 pub struct ChildPipes {
     pub stdin: ChildStdio,
     pub stdout: ChildStdio,

From 0a5a84ee3427756c2329fa08905d3b186b58dcd3 Mon Sep 17 00:00:00 2001
From: Daria Sukhonina 
Date: Sun, 28 Jul 2024 21:10:59 +0300
Subject: [PATCH 190/489] Add forbid(unsafe_op_in_unsafe_fn)

---
 library/std/src/os/vita/mod.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/library/std/src/os/vita/mod.rs b/library/std/src/os/vita/mod.rs
index da9edd12f7b03..92a2bf0a59ab5 100644
--- a/library/std/src/os/vita/mod.rs
+++ b/library/std/src/os/vita/mod.rs
@@ -1,5 +1,6 @@
 //! Definitions for vita
 
+#![forbid(unsafe_op_in_unsafe_fn)]
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
 pub mod fs;

From e8644f85b8b44285e3d74dfa64362e58072e4683 Mon Sep 17 00:00:00 2001
From: Mark Rousskov 
Date: Sun, 21 Jul 2024 08:55:06 -0400
Subject: [PATCH 191/489] Update CURRENT_RUSTC_VERSION

---
 compiler/rustc_feature/src/accepted.rs |  4 ++--
 compiler/rustc_feature/src/removed.rs  |  2 +-
 compiler/rustc_feature/src/unstable.rs | 12 ++++++------
 library/core/src/char/methods.rs       |  2 +-
 library/core/src/char/mod.rs           |  2 +-
 library/core/src/error.rs              |  2 +-
 library/core/src/ffi/c_str.rs          |  6 +++---
 library/core/src/hint.rs               |  4 ++--
 library/core/src/panic.rs              |  2 +-
 library/core/src/panic/panic_info.rs   | 10 +++++-----
 library/core/src/sync/atomic.rs        |  2 +-
 library/core/src/time.rs               |  4 ++--
 library/std/src/fs.rs                  |  2 +-
 library/std/src/io/mod.rs              |  8 ++++----
 library/std/src/panic.rs               |  2 +-
 15 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e671c7682391e..f86a65698aa9e 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -85,7 +85,7 @@ declare_features! (
     /// Allows `c"foo"` literals.
     (accepted, c_str_literals, "1.77.0", Some(105723)),
     /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries and treat `extern "C" fn` as nounwind.
-    (accepted, c_unwind, "CURRENT_RUSTC_VERSION", Some(74990)),
+    (accepted, c_unwind, "1.81.0", Some(74990)),
     /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
     (accepted, cfg_attr_multi, "1.33.0", Some(54881)),
     /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
@@ -237,7 +237,7 @@ declare_features! (
     /// Allows `let...else` statements.
     (accepted, let_else, "1.65.0", Some(87335)),
     /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
-    (accepted, lint_reasons, "CURRENT_RUSTC_VERSION", Some(54503)),
+    (accepted, lint_reasons, "1.81.0", Some(54503)),
     /// Allows `break {expr}` with a value inside `loop`s.
     (accepted, loop_break_value, "1.19.0", Some(37339)),
     /// Allows use of `?` as the Kleene "at most one" operator in macros.
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 80a108d2fc87f..67f250a0614af 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -222,7 +222,7 @@ declare_features! (
     (removed, unwind_attributes, "1.56.0", Some(58760), Some("use the C-unwind ABI instead")),
     (removed, visible_private_types, "1.0.0", None, None),
     /// Allows `extern "wasm" fn`
-    (removed, wasm_abi, "CURRENT_RUSTC_VERSION", Some(83788),
+    (removed, wasm_abi, "1.81.0", Some(83788),
      Some("non-standard wasm ABI is no longer supported")),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index d3d071810962b..e4d33c73d80b9 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -518,7 +518,7 @@ declare_features! (
     /// Give access to additional metadata about declarative macro meta-variables.
     (unstable, macro_metavar_expr, "1.61.0", Some(83527)),
     /// Provides a way to concatenate identifiers using metavariable expressions.
-    (unstable, macro_metavar_expr_concat, "CURRENT_RUSTC_VERSION", Some(124225)),
+    (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
     /// Allows `#[marker]` on certain traits allowing overlapping implementations.
     (unstable, marker_trait_attr, "1.30.0", Some(29864)),
     /// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are
@@ -563,11 +563,11 @@ declare_features! (
     /// Allows using multiple nested field accesses in offset_of!
     (unstable, offset_of_nested, "1.77.0", Some(120140)),
     /// Allows using fields with slice type in offset_of!
-    (unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)),
+    (unstable, offset_of_slice, "1.81.0", Some(126151)),
     /// Allows using `#[optimize(X)]`.
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
     /// Allows specifying nop padding on functions for dynamic patching.
-    (unstable, patchable_function_entry, "CURRENT_RUSTC_VERSION", Some(123115)),
+    (unstable, patchable_function_entry, "1.81.0", Some(123115)),
     /// Allows postfix match `expr.match { ... }`
     (unstable, postfix_match, "1.79.0", Some(121618)),
     /// Allows `use<'a, 'b, A, B>` in `impl Trait + use<...>` for precise capture of generic args.
@@ -579,7 +579,7 @@ declare_features! (
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024.
     (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)),
     /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant
-    (incomplete, ref_pat_eat_one_layer_2024_structural, "CURRENT_RUSTC_VERSION", Some(123076)),
+    (incomplete, ref_pat_eat_one_layer_2024_structural, "1.81.0", Some(123076)),
     /// Allows using the `#[register_tool]` attribute.
     (unstable, register_tool, "1.41.0", Some(66079)),
     /// Allows the `#[repr(i128)]` attribute for enums.
@@ -645,9 +645,9 @@ declare_features! (
     /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
     (unstable, used_with_arg, "1.60.0", Some(93798)),
     /// Allows use of x86 `AMX` target-feature attributes and intrinsics
-    (unstable, x86_amx_intrinsics, "CURRENT_RUSTC_VERSION", Some(126622)),
+    (unstable, x86_amx_intrinsics, "1.81.0", Some(126622)),
     /// Allows use of the `xop` target-feature
-    (unstable, xop_target_feature, "CURRENT_RUSTC_VERSION", Some(127208)),
+    (unstable, xop_target_feature, "1.81.0", Some(127208)),
     /// Allows `do yeet` expressions
     (unstable, yeet_expr, "1.62.0", Some(96373)),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 4186565c131ed..6b41540683816 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -225,7 +225,7 @@ impl char {
     #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
     #[rustc_const_stable(
         feature = "const_char_from_u32_unchecked",
-        since = "CURRENT_RUSTC_VERSION"
+        since = "1.81.0"
     )]
     #[must_use]
     #[inline]
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 37c27ecb8c4d6..7745041bb21c9 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -126,7 +126,7 @@ pub const fn from_u32(i: u32) -> Option {
 /// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`].
 /// instead.
 #[stable(feature = "char_from_unchecked", since = "1.5.0")]
-#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
 #[must_use]
 #[inline]
 pub const unsafe fn from_u32_unchecked(i: u32) -> char {
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 19b7bb44f855a..5bc2195631a8a 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -1,5 +1,5 @@
 #![doc = include_str!("error.md")]
-#![stable(feature = "error_in_core", since = "CURRENT_RUSTC_VERSION")]
+#![stable(feature = "error_in_core", since = "1.81.0")]
 
 #[cfg(test)]
 mod tests;
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index ae42ae3baf418..2bde9d20ade4f 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -277,7 +277,7 @@ impl CStr {
     #[inline] // inline is necessary for codegen to see strlen.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
     pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
         // SAFETY: The caller has provided a pointer that points to a valid C
         // string with a NUL terminator less than `isize::MAX` from `ptr`.
@@ -539,7 +539,7 @@ impl CStr {
     #[must_use]
     #[doc(alias("len", "strlen"))]
     #[stable(feature = "cstr_count_bytes", since = "1.79.0")]
-    #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
     pub const fn count_bytes(&self) -> usize {
         self.inner.len() - 1
     }
@@ -734,7 +734,7 @@ impl AsRef for CStr {
 /// located within `isize::MAX` from `ptr`.
 #[inline]
 #[unstable(feature = "cstr_internals", issue = "none")]
-#[rustc_const_stable(feature = "const_cstr_from_ptr", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")]
 #[rustc_allow_const_fn_unstable(const_eval_select)]
 const unsafe fn strlen(ptr: *const c_char) -> usize {
     const fn strlen_ct(s: *const c_char) -> usize {
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index b3e36e6fbc4ac..a428906522689 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -195,8 +195,8 @@ pub const unsafe fn unreachable_unchecked() -> ! {
 #[track_caller]
 #[inline(always)]
 #[doc(alias = "assume")]
-#[stable(feature = "hint_assert_unchecked", since = "CURRENT_RUSTC_VERSION")]
-#[rustc_const_stable(feature = "hint_assert_unchecked", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "hint_assert_unchecked", since = "1.81.0")]
+#[rustc_const_stable(feature = "hint_assert_unchecked", since = "1.81.0")]
 pub const unsafe fn assert_unchecked(cond: bool) {
     // SAFETY: The caller promised `cond` is true.
     unsafe {
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 37c338dd9b778..45c2d9c66b980 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -12,7 +12,7 @@ use crate::any::Any;
 pub use self::location::Location;
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 pub use self::panic_info::PanicInfo;
-#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_info_message", since = "1.81.0")]
 pub use self::panic_info::PanicMessage;
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 pub use self::unwind_safe::{AssertUnwindSafe, RefUnwindSafe, UnwindSafe};
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index 6bbb9c3017110..00e874e692241 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -24,7 +24,7 @@ pub struct PanicInfo<'a> {
 /// that were given to the `panic!()` macro.
 ///
 /// See [`PanicInfo::message`].
-#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_info_message", since = "1.81.0")]
 pub struct PanicMessage<'a> {
     message: fmt::Arguments<'a>,
 }
@@ -57,7 +57,7 @@ impl<'a> PanicInfo<'a> {
     /// }
     /// ```
     #[must_use]
-    #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "panic_info_message", since = "1.81.0")]
     pub fn message(&self) -> PanicMessage<'_> {
         PanicMessage { message: self.message }
     }
@@ -164,7 +164,7 @@ impl<'a> PanicMessage<'a> {
     /// For most cases with placeholders, this function will return `None`.
     ///
     /// See [`fmt::Arguments::as_str`] for details.
-    #[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "panic_info_message", since = "1.81.0")]
     #[rustc_const_unstable(feature = "const_arguments_as_str", issue = "103900")]
     #[must_use]
     #[inline]
@@ -173,7 +173,7 @@ impl<'a> PanicMessage<'a> {
     }
 }
 
-#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_info_message", since = "1.81.0")]
 impl Display for PanicMessage<'_> {
     #[inline]
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -181,7 +181,7 @@ impl Display for PanicMessage<'_> {
     }
 }
 
-#[stable(feature = "panic_info_message", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_info_message", since = "1.81.0")]
 impl fmt::Debug for PanicMessage<'_> {
     #[inline]
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index efc07f38f68e0..37050a74c67ab 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1080,7 +1080,7 @@ impl AtomicBool {
     /// assert_eq!(foo.load(Ordering::SeqCst), true);
     /// ```
     #[inline]
-    #[stable(feature = "atomic_bool_fetch_not", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "atomic_bool_fetch_not", since = "1.81.0")]
     #[cfg(target_has_atomic = "8")]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_not(&self, order: Ordering) -> bool {
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index d66f558078ea8..33d27b219f3ad 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -625,8 +625,8 @@ impl Duration {
     /// assert_eq!(Duration::new(100, 0).abs_diff(Duration::new(80, 0)), Duration::new(20, 0));
     /// assert_eq!(Duration::new(100, 400_000_000).abs_diff(Duration::new(110, 0)), Duration::new(9, 600_000_000));
     /// ```
-    #[stable(feature = "duration_abs_diff", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "duration_abs_diff", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "duration_abs_diff", since = "1.81.0")]
+    #[rustc_const_stable(feature = "duration_abs_diff", since = "1.81.0")]
     #[rustc_allow_const_fn_unstable(const_option)]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 536d0d1b356a9..8f39efdedfb82 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2744,7 +2744,7 @@ impl AsInnerMut for DirBuilder {
 /// ```
 ///
 /// [`Path::exists`]: crate::path::Path::exists
-#[stable(feature = "fs_try_exists", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "fs_try_exists", since = "1.81.0")]
 #[inline]
 pub fn exists>(path: P) -> io::Result {
     fs_imp::exists(path.as_ref())
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 1345a30361e28..8c4f7e690d17c 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1266,7 +1266,7 @@ impl<'a> IoSliceMut<'a> {
     /// buf.advance(3);
     /// assert_eq!(buf.deref(), [1; 5].as_ref());
     /// ```
-    #[stable(feature = "io_slice_advance", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "io_slice_advance", since = "1.81.0")]
     #[inline]
     pub fn advance(&mut self, n: usize) {
         self.0.advance(n)
@@ -1305,7 +1305,7 @@ impl<'a> IoSliceMut<'a> {
     /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
     /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
     /// ```
-    #[stable(feature = "io_slice_advance", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "io_slice_advance", since = "1.81.0")]
     #[inline]
     pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
         // Number of buffers to remove.
@@ -1406,7 +1406,7 @@ impl<'a> IoSlice<'a> {
     /// buf.advance(3);
     /// assert_eq!(buf.deref(), [1; 5].as_ref());
     /// ```
-    #[stable(feature = "io_slice_advance", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "io_slice_advance", since = "1.81.0")]
     #[inline]
     pub fn advance(&mut self, n: usize) {
         self.0.advance(n)
@@ -1444,7 +1444,7 @@ impl<'a> IoSlice<'a> {
     /// IoSlice::advance_slices(&mut bufs, 10);
     /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
     /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
-    #[stable(feature = "io_slice_advance", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "io_slice_advance", since = "1.81.0")]
     #[inline]
     pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
         // Number of buffers to remove.
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index c5d1a893ee809..e024ac2816aa3 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -39,7 +39,7 @@ pub type PanicInfo<'a> = PanicHookInfo<'a>;
 /// ```
 ///
 /// [`set_hook`]: ../../std/panic/fn.set_hook.html
-#[stable(feature = "panic_hook_info", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "panic_hook_info", since = "1.81.0")]
 #[derive(Debug)]
 pub struct PanicHookInfo<'a> {
     payload: &'a (dyn Any + Send),

From fceb0863d8e5b01fe9c315e5b52e2c7a862dd85e Mon Sep 17 00:00:00 2001
From: Mark Rousskov 
Date: Mon, 22 Jul 2024 22:02:58 -0400
Subject: [PATCH 192/489] Bump stage0 to 1.81 beta

---
 src/stage0 | 870 +++++++++++++++++++++++++++--------------------------
 1 file changed, 442 insertions(+), 428 deletions(-)

diff --git a/src/stage0 b/src/stage0
index f36010fa4b459..41fabb23cbf14 100644
--- a/src/stage0
+++ b/src/stage0
@@ -14,434 +14,448 @@ nightly_branch=master
 # All changes below this comment will be overridden the next time the
 # tool is executed.
             
-compiler_date=2024-06-11
+compiler_date=2024-07-26
 compiler_version=beta
-rustfmt_date=2024-06-11
+rustfmt_date=2024-07-26
 rustfmt_version=nightly
 
-dist/2024-06-11/rustc-beta-x86_64-unknown-freebsd.tar.gz=4bf5a3ae2656a992beedec2f41dc98c791426a1a6a88f3503b003b4d6f0ddc1f
-dist/2024-06-11/rustc-beta-x86_64-unknown-freebsd.tar.xz=feaa1484586e78d77225734328d460277dde14baaf1299a30b30ef91e9a26a82
-dist/2024-06-11/rustc-beta-x86_64-unknown-illumos.tar.gz=9c692a71916f7ca9d41a97416f51d463b0495311491ba92b4d3cdb0f6c4e7c87
-dist/2024-06-11/rustc-beta-x86_64-unknown-illumos.tar.xz=97dece0cc2e4856a49f9ae17f09171fb55f140987acd0f988bbd0aa1e8971936
-dist/2024-06-11/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=6ad2e87e637302e8458d47dc1af923e38bffd7332775cfa5520c29110594d9b9
-dist/2024-06-11/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=84f6755c1377ced8ed2700b5ca9a2d38dd2e26a03e1fd636841ad46d3cf63895
-dist/2024-06-11/rustc-beta-i686-unknown-linux-gnu.tar.gz=11b439045379be2722cb42409b8bc342ff4b5f7df85e42566006cd72bb1a4e8a
-dist/2024-06-11/rustc-beta-i686-unknown-linux-gnu.tar.xz=4e5103702b4e43ea71914e9c508aeb0db6382ea331c31981142163b2a89e19e1
-dist/2024-06-11/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=396a3aaefca9511086f7e5442209b70622082d133b96783b4237c3f01f42bf87
-dist/2024-06-11/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=66e46ed344af9f165b7c4fde2c576340fa81ecade61c45ecc1562de70a9203da
-dist/2024-06-11/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=831420b262c5a2f44459e0daceebe271f298179c37aa5b7a1704a15bbbb1fb97
-dist/2024-06-11/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=691a6c4d0276add72cfab40968520ff48f683d4e660a50d1626ba9564dbf4914
-dist/2024-06-11/rustc-beta-aarch64-unknown-linux-musl.tar.gz=ebe1efe3c5d74e37d1c40dbd585ada7a7e256ce76911746f54994dfa15f9907f
-dist/2024-06-11/rustc-beta-aarch64-unknown-linux-musl.tar.xz=3bb37fcab069713fe8aa5ca72291a439eba5af4a3cc0be9d152e5f29ccaef864
-dist/2024-06-11/rustc-beta-s390x-unknown-linux-gnu.tar.gz=c00c2ecb5aae552069395d03f4135f051da073efc68ed645348f026c1884799b
-dist/2024-06-11/rustc-beta-s390x-unknown-linux-gnu.tar.xz=2c72347688058091a4bcb0c2fbcff49020df2b2c1733bc19d93b6e5149d5b13a
-dist/2024-06-11/rustc-beta-aarch64-pc-windows-msvc.tar.gz=517977edaa51470d460aa9ec09309eea2082cffa6adb13571a8f36efa9351dff
-dist/2024-06-11/rustc-beta-aarch64-pc-windows-msvc.tar.xz=0cc0b740cb267fde814b4971591b5797faa528b1e6250ef7b2d5220f0916208d
-dist/2024-06-11/rustc-beta-x86_64-pc-windows-gnu.tar.gz=9fe7d85fdbca12fbfdb776789c336f726303c8845a6f6c93b2dc6ea8487585d4
-dist/2024-06-11/rustc-beta-x86_64-pc-windows-gnu.tar.xz=38130e3d9779ad54bd890c4001b34b7c58368ed1940e7e676947e9c05a8f6649
-dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=acca3e045de3c0d908caec4249e3905d207d96b4a1722644457b3cbe5707422c
-dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=e4e92fc4b672f72b1f03db62ae712d9f944b982db89cf0d8dcb94adb1d560b3e
-dist/2024-06-11/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=63274e707bd0d2b2f08c49f170f26773f802db833347d2aa694d345d11c841f5
-dist/2024-06-11/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=13702b24228d983710d5678e0a1003e4f77e2244fbdf599015f52adbbb77bfcc
-dist/2024-06-11/rustc-beta-x86_64-pc-windows-msvc.tar.gz=ca877491bf7bf50989b9ac21c12e335fd0ff002ccf4a2c07316ae1df1a3d7e6b
-dist/2024-06-11/rustc-beta-x86_64-pc-windows-msvc.tar.xz=d757a328595887039d8017e9e3faf79448850c3dd9bd3c26d309a313ccc09a38
-dist/2024-06-11/rustc-beta-x86_64-unknown-linux-musl.tar.gz=155497f2abe036f09f6aa014969d58132a9e2e4e148fea485b483e0dc3705a39
-dist/2024-06-11/rustc-beta-x86_64-unknown-linux-musl.tar.xz=6204d1fa08beeadcf1564e334cbb65a7317c571557cbc5517eb6bf08f5b0ce75
-dist/2024-06-11/rustc-beta-aarch64-apple-darwin.tar.gz=3bd7db536344c6a3d0d0bdf95986136d5db8996228802444b561783f2e7c3c9c
-dist/2024-06-11/rustc-beta-aarch64-apple-darwin.tar.xz=b425561b3e7d9130fae94e78522bb262c634304ced32030828743fb332b11ecb
-dist/2024-06-11/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=e2f78198d33f98aa34bedd4f5920868a8f68620e29eca2917833f6a8f23f787c
-dist/2024-06-11/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=22f3b45678081fe52a9c8e89234a9939aad5623eb43ec54921effc28c0bdcd80
-dist/2024-06-11/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=beb5ec95069cbac4e53c51ea3e785ab5f25122132c8b78b196372bb2a31ed46f
-dist/2024-06-11/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=17242f74c96cf581f2e40a82f6d7fbd585af2c2990cc73ad4ba7a3503dd279a3
-dist/2024-06-11/rustc-beta-x86_64-apple-darwin.tar.gz=d952d90397c70c5b53caa98b2e5d48e35780e1e5b342775c10fcbf504717d2ec
-dist/2024-06-11/rustc-beta-x86_64-apple-darwin.tar.xz=14bd4336eb396a133ddbb2acd01ae799f2f68a7ac723a00a9db8c3e06bfa8027
-dist/2024-06-11/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=a2118f80091d62ebb762df0bdd159d19befb440d754034da7348aae50d63628f
-dist/2024-06-11/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=a4b9d1a04d8f9cfd4daaf57fbeed3615d000c5107c6fa1b2992dad6ca552e35a
-dist/2024-06-11/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=d5c16c5621e43cd3007ba4d2bc0f6e8a3a2376bc2a911e42bd2f2670ff94c12c
-dist/2024-06-11/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=202662492afd863b6b6428a3bc5ed822c62ac2aeb8a0264df1d69cc5a3728d8f
-dist/2024-06-11/rustc-beta-i686-pc-windows-msvc.tar.gz=a9fb64cac53595444bdbe8f152e52214812498e0c6e2b664db10f1f693a92dca
-dist/2024-06-11/rustc-beta-i686-pc-windows-msvc.tar.xz=fe78c5ac51d96c3c3e222828dca3d105a2d4d7f8acd6e0d86ecd4b27ea70a4c3
-dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=8c584010c964ef1b02e1014ca1c6ed9584c1ff781f8af115ee001e3a13213954
-dist/2024-06-11/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=4a407fb59db284ddf6fc0ccd487116fafbcd7c227f3dfd4e0b7b64dd560dc113
-dist/2024-06-11/rustc-beta-x86_64-unknown-netbsd.tar.gz=2f07a283bb0e57ad50366b67d216503a423867eae205e4354b74b748e9d3ce85
-dist/2024-06-11/rustc-beta-x86_64-unknown-netbsd.tar.xz=8008331b32e9d0daeb275327082e38671dcc91864a3ac95be67bd15ecaa852ad
-dist/2024-06-11/rustc-beta-i686-pc-windows-gnu.tar.gz=c42637a8aa8666d746a45c9f47b437a9720d355b5bc6db42c2a90fb03d2c4a26
-dist/2024-06-11/rustc-beta-i686-pc-windows-gnu.tar.xz=eabe3a7e72829e0e5904ef381157cc3da169d9f5942e0367b2d1b1781c387560
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=f4010eea815cbab895c96311a456c4e3aa24c5f0d55f09052bcde59de7f286e6
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=a8f555c713cbe4a1860ee5bc812eb624f2775e034da54bd0e37c325453d70448
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=c89619ed4ec28d4f48ef2f7e51155716483a7f4bb51fe38235e69d4694cfcbe5
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=89aa3d1add14298bd40e3bcbc6b41df91312258ac6f203fff9eca4422f0c5e9f
-dist/2024-06-11/rust-std-beta-x86_64-apple-darwin.tar.gz=2303e7926bcc4fa2c67c7063fcac3a7b581fdd91fb89123cb6cdf514ff38afed
-dist/2024-06-11/rust-std-beta-x86_64-apple-darwin.tar.xz=9ddf392d8c696e902c2924ff938a4bd099b9a54834dc62710e42527e464e776f
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=6016b465a0cfc628f2c978ed18bc19a4a27e20a5ac11a170c40d01a857a5f50a
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=8e3d6f7ef6efead7d08b1c889bcc6e520d0a6d29226ade1b150aeb625fdb9abd
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=5f53b7630fa7703fc6752c3fb8c8eba8e25b9f77a3b91e14982510a0091d9e44
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=8ed3c2f0b0f81d197d0dbd01aa777eb17ebc7303176601be2b2b05ebe1bcc971
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=dbc1a1bb8cfb4472739d7f3a52bcd571357d2d2761f3723aa4c7d69abe9a5dfc
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=58f46f20d58669d497ff683d6ea85e18ff68d51a442f6e21bc20ddee779e1c4f
-dist/2024-06-11/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=d71947b5ddcfe538162b14d6b785c365c34f2b6ac2f1abdc90b020c4a446a313
-dist/2024-06-11/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=ca0a665e566b3ff74c5f552e7e4e030d3cae9080dbb6055dce3aa41206b5b111
-dist/2024-06-11/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=e927c0890d2c5135d86b1960b6b182d5c47853b53eeb196b4748e7b8ec9362e4
-dist/2024-06-11/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=df33672f826ce8681d6c18ec2129ef47623b7cbaf6515cd921d39dfc05cb7a06
-dist/2024-06-11/rust-std-beta-i686-linux-android.tar.gz=2559fdcf250e7e0a1b5589e8f2bc69340f5610b7e6ddf08185936fa2e6f10534
-dist/2024-06-11/rust-std-beta-i686-linux-android.tar.xz=442f0aa53f343eec2b6984934bbf0651ff45f314d1f46dad2aa11a2f5c5a5a5b
-dist/2024-06-11/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=cb657852d05766e1c18b11d99a94f3570b6c6147dbf9b2113b80236566d2d4ac
-dist/2024-06-11/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=943de72c556821b67d59afd9dd128bfb01b3ba743dd3e7561c50559afd3768f4
-dist/2024-06-11/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=a7c6d3f54d925be073007e3737173b0def7d781b6bfd5345971a69300aeee9c3
-dist/2024-06-11/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=cb9115328bf6f5ae661ce5bc9cc9165c6c9e6f759f3cc5038154531b314e6013
-dist/2024-06-11/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=2a2dac9fba84958818f6b31f30f91fcfef521111827937c88aa696b646f5b075
-dist/2024-06-11/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=d16b28da0196a815f028d432dfa0957d0bfb512b259129969548bd050afac872
-dist/2024-06-11/rust-std-beta-armv7a-none-eabi.tar.gz=d78f96102490f9025598b11cb72e31e96d3f5fd566e8f7b2b2c503a37b0dc6c3
-dist/2024-06-11/rust-std-beta-armv7a-none-eabi.tar.xz=a439af58e90970b4dadaa04d8f94ea53c6c7a159117926c46b7da0eaa0d0ca5b
-dist/2024-06-11/rust-std-beta-i686-pc-windows-msvc.tar.gz=d7847f3d9b1a2f50541ef3d2c25eeda469b28412817cadca52756aeb4f2c57b1
-dist/2024-06-11/rust-std-beta-i686-pc-windows-msvc.tar.xz=622cafc347ec1d3f0ef70354a0713cd255029730b17ad1f1ee951d9b0cb515e5
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=5fee2542ee8ee8d155edc0ac36ec8822896e6f93f9f573b9284d70aeb186a05d
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=dfe9ca3e3f217922b65db0d65826c0962369fefd3d5d72d6f03039acd710f122
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=b0937c5dcd458f313aabe07668ea338f2629bfc9c45d6139211b6923a7c7eb0e
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=65973a26c69f8ca7d3022180e2729161f7a618706cd9974fc54b14cf48f1af79
-dist/2024-06-11/rust-std-beta-aarch64-unknown-none.tar.gz=def2fc3aca20a74d023156606067f88ea8f1c8b602fb628b8f27ee43e3b62cfd
-dist/2024-06-11/rust-std-beta-aarch64-unknown-none.tar.xz=43cdb54af35a6c00ee10759a3f6ff6ca5c9080ba817aaf2eab7df8f239d77196
-dist/2024-06-11/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=ae2cbe53d304442e112585dd968f72454cc33bb75d3b4d7854a04575ff7b5301
-dist/2024-06-11/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=b3192290a45ff978126f4f08e7ddaf6de8720a2f6abbc5b41536fad6f994d7ae
-dist/2024-06-11/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=0e2dc167dbb66366252100fc87b94a67cca3360343302697c2989beb2eb14704
-dist/2024-06-11/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=6144604269f533eed11471b4c5d2f31a9f8340d9edf0f398a42e6e970c95b991
-dist/2024-06-11/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=b57e11248924ac54500d80525b8fe823e7dc74bc579c2b7f3f076c0a4c85ee2a
-dist/2024-06-11/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=9e473a5de0d02e6d8278a9e2430af135e3d6d4ecf5ce59827b384c8f20af39c2
-dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=1a62b5af52767e68146a45a47384b33c93b32a4579e51d41f66746e38dfa6eba
-dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=81bcf448ec54470edf60c2079ad9ef03f34052aef5fe9d8f5af933c565fdfd29
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=88eb49f86265a7fdb49b455cf5a9a373ac1e0f7cbcac08ef2194eaefbb039b22
-dist/2024-06-11/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=bf9a278615765e199786d16f154006007ddfca0d5a5869c55a05e513a7b06580
-dist/2024-06-11/rust-std-beta-thumbv7em-none-eabihf.tar.gz=13f16402dea66facba6e10a9556e0afdbd6b004e8aa5d08e106cf76ea59b8288
-dist/2024-06-11/rust-std-beta-thumbv7em-none-eabihf.tar.xz=7ecd66dc65758cdf32cdebc38f6f399392788a7085d69ec7e8fbd63be7b3e904
-dist/2024-06-11/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=96ccb2252defcd5bcd9eca19380b9d4e4115ffb135efebe6717b1527ee440bf8
-dist/2024-06-11/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=c31f4ef95857a445bc480b73babb886e259443b3137efd694c4b67f913838212
-dist/2024-06-11/rust-std-beta-thumbv7em-none-eabi.tar.gz=0637fe1ab1284334ed4f9aec87a4b51b6983418997844e10ffe20326078f6d18
-dist/2024-06-11/rust-std-beta-thumbv7em-none-eabi.tar.xz=ac7f13ba1a107d03c1b7bb0d2e6753b926a26554c82de38263113e2d5dfeca21
-dist/2024-06-11/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=0e8a21970d4ea6331968b10e990cb6dbe3d38af393e4dc8d603efec1b59aa0bd
-dist/2024-06-11/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=04b9663cef2d3507c96b77b18aff7c9beee0f6bd0e0cb9ef37b8c9cacadbb198
-dist/2024-06-11/rust-std-beta-wasm32-unknown-emscripten.tar.gz=01d4da0efebf4615da7c92c6cfdaedaf283d3f5e66c58a1b1e2e17488d86b3d3
-dist/2024-06-11/rust-std-beta-wasm32-unknown-emscripten.tar.xz=c203ec9216407f90d0bcc451e40a29e50279dae8ee161f05d9245e3cc8e1b30a
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=3621e0a16f7e6d9f292894a343941399a54b5d76a858fe5a69b83c95f15ada07
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=5944208b88c6924f8586304abea6827cdf756066158dc64200e207027143e843
-dist/2024-06-11/rust-std-beta-aarch64-unknown-uefi.tar.gz=1887e342d5c6453a63336023e51c124838762f89e9289d1abd8226a717bb96d3
-dist/2024-06-11/rust-std-beta-aarch64-unknown-uefi.tar.xz=ba0ca831ed66a72a14c8c9dd591e97d7d6cbc55762c961283088e897de4a8669
-dist/2024-06-11/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=59790fb6982ebfefc40d352d411604840b7540a6ddfb26ad14d70e139df3ab99
-dist/2024-06-11/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=c022c80da2debecdbea32ce34ef040bdebc8566a78e2867512815532746e1c95
-dist/2024-06-11/rust-std-beta-armebv7r-none-eabihf.tar.gz=4d4a380bed233e86ea957c173412b819fce00d66d369657a0778da5e4f244034
-dist/2024-06-11/rust-std-beta-armebv7r-none-eabihf.tar.xz=577763a4758c42bcf0c875d606a6dd538c07866e9a65c2b73271f0e9d0762830
-dist/2024-06-11/rust-std-beta-i586-unknown-linux-gnu.tar.gz=29f8e4dc5d88bfd66f600402022267ad85d4afcffd7142107d0fd28d0cae4cd8
-dist/2024-06-11/rust-std-beta-i586-unknown-linux-gnu.tar.xz=d030db59dd1788fa8438c52b9a8cbc6754eaf529de60fa4fa9693a687e644dfb
-dist/2024-06-11/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=df978c1519ea4b50fcec2ec18d2cd9a6b813982dc50f6442af9ce340b98a8c46
-dist/2024-06-11/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=13585b56ce162922dbf03d0b6432a6af9b9059a664063a6adca957301c23b905
-dist/2024-06-11/rust-std-beta-wasm32-unknown-unknown.tar.gz=6365c96d363a345c4882ad47a3e9242f37c930a10bdc89d137e5e05b1b599351
-dist/2024-06-11/rust-std-beta-wasm32-unknown-unknown.tar.xz=480e07d3f110ff9f201315f5a01bf674ead911773241d80d9005772cfe4a3d88
-dist/2024-06-11/rust-std-beta-armv7r-none-eabi.tar.gz=0514e7022540078895be3000fa0405157bf1165762e77672f78230e62ef2c8ec
-dist/2024-06-11/rust-std-beta-armv7r-none-eabi.tar.xz=659cec4d3e3f0783bf9a8b42a245b995e00b36a8ff04a9b6b458ace016d825d1
-dist/2024-06-11/rust-std-beta-i686-pc-windows-gnu.tar.gz=2c6b17e0fa22a9d528217fdb8231aefd21839e29babad0fd975fd3654a9706f2
-dist/2024-06-11/rust-std-beta-i686-pc-windows-gnu.tar.xz=c2c98b0c6b21618d5c49283f19ccdd3ba76159afd904c9683251d36317582615
-dist/2024-06-11/rust-std-beta-x86_64-pc-solaris.tar.gz=9433aed1f5f87157cf02d13e7ad375e9a2e9a260afb8419a05eeb1856069ab26
-dist/2024-06-11/rust-std-beta-x86_64-pc-solaris.tar.xz=2a39a792676fd60f47db90979fd56f3fee709d05d91b5c8bf4e0a01f39fed14e
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=29e4553e9889c3e202f550042555b5c24cf52ce68979870fe33d9e9eaad37db0
-dist/2024-06-11/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=7d56ef2eb64550f95b2ec1e1cfb9f153e9c6b412dcceef35f76db44eccd4d8a1
-dist/2024-06-11/rust-std-beta-i586-pc-windows-msvc.tar.gz=da7c08348c6834793263e136747e0e3dfcd5cd805c0c6ca25323fab8a30de427
-dist/2024-06-11/rust-std-beta-i586-pc-windows-msvc.tar.xz=3d60ea1671800cb8f271f1869186ed099f35ee8171d23df7c6ef0c79b4567540
-dist/2024-06-11/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f3cfa8625f3586ddf48c301b7016d49d216324daaa3b76168a97f15506346c3a
-dist/2024-06-11/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=2e5388097f10a3640514d1a4040f6fec090e1c4aba0259cbdd900ead7fcdfd94
-dist/2024-06-11/rust-std-beta-i686-unknown-freebsd.tar.gz=cf38eeced5efe6139043e123b217a5c3f43bef3d86001a9a51fa21b012c9b468
-dist/2024-06-11/rust-std-beta-i686-unknown-freebsd.tar.xz=e078625da24308d78603400e96454e60606bed23f1132b64efbbbc815791d58c
-dist/2024-06-11/rust-std-beta-aarch64-apple-ios.tar.gz=2f1dcaa67df6adacbb850bf17ed5df8258fd2087668d028814874fc8292bf420
-dist/2024-06-11/rust-std-beta-aarch64-apple-ios.tar.xz=2a11e0abb8b162a12f72825cac59cc0df993b5582d911bdf6b97252078887651
-dist/2024-06-11/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d7f4366df7f3599f031b9654d3c0bebd9c21ec530330283e6560cceccc17365b
-dist/2024-06-11/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=cb9e8470fd9934870cbb881f7611a0bd614416faa42cfa6096a1ed19abdf9cac
-dist/2024-06-11/rust-std-beta-wasm32-wasi.tar.gz=5e7d7b535a7c1449a4dcac4022de279c7676852a7da3e63dc063595dd3fa1b54
-dist/2024-06-11/rust-std-beta-wasm32-wasi.tar.xz=c4db5ad4aa261a01ba3fd8a191c7ac6323e6134b2e17522b3fe0891a642d4c87
-dist/2024-06-11/rust-std-beta-x86_64-apple-ios.tar.gz=a27f3ff22b233c72673e32bf257f766ad8e11abfaf9f83fc7c3e756f785ee83e
-dist/2024-06-11/rust-std-beta-x86_64-apple-ios.tar.xz=8592a2f8b1d6c3cab199cabe8b6e9a668b90bd77bf6a5e0869e2b4f3cc6d1170
-dist/2024-06-11/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=ffd9d5acd9a2a33e6a699b850d1776521da443b52504ba77fc71d6dd7353e18d
-dist/2024-06-11/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=e92eec9cd55b37f135237c98cfe00c4ee23d2ef400cc3470deb8f1a0010e94c3
-dist/2024-06-11/rust-std-beta-x86_64-unknown-illumos.tar.gz=b1d2e427120295375eecc3d8fc647fe57e1195210d7d0243b20d156f173c3155
-dist/2024-06-11/rust-std-beta-x86_64-unknown-illumos.tar.xz=b97fe83bb5050460465c57c37456868368d0ce18e5134fedad07ae00df8b7432
-dist/2024-06-11/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=25ad2d1a91456394427a5db691ebd903e56e60daa89d73598155655caf6592b6
-dist/2024-06-11/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=88b0a7fb002922f78af0f8e9580acdfeb4c341c9fad35e53daf4d6073c73ab8f
-dist/2024-06-11/rust-std-beta-x86_64-unknown-netbsd.tar.gz=b5e129c655bdc051eaa5aca8c8a577914100137a5bca753df619edd22889a1c2
-dist/2024-06-11/rust-std-beta-x86_64-unknown-netbsd.tar.xz=5fc42453c00c3498af2fd60fa4345c2047f302113666bf4a1d044539e3c1e66d
-dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=afb1e9e37af72ba42b71f2a8a78ef7ba8593dbf8e35501e20a81e2aae204722e
-dist/2024-06-11/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=3b7f63b544a5e8aad8a18097b915e01c1fb880d48514bd1fefe3a5d4872eae28
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=bc151debda651b76573e77c489c3b9c2be4af0f632e0061e067889f21ab254fb
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=f2f9225460e2e7fa7d28cee2dfdab483698c6f51b0eeafe49e2d8e44381a727c
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=5418a327d270c603ddc903ae6061fcb6bc9bca14593f13fe10ab3fe0f4a656ca
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=423e7f6fd6555c6d850e7317a8677d4778bc1270d3cfefc05614ef1acc61fd96
-dist/2024-06-11/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=d30d36a72c1e874a7f9df7f805f5cea3617f912b5ad5e7163616b07022e0f7ae
-dist/2024-06-11/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=4afd0b4ab3787dcbb2b2f686d56844c6aa3af69fbd72d04bd57901fdd58b6333
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=0a9b8bd1d39d346a20803ede808815dbf0cd55d9167561c8aabe7db3300a3dda
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=e36372611dd3cdabd1f32fb942c79bd31b5fc13946448cbf9a178ad5005dc7b5
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=2fe6221704614b167d837f52cfd439d9586e27ae82a34577659f86382c3192fe
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=55ffdc97b8b6d309b1aa8443b49a5fd6133f5d7653069eb7f32625c1c0bf86ea
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=87386371b64d4d922dc2fd01a0db28191748002b74a59437ddbab572b0d6fce5
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=6c1f9a6683a9d3ad8203b9d08ed829e4990675cb07fdc2214fc1f7970dee7e60
-dist/2024-06-11/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=525a64f28aa0d757e82558737db3150ff90ecb885c3da8e0215370e47fb2ff23
-dist/2024-06-11/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=af49d1730949036a48c05a147a3c67885326df5bea314fef2828e04433f33ef0
-dist/2024-06-11/rust-std-beta-armebv7r-none-eabi.tar.gz=eba00bc621ee0235444698e5bc67780bc93765e70bed11634a8555d8d645635b
-dist/2024-06-11/rust-std-beta-armebv7r-none-eabi.tar.xz=236fe5262d76fd8ab7c12ab6c231608c7e704e5fc0d95210b47e0c86201d8a8d
-dist/2024-06-11/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=ac98cc34543e6faa0429cb9756d1b0d30dc13d8d8a44380b5feecc0e7d083e40
-dist/2024-06-11/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=ed8fffbe7899a7c35e5985adae1b35b7eabd076970a8eac280e834b7877f272c
-dist/2024-06-11/rust-std-beta-x86_64-linux-android.tar.gz=fa53ef5ea66f93f9fa46ac84d3cf6a16743b46a941910b092c9c71208a15defd
-dist/2024-06-11/rust-std-beta-x86_64-linux-android.tar.xz=66b394876549c4faaf872d4103ee49ef59cfba5c78777c01ad1df00dc6babd14
-dist/2024-06-11/rust-std-beta-sparcv9-sun-solaris.tar.gz=63794d1cc16a541cc07b56870d86db2212c2c8e3f06e11fd9bdca90fd93aa56f
-dist/2024-06-11/rust-std-beta-sparcv9-sun-solaris.tar.xz=4d419a3c4402c303b9437c7564e2bea79575623eaa0b300c2fe688d9d8f9db95
-dist/2024-06-11/rust-std-beta-aarch64-linux-android.tar.gz=b82186abf1bb250753a2640def13aa477b606e0601c5c1fdb25af0e37ea638b0
-dist/2024-06-11/rust-std-beta-aarch64-linux-android.tar.xz=57065c7b4f1f5d51d1366164b62b4114ab95f1a68cf551d12db8e9a2dad044dd
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=bef7ed6391f906226a20f8d2d842fbc335891d7fb92f91b1c5873ce778d70675
-dist/2024-06-11/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=d80843f5f25923605681541b285ebf6868c0368841efacd376aac4dc9f01d0ce
-dist/2024-06-11/rust-std-beta-armv7r-none-eabihf.tar.gz=5b7d75f5f9294327ffb3c441b2e99fbc8402d1dfe0afaa20b2981a987e96801b
-dist/2024-06-11/rust-std-beta-armv7r-none-eabihf.tar.xz=ab56542b3be354d6c4f19fefe90af2daf59507e969a4144b6553a900e37e2a4e
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=7365d0ccde4cd000b44992c80cf0e48ead99c2a00e18cde4446d9401792606a3
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=69124687ee3ff876f557b7b21c8f78f7015c5f3b6537b65480613469772e00ec
-dist/2024-06-11/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=d1307c1b3fab3dcb6b1e5cfd5c30e1ef1c7b7e1e831ccecb00ce35bc2c1d8b9c
-dist/2024-06-11/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=8685907906feb9e16e34d4ea72e3ad338df9d6407dca6da81739b100926efcd2
-dist/2024-06-11/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=d8c1c3d800eaedcf23c25f436e30892df1938a618200f0f041fc1921a5b517ac
-dist/2024-06-11/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=53493d039721d5a2f54eb49ba7e16a205dd846bee559519182ca0af30111d182
-dist/2024-06-11/rust-std-beta-x86_64-unknown-redox.tar.gz=3f9842f81f45cbf35fd923ea69f1c88696070edfec0dcecac286519820741078
-dist/2024-06-11/rust-std-beta-x86_64-unknown-redox.tar.xz=73bc6b9b72bf6a9ba7dabe63b7a7d426eb47716466000d05802ef78ccb9128e4
-dist/2024-06-11/rust-std-beta-i686-unknown-uefi.tar.gz=c9954b477c329c3706891f77e9163d98aeadd96b1aa8a71f1eac20f316a9269f
-dist/2024-06-11/rust-std-beta-i686-unknown-uefi.tar.xz=88876cb6cf03707065fe172540e82faaf5dd55332c939891253476d4da3f8a00
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=e731faa24568e97821c5960229dd9a489ea7ead964a5aa052a6db322bcc55c18
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=47b529a6e19c9d609c41809fd62906c34f23a5c515bf62d91e88a87cf7cc0c85
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-none.tar.gz=c6150b3b7481f2396b305188a16c4ce2206c440e9d7639446c76566d00dc5159
-dist/2024-06-11/rust-std-beta-loongarch64-unknown-none.tar.xz=e641747ef4ae46e4d0a8a3050d00b1b8c21c0f25da53a54de8e540a9953468db
-dist/2024-06-11/rust-std-beta-wasm32-wasip1-threads.tar.gz=37d141ba5beeaefd08834154f66219df734c379c9315c094433aebb75b82bca7
-dist/2024-06-11/rust-std-beta-wasm32-wasip1-threads.tar.xz=2045a0b765de96eb17e18d8028ed2e553cc998fb71a4811e3d848db320f6b9a3
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=82de12e6a2b01c0b98c83b4264a4e00ceefc424f673c97826bb28729c3f31382
-dist/2024-06-11/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=c97b8a57ed8eefd60bbfe2df54121c548d9e271d9691def843185bac9d82b703
-dist/2024-06-11/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=6903175fa7cc3fdda5545ce11f4cc504e4183e56c626e25ff2b0d20a4f5190c4
-dist/2024-06-11/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=df06eee91ba57ff2c0a779da5d746db02f682514b8c03de875f03c96d05188e5
-dist/2024-06-11/rust-std-beta-thumbv7m-none-eabi.tar.gz=d7023edb8c723803e114e5b8ed316a6839e0c37d92cf6a2a09b767ee5ea2b7b9
-dist/2024-06-11/rust-std-beta-thumbv7m-none-eabi.tar.xz=41e19659bc0e0445ebafc49740579f0ac23a9af8e233c529ba2132f3d111faa9
-dist/2024-06-11/rust-std-beta-arm-linux-androideabi.tar.gz=42c0a6bfed8ca53b8833dbee78f2eab92bee061c42a4d629e870c8e655bc3728
-dist/2024-06-11/rust-std-beta-arm-linux-androideabi.tar.xz=5f85c99315a18bfc7fcc3f0caa7218ddc3b6548eb04be0ded835b5c45ec2ae89
-dist/2024-06-11/rust-std-beta-wasm32-wasip1.tar.gz=97abd2b9a68973263da0116eb5a0b9ead2145c1550f3190d02b35606bb9dcf58
-dist/2024-06-11/rust-std-beta-wasm32-wasip1.tar.xz=4ba0ef9b136761e739ab8ef125ffd993ccf71161d69e7640d94de6d5df601dff
-dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=886562504ee3e73ceedce6cfcc8d128f22a80f0a33c84b9c29920d7760a8a208
-dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=a8f28e60aa1938cdc7b7d46a1fa770d587be9534a291f5367a80a52772a0b458
-dist/2024-06-11/rust-std-beta-x86_64-unknown-none.tar.gz=642e7fbeaa76403ccfaf6c3c1bfaa8b94ded7311abfece44c863df231c282406
-dist/2024-06-11/rust-std-beta-x86_64-unknown-none.tar.xz=b1441ef88a1a97ecb6d7b674b571beeefab9f59fc8799d9e63b8a01078042f15
-dist/2024-06-11/rust-std-beta-i686-unknown-linux-gnu.tar.gz=fba54c97da35d0f11af99dca7cb0f43784da2104c461518149974da1f2248301
-dist/2024-06-11/rust-std-beta-i686-unknown-linux-gnu.tar.xz=e7acfab1f7bb8b2c2a0f7558b813f627a3f6b6dadcd05f62c5895f753c2f3ffa
-dist/2024-06-11/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=e4d5ec39520d069609f32c4dc7dd4114623bcd112a729529a096c992fc19f61e
-dist/2024-06-11/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=94d508cc6c86516ae5e3bba9366cb466635a1e3f41fd00ba6b1a44a87175fea5
-dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=76e17967c09311f9e0c684531f21588d5bfbbdd4c707e454068df240fcfa56ab
-dist/2024-06-11/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=e627a81855b3d93497b071138917dcf6382b60793a4a76073769537531d01789
-dist/2024-06-11/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=aa5a1b430e31bd5f912d378eab8447ecd920a5840c03b01799a410d86a7c4850
-dist/2024-06-11/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=20f6fc50caaff58aa2883696c61031e9cec5cc24aea94026cf9b84a7642c4d31
-dist/2024-06-11/rust-std-beta-i686-unknown-linux-musl.tar.gz=62d2daf4c1a0a6b4630559c64bc22ceccd658ea0e9e74ebf58a9b791226964fd
-dist/2024-06-11/rust-std-beta-i686-unknown-linux-musl.tar.xz=34681e4cac9a6e18f1952f51d6192c8b71b970a0edaf0a06766e1a576a7898d9
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=da45a5c9a7c7c1db32d6664358699ceeb27f59247862190a93ac203e5f49f116
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=f881c61a8ed04f02576374a82f28505be2ad4b694254503d30c1ab415b6b5a74
-dist/2024-06-11/rust-std-beta-i586-unknown-linux-musl.tar.gz=2056b8d9d54baeab1fcf7dcf65916645f8404413bff60851fd97108b7822a54b
-dist/2024-06-11/rust-std-beta-i586-unknown-linux-musl.tar.xz=d06fd5dcb976c5331185d308e2ac0e53597275a57603aa171a753b3d005f0667
-dist/2024-06-11/rust-std-beta-armv7-linux-androideabi.tar.gz=27fb1ba34b2331810174f88d0e75075d6af26ef3fb7cd3ec820408e819f36cc8
-dist/2024-06-11/rust-std-beta-armv7-linux-androideabi.tar.xz=f44ff932cecc16cb292a6149ac42fb440b5e4a8a6b56f55634d9031002eb56f7
-dist/2024-06-11/rust-std-beta-aarch64-apple-darwin.tar.gz=3ab3178d3c1d4b9908dc2d0b6236c147e8f787f323c0c02fb924e2d692ec839e
-dist/2024-06-11/rust-std-beta-aarch64-apple-darwin.tar.xz=4b67844f0413cd1b0fde9702542eb2ce297020c29531230c37d3e2f65d56b0e3
-dist/2024-06-11/rust-std-beta-aarch64-apple-ios-sim.tar.gz=317035259b48845882a4561bd1c61108331ce68231b3362fa6e9b0a323ea3fc5
-dist/2024-06-11/rust-std-beta-aarch64-apple-ios-sim.tar.xz=04585ea6b3e53cdf62372dc64f00237d26991a2f7ca6ce06f921065957c2ffc8
-dist/2024-06-11/rust-std-beta-x86_64-unknown-freebsd.tar.gz=048684f3b437110dee704d8ef58f166806d69504a0fbf661ad71d19575cc8436
-dist/2024-06-11/rust-std-beta-x86_64-unknown-freebsd.tar.xz=43762fd9d2cf4dda5e8b64dccbabf5637dde37685530eceba060faeba8212b62
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=40b3feff4834beb31125cffff479288adb2cc8a2d9b8963943907ba2b5478589
-dist/2024-06-11/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=f088ad7f9697570c251655adbf6921341f74bb8deaa445cdb0d15e5ab556699c
-dist/2024-06-11/rust-std-beta-thumbv6m-none-eabi.tar.gz=94b65456fa327c6d8acd59f1fd004feea8572374e8eadc022338de75c45a6c03
-dist/2024-06-11/rust-std-beta-thumbv6m-none-eabi.tar.xz=9ca368829aaab88a93abb580a0ecc1195ce5fa3877bd556c856ab52af51095ec
-dist/2024-06-11/rust-std-beta-x86_64-unknown-uefi.tar.gz=1a9892b1efce5e6aaa361675e008c623c47056a64deb73246c4211f5194f31a9
-dist/2024-06-11/rust-std-beta-x86_64-unknown-uefi.tar.xz=e9a2df6f754ff4c1ced354250de51939efb1e003843f1d0d8962c2a25e7c0f46
-dist/2024-06-11/cargo-beta-x86_64-unknown-illumos.tar.gz=d6f794f092c47e97e822dd6526ac2622f8a7b3a3cfa8b8462b3378eb16dc4801
-dist/2024-06-11/cargo-beta-x86_64-unknown-illumos.tar.xz=bcf8204f4750c6ea9ff5667ae07de7d06e5b68e78176adb79fc1bc433f7d90c0
-dist/2024-06-11/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=27ba1abe717de9e96b802c8026a17a6b5f5dc728ba4813c705a03d54c234be3f
-dist/2024-06-11/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=55cbb9abf863c05f13049bc59e99ea3e64523f0193ba1dd155b21cb732db50c2
-dist/2024-06-11/cargo-beta-i686-pc-windows-msvc.tar.gz=ceb0b610395fb2519bc6207b7916f402a17fac9685cf8b5c2ee354b350b396ff
-dist/2024-06-11/cargo-beta-i686-pc-windows-msvc.tar.xz=73f1cca9028510331477a0299e214d50a3b9ad02ac035d056acce110f52a1463
-dist/2024-06-11/cargo-beta-s390x-unknown-linux-gnu.tar.gz=eb0dbf227a1ad39436af2334ddb6e90831881c75c24855e9c040bcbb6ce8d876
-dist/2024-06-11/cargo-beta-s390x-unknown-linux-gnu.tar.xz=1b95d58699e8f534b5d93ad02c4281d8e791e8c266f10820de887fe13b1d88c6
-dist/2024-06-11/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=b078cbb4e2e18b6da3618a1048b038c52bf37a398618179b1c03f25d5e154ce0
-dist/2024-06-11/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=80bd1e79864e21ed914a6a2b8ee5d66867734252002789c6d76c3f7e82133eab
-dist/2024-06-11/cargo-beta-x86_64-unknown-netbsd.tar.gz=e2fb5140e90588e6ab158352e3f198ea71107a1aa01785f692d5ef64925af58d
-dist/2024-06-11/cargo-beta-x86_64-unknown-netbsd.tar.xz=6bf7fc08f593ef8847b3b14a33783fb3c54c542fe61a8a92c0e462a1bbf34b9c
-dist/2024-06-11/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=6cc72fe175632e68fefaea683c0569e9fe8f036488154e4f1ccd6a3135479cfa
-dist/2024-06-11/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b27004517d35019ead69bcd1a09c81aa20d2b00b57ad42655f1f434f8d66eed3
-dist/2024-06-11/cargo-beta-x86_64-pc-windows-msvc.tar.gz=e5d5945884554970344d16e90f9eed0dd60f61ed57e48b40fac2ee1d7c035475
-dist/2024-06-11/cargo-beta-x86_64-pc-windows-msvc.tar.xz=421ee0fca436d4d4d3bcd03c242f9312fa620da854b906618a1d8ab27979d609
-dist/2024-06-11/cargo-beta-aarch64-unknown-linux-musl.tar.gz=7406ba1c14e53da0a9ca696dc6c90fb816c072734f569c01f49c6b8f7d542d81
-dist/2024-06-11/cargo-beta-aarch64-unknown-linux-musl.tar.xz=917a2e63fcf03be81375143692306afb54fc2addef9f5508dd58fc1729119752
-dist/2024-06-11/cargo-beta-i686-unknown-linux-gnu.tar.gz=bdbd9c4e2808d9dd0acd219c3ba9972634d73fc4f177468bc196c66be620df65
-dist/2024-06-11/cargo-beta-i686-unknown-linux-gnu.tar.xz=e64d3405f99f8ad74984b81238a088b250be4e079e2c05aa68be1cf84f04154c
-dist/2024-06-11/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=bf7c374c02676f9e5a50f4964e6deb4d3aab19ecd66c4d246de0c9a06ebd23bd
-dist/2024-06-11/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=52e7907ca99467c71429d03012a3f6cdd95711b9cf002d3aa06ba25b3e53d2b1
-dist/2024-06-11/cargo-beta-x86_64-unknown-freebsd.tar.gz=bd9aace135befd19104b193e09bf982c79c8cb9cce301ff709cde2ee2dc82821
-dist/2024-06-11/cargo-beta-x86_64-unknown-freebsd.tar.xz=c0d2c3a2e56a1f43f62fb73e41b07def93baa278172d822a2a33f571d54f0463
-dist/2024-06-11/cargo-beta-x86_64-unknown-linux-musl.tar.gz=61526c6e4f0ce1a57d4831ac67252cf5a6cef3c106c6953b329bc0aa9c685e6c
-dist/2024-06-11/cargo-beta-x86_64-unknown-linux-musl.tar.xz=82bcddea6b3d976e7dee07afe7f805f5a6ff66f0721d281d2c896f352f395c89
-dist/2024-06-11/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=70c5bd18c756123f033a7cec027631f71d7400cb4d0c85d7602a8a6309379070
-dist/2024-06-11/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=f8a6c7dd8ba408a5fe623a0ca1d2f8bfe287b13bc09b1d8ea636ebbdec06c557
-dist/2024-06-11/cargo-beta-x86_64-pc-windows-gnu.tar.gz=fe26e842e6e4186437ea679cc75cd37d70a98b1ed0f17ed9ac876aa0501ebd5d
-dist/2024-06-11/cargo-beta-x86_64-pc-windows-gnu.tar.xz=f3fcb2b698736b3df87c06ba829a1f09c218e37b51ff1c59f165aaf8078c619f
-dist/2024-06-11/cargo-beta-i686-pc-windows-gnu.tar.gz=607f623f30e25541d9e6c8412bffcb9c16f7180250a244dfe1e2606edd45db42
-dist/2024-06-11/cargo-beta-i686-pc-windows-gnu.tar.xz=604369c997e05719d0fae92f7904e6b66f662bb75add1d836cb100e0032526a3
-dist/2024-06-11/cargo-beta-aarch64-pc-windows-msvc.tar.gz=de283125b79d17f4cf24bb608819177ac1637525b8c7e67a66e798f0c0b1024a
-dist/2024-06-11/cargo-beta-aarch64-pc-windows-msvc.tar.xz=8228a47ce003faf1edb4a10cf800d3316ba421a97176c97f6952743f7eddf734
-dist/2024-06-11/cargo-beta-aarch64-apple-darwin.tar.gz=8525a4015fa8078921f8bc5f67012c0d5747b7e7111079bffce79f2b696fbd4a
-dist/2024-06-11/cargo-beta-aarch64-apple-darwin.tar.xz=038c700f1b0ab543bb765a4b86638fc7eb1e44257a19d5a5457fcff4fc08f280
-dist/2024-06-11/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=16c75d17531e10f1bb9e95c79d8c3aa05549db3029663c69d2f56b2d2f3214d8
-dist/2024-06-11/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=113d97f781bf8d54f457e07fbe3de1d3a0ce0a1f8054a652083b67b81f4cb642
-dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=7856fc9731c3dd7b360eacf422ce358acb2d33a7fd8b16fa190dc77cd9bdb3de
-dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=85c930785fe9857458c9256c5a2849ae223c5dd162bd20ccc8021b2d2ff0a6ba
-dist/2024-06-11/cargo-beta-x86_64-apple-darwin.tar.gz=aa4aec2cf417a7446c2990d03cfb3dcaab9d99f5ac249cbb955a59a64b5b7b0f
-dist/2024-06-11/cargo-beta-x86_64-apple-darwin.tar.xz=01d4bd8dd8a58f16ee31df775d0d7046ce671dc86f8907514e3713a62aadbb12
-dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=6e5c68d0665add368a6574528184dc1d182e7d72b8da0827b69eb9f9aecbc4ac
-dist/2024-06-11/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=180a6148f5c5be222d4e2626eed9cd7de2e0f62d0b456e520d1ab7c4931e1f4e
-dist/2024-06-11/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=6af892aa858f35708bf9db322abf35967b1e92725e05f6974e1d9ee3cb4c7b84
-dist/2024-06-11/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=40ffc9713504366978bb6f2eea12741400164318945df22290c7b669d3b77878
-dist/2024-06-11/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=9989b0189f7a4c5aa39c39c78be04e7291cc1358ebed597636f404f56980c199
-dist/2024-06-11/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=8c7d7dc2530f25cc771c75d454fd11f3e94c7954bb869e43736860be1f253d2b
-dist/2024-06-11/clippy-beta-i686-unknown-linux-gnu.tar.gz=94505902c45770c45a89ea12759bf46cd97efed657b43322d5dd09c13ed26331
-dist/2024-06-11/clippy-beta-i686-unknown-linux-gnu.tar.xz=14830f6fa92b0d814527a9aa5575d0cd529e76dbe2481533b819c735470ad684
-dist/2024-06-11/clippy-beta-x86_64-unknown-netbsd.tar.gz=5cc5f4202003b940a6a62c2384c749b741a9f6d62461ba13a6179464f6c3e6ea
-dist/2024-06-11/clippy-beta-x86_64-unknown-netbsd.tar.xz=01f4f0ef78f17e4991ddf3d974ef7b1dc9d56702ee2d65ede4918e9db99ec222
-dist/2024-06-11/clippy-beta-aarch64-pc-windows-msvc.tar.gz=ee6b64a7a0fc8d8482c38d2a263f9a9ed0b9462e6bd748a72e33c5cd7dac015b
-dist/2024-06-11/clippy-beta-aarch64-pc-windows-msvc.tar.xz=f91457f5dccfc81a601b075da340bf521e3cc17ba05d12f90c31c7f5b215a7bf
-dist/2024-06-11/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=7da546ff13b3e340f2ba22e6995566cb26e487271e3f1b68b3b7dc0bd5122623
-dist/2024-06-11/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=01807b62c65fe33acd05d10191cb16ee1bdeb1bd7b410a9c0cfd8f53006624da
-dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=64f41430de84569a7b933db7f0c573fecf99f5d0c6900e35598c94a433c0296c
-dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=b30a73278552ddf511ae82620f14ec7324f281582fa4fa9df3fe984510835aa3
-dist/2024-06-11/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=e6b0ac4bcec2871d2a50e644733399e684d7fa86798131243c4022cbe2ee5222
-dist/2024-06-11/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=edc629f04503ce88443ca6cce0b74b5833ce50f428e00a02b544f422577abb1e
-dist/2024-06-11/clippy-beta-s390x-unknown-linux-gnu.tar.gz=ac52f8b4a1b6332aca1ad2363195daf571f7f1870ffa6237441dc7928a408167
-dist/2024-06-11/clippy-beta-s390x-unknown-linux-gnu.tar.xz=96b366fa989d2f739a92ee03bcd141b666b942e0b26922acd620e0fea6d44d8d
-dist/2024-06-11/clippy-beta-aarch64-unknown-linux-musl.tar.gz=8ab584ad05a7836bebb20be8d84b0dd3a29d1823dcee3897abde3a47a10e582b
-dist/2024-06-11/clippy-beta-aarch64-unknown-linux-musl.tar.xz=e7b669a2936a22ed6d2a36b70a6593657488e5ed8d00a911bf33ce51c4c0cc51
-dist/2024-06-11/clippy-beta-x86_64-unknown-illumos.tar.gz=419ef233cfdbe9011d74796e8413a8b6c1f8e6281248969eaf7c9157542c1b70
-dist/2024-06-11/clippy-beta-x86_64-unknown-illumos.tar.xz=673a2f16268fba4d9bf7dca2c0758f3ee60f9754cdcefa36032b8140e6fcddbf
-dist/2024-06-11/clippy-beta-i686-pc-windows-msvc.tar.gz=a3c3bd3b90c951ce404a26a59421f00a03e0dc3351d9dd2876346ff096b7361a
-dist/2024-06-11/clippy-beta-i686-pc-windows-msvc.tar.xz=c3e7c1cc91f48003e1b68fdf753011711ee516bc2ff8c7227d427dd8ee98a72e
-dist/2024-06-11/clippy-beta-aarch64-apple-darwin.tar.gz=ad7b4ac9cfacd860e03f8a41da51b4d279d76b7f3f2f8ac8a048a45f89a7ed04
-dist/2024-06-11/clippy-beta-aarch64-apple-darwin.tar.xz=ca5d2d63b8d7cae00c86383d9075b2292a28d1a85864877a6c8282f5596631f6
-dist/2024-06-11/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=12820c3e8b952dfa931783b550f882dd96c48d3b776fa9cdb29b02d66ad14d96
-dist/2024-06-11/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=394873c6b2499ebc385a11b512c7378b95478a0b6f530c5b313fe86b65a18eaa
-dist/2024-06-11/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=8d9353baa4388d02d89b42403e07d6a61f314fc975b8fcd737d8f4edb0ab027e
-dist/2024-06-11/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=3cf0511bc5b14619dd6ca1cfeed003effa7fbfecb42fc096a45a211d1ccf419a
-dist/2024-06-11/clippy-beta-x86_64-pc-windows-msvc.tar.gz=cfae39e5d5cbc817aa3ba892822fe2ff122df8a648106aaf0ec18b1ce1a02632
-dist/2024-06-11/clippy-beta-x86_64-pc-windows-msvc.tar.xz=1f1f0596bef154eb3fb4e73993794850f8ad903f4dd0ef9697aa8d5b4d6ec2b7
-dist/2024-06-11/clippy-beta-x86_64-pc-windows-gnu.tar.gz=0909caa93377b2aaf2a05a345e8cfea2c69dc27bd7f7d7a9515576e90cd0aad3
-dist/2024-06-11/clippy-beta-x86_64-pc-windows-gnu.tar.xz=9125bfbaae2103f176b1e1b444fd38c7e74d3414536370037ffc6a85d8567551
-dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=3721470fcc17f8d37c66281bb66c65a66181c80775571520fcc2dfdb583dc640
-dist/2024-06-11/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=79ec48af2925aaad12be405fb72dc9bd9e2ca89fd3a6017111020570ddeb6585
-dist/2024-06-11/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d957f503dd4d9d228b6a445eab1183dbc6509a49ccbd475d25143cf1dd28f03d
-dist/2024-06-11/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=da7ec767b4a85fa327c957888b228671b2311286043165926942504239008d3b
-dist/2024-06-11/clippy-beta-i686-pc-windows-gnu.tar.gz=51ff631084254be43d79d7791000a14ad9f11239e42be73f48383f774109c2cb
-dist/2024-06-11/clippy-beta-i686-pc-windows-gnu.tar.xz=52079acb4f908150d207a838cc7d3c15a725c1d61be35d0d0b2ed85b3386f3fc
-dist/2024-06-11/clippy-beta-x86_64-unknown-linux-musl.tar.gz=99a534de9e5fb552a4e7a10eca2645ad260a723f42e15df3b4e2bacf82e90348
-dist/2024-06-11/clippy-beta-x86_64-unknown-linux-musl.tar.xz=7f9e6da187bb71c384f5040298c43bd303fcbc5e3034dd7fdc7b251c5d7b3a34
-dist/2024-06-11/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=acf05b62fc219ddc2fc4e4bca2bc4c2cca24398d6276bd7e7d9f8504627094c4
-dist/2024-06-11/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=c737aaf9c4bc3a743752b13159902fc5a8ce746f44221799bbcbcb1f9d04dc4c
-dist/2024-06-11/clippy-beta-x86_64-apple-darwin.tar.gz=422e97d9081e66a46ec3f4c2a7ccbf9b6443c7b343e0a2e90845f233536f545c
-dist/2024-06-11/clippy-beta-x86_64-apple-darwin.tar.xz=c9d02836c9d0e48684f0a343d6935848ec75e1faaf7007a6a3e0718b71e77f7b
-dist/2024-06-11/clippy-beta-x86_64-unknown-freebsd.tar.gz=f207fbfca76eb22f7097eb98ccda1da513fed417371a391e43e8d19fad9b76b4
-dist/2024-06-11/clippy-beta-x86_64-unknown-freebsd.tar.xz=61e39b0aa88a1d8e131a461cb3cebd05154c261058b735f29dc6ed603464b5a1
-dist/2024-06-11/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=c68d27b08f9699c7c2cff9e9bdb7485991d8445074e8b84c2e2222fbff209f83
-dist/2024-06-11/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=d5961f82b9688b9c1ccdcaf578b8325e8ac1e0cc2ffa02131fcc3281cc88dcfd
-dist/2024-06-11/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=12ccb5b1d82ad22292b337c49d1c5b0c0d584cfb4e649faf6c53471915df2473
-dist/2024-06-11/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=80fa7cb902135006046c10db64d9060103dfb1452e8e0ef256f8344fe0a9c8c5
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=c08499ebec188f67477d0c4eac2e172b59f6d66ad4becb36330b5066af6547d8
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=b3f29c79fc8bd64a2e62101468bbaa28338f444839659d4f99df34ccccad5eee
-dist/2024-06-11/rustfmt-nightly-aarch64-apple-darwin.tar.gz=4866e6d478424fb1c01b2b98678107b9c89e67a2cce3db49833bf34007f868b3
-dist/2024-06-11/rustfmt-nightly-aarch64-apple-darwin.tar.xz=e8e6fd846f70a99e6fad735ce4f4c8bca5f6b5f2d63364c2f8a7df85c13b63f4
-dist/2024-06-11/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=f14077408a763f0fa6218ed97d7697499c2bded289a5953336c727e2de93bd92
-dist/2024-06-11/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=27324f62ecfdeeb4a66ce3c62219c491f04ac3822305ea771df0381a5f4e5418
-dist/2024-06-11/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=1147008dfa30891e264bf5f469c9528fe47bdfc729a12215e5a985179513cc66
-dist/2024-06-11/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=95fd945a6c9bcbc9549913906a8f2de20adf54b84b82fe8d981dbb5b767f0cfe
-dist/2024-06-11/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=4f423c5ce278204dce918ece2af84bdb55429b7a11f630de95a1516e7b113f53
-dist/2024-06-11/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=c86fe94c9b6cbc56285478ffa715877d234af19f1b58b3fd4b2af23a0267b657
-dist/2024-06-11/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=f1200f077402474049f6b817688435db0ebef7fb52ef645d5b5d2f7ceea52a08
-dist/2024-06-11/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=a0d801ec3aa93389d5c6ae2a95be25ba3a50f53182c0a84a00c38a2f708447e4
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=d4e28ad9b054cdd19fce6bbc37dc86210b0536aee5c23bca53a6bf1340fdb5bf
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=b0958ab975026e09ba921234353f5a81b3227d23c10ded4be4fe37831e6abd12
-dist/2024-06-11/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=f1caa15f16aa1c93ee783bf273d0ae6a7abd0b38c93c717f2d49af5444cd4e09
-dist/2024-06-11/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=130687b9de22fb1d0c4c845cff5475e5959278718e3b6a1af7f1b9e8869b527f
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=32e3881c61abfff7f9c006083045ffa5765c0b3a5a6ec46607e5428423ab76da
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=c1859b8a44306b5b3ca27b9226bbf351cd3ff3cacb4faf61200d7baa76009367
-dist/2024-06-11/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=4f5c23ba3426719c39a7c767be8db83382c84ff7798c5194aefbeda821462269
-dist/2024-06-11/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=18d9a2084cd5e55792f3841fc7d6602bd4a973726662b516289385b7908ffa4c
-dist/2024-06-11/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=df5478f63a49c55ffe9cf62a1882feeca019290c0cc9a9ed5a4122b8aa1325cd
-dist/2024-06-11/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=f54c3b8febfa4023a0334dfeee59d75a44f5c1d3a02d2d57959473d6ad51205a
-dist/2024-06-11/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=dd2d83a7bcd45a0d5de312a2a4a28b2471a9597d318135214b45a69e1e449f91
-dist/2024-06-11/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=02a8ada9d737e115033d26b0691f2ef22428ba2f67b7fbab7c4205df8162a96b
-dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=20bde0cb3ddca790c0d126d5d590b9a35a1c8631b42fbc2d4e85cfe5aa880d04
-dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=dd29e278f79ce1be14ad44d61039e5a6a63e0e597c4736ab153beb758ad37fb9
-dist/2024-06-11/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=09d98f5c61def16b62b980a6cef3b1b3704cde5c0ad2fdd7d23521db410b6b8d
-dist/2024-06-11/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ef43e61c2d3d90b09494a8dcbb5d2375223fcba6078f2bfb02ea43750b1a76a3
-dist/2024-06-11/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=80318fdf7d55c71beb8ff1434b79776c59008f5d62c63530da9f19a67cc18484
-dist/2024-06-11/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=05ae6d4f8ed07cc75b333e606af14f239978abe197b70409a5f2aadc7de43a4d
-dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=a079a478e9a89c3a24864b44670bdffcebc139bbec9c54e7aab6394c08bcaab4
-dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=243c2d7c23e8aeddf9729e1f7f9add6f88f50d012efa02644030110cba111713
-dist/2024-06-11/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=76b69b4b25e8c0d47b80491bcbb724a25c02d95e7f9cfe7a9c3c3570c24363c1
-dist/2024-06-11/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=027e075c94f53403f03a4fb29d4575928e1cba141fc0713c93edaa4ea5917e42
-dist/2024-06-11/rustfmt-nightly-x86_64-apple-darwin.tar.gz=b34d3f33e7ae81a5a95927997658d738a3d39db01408dad2d9fa72efb539c73f
-dist/2024-06-11/rustfmt-nightly-x86_64-apple-darwin.tar.xz=7efe129502b732219d1d24d59584b5ad002e7dc5288e047b06bbc81fab36e054
-dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=231f11ec1c6e4f57556aa32226d22328656d2ceab075cff67c8ab0a1ec32a823
-dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=b1cd7aa45a516df3a68814ce52753eeead4134943d610449456a30c682079ad0
-dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=3fb86c9281ae8203e1119bc00e8001afe7e894360adc791a9a0ca1d50e6a9032
-dist/2024-06-11/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=6380fcfb015a40c4605ff18f8ba54c3be9a8e6a0115ede378565d9cc9943c627
-dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=f3ff749dedcfb259a4b2d66ae30245caeb79fdec3b41a3bb4f65d50b1cf18120
-dist/2024-06-11/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=1ca50ca8ff36df7433a4ab4c8a63c3c91e214f6c7889843edfb9120c1f4f68d4
-dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=a7f5f171dfef5b67498c93354d9dc5a7443d69f3f9bc0bc56b660d1450e9b7a5
-dist/2024-06-11/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=dff02f7a7e9ae58c41faf4c5731862d11fee06d17099c1ed18863219a4a82815
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=71dc189c1d29d3fec849b47f64deb831569515e56821511b1221983eb9ed99a9
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=17736f80644c8cdf8239940812962e6f55c1924896f79bd2581d20582a9c752a
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=b77e4a1e42c7169d91e268972a9195f7c8494e5cffa5fc71720df799a4eaf74a
-dist/2024-06-11/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=8cf89f982aaa5559f2cd1721edfdc25f5e99518c418e1a6818c566d668c8f842
-dist/2024-06-11/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=7703c27800aa2d871624563380596a18deb90081e38cdf6c05cab8e794e5805c
-dist/2024-06-11/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=ca9dcda51c8945db32e004424eaf26d4f541a51a78be87be0063e5a0b06fdd4f
-dist/2024-06-11/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=59a2173462baaea0cef3e0f088b4e6ef64e2fe469d1833798d92e844f0126902
-dist/2024-06-11/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=0cab2fde15bbfab741eead0b084886f8b640aeb181251368464bd833fd08df73
-dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=8473ef60ff1d5c7aee90b8e0a984c9be7e095446d87e0f13ebcf10f245c0ef0f
-dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=657a55f27794460bad174c4f9412e771c679c6b608cc3dbe32903efb075418da
-dist/2024-06-11/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=bea7aff88f7d7622a23e91c437d9616a9f1adfbd56ddcb42ee33589d064d5161
-dist/2024-06-11/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=a5ab0850c71e322b1042815c443c79505f1daab2b4a69f8cce05e3761a24f10c
-dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=8c00db9c85fa8053f78285c8a546afb32d6b864795388f1ee7a6a49d12643625
-dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=c137f5f943d1c3f14a4a8b5eca2b541c43c82738452646df524e57a6ef0cbd3c
-dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=a4087ded3076e4d487efcd4a957554255ea1fad5052a01529ea1847559f7b40f
-dist/2024-06-11/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=ed2b01ad985668564ba2c3f87dcac4f5c4bcf7ea0b5ecca6a30c1f1c4b63a4ef
-dist/2024-06-11/rustc-nightly-i686-pc-windows-msvc.tar.gz=41db0331bc8f9d164d4198c93234dae41c1b9d2f53d466ee8cdfba4f9704c45b
-dist/2024-06-11/rustc-nightly-i686-pc-windows-msvc.tar.xz=49766cd2ad581f253f3fc0ba4f755a4aeaae954c75d41fa29a9302568e78aa75
-dist/2024-06-11/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=b57be1a1dc9e70c47564253877bc0cbbdde8a8064a6a4bcf68f8adc6b4c5d4df
-dist/2024-06-11/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=cf2c4651297993671f033eb9bb9877b157638bc41cb40ccac3294c3fd13786ef
-dist/2024-06-11/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=619c2eb3ed3f153d2c0ba6cbeb7f0e72c67fbb1e40c025752f94b46c9b740426
-dist/2024-06-11/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=105560769c3672133ecb063ac0a8ef541229490401470180af75151403287d3a
-dist/2024-06-11/rustc-nightly-i686-unknown-linux-gnu.tar.gz=211498f7eb884908c8110ce922183bbd6cc05d96d9c8b5c9068dcfc4d29010cd
-dist/2024-06-11/rustc-nightly-i686-unknown-linux-gnu.tar.xz=61beb47b917ce644defed991afa6d82028cb8f1e6a191cf5c84e8be883ad3870
-dist/2024-06-11/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=06036f5bfc00950e03a66e8dcab0eb7420fd055aadb85bd42e11845eef122122
-dist/2024-06-11/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=39d3dc95b1e0cfcc381d27540d100b8325728ef9a6a8b72a0e4ad85e2e957a63
-dist/2024-06-11/rustc-nightly-x86_64-unknown-freebsd.tar.gz=9b7badc1c8443571aec7b403e890d14846c3972b02159c8aacf3157ede69af9a
-dist/2024-06-11/rustc-nightly-x86_64-unknown-freebsd.tar.xz=a1fdcbe1ca277b22c2dc8aced8ac0f34f841e7a7512fe421c2b045608c4ce07d
-dist/2024-06-11/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=5e6105bc6304ea630a8170c785df11cd435521a2ac90348284898c4aab6ed5f2
-dist/2024-06-11/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=97dc7091b1ffa6a23a4b609a680c1f2f63debab80b5c01bc90fe271d6599bf89
-dist/2024-06-11/rustc-nightly-x86_64-apple-darwin.tar.gz=64769377c3714749acf6404d75f46b00ede0107840e736432d759dbfff15b6f9
-dist/2024-06-11/rustc-nightly-x86_64-apple-darwin.tar.xz=8ce829c39fdf21467307ee540c6b06b510d45c76c395947afdc2e5592d775977
-dist/2024-06-11/rustc-nightly-i686-pc-windows-gnu.tar.gz=4c9425ef2d5fdf9badec75783fe61ce0a251fde672c993c5b0069182449e2d7c
-dist/2024-06-11/rustc-nightly-i686-pc-windows-gnu.tar.xz=442467ab4199e2fb62c69a96cc1c9f03478a415877996f0fef20c54760b2e8b9
-dist/2024-06-11/rustc-nightly-x86_64-unknown-illumos.tar.gz=0b4c3520ff6e5b053a6b37f7d3708fb115fbb99981f337a1786d675e70034acc
-dist/2024-06-11/rustc-nightly-x86_64-unknown-illumos.tar.xz=d192e69dd328e6f930ad5b578065ebab12913762845f68ee55b43ddc9ba074a1
-dist/2024-06-11/rustc-nightly-x86_64-unknown-netbsd.tar.gz=0828f2d9395cdac8e9db6ad5c6b3cab3587fc82bccdec9962cd096e43e4f7793
-dist/2024-06-11/rustc-nightly-x86_64-unknown-netbsd.tar.xz=542f61a4c5a719f2583b0ba820207dc9d09cb9a2bb802da7cfbee5273bbfddfc
-dist/2024-06-11/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=289b1bee22b8d9d84e92461694c6558476f944ac07caf2d22f0c4ccf3d29dbcf
-dist/2024-06-11/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=23c86fc06ed9e7bcf8da72085ff88ec224ccddeca78ddc31032b314cb254ad64
-dist/2024-06-11/rustc-nightly-aarch64-apple-darwin.tar.gz=cf045620e63a5e623047490af956e0daf0bb321ed6a215ae355b8829c047e58e
-dist/2024-06-11/rustc-nightly-aarch64-apple-darwin.tar.xz=0abec976185b9573dbc91868ab4fb84ba2837d25f3fa1d74b3a193609387f3fa
-dist/2024-06-11/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=0b1146e24e4e59e4577b1e40d3ca45096864e87bcf9f258a34b9d9cf5abc3eef
-dist/2024-06-11/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=289e97314fd22da08c8943d1240fa94b1cfd2cdf061dea15bfb582a9d482d6a6
-dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=8957493cf92d57381b35d6ce5bbdb408a05c2a6becc8e2cd37b0502e3ef35ffb
-dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=9015e492f773b91054c53aca92ac704336504959779e4b916d42fc966e6058ea
-dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=aea2dc3831864dc5ea2c389c8208fc82baf1566f4e5688511495db25525e6020
-dist/2024-06-11/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=9b6f1c3b1656ee2037afe170d6909aa037d484897a83679e2115392a35559062
-dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=3a962a42e427675df5d8fbc4e638949ec0669a95ecabcdddf5103a9c19f291ac
-dist/2024-06-11/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=6fe48c92425b41ad7c3e812abe2e5decb117be178a16f6910bd60000fe8f355b
-dist/2024-06-11/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0a3147dd45cbf54e66b92baec479a5550c63327185baef3df9638c5a740e0921
-dist/2024-06-11/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=d35948d49fa1e526434ca89c2f7542fcfeb86b4ec35bb92f87f387ec37f4ccda
\ No newline at end of file
+dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=6e58397829f67bf952037c94894409032e52ac8ccdf3858346d131fff6175a50
+dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=8e834602e7cd1fcd585f51ab280266b4ffc57e0c974a1a26b901701b5127135d
+dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=02bcdc3eed81ba17e485556f1c4d5a00e851afb75a20f860ce7b6d22cb8f9e99
+dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=52b72cc7270fe75e023ca9c40d095a84cb0ce31657357cd7676d6570ca59bc1c
+dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=904029f0c81ec9679851d952f0f0f616cc183028882c6686f5b5bb665ca00cef
+dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=31f3f895d665acf082a6dbb40e91fd97f823f84c8e62074dfa82e60f22606f5b
+dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=b47ba6f2214f238cf8df3c386765e7816bc86e1166f27ddb6c0ce678ec716939
+dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=95537778025708922b4bf27f34f0634a61a1d963a8424f8a06c82564c74e849a
+dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=70eb8f65e91068ac20366fca1fc30227f36cb2b2ce1abdaa72504583cc7865c7
+dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=3372e272cf9620191000a95fff23e417586e6b894e211d44e4f658c241c3d014
+dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=94a8a08495b8093db5d9a32c3258c9f97ea8b0f57947d7ca642664c06cfb438d
+dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=8d057c7167cffeebeddabf25f08a50de8dbad5ed7cfffce625c81a99d757e998
+dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.gz=045fe2478c5a5341d7b7a05b9df23ef8f81ddbe0faa78e3f2107341a0e8189f6
+dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.xz=d7f3888692210b6024ed72864015d1c101f28814dec5b60c9e32a772f11f3b47
+dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=840131ab570c68c0d46244eac743f7d8a1f470d1926068868d288307a488b3c9
+dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=6513a144014807bd258d2a90fa4618aabdb4e265268e408d5cb699a610b78c31
+dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.gz=a265d7831284938f090ef34cf2fb374f4d2b946c52829de8e53a06b7373c3d7e
+dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.xz=f2420846f82f474892776f0bea176fbb2f1850a1fb9f51a1afe40ae6de8bbc17
+dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.gz=ef5a0d34b78848962e83ed468934d7cbedff778a89e50f2128ba25d0943e25ed
+dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.xz=5cccc7bbb15b63d422dfd2c8ac25e2103906880e843feccd318ba8b8c614d3b4
+dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=7b037163f1c19a0fbbf4029d12a7b3764e747c9ea7944f1e45a6f91a068df224
+dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=f5044d8f3784e5bc682b03ccbe7389abf5b254a01074fa67eb824d2dfc9fd3ad
+dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=5e0d51532c4bb0c29fd01ef5d931c229f711c9326df0bdcb2b88c75aa72dc210
+dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=5fe623cab0afd5f7bdd664a593ac02791915e30cfc9ca76a02ffd70e1e865ede
+dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=40b7312ce424dcbde5537da50d17854c255c3ed535a124f4f0102cf62bc86b5a
+dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=222a86f97d9bf2db38ebea9f45901790429658154d3448d05e7f0ddd9833ff18
+dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=1df1e1a44170d6c9ab4988e9841ab56ee00248ca5cbf7e38b69677bd5b2de585
+dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=70791fcd1aef6686e012740017a0e5bb4441eb4018f875e8e50d5597c183291d
+dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.gz=81fe4bef33afb3010fdd7af42653fbf5dd9abf0d69268576dfe144c88c7b9944
+dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.xz=c4785475e3f7087cbab405937c0ca3ebc08455dd36df156680cea1ed38fcce5b
+dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=e8f09f56c43ae6e99a42a8c430492157415fa6baee2c3f8f86f94ab4279634cd
+dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=599fcd5c57687e29eec085f7cc2733965a8e8fe5eac6499abd92ffda64f6e500
+dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=d79c8b744d00b174be7630a54f9ee23562f8977d7e09e2ee46a9d72a80eef514
+dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0f7d3d0773a3c1f94e8252d95b134f7f5e727a884ece54aa0f77e5edec5c6e29
+dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=5e6fae2fd75e1780995fa9839593044539fac3f095c8948ba446b7024f632ec9
+dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=9eb16965a7f1f7be7751fb61280f272c2497765e552fc0dd653700d551a04539
+dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=4d374e60b8ac2f3fddd5ba9b46ab80555bc5b19f080b86604dde994087b00ed9
+dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=c905a880b98d1eaabfb306d5b6dda018e5025b42028cbb12bad408f4d469f3ae
+dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=d703a904da3604e553ba0a74775f8005e9f52615be3266197b71362b20414def
+dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=8ab79d34b3c182a4349fd01a50aa13ca064ecea64c2ab09f7a9ec38046741c7a
+dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=69f0228799685960f36f31eb4c139cbd7925f5180468e2d4a435ecbad63e9535
+dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=1da1caf5b2ad149ef82af58278dea6c381c372366c48cda8ca7f520cc8752b2c
+dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=e3e0e2b8d1f8804cc2b5785765cc6807bbf7120fb010d74453097b5931c82e96
+dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=1270aaea2f20a378e68d26518e1d34810ed346a4d4c272138c8aef67e3c386d5
+dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=dcc93e7b76ca7a469544597885a7b5f4b5f822e05a89b2d7a093e06dede9f52b
+dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=3efb7d4d97dc9b13a0178464e79bbf96bb71763a588b48c587746acd456ceb8d
+dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.gz=5b2988c87d91013cd92ebca43fd6cf5d49250fc0452830ea46622e418984041e
+dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.xz=b9d65cca6691baf2841432d6d2d566face171c460cf161f39a21acf7c0b033c1
+dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=a9b352f61f8124c1fba0c76ecc8c1c972e61e97f5299f3b86bc17f035351ced5
+dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=a8fced9a5de02bb660491b440f6596e4baf6eb9114b8dd8d93ac7ada6266d274
+dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=2cc32752932477945f248dee4d277754928b982815e2e2e0d27883522fb9b8d2
+dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=e40eae93c31c1fa06517a21cfbdd2dd18e2f740aee1251bcc9bdc680a565241c
+dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=975917e862347f7e1472cdaa2258de16cb9981e3a8256f9b7860104740076187
+dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=bb89062b05f025a964e0110fcfc8fdf57300b23314409924cd4a05e9af9614af
+dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=e487752db0ecd837fb1ecb57064ef2464f7f85ed5fdc9d47322e7b5c37c32300
+dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=e74a462d598c55822b5841bdc35cb2605b4aa7993e305246b3adf079ae79ea1d
+dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=905d378e6fd4387381fc166718ff31f017c99e725a9c8461bbac39d5571e246f
+dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=6c5fc29004bda36ddfb0280636ac2b2c28c538f33cadb07a55174fadb068daa5
+dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=0228f8d7e0913cca5db975e0b9ec4807e817dcbc0cd0bd64b64826c9537f25e5
+dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=d37d5ae3605d745a393fc71c5f0e169cee283aa840edb9543682b339cd040310
+dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=1bd5a11163f5fb9325e21c425d5d2fb3e1f845d265cbf7736679c3bb9c8d22a7
+dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=d858d0077df0fa7363258994e76a1bc0ff850734de6a0fbe955c3c9b9cd46cb7
+dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=ae56b334234ba51cf68be42d0fd58cf3487673dbe747bb3efa01e8563b9b8a90
+dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=1468622e9bb6384a6ab7006863d2b7d55307e74239befc8e72dfd39f83c0af1e
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=d1e861a9176a5cb934270592f7b98528283c363d135736477a844499015ac44a
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=c5f548845c6ccbee1980892e630ab06ec1bef498fb7f6fc80b4ced4a84c23f85
+dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=95244114ed2d6dd2de488f49115b11a25b008134f1fa1c8f2e2a62849b51f213
+dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=fcb3280dabb4aae920a14c7f4fec52dc3f11bc68f5143961fa88347aa020bb9a
+dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.gz=8c129310921ed45d3cdfc30e60d93403adf8158a6661de96ee5d4a63119cf3e5
+dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.xz=e1fcee4b062f25b0350e5e74064615c354ee8b399adf792d46319ee782857398
+dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.gz=68fe7b30550cf1ccc44a1669f26620ae418b48cd6283b716aff3dee91acfcbec
+dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.xz=81f24aedc06a25c8dfce729132a77e90adc5fe2aec86a3a9548aec9458127ce1
+dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=6dd97a7215bdc8145cee5856957bf3f20719f65c73033006243ac2a9e347394b
+dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d7541a8e83f7b8a9761988c3ac295a665e21e4d5dc9e2284ef48314f6c784166
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.gz=f20ecabfab9d8ecbab44d661018b865e449137993726e76b20c7749db4d0986e
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.xz=7da2cf413c0665b07b3083862747c9815a78b3775c2bee6cd1f7551e7f2e4c8a
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ba1b4f772faf2e738d2696eb576f74bdbd1fed1a073053eee341ec6423b6e1c6
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=f3f3eaafd9ecb1ee0ba68259d88d65ced56f20323a4f542fc85993e92a044206
+dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=38c8b07558734a9fff1807a823af72faaf8ab5ea47042f1b88a38d6c3648c43b
+dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=e30e0000336449a8aabf60839cba4ecca32cf82b02ed0a7a23935793072679f4
+dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.gz=676786bd5e7f0739d18d40d99158045fcba746dc306485c0f15ce49ef2b63b0b
+dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.xz=d7fdba095ca515454034891c8a862aaa563ee7451289138ce32b10691dbfe38a
+dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.gz=c12bc5543c262645f7000cc84247518033f15fcbdfed510eb92393d723906eb1
+dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.xz=a5fc26dd6068cdb28ee2a252af545a34dd2be6e075e7d0aac2d03796c07579f4
+dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=dc20c2fc14b2211bf4517464109871f940a227298302d2ec84eaca539a19e9b4
+dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=5a7fa24ca3f7b43526c116a5ebce60f29116640ad51c1ed426f9aee705b10897
+dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=db784556ebf56a79e6330de3204ce6ce5422eca2543b872ed55c238aedbfedae
+dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=373efe8c55e85aae60dfac234471b76fefbc2ba722d97e0338ec593b7c70cce3
+dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=809d7f027aecc4a131921181418e66b956ad0a2a7170a3ec3649e21659c5a524
+dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=1b9589a72d2902cd4491406d93c599d2e850fa2ba19b1bcc6bdc5cc7196f9643
+dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=3ea692ffe99c953d0049c0a16b71eb0bc3da492b9f9308463311dc0143af84dd
+dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=97005f0d686a6481c5a532b6e1ea14befc794ed89394a8f1c94ad39257ebdaa8
+dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=6d7210503568d9fa02231ac2d9a1b400d00a37f38ec8f00bfcfe45c325aeed02
+dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=cdd81201e38226750f2b4292b099b5d78fe0115cedb4c28bf20200144297d8b6
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=44ce7faad791029b670a9d815766a647d488dbbb56eb09024a09a595427fd19b
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=cd7011512df191100d31caef920d1a5c6d5ec2a771e0b52078d5d60b45e9a497
+dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.gz=b40dbc6ba0f3f80414bdc11260f291f067acbceb50d84597a9366746cff53348
+dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.xz=1564c3215b173956bae41cda7312ed7912812e0fbb65dd8d75808a1d5084fc8d
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=0da01efb79d43140515c48561cbe7a2fdb83895fe4351f2fffaaf108fb163268
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=baa52bf16290d71b1b89f12ddcee5adf18c480071f9fd4daf3fcab72f92fad4a
+dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.gz=dd38446053d1500f3bdc325ae5cd52d0434c618d79a7c0a0473c76691353bac4
+dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.xz=5b82a2f970be59563cc4f550e4202be802cbe21dcbf14de413ed8f30b0e22020
+dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=33fe3c61aa2e93c6a925b132fabc11c24e102cc070260d5f89a66e374e9a4d23
+dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=f50bb682fe484f23ae1ae9b2466c450b8fe9ecc3694fb68e162ce43cc8917af7
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=58dcb73ba02fa38742d255bd346a77340cf634247904624c7af9b11e769a364c
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=ea4417de121ab7e869659b26efd144baf2fd839a956da4acb30121d1bc9132aa
+dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=fea794a4c8aec3e5357199db7a9b701ceedded1dbb50167b002d368a6ae09cc7
+dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=47fc6e497bd4c8013f708ed052701129c308b657d28ee2dce877cb63ccb1b06b
+dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.gz=4169c938b638faff18a5db1bed5e7d2036f45d25ec9799dc2967ad1589d447a9
+dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.xz=8cbda8eeb98be575b78170e9895390e9406c4de41db8363988185dd24e276427
+dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=bc6ae4d5e93b47828678f1af55efc1baae2d76975be3259854272a566f5489c9
+dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=51cf1d675e61aaeedf895e52a9a81b188aa066a68d599963e0435bddfd2f6a5b
+dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=9dce2956e4b01d867ef6c229dbff9319a779a80e43a29fe1f8b10a333049264d
+dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=b64e7b87027dceba21283ba71430a8053a918bfaf6c071cc70d5f5da00155944
+dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.gz=c675df742bd9fbc01f67411a19926e2814412f12e09b53d1492e8c7250f3e685
+dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.xz=d5b9c3783f6d2dbdf25e0495e32a295c4820bbc5b65a44f19f018b1141e85371
+dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=fb33110ad649aac6f55310e6f03d03d4d75ccdca43ada93fb97a717975ef867f
+dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=cef39c2886fffef2986e9fe8f3be58f0d7f3846466a35443bc0d49464bdef98a
+dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.gz=a9b3cfe03b3053cd533ff02fb54f95db009396802464f32840b3369e9a3e6afc
+dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.xz=9ddb6b8291ade9224cc76f4d946c179bdc6e25f5819a4ba1ebe1f207d4c663ac
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=b3226669f49ee8fc89c1f84855c29f8416df3e32d3276547f521f738179164a6
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=9a5711743a0984ab7baed2a50f87e50d7facff2ef05f5b936b7b25f5a5992734
+dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=151863cece818be834261e6c148eeabbb1c796c991065c84b813bac64e73fef7
+dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=94cbae695036a4a1fa1faac12a6dd5ebeea18ec2d6e7b01c311d340ce7ddba39
+dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=c6147e9c6c39501d133a344972dbb8108bdc45bb2fe8ad624162ad04a9c00c6e
+dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=6207bdfe0796e4bd4e7d25457d67559f15aa2e8bb91b05284ed147f8799de869
+dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f971daa3f8c3d0773fb6667cb7a544f96ebd049e9b5d1b5ac4bd3ea0c342467b
+dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=3cd2f4ad7d9f41e9f903aa49eb86d142bb5ef69c2c39d9ba16a00a39d74046f1
+dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=0d103e0c4ec8039dd42be09bb9c74f269a9567fe7dfacfc54106912cd2aeb35b
+dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=4b3627e9e363e9b2fd85222c677a7250b12a5d32919f38a31ed7375637a79a81
+dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=748dfafeb6b953017b9129be9697d02a73d5bc8b1371a6a00bbfa20b7b45033c
+dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=0c9a0717054858fa821e4c418b9e99cb0a0f852ec3c866951c1d1795cc1e8152
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=85c3684f175642463777aa69889a20391e39afc0d6356baa3ac0445f7aa25119
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=a8d67436a8ee232d57e2924f8f9e5cb0050c71740d57a4e677674adb75093f31
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=99a14bf8cffa0c736a25ce117bc5d4ab64963d81c9d9ac377f118a77a6a3c4b6
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=9902878b75b3f6cf944909cf6d17efc26dc820708b164b34757d841e89c948bd
+dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=f2840d36b089fdbcff5f6f9f7a6e576cf21836824957cdf2d1ef2c75a1f5c11f
+dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=5723cf48a1ff47fb764cc5ad921356e490997aa09ecd86404e370ffdacfa4b31
+dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=53a17d10d498f1b6ebd6852987f304b2e1187544f2c9e91b69d0fdbf88630910
+dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=fb97e6f2b047d6251eb6e34891b64f20d0dbc648beb78bb7364fe563670d7de8
+dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=b319ee87ee034a6a2a67dc2efdc72f8285c73d9bd1bd893586170ac54049151a
+dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c751e65bbdfd72de07abf138162ab64dcbce51ba50375cef5ca8f35945d9ac7b
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=a63c5d40bcf8b0702c1a91e992c042130916edfdcf94fb4615ba10c89dad6642
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4706424b53063b768223880d87bbec0cf57e524374a6ef053ebef02d096484e4
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=c47cab4bb196e749f07d03f6f6c8f2fe538c84a055a298f0b505ab98dadf4a1c
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=b36aa3f0bab63ac21fb69610d379a87fbd1ee87041153eb1e6886a237d22b171
+dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=ed1b9141bd68b8c13e295904ac66d18ca92c5b92a263fa5109262d15065aeded
+dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=0c036271c4c4e04357b630146cad296dc6a57363f7dc0cd2f3142ead13bf0602
+dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.gz=da310568bee0d4868132589399c9229df5ac575a028f2409f51fd1f8c9e81779
+dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.xz=f3079ebecbe5b9f23495fe0966fc39fee1d38869287695804c3c04d53df07496
+dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.gz=baad78bda532ed77dbf3e4265595b9dac82f6fdc27dc6deaf7386a60b981b927
+dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.xz=cf4283b1224d4dac3c55da905608c5bba7639b6511977f3de344a999ae39e571
+dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=e84526736c1a48dbec3b122b8c01458ff549afdbdd0f73e705c76cca1bd1f767
+dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=df8d9909b0afd0e02b9c027f12e28aa2c40716d7c8a8f5e82b7521d2e145fbf8
+dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.gz=1f11ad1a66d01a09c7237da76327b70ae2e2a9f7647a3ee0de58d563576efacf
+dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.xz=960fb614a927e1b3d1d8e4a9fb7220ae675d0e8219fdde204bc6454fbe69a0a9
+dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.gz=8d56f1aa8661047f854806278b83a514fa79b7a5097635cd095943b3f848ea74
+dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.xz=78609204d01e0d0bcbc1fb5dd3d9cfcac60db23bfbd2428f1e021d1b05793519
+dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.gz=84d03b1c1fc7338895f82f54fdccb18ea6c4ceb43f47c3d46fadb014aa0c9549
+dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.xz=f28cbf9552e3c680342364087e7305a12417a92ed6b6696d71d476e1c1d8d4e7
+dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=44463b4a17c87a2de8554e2629eed8172b60b078ccca7e78bb2b0a20324f51ef
+dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=1e4c3a1d8585aac5aa3e66541b4aef03a0b429a6067300c58f6cf588eac19fa6
+dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.gz=6142ea4cdff99902181379fdb9a651fd9d1ab6276ebc104e73b2280a6d9f380f
+dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.xz=bbf4c74f6b6a32f01d03bf101f69dd19b909717036117064fa2c8cdd0b4146da
+dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9d957edfba201b541bd589ca4085e26bf6f890b3970817fe9af6ccf5f2eb0854
+dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=0f867e1391009d1d0caefb6b9217fc8e9f3e087a7dd9b22a157719bdc44ac074
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2325e8bc225a24a0a8c16da6dded16d4befb671b913051a7cce12ee3e183eac7
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=ab9ad0ec7057deda5c29e5d7de317eb32512fb95b62ba628b91b5246dde9c90d
+dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=40d6d48dea64407bf31be39f9e0316a1e47648ee75bc0d3361edb961e062aa6b
+dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=3e01648f45e0c7cb040d3c293024477801930d5078d54c6291ba13aa8eb4e1f6
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=710be82238e9ad617b2d5f52ef37976b415e7b6ba3d5f3677080f2ccf78b9d44
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=2cd0956277cf963f95ffa0104bdcd60cb4e6c4bb2a443a683d67f41726408159
+dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.gz=9758806233e59d7d40eeda0740559d9838f9a6c608309567af61245ea57dc212
+dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.xz=4266b69d61a46c0c6f6d3aeb2b3378ff88201039df50cd8d3a51c9ff910be181
+dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d931a3611003cbe61003ca4feeb637449f1d10f7969cd27ca37f11cf5536e465
+dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3c7a3a9e1e03c2fe097e2e7353d00d02e864d3964db559f6a08a3d33f1fb7927
+dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=a02ccac46574fad8929b419eff7510b8a773211d3ccce9ca96f0485e2dab8eaa
+dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=b70f37cddd519d0d207e28089b469f702bfe72ba5d32a631c85270db75b83d61
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=3f7529ea5dcb17c18efa949916dd1ebc29b123a265cc8839cee4fe4e637f19be
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=d2a30f8659cc66d48da0e6c1919707943321d7f3ac0e2d58a9078aec16c86ef7
+dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=34b21aec2cc1b92b2911211fe3c798918ea6c99d51975f6a979c2da3a09b0a05
+dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=50ba48e76e60ffbfb2bb0ba0b8e12418b7f6a9d7cde31b508bb4656536934e82
+dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.gz=3af955fc52feaee2d89d6d50e0df4d00417897679f0d607a0f146a8d34c20496
+dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.xz=cb607387d0524bc84610cd6cc0a0070e0dadc379a7fb1a736f3f336cf0458b8d
+dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.gz=a62be7f900cec101b1b7444c7466e8fe0b823d708fadd92bce8bd531866b4938
+dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.xz=993875efe27c1018bbcb8326665247a33eda6fc0e934f71124b0a08d72685474
+dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=07b356cd0ec3f18617e8f5be04d784847acfca43d6fa2101821dcdee18aada36
+dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=aecacd11945e6e053fe27faab2c0816628b392cb06c41feb8ed693d43043eba4
+dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=17eb45b10a0c9cc702e7fb4f0c7926591d3ad0f052f2bded9cf852ea082cd2bb
+dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=1f6b1a3082fc29546e4d8dcb20675f62ead20fe96112998dcb1260e206e93cbc
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=be6d9a01609152eb815cef9462023f0ca2f2950ed03d914629d8e6e3a96af8ab
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=75ec6023cf9a43ec7ed0f52a1633b56154d9505c5d5d769153b48b9991ce99a8
+dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.gz=6bd4089f30f05d9902d667a2d48028345bd558e7365bd3957bc554a4d0c1f939
+dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.xz=2a7e9250e3bea7f7e502131012139eadb66c71e95e8cec1698e22b21e7c9fbcd
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=3f8df0e35e2e8d5e0f8181f20f0639323aa8e8c21da60697599447c0d77f783a
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=d0e727d9176abdbef02b1276b3b1acf69068b9c0fc0477fb3248fd06c99292b5
+dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=3f6677ecdb1a2f016e9941234c221b06fd0a21cd9bae83a59bdcfde055c4878a
+dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=60eae08756d92a70b740ecd8a1412138a9a14486289d73440bf7ee068586f9c4
+dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=7bf6bdb443503d48cb711f8b3e2670fe20e02f71ae940c2f1b273ab1d15452b7
+dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=9ed34d7467722660d625e9a048fcb843bdb80aac407b0395a693a5698f6c1465
+dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.gz=92de36c897dbf90f9986396da1f8a954ad7b4fdab3e466d63974c82611e76d47
+dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.xz=fb5d50ce34bd222c1b624e5aa2248776f8926f3ee360b7c4c1e0bd412d01bae2
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=73ba835c5c4c9fcabbcb4e1460d402cf0c0aa9b2e01342521897abd9769dcc02
+dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=64e6fc64ccfd0adb2fabc610eba6e877ab83f2de49532363deef4579728baf6f
+dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=940eef037faceb2b9bdb1094eac6b175843094d3a3ab3c9850eb28742643e92d
+dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=c892b8a80db788d1f4bf64ec6f740bb1168a8b9dc88d105366892a476ad3c244
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=54b83918128c3d19b09a4e1801783500266794395e6a6f138ad647bd890b79f6
+dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=2b0ed80c922e25f3783fbc0ce181b76b7f758d2a1b85b823851b7ac35c6872df
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=fd2db70418d432c7b32bed92f5af0f301baa3a71c171d0ee8b0798bbc8e239e2
+dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=97922d70b37e1e2ff6dc447625b3482094824910a1d7a483cc707985406560ee
+dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=949a18d9d8b4c7cb3442ec4e387c91feddf0cc26f1fe602ec6c2c484312c9845
+dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=7adb9a93d35002d0335b3449b8d9af35a80a35524fe98bd86c3896481f020597
+dist/2024-07-26/rust-std-beta-i686-linux-android.tar.gz=d36c3baba2df9d69e197a773f752bc36e107c2411d78037a357039a856e35aa5
+dist/2024-07-26/rust-std-beta-i686-linux-android.tar.xz=14b9bedd1bb95e1bac2bb028670b1d9dbe6998bb6ad0cfab1db0be0cd9e3d4cf
+dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=7b671c5257a7653481fe6bc090c55398607590292590e0fdf5973f5f9b7b18b1
+dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=7f4d1a8e757fd29f4f58005032608df709003098eb661fe98a0b3116b7237e6a
+dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=a1c1e3e15bea1c4e6c70b8a56c4fef1c231b6ab5528c32cb69ded38456b3fa21
+dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=43b31f7dd50621faff96c13a2246c80e84fc4da4076d4aedca4e9a6bf63ca43b
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=a7116c13a413989f2ed874d45780aced3299c4ef8ce8e3bc99efe960a73cadb3
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=80ef87143ee2339e90842c4893284217ddfa56926524baf94341277c1210dd07
+dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=96afb9b33c86a6007f9c02f1f418d28f13014ec5154b648ceb7f725449dcbddf
+dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=7ed52c039fdd13a7477ed211ad8432cfd2fab98832174c8a534e5ac280f28572
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=ff2eb11f284da7883dbf6ae465af86e50a9cd98c9b7d22b1e710626716e07db5
+dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=953fedb9dac336cb796290f619919f4ff9b2a6fcce09e23072f93a40b5498bdd
+dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=061fdac14ee0bd3abba36269f68e9ad25a243ac7062f946155f98680f484a84c
+dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=8acc12f14ac643b822595a6a07c7e5ac65855b83938ac122e3278f64769eeb13
+dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=f877200e388345c10d3b0f5b8c484dd42905e769dcc1e21692e1cf7f2d59317e
+dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1052e8e5681c95ed3c004adee2492ff19d109965e9441a3362df876719899486
+dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=2aa967414bd03764774338e377c4714b8d169b1bbc651624a20158441b8111c3
+dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=d1a3b6ccbc55d1d9555674d1596a0c9f489304f9cb211e0c4645c17256ada4d1
+dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=5144fe563c42205ba777678291950bd1b8c2b010b9aae28e2fe96e14e93e28cb
+dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=6e55e79f65a02abf37e1533c2590f53dfe56b474b58a3220d88f3d1458b6dcdc
+dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=b1d9d5967c039721eda402a7227074ba6e6e8f2877be49eed961ecbce00004ed
+dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=2436343b99d81abae0e6bba16850dbc1c005ebba5defb991c3a0e99834410746
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=cc1d361b775e966c700d122f925a9f2feacecaf7d2891d9c5c5a4a1060336408
+dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=934c10c58db5d7644bd0b7df6c3a128cc53b88b412128c33de5932fa0194f4bb
+dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=3c8ca657208a4d96eff193363375a33d966dc319cd329dd7a0d379e052ab43bc
+dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=037f7b599421eca888332dadd797509d81af04743eac06120a9882b27aff5ca2
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=199498df7d94989d4ff1773fdfe86e97ac99ead487f402d020f78688bc6dfba4
+dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=1337c2f00e9bec2e0a553234d74daea67a9781459d0abe3c8de954981d9354d2
+dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=53c64845abe4582a90041b2128b3f931ce636d01fc9a8509b35ded5dd7ae0a35
+dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=61805cfca6e7f602eaab0fde2be48cfed244105b2f4b5bff798752ce06d62713
+dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.gz=62f687da4c02bef3e114b92c75b62fc6f7fdfcd210fb66329f6d4780f7dbcd70
+dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.xz=f9346e9ed4e5638f58dc237b22aef9e1b25b23bb588c736dceaa25b7b935f2bb
+dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=01ba37e80e18e673c275538fc0db63b667ef52a72000dcbe76ac68018bd585e8
+dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=004f5119454fa53c2a7a58f6d176f65903b3c5bfc8eb1f894f6ca4e9bc32b7a1
+dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=cbfc580db37b135a20f42f9da02517ec8cf0a286b7274252c23c6a4947ba6755
+dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=dc2198fabb6fe6f68353c268698dece4ca3d6901b424a7cc2c68850f81f75f20
+dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=bcd0e100d4c66784a2357be74813551c68d4e3b5e6846bfd1bbcb316e5c82c53
+dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=cc31bb9f5a67359f4af4743afbdf9b694e40cd209211d4ea819c94183de6ab60
+dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=46ea726328e1700cf2b7d0ddeb16e25ebb648267c76268ba2f4aecb75ba47661
+dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=520ee25c1f18d80b4e4ce25e8fd961a19c0dd2ee0274e9d9cd3201f7c57c6f77
+dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=b36871d3c88eca54e4c24d50171fd649d10a92f689d4812ebef7b510f0c3d799
+dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ee550d60ae217fe7aec12feada1ba1f84222427677de42382d192ec748f73f18
+dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=f48bb7b7d13862edaa8949be046b5bd2b8c63b0aab8e29bffb1940ec149eb123
+dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=0a6e09604fe291d0a9a0845a8ac7f434c9f4ffbb698c042ba83a070c23f804fb
+dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=1bf5d0201ca87a76de8044dd8222517bd130ef3db631dc60a84e2fceced465d7
+dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=2eaeb6863c655047e6c938e208ae952df4da2d8b4326aeda60918414764aa7b6
+dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=92ac04de9689176a42e5f0ccf1e44ce78b64bcd15d6e570c171d51c44cf8c6ce
+dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=59a371de4343d330b79e84f629c98b5cb9dc58bd9706d1a7a9ff474b28394851
+dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.gz=521f03a968c6e0640de6f09ecbc6328ea57b2815f353a14e1d4dd09925e98366
+dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.xz=14b733585cc768d26a822de630d990f519b6d6b4ae079f09bacd51b7449c18a4
+dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.gz=58b31a781da4f5215b0fbb5f355cbc3c5b2212971c68a1e00de19b851698fda3
+dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.xz=008125eca7351844707c9c14637030da45441a68d74f6e2752ee713f6403f03b
+dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=f2442eab2908bb90c551f56da8889e39ce44a31936ce63e13a54432105a67cf9
+dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ffc8c803668d09333fdfee996fa72c8874e91d92567f0b4eff9077d7b9a3070a
+dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=74e57cbc139d548202d94262170ee45e33ae01331358ac2eaa9fa67c968ea1ea
+dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6cf99b689e32ff0caa56e9704dd185f6c268b484ccb657eff212e66fe64d1c10
+dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ed13a39d74e9d814d585ce7fb1aafd093f94317d6ead76e4b43c03b01e210086
+dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b5379d677d6596ffcbd7f3ebef2fd6d968096228101104a45565b170fb050042
+dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.gz=12f6a8d3d17b54ea260f6f5b19be9e208111b0ad37518ae6b6eae558d77a1dc5
+dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.xz=221c9cf9d1fce2b5c50bcf8f435f5335f1c5e9533f51d52b941593d6a964b4c8
+dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=1a29502881e6512a8bea566a90781870181f5727359668fa3bed2b3210a21b8d
+dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=95970245a7f304c6b83b8dad58b4c877ad2c9b0ca6bfc0090151561ce53a217b
+dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=97f6b771f7e559df03f00f8665c6580535499d4afa7bf2a252a145b1aa0e2c0b
+dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=3ee58d5c57ba00e27428392dab1d69655bf7e997a0d3aa6629bb32f4f863396b
+dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=edbdd5fc1e9bc5fdea67e7c2fda3fa9f3eb3f599c307a278bc7bf45ff97d1f48
+dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=9c7d487f65a6273b76970b2c057b8120abbd89ba67a2f92dd446ecbacf218576
+dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=7b7ef80aa6131ddcb8bfec0f9493417e9a1e617a8f599a27de52ee914d022f95
+dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=647a6d0ff8f38dd4404c0006e5ed7b3a981dc89bbc334b1bd53225cc4f5511c8
+dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6599270c877164e76ef30f00a9b47da1a021fdaf1d4f7fdb194500f861ca8d21
+dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=46429528039b5499c6ac4618c4b73fcdfabf7fdd5ed9f9f3d64ccde0428d78c0
+dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.gz=779d704f8f64a7290227631d1e396fe00bdada3cfb7f3e6c775a0bb00047cb97
+dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.xz=8cce8e286ff04f4d58235e8716a0ca05aedfeb9db6fb8952c523264ea649e542
+dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=2bb2e69563684bf64607d3f584b4216b24fe190dd2eabd6c00c2044290beabde
+dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=454b0dafb3cd62788dc541ddfea5b484ac799253937602f6456e853c2a293707
+dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=fb710b6ae058619042bdf80ef5c2a56457076692a122b4155e0a53f382e8ad83
+dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=ac15e80c28c7a4570bb4a99fa70522a3ae5ba602ce25e96b8e82d097f8b42904
+dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=6907a40c1e7b18146ff2a60c6d44c9716f31cd4aeaae4fe858032aa26c359d27
+dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=4287d73ae2b3272a1893c2ffa32d007edf0b05ff2dbf1da92aa20f2b857e0eab
+dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=101e3118bf23246195b159abab59ee5626e767977d97f00e71fc5e67dfbf7784
+dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e40c0c15a7b195ed03c5e1167c2cb5e765ef643b0f6621c36643faf87bf46369
+dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=f794412df97e19240f628037f5d1d7391dd09ee1a6de02f4dbff72e2b03d94b6
+dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=49a78a14b9638cabd19ba4261f5bd04066646e1260146e3be288182b73fa1864
+dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.gz=4c8991c692f200c6a5f25957e6648e07b7271681cbd9c61749bc990216dbbe6f
+dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.xz=51b5b85d46af2a3faeb53b81472c285eccc01f0c83575f62f37739cd48397fe2
+dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=57f7109bef934d0da06f7aea6eaca72b0e66f82d1160fbae05f53c2276da2b82
+dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=5ed50d8d088ae0d86ba51a03bf56040da027376f70b5114f593813daa4ce7a40
+dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=a2cd11651304ecf5ce6a1ee5fdd1acbfd36b1dbd2680cd76f2b9d3a86012b837
+dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=c8a8d9fe8badb1e06811412a15ce9cdfef07ecc59bf83cd578b33889751bb560
+dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=c2a30c78a6ab64d1655651fdd5c7f970dadcd6dfd1a585d130bd890190fe67f6
+dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=05c2a38fa5bca162e365218670a7c195ebd9b3491d14464282a273dfe93b0ad7
+dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=267b8dd0b5024152e36bcfb15af0b8ae3c68a71f559b8ecea1a3c9a8982e315b
+dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=6aaae715599da14ca8cc405e51deed3bc160661ec56e929ae347ef1ead7ccf00
+dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.gz=d8712ca2ab26256c0fade4ecc8dd8e4ea6770d91e16e460ff2fe3f070febc59f
+dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.xz=9d0c88881e0535f9cb4a48f59b389b1c2a0b5fa46ad8bfa37fbc540676a8f557
+dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=4009c19d557156e63ad7123d27264650d046cd20e723ec6cc8ffdb3fc1d3b8b1
+dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=9622117651423c53c35f69cb3087a5294cca098ac93aeb7c18bcab035a1e69ef
+dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=89bd927bc9370a405561f6534c5cd88e0f6e06b0b512589e5722349b12a17763
+dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=732120c4fcdde08fadca139216a91af7a6abee15f0a41735dc8860b36039d88d
+dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=3dcd9775b46a100a50fbb00188dffdc6f07fca9843994c8406a2d053e41c1672
+dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=e069b852ace430b2f75486a291d3d7849439c67c3381f5eedc0d6a9e6cde56db
+dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.gz=ffa017562648e98c7229e43a7422602c265441228485f0e14e52ebaf48a13e91
+dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.xz=292ab3d318a34e67463728752dc175f65cf5530f9368344dccaa79bad4df3b85
+dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d53fb59c723a2e76f1716cf1c82aacd2627e1694aebf70511c24529a4fe1ee99
+dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ffec66667d95cabc893cc87988218552eba8930f031419612f80144dcf2cc881
+dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=75ee727a80119a810193519535f962721d547297feb9b5597b397e59277de701
+dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=002b726868a14df5ea31fe8eb75fae24660fb1cfad73591e86f9179dd1bb2dc4
+dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.gz=edd631b7938dae6bb6c2694df0dab3ff6670e1a5ab3b5f0e6ce5bd7e992b6310
+dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.xz=e4bc44ff13cfdd70f94c5efe86e93de041599e570c19611141c00700a656b40c
+dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=e467501c65651d519ae9a489e821e7d5dc82fdbeb2da2d4c75f093e1b898abd6
+dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=9dcbd07899af86db3c101275ab0f2fd3b5b0c43d4a92c5b5be05f0e4500d7535
+dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=3a7755c10b32ee3b4f95875c974f21efad2be7ae27d317bbac056b3e5b9298b7
+dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=718692e6a1e00ca042d9767273e487c941c65440e64729844a46e42ec6a8abb2
+dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=1b1aff83773de4dd972734cb03209eccfc3793f442a1a5dea51f451ca34cd1cc
+dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=71c357ff694cd954314c47e3bd458465453c65e6022799827b8560ecae16fdc8
+dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f6ed6391c8997f942d180cd32e81aca654450fb050cd865a8a1b13f77a892245
+dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=16e736f65b0ff029fe9fbafceec938123dff1b5a133f6c48b25edab379a20685
+dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=18da4a1fac25597186bdc5c825c71bc6fe020e8e6552ac97dd307a0311acab20
+dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=86a7ec123586e0c953efd23b82aea5eab62ab8c065bf3596d3001a23b01243ce
+dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=01ba50dae501edf3afa60aab59d8d81ccfd91126ded4cf7d45f7c4b13fb8c4aa
+dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a7e749bc581f9c64137a00dd891c4abff0d7f5684d2d501aad20ed1b01d9a312
+dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=f19081755c37e3dc43091b06bcdc59c82b28c6fa0a78ff02d800a25d6d9f22f2
+dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=d5f222e23f4f0ed4929e11684bc7b861c29fa183fffba0dbbfd5739b921f5234
+dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=d4759993b9659ad8354d3fdf858cf99efebdf8202442505e11b55d24a54b31a0
+dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=e29eaea7b7f2e54b9285a2216f5b85440313650090c268048ce9e830e007fa92
+dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.gz=a88fd4b3e30faaecf270936422e254a25ff5dba93b08ca4003a9978ee80d0838
+dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.xz=f391b26009b7089f3d49d2f3409bb4e02e3de0700284727d2d26e7062bb18011
+dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=711fdb406a23ab5c3b1199e7af06608297bd071d7e48734a03bbc1f7a00b66dd
+dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=36d05ba29927b56e0d815dd09b39a3db12b6395e9717e653c20449fa83aa636f
+dist/2024-07-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=b6e2e07fbfe9de4e41090cb45fa680d6c402f34e37d6f5144f90896643ed51b0
+dist/2024-07-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=b83c0f949d898df72c1a52eb41c1110bc02e101c391ffd49f67771d60b2010b8
+dist/2024-07-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=ef6245c042b255729112142b94a15082adbd172ecf465fd235aa747cbf29bb1d
+dist/2024-07-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=c55ad9c9ef4f14929c00c3378ae9888e268c6ac40d53f811a8c4bd5f90bd9010
+dist/2024-07-26/rustfmt-nightly-x86_64-apple-darwin.tar.gz=5fcbe00f6adca3ed5d76a7c68e69af8103ef479b1ca09b6c81f1c0ebf3bd23fc
+dist/2024-07-26/rustfmt-nightly-x86_64-apple-darwin.tar.xz=ef8d4b12b85935517ad767a6bfcddec9137560544503b4550b3d8b6d8d0b6d1e
+dist/2024-07-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=d3fc0be767f6f1bf17fd7d98bae14a2a8b57d806b8f968120d2ef53d51809603
+dist/2024-07-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=7c32a2fc5724e5204287caf6e9ffa41b0dc9fd52de9258732b5fa875e53a700a
+dist/2024-07-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=45b73c64128663c09841822c8fb3deb6a5a301ed263278df371ce01d8ad9042a
+dist/2024-07-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=8c95bb793a4c527cba96032d6f23555d2e85ab29ac95d75642fcd297fef2daf1
+dist/2024-07-26/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=a5c15ab3650fdd6141a2cbdb9c830af716ee472d8900d140aaeb7032dec1aad6
+dist/2024-07-26/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=24c0f8efc889d76552f0ee80dc397fab2f6c142c0b6a1b72e3ef2975b9c05eb6
+dist/2024-07-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=7a703525762f4913715327edc4945a3d55aa5dec02d985432cce83aa9fef1470
+dist/2024-07-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=20258cc2bc456a689f6b6abe48eceb49993ff4632b138855390091bca83cbee9
+dist/2024-07-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=51080ea5308bb5ec3dd8be62dccb0ce04744b9b48a619c08805d35068858bb4b
+dist/2024-07-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=ea11bab9e90c2bfccf734e138e8b75b997d14d5c471989d6e8fdcab279c8c16e
+dist/2024-07-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=efadb18590ca310697a4897f7a441494495d01f235ce92fa9dfd3dedc1027a42
+dist/2024-07-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=c2c36fd4d8fb2be887db1f3f3304e3e0b7fd1359868d1d221414efec631a1beb
+dist/2024-07-26/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=c07217e18d83f5afb4b57465861d1f7dde670c17167843f2af7f7a58d2e37a20
+dist/2024-07-26/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=2e2c8bc75b7691e4f1fca9b4fbfc3d6ab210ed216a334838ffda11c51ca19707
+dist/2024-07-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=66e882dfcc22f8b8293aec8ca5bd859a322c1430c6ae6556007e5b4f15e380c9
+dist/2024-07-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=8ed347717e758390d1f0a31412d8f86ced65002a316b15e48cde687e67ecd60d
+dist/2024-07-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=84917b3c08566abca67f6039e483fa964b02c775459b3654e7b72b80df483d2b
+dist/2024-07-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=6848d6b2aef03f51dc8564716c8a3761f0583b8e360d5223058ad746a366d91c
+dist/2024-07-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=049c174a7a4f22865ec7d6bfa1dd84a70f2da83677aad3356ad2e007ab167be8
+dist/2024-07-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=29c1e5a2217ad531b86da6c01c1cb94cdf1b935fbc08d9dab8088b9985dee140
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=68bfff981e0e8479a1335cd3a143d220a36091b08bf7d80d435fc999adc8e7d1
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=ac4f1ad6528d295374083e4edfb6bb8139979a069f9946c863f7764d0a6a1a58
+dist/2024-07-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=427caba43e4aadf685d09e838aaff0e2b7f805afe6efa557b6ab6f65afc45900
+dist/2024-07-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=2d7447476440878540deb2e1f51876467b77b5591b3207edb313675377069a35
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=1ac2c3f043bc410c5b6dbdd996ed4d1e1ec2d7513b4a21e9f0c6f51ffd5189c8
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=ae904145eb7086de7c69c48a0958e1d925db9a9d51cbf6738a71218bfa684963
+dist/2024-07-26/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=476a6944de96dd26b9984ba7248dd5e9394784c2e5c0fe8ea13f79966d284240
+dist/2024-07-26/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=4f778cc234a97fc8cc1d877b3753e7f466f9f557216cc4e1c5eb7f157b6d3811
+dist/2024-07-26/rustfmt-nightly-aarch64-apple-darwin.tar.gz=bf52d6c3824151664479cef6cc9c57dd94f9b5a2c89f6f244a46dd4438158722
+dist/2024-07-26/rustfmt-nightly-aarch64-apple-darwin.tar.xz=d45ebae395b15a651ec7f6fd17f52f2cb9561d7e76faffef090d78ed47780442
+dist/2024-07-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=8275a2cc79013a9025ba221f5d02735285be022ea7d2e3aed4eeef3fd295cc34
+dist/2024-07-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=2dbfe4b19e9b82b249a5759202322fec4ecfc4a089f0aa14e55a245154dab6ea
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=bffcc6e98b736fa7876ce9634eafddc0508b22177e2a0510e665bb3e7219aff7
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=8fc38e8a25724d21b8c1cfa2037abad5132f798b595989e8317104d28dadfa22
+dist/2024-07-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=8b924095a51e7c4a85377cf626c684aee29c8c9fea7dd3f6b3118bf07b45cac8
+dist/2024-07-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=527a9ffe420e944467485f8883437fd2a222c26285013a961079025817c39a08
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=9337cb22df008b570ed28dd896c6dc042081b3ae06b3e02d5e728a8acb1dc467
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=a84d203bc42be497149f03fafd9338392d1dcbf097012780a12cc285cd05b349
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=02a86dd1e924fc4a87b728bba307bc66b871bb14c73dae70cfb72b4e617a9ecd
+dist/2024-07-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=4a9f35ac0ae4fd6b5fa69f3152975b9eac3a8751e9e1ae87d10cd984a5f412a1
+dist/2024-07-26/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=3c2dd7afd93117932751cce5c016006b4104af85cd9997131e19268cda603050
+dist/2024-07-26/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=4b4fb076ab64d7f86b7f4dc77bba378357bb3f4d000528b47b80d2f8a0b84ec3
+dist/2024-07-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=384eec30f643dddd70d392a42adef611607d35bfc6f63665a8d90fbd9c493c8a
+dist/2024-07-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=af18b698508d661b1cb5d725fb49794e0fcede1a8e0f5018a85d7e1e4f3d5486
+dist/2024-07-26/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=837e703a43897fede9a7ae5319bdd7c21990e901fc38f5f836dde347705c5788
+dist/2024-07-26/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=c91f5cd535e46b7e58829d5681ac04213da84aa4c219fe56822568599fe7ec76
+dist/2024-07-26/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=cca2302d56d4d2ee44167bcdb7a30c34f38b8f8541bbb2bb19abda3d3e7457fe
+dist/2024-07-26/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=d943576b06db887441e7ac123c8b06fca2e84ddb1fa42ad40b4fc502f7158afe
+dist/2024-07-26/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=edbbac62919265c23a8e2313cda9708039fa2d66c0db177e53716a8927d444ae
+dist/2024-07-26/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=7bc3377545230cc80f1faf4f1dc5b07d64c57fe52beea95137dacee62faeb331
+dist/2024-07-26/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=b10d79eb7303b07f0d2f421881b642523b471fa0f9dc822000b439ba57935062
+dist/2024-07-26/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=a92a8a435f8c7c79d5e433ad7d4f559f483b352d3d7eece7ee0e58c927b1c8d9
+dist/2024-07-26/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=06ddc3690e06102f00977094c2f31d9e54814cf4a7905bee3772d082440063b3
+dist/2024-07-26/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=7702f544459e0e1faafc23e5b98061f52f783d1c9030f5d759f4bc27726b79c5
+dist/2024-07-26/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ef2eeee07a64200e3c7d2a6094e1530a014a1004d3cfd50de2445ab59b20b090
+dist/2024-07-26/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=35e43032e091c6e1fc217dcba407f2a23a84a57007d8fd72fc80abf12e1dafc2
+dist/2024-07-26/rustc-nightly-x86_64-unknown-illumos.tar.gz=814a373f59bd6a0b5e0252cc91a59b48a16f74973dd722e1e4a6699f37d9e2d5
+dist/2024-07-26/rustc-nightly-x86_64-unknown-illumos.tar.xz=231d060f5443b5b8b55771ec7d1a7fa99ddc34ed70112d227e2589137b6ecd61
+dist/2024-07-26/rustc-nightly-i686-unknown-linux-gnu.tar.gz=69fcdf5b9418a6a86ec3bd6385d5d77bc0be5a1ab371db10b390d2c78721e23b
+dist/2024-07-26/rustc-nightly-i686-unknown-linux-gnu.tar.xz=c7f6b21175d19c7bb5077ccbddf58df36e1547934bfcb3e33db4902d4fbf4760
+dist/2024-07-26/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=b636e31098fba7dd8cbe1cd32866926c44c5ed61731a05f759a6255cafba92f2
+dist/2024-07-26/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=55a3d50acc5c81ed8a86148f67e311c9ec2fbd119f603dc5fba2f326a7ae0914
+dist/2024-07-26/rustc-nightly-aarch64-apple-darwin.tar.gz=fe5b69710fa6a918d43f41ca2e48fb87c3e03123e4e3fc22c713482682d88745
+dist/2024-07-26/rustc-nightly-aarch64-apple-darwin.tar.xz=1a21e5f9def991ba50d60e32e0c5865c7783280523abd1a72e35daf22316102d
+dist/2024-07-26/rustc-nightly-i686-pc-windows-msvc.tar.gz=7f42d475dc8a82908869443a08df879be6cad396a802cc76b8cf475628a50e76
+dist/2024-07-26/rustc-nightly-i686-pc-windows-msvc.tar.xz=6f8745cbefeed0add770d368af3519dca65d15718a750579b706b18e6fb37198
+dist/2024-07-26/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=5669cd2fb73cb708f45ea5b75b72184430d26739b89da869a40b3e156e44ed18
+dist/2024-07-26/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=31ae9d43808729407ce75594fbc1144711efd1af56837117c596d58f5607dc79
+dist/2024-07-26/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=a2e4c919548dc864eb51dc8b6743a004129eded49e25ccec66838e5b252673da
+dist/2024-07-26/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=67d09df96c68077a20e26626a6b3f5bd3d1f803c8d54eaed67c17003d50fe9a5
+dist/2024-07-26/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=939f37bdf5684f14fcd134dd569c0318e0f04d3820693576ac62a5621afa5d70
+dist/2024-07-26/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=c4bf7f89b1d7c94337d7c0a53ecd3c800d84123784ec019edc26393b8870628b
+dist/2024-07-26/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=24bbdc9683594aae2ad12882fb0e102fda8a5c54c812ad66062b6e9ac1d686ff
+dist/2024-07-26/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=48fb68d6a063b9973e42686ad7aa3104574972c95ed72386c68fb20e9aa33813
+dist/2024-07-26/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=d73fb553d6b3c8ffae4fc1d0f23bec0315de4e7546ce446eae015bef8c2e5c8f
+dist/2024-07-26/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=3b5c48fba434f0a24c47de9ba95a74e16a0489e5c6184d44acf44ca88695c598
+dist/2024-07-26/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=f49139fb26a6d26f53653bc69a6665e47b4bef4bbbad3ca2150a486b95c5b2b0
+dist/2024-07-26/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=ce75c9f7edc0141d4cc5c09f1691e6beb476d1934df721d7edc357e46e6a5490
+dist/2024-07-26/rustc-nightly-x86_64-apple-darwin.tar.gz=e334d3ee6ff3d4da892dfa51dfedb15394159f9d21ab9e3ff7c82f9768dfe9c3
+dist/2024-07-26/rustc-nightly-x86_64-apple-darwin.tar.xz=43e2db93b5bd6e5ee4336db8f3fe9185c8ca1a2a049edc2e27a0768ff79766e8
+dist/2024-07-26/rustc-nightly-i686-pc-windows-gnu.tar.gz=8c63711b94e332f0f2304160b9dde73201e75105b1592470a1e0d1b24bddaec9
+dist/2024-07-26/rustc-nightly-i686-pc-windows-gnu.tar.xz=d20400d6c09ef1ea3e6d375d52c9b9eee8cf998f3c6c2fa79a14762db70e3285
+dist/2024-07-26/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=a28aeb05f0180e6e40bf3abe70030839ef0a48b088029915c5c1095160c8b45c
+dist/2024-07-26/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=48cba7e5b56f93264c09c319bd5a14544acfa12e7c795291bc6d65507c23da07
+dist/2024-07-26/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=90ce5007ec9d24c5941d1d34c67f0abb3169fdd9bbad7b28c9a96ad95559027c
+dist/2024-07-26/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=3ec63acac9d808b9dc4721d5a2c731d16e0514998c8d6e1eaa91419898496803
+dist/2024-07-26/rustc-nightly-x86_64-unknown-netbsd.tar.gz=f20db202866a639406090b456eea504eee53fe572a02b68295257c88fe9971f3
+dist/2024-07-26/rustc-nightly-x86_64-unknown-netbsd.tar.xz=909eddf1ccb61a7d80227dcf4e856f996346fa33d4a9e5d3df1f0247bc295174
+dist/2024-07-26/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=43fc6478e546f47f865e586d836a764b821d0543d069c8f1d5ea3f5b0b6b19ba
+dist/2024-07-26/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=a6b89bf8d524c423a151b4221e01ef661f8b1810d13f41bdfa6be02908363805
+dist/2024-07-26/rustc-nightly-x86_64-unknown-freebsd.tar.gz=f2054204067683419dc553010cf063e91e4fefebdc7bff4c2e185416a94d5cd2
+dist/2024-07-26/rustc-nightly-x86_64-unknown-freebsd.tar.xz=fe549197eb863801f463eadcde86e85082a2dc655ade56fd425e8648012f82a8
+dist/2024-07-26/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3ac50b66d7d572efdb587f1f54069235f20de5273e3f5c670e1793371f925bd3
+dist/2024-07-26/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=ff576d6781e4bb8d1c48d985b7ea5fde440ab461e3cd9975557e1a465bbbaa50
\ No newline at end of file

From 5eca36d27a5599f1e15885cd36d6559d36048cd3 Mon Sep 17 00:00:00 2001
From: Mark Rousskov 
Date: Mon, 22 Jul 2024 22:06:16 -0400
Subject: [PATCH 193/489] step cfg(bootstrap)

---
 compiler/rustc_builtin_macros/src/lib.rs      |  1 -
 .../src/check_consts/check.rs                 |  5 +-
 .../src/interpret/operator.rs                 |  6 +--
 .../src/interpret/terminator.rs               |  3 +-
 compiler/rustc_data_structures/src/lib.rs     |  1 -
 compiler/rustc_lint_defs/src/builtin.rs       |  2 -
 compiler/rustc_parse/src/errors.rs            |  7 +--
 compiler/rustc_trait_selection/src/errors.rs  |  5 +-
 compiler/rustc_ty_utils/src/layout.rs         |  4 +-
 library/alloc/src/lib.rs                      |  1 -
 library/core/src/char/methods.rs              |  5 +-
 library/core/src/intrinsics.rs                | 53 -------------------
 library/core/src/lib.rs                       |  2 -
 library/core/src/marker.rs                    |  2 -
 library/core/src/num/f128.rs                  | 20 -------
 library/core/src/num/f16.rs                   | 21 --------
 library/core/src/ops/coroutine.rs             |  4 +-
 library/panic_abort/src/lib.rs                |  1 -
 library/panic_unwind/src/lib.rs               |  1 -
 library/std/src/f128.rs                       |  1 -
 library/std/src/f128/tests.rs                 |  1 -
 library/std/src/f16.rs                        |  1 -
 library/std/src/f16/tests.rs                  |  1 -
 library/std/src/lib.rs                        |  1 -
 library/unwind/src/lib.rs                     |  1 -
 rustfmt.toml                                  |  2 -
 src/bootstrap/src/bin/main.rs                 |  5 +-
 src/tools/clippy/clippy_lints/src/lib.rs      |  1 -
 src/tools/clippy/clippy_utils/src/lib.rs      |  1 -
 src/tools/clippy/src/driver.rs                |  1 -
 src/tools/miri/src/lib.rs                     |  1 -
 .../crates/salsa/tests/macros.rs              |  1 +
 .../non_glob_import_of_type_ir_inherent.rs    |  1 -
 33 files changed, 11 insertions(+), 152 deletions(-)

diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index c77ff9eb13cdc..5157bd46c853f 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -5,7 +5,6 @@
 #![allow(internal_features)]
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(assert_matches)]
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 8700ec4c21045..3ca47e4ab5cb6 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -635,10 +635,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
         trace!(
             "visit_projection_elem: place_ref={:?} elem={:?} \
             context={:?} location={:?}",
-            place_ref,
-            elem,
-            context,
-            location,
+            place_ref, elem, context, location,
         );
 
         self.super_projection_elem(place_ref, elem, context, location);
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 2723507397eeb..9a662837c9ae3 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -331,11 +331,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         trace!(
             "Running binary op {:?}: {:?} ({}), {:?} ({})",
-            bin_op,
-            *left,
-            left.layout.ty,
-            *right,
-            right.layout.ty
+            bin_op, *left, left.layout.ty, *right, right.layout.ty
         );
 
         match left.layout.ty.kind() {
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 56d3dc9410412..f996d361276a0 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -440,8 +440,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         } else {
             trace!(
                 "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}",
-                caller_abi,
-                callee_abi
+                caller_abi, callee_abi
             );
             return Ok(false);
         }
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 3f18b036940bf..28b3aeaabff4f 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -10,7 +10,6 @@
 #![allow(internal_features)]
 #![allow(rustc::default_hash_types)]
 #![allow(rustc::potential_query_instability)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
 #![cfg_attr(not(parallel_compiler), feature(cell_leak))]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 06d6a6cd612e0..2414a20429c5f 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -616,8 +616,6 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust
-    /// #![cfg_attr(bootstrap, feature(lint_reasons))]
-    ///
     /// #[expect(unused_variables)]
     /// let x = 10;
     /// println!("{}", x);
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 2e81d2a876bac..6adfe3e84a7d5 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -554,12 +554,7 @@ pub(crate) enum MissingInInForLoopSub {
         code = "in"
     )]
     InNotOf(#[primary_span] Span),
-    #[suggestion(
-        parse_add_in,
-        style = "verbose",
-        applicability = "maybe-incorrect",
-        code = " in "
-    )]
+    #[suggestion(parse_add_in, style = "verbose", applicability = "maybe-incorrect", code = " in ")]
     AddIn(#[primary_span] Span),
 }
 
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 0ee4485a36543..0af38dbe4b874 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1585,10 +1585,7 @@ pub enum TypeErrorAdditionalDiags {
         span: Span,
         code: String,
     },
-    #[multipart_suggestion(
-        trait_selection_meant_str_literal,
-        applicability = "machine-applicable"
-    )]
+    #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")]
     MeantStrLiteral {
         #[suggestion_part(code = "\"")]
         start: Span,
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 6045abc50a9da..ae3f72c37b90e 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -733,9 +733,7 @@ fn coroutine_saved_local_eligibility(
                     // point, so it is no longer a candidate.
                     trace!(
                         "removing local {:?} in >1 variant ({:?}, {:?})",
-                        local,
-                        variant_index,
-                        idx
+                        local, variant_index, idx
                     );
                     ineligible_locals.insert(*local);
                     assignments[*local] = Ineligible(None);
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 49036077e2e67..8c0caf9a35e51 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -165,7 +165,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(c_unwind))]
 #![cfg_attr(not(test), feature(coroutine_trait))]
 #![cfg_attr(test, feature(panic_update_hook))]
 #![cfg_attr(test, feature(test))]
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 6b41540683816..08ae13804f168 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -223,10 +223,7 @@ impl char {
     /// assert_eq!('❤', c);
     /// ```
     #[stable(feature = "assoc_char_funcs", since = "1.52.0")]
-    #[rustc_const_stable(
-        feature = "const_char_from_u32_unchecked",
-        since = "1.81.0"
-    )]
+    #[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
     #[must_use]
     #[inline]
     pub const unsafe fn from_u32_unchecked(i: u32) -> char {
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index c4c6388338949..b219b70fde8a1 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1017,45 +1017,6 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn breakpoint();
 
-    #[cfg(bootstrap)]
-    #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn size_of() -> usize;
-
-    #[cfg(bootstrap)]
-    #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn min_align_of() -> usize;
-
-    #[cfg(bootstrap)]
-    #[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")]
-    #[rustc_nounwind]
-    pub fn pref_align_of() -> usize;
-
-    #[cfg(bootstrap)]
-    #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
-    #[rustc_nounwind]
-    pub fn size_of_val(_: *const T) -> usize;
-
-    #[cfg(bootstrap)]
-    #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
-    #[rustc_nounwind]
-    pub fn min_align_of_val(_: *const T) -> usize;
-
-    #[cfg(bootstrap)]
-    #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn type_name() -> &'static str;
-
-    #[cfg(bootstrap)]
-    #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn type_id() -> u128;
-
     /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
     /// This will statically either panic, or do nothing.
     ///
@@ -2385,12 +2346,6 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn discriminant_value(v: &T) -> ::Discriminant;
 
-    #[cfg(bootstrap)]
-    #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn variant_count() -> usize;
-
     /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the
     /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs.
     ///
@@ -2768,7 +2723,6 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize {
 #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const fn size_of() -> usize {
     unreachable!()
 }
@@ -2786,7 +2740,6 @@ pub const fn size_of() -> usize {
 #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const fn min_align_of() -> usize {
     unreachable!()
 }
@@ -2800,7 +2753,6 @@ pub const fn min_align_of() -> usize {
 #[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const unsafe fn pref_align_of() -> usize {
     unreachable!()
 }
@@ -2819,7 +2771,6 @@ pub const unsafe fn pref_align_of() -> usize {
 #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const fn variant_count() -> usize {
     unreachable!()
 }
@@ -2836,7 +2787,6 @@ pub const fn variant_count() -> usize {
 #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const unsafe fn size_of_val(_ptr: *const T) -> usize {
     unreachable!()
 }
@@ -2853,7 +2803,6 @@ pub const unsafe fn size_of_val(_ptr: *const T) -> usize {
 #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const unsafe fn min_align_of_val(_ptr: *const T) -> usize {
     unreachable!()
 }
@@ -2871,7 +2820,6 @@ pub const unsafe fn min_align_of_val(_ptr: *const T) -> usize {
 #[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const fn type_name() -> &'static str {
     unreachable!()
 }
@@ -2891,7 +2839,6 @@ pub const fn type_name() -> &'static str {
 #[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
-#[cfg(not(bootstrap))]
 pub const fn type_id() -> u128 {
     unreachable!()
 }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 9f0055d191134..42af20e78ce10 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -192,8 +192,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(c_unwind))]
-#![cfg_attr(bootstrap, feature(effects))]
 #![feature(abi_unadjusted)]
 #![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index cf428e36ea7a0..fcd8fa93f58a5 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -1061,7 +1061,6 @@ pub trait FnPtr: Copy + Clone {
 }
 
 /// Derive macro generating impls of traits related to smart pointers.
-#[cfg(not(bootstrap))]
 #[rustc_builtin_macro]
 #[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize)]
 #[unstable(feature = "derive_smart_pointer", issue = "123430")]
@@ -1079,7 +1078,6 @@ pub macro SmartPointer($item:item) {
     reason = "internal module for implementing effects"
 )]
 #[allow(missing_debug_implementations)] // these unit structs don't need `Debug` impls.
-#[cfg(not(bootstrap))]
 pub mod effects {
     #[lang = "EffectsNoRuntime"]
     pub struct NoRuntime;
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 05dc1e97852e0..943ae3f774d41 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -234,24 +234,20 @@ impl f128 {
     /// This constant isn't guaranteed to equal to any specific NaN bitpattern,
     /// and the stability of its representation over Rust versions
     /// and target platforms isn't guaranteed.
-    #[cfg(not(bootstrap))]
     #[allow(clippy::eq_op)]
     #[rustc_diagnostic_item = "f128_nan"]
     #[unstable(feature = "f128", issue = "116909")]
     pub const NAN: f128 = 0.0_f128 / 0.0_f128;
 
     /// Infinity (∞).
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     pub const INFINITY: f128 = 1.0_f128 / 0.0_f128;
 
     /// Negative infinity (−∞).
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     pub const NEG_INFINITY: f128 = -1.0_f128 / 0.0_f128;
 
     /// Sign bit
-    #[cfg(not(bootstrap))]
     pub(crate) const SIGN_MASK: u128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
 
     /// Exponent mask
@@ -261,11 +257,9 @@ impl f128 {
     pub(crate) const MAN_MASK: u128 = 0x0000_ffff_ffff_ffff_ffff_ffff_ffff_ffff;
 
     /// Minimum representable positive value (min subnormal)
-    #[cfg(not(bootstrap))]
     const TINY_BITS: u128 = 0x1;
 
     /// Minimum representable negative value (min negative subnormal)
-    #[cfg(not(bootstrap))]
     const NEG_TINY_BITS: u128 = Self::TINY_BITS | Self::SIGN_MASK;
 
     /// Returns `true` if this value is NaN.
@@ -284,7 +278,6 @@ impl f128 {
     /// ```
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
     pub const fn is_nan(self) -> bool {
@@ -295,7 +288,6 @@ impl f128 {
     // concerns about portability, so this implementation is for
     // private use internally.
     #[inline]
-    #[cfg(not(bootstrap))]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub(crate) const fn abs_private(self) -> f128 {
         // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
@@ -326,7 +318,6 @@ impl f128 {
     /// ```
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn is_infinite(self) -> bool {
@@ -354,7 +345,6 @@ impl f128 {
     /// ```
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn is_finite(self) -> bool {
@@ -389,7 +379,6 @@ impl f128 {
     /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn is_subnormal(self) -> bool {
@@ -422,7 +411,6 @@ impl f128 {
     /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn is_normal(self) -> bool {
@@ -448,7 +436,6 @@ impl f128 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn classify(self) -> FpCategory {
@@ -557,7 +544,6 @@ impl f128 {
     /// [`MIN`]: Self::MIN
     /// [`MAX`]: Self::MAX
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     // #[unstable(feature = "float_next_up_down", issue = "91399")]
     pub fn next_up(self) -> Self {
@@ -612,7 +598,6 @@ impl f128 {
     /// [`MIN`]: Self::MIN
     /// [`MAX`]: Self::MAX
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     // #[unstable(feature = "float_next_up_down", issue = "91399")]
     pub fn next_down(self) -> Self {
@@ -649,7 +634,6 @@ impl f128 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub fn recip(self) -> Self {
@@ -670,7 +654,6 @@ impl f128 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub fn to_degrees(self) -> Self {
@@ -694,7 +677,6 @@ impl f128 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub fn to_radians(self) -> f128 {
@@ -1141,7 +1123,6 @@ impl f128 {
     /// ```
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
         let mut left = self.to_bits() as i128;
@@ -1201,7 +1182,6 @@ impl f128 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn clamp(mut self, min: f128, max: f128) -> f128 {
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 2a8ede9383844..6b77b103c0cf1 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -229,24 +229,20 @@ impl f16 {
     /// This constant isn't guaranteed to equal to any specific NaN bitpattern,
     /// and the stability of its representation over Rust versions
     /// and target platforms isn't guaranteed.
-    #[cfg(not(bootstrap))]
     #[allow(clippy::eq_op)]
     #[rustc_diagnostic_item = "f16_nan"]
     #[unstable(feature = "f16", issue = "116909")]
     pub const NAN: f16 = 0.0_f16 / 0.0_f16;
 
     /// Infinity (∞).
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     pub const INFINITY: f16 = 1.0_f16 / 0.0_f16;
 
     /// Negative infinity (−∞).
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     pub const NEG_INFINITY: f16 = -1.0_f16 / 0.0_f16;
 
     /// Sign bit
-    #[cfg(not(bootstrap))]
     pub(crate) const SIGN_MASK: u16 = 0x8000;
 
     /// Exponent mask
@@ -256,11 +252,9 @@ impl f16 {
     pub(crate) const MAN_MASK: u16 = 0x03ff;
 
     /// Minimum representable positive value (min subnormal)
-    #[cfg(not(bootstrap))]
     const TINY_BITS: u16 = 0x1;
 
     /// Minimum representable negative value (min negative subnormal)
-    #[cfg(not(bootstrap))]
     const NEG_TINY_BITS: u16 = Self::TINY_BITS | Self::SIGN_MASK;
 
     /// Returns `true` if this value is NaN.
@@ -278,7 +272,6 @@ impl f16 {
     /// ```
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
     pub const fn is_nan(self) -> bool {
@@ -289,7 +282,6 @@ impl f16 {
     // concerns about portability, so this implementation is for
     // private use internally.
     #[inline]
-    #[cfg(not(bootstrap))]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub(crate) const fn abs_private(self) -> f16 {
         // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
@@ -317,7 +309,6 @@ impl f16 {
     /// ```
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn is_infinite(self) -> bool {
@@ -344,7 +335,6 @@ impl f16 {
     /// ```
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn is_finite(self) -> bool {
@@ -377,7 +367,6 @@ impl f16 {
     /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn is_subnormal(self) -> bool {
@@ -408,7 +397,6 @@ impl f16 {
     /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn is_normal(self) -> bool {
@@ -433,7 +421,6 @@ impl f16 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub const fn classify(self) -> FpCategory {
@@ -478,7 +465,6 @@ impl f16 {
     /// but getting floats correct is important for not accidentally leaking const eval
     /// runtime-deviating logic which may or may not be acceptable.
     #[inline]
-    #[cfg(not(bootstrap))]
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     const unsafe fn partial_classify(self) -> FpCategory {
         // SAFETY: The caller is not asking questions for which this will tell lies.
@@ -593,7 +579,6 @@ impl f16 {
     /// [`MIN`]: Self::MIN
     /// [`MAX`]: Self::MAX
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     // #[unstable(feature = "float_next_up_down", issue = "91399")]
     pub fn next_up(self) -> Self {
@@ -648,7 +633,6 @@ impl f16 {
     /// [`MIN`]: Self::MIN
     /// [`MAX`]: Self::MAX
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     // #[unstable(feature = "float_next_up_down", issue = "91399")]
     pub fn next_down(self) -> Self {
@@ -685,7 +669,6 @@ impl f16 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub fn recip(self) -> Self {
@@ -706,7 +689,6 @@ impl f16 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub fn to_degrees(self) -> Self {
@@ -730,7 +712,6 @@ impl f16 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub fn to_radians(self) -> f16 {
@@ -1167,7 +1148,6 @@ impl f16 {
     /// ```
     #[inline]
     #[must_use]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
         let mut left = self.to_bits() as i16;
@@ -1226,7 +1206,6 @@ impl f16 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub fn clamp(mut self, min: f16, max: f16) -> f16 {
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
index 753f14c6b85ec..13df888d24c5c 100644
--- a/library/core/src/ops/coroutine.rs
+++ b/library/core/src/ops/coroutine.rs
@@ -76,7 +76,7 @@ pub trait Coroutine {
     /// values which are allowed to be returned each time a coroutine yields.
     /// For example an iterator-as-a-coroutine would likely have this type as
     /// `T`, the type being iterated over.
-    #[cfg_attr(not(bootstrap), lang = "coroutine_yield")]
+    #[lang = "coroutine_yield"]
     type Yield;
 
     /// The type of value this coroutine returns.
@@ -85,7 +85,7 @@ pub trait Coroutine {
     /// `return` statement or implicitly as the last expression of a coroutine
     /// literal. For example futures would use this as `Result` as it
     /// represents a completed future.
-    #[cfg_attr(not(bootstrap), lang = "coroutine_return")]
+    #[lang = "coroutine_return"]
     type Return;
 
     /// Resumes the execution of this coroutine.
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index 14ba4af2bb575..dc2b42bb90ae8 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -14,7 +14,6 @@
 #![feature(std_internals)]
 #![feature(staged_api)]
 #![feature(rustc_attrs)]
-#![cfg_attr(bootstrap, feature(c_unwind))]
 #![allow(internal_features)]
 
 #[cfg(target_os = "android")]
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 77abb9125f651..2d174f4b1a4a2 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -24,7 +24,6 @@
 #![feature(rustc_attrs)]
 #![panic_runtime]
 #![feature(panic_runtime)]
-#![cfg_attr(bootstrap, feature(c_unwind))]
 // `real_imp` is unused with Miri, so silence warnings.
 #![cfg_attr(miri, allow(dead_code))]
 #![allow(internal_features)]
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs
index 0591c6f517b44..089d972cd599c 100644
--- a/library/std/src/f128.rs
+++ b/library/std/src/f128.rs
@@ -53,7 +53,6 @@ impl f128 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
diff --git a/library/std/src/f128/tests.rs b/library/std/src/f128/tests.rs
index 0b3e485b0e735..95bdf6f0c74e4 100644
--- a/library/std/src/f128/tests.rs
+++ b/library/std/src/f128/tests.rs
@@ -1,4 +1,3 @@
-#![cfg(not(bootstrap))]
 // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
 #![cfg(reliable_f128)]
 
diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs
index d48518622999a..b2fe781e1c183 100644
--- a/library/std/src/f16.rs
+++ b/library/std/src/f16.rs
@@ -53,7 +53,6 @@ impl f16 {
     /// # }
     /// ```
     #[inline]
-    #[cfg(not(bootstrap))]
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "method returns a new number and does not mutate the original value"]
diff --git a/library/std/src/f16/tests.rs b/library/std/src/f16/tests.rs
index 26658a0be87bc..3a1500c7766f0 100644
--- a/library/std/src/f16/tests.rs
+++ b/library/std/src/f16/tests.rs
@@ -1,4 +1,3 @@
-#![cfg(not(bootstrap))]
 // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
 #![cfg(reliable_f16)]
 
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 9fba657d116de..02a720d3c107e 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -275,7 +275,6 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(bootstrap, feature(c_unwind))]
 #![feature(alloc_error_handler)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 45a1c334a44dd..b3de71f29f394 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -2,7 +2,6 @@
 #![unstable(feature = "panic_unwind", issue = "32837")]
 #![feature(link_cfg)]
 #![feature(staged_api)]
-#![cfg_attr(bootstrap, feature(c_unwind))]
 #![feature(strict_provenance)]
 #![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
 #![cfg_attr(not(target_env = "msvc"), feature(libc))]
diff --git a/rustfmt.toml b/rustfmt.toml
index 8c1d3b94f195b..9d4d6893faf14 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -22,8 +22,6 @@ ignore = [
     "/tests/rustdoc-ui/",             # Some have syntax errors, some are whitespace-sensitive.
     "/tests/ui/",                     # Some have syntax errors, some are whitespace-sensitive.
     "/tests/ui-fulldeps/",            # Some are whitespace-sensitive (e.g. `// ~ERROR` comments).
-    # #[cfg(bootstrap)] so that t-release sees this when they search for it
-    "/tests/rustdoc-json/impl-trait-precise-capturing.rs",
 
     # Do not format submodules.
     # FIXME: sync submodule list with tidy/bootstrap/etc
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index a7d21ba6ae127..9fdbc4b899ec1 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -30,10 +30,7 @@ fn main() {
         // Display PID of process holding the lock
         // PID will be stored in a lock file
         let lock_path = config.out.join("lock");
-        let pid = match fs::read_to_string(&lock_path) {
-            Ok(contents) => contents,
-            Err(_) => String::new(),
-        };
+        let pid = fs::read_to_string(&lock_path).unwrap_or_default();
 
         build_lock = fd_lock::RwLock::new(t!(fs::OpenOptions::new()
             .write(true)
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 22d23a175094a..a388b6b2eaab3 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -8,7 +8,6 @@
 #![feature(iter_intersperse)]
 #![feature(iter_partition_in_place)]
 #![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
 #![feature(never_type)]
 #![feature(rustc_private)]
 #![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 3a9714c49ae73..1d5f1a2a2bb13 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -5,7 +5,6 @@
 #![feature(f16)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
 #![feature(never_type)]
 #![feature(rustc_private)]
 #![feature(assert_matches)]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 9b1577f24b8e7..3fafe2427a256 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -2,7 +2,6 @@
 #![allow(rustc::untranslatable_diagnostic)]
 #![feature(rustc_private)]
 #![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
 #![warn(rust_2018_idioms, unused_lifetimes)]
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 7fb68d782f11d..24909f21eb2b3 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -10,7 +10,6 @@
 #![feature(yeet_expr)]
 #![feature(nonzero_ops)]
 #![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(lint_reasons))]
 #![feature(trait_upcasting)]
 #![feature(strict_overflow_ops)]
 #![feature(is_none_or)]
diff --git a/src/tools/rust-analyzer/crates/salsa/tests/macros.rs b/src/tools/rust-analyzer/crates/salsa/tests/macros.rs
index 3d818e53c8e93..9b07740e7de3d 100644
--- a/src/tools/rust-analyzer/crates/salsa/tests/macros.rs
+++ b/src/tools/rust-analyzer/crates/salsa/tests/macros.rs
@@ -5,6 +5,7 @@ trait MyDatabase: salsa::Database {
 }
 
 mod another_module {
+    #[allow(dead_code)]
     pub(crate) fn another_name(_: &dyn crate::MyDatabase, (): ()) {}
 }
 
diff --git a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
index 33e10a0071330..c761b8e94bd7b 100644
--- a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
+++ b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Z unstable-options
-//@ ignore-stage1 (can be removed after beta bump, #[cfg(bootstrap)])
 #![feature(rustc_private)]
 #![deny(rustc::non_glob_import_of_type_ir_inherent)]
 

From 649d99b9731b15faa744604027cc6a24e4dd27ec Mon Sep 17 00:00:00 2001
From: Trevor Gross 
Date: Thu, 25 Jul 2024 22:34:39 -0400
Subject: [PATCH 194/489] Bless a bootstrap-dependent UI test

---
 ...non_glob_import_of_type_ir_inherent.stderr | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
index 84e3867c95bc1..c5c10bb070a31 100644
--- a/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
+++ b/tests/ui-fulldeps/internal-lints/non_glob_import_of_type_ir_inherent.stderr
@@ -1,5 +1,5 @@
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:17:9
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:16:9
    |
 LL |     use rustc_type_ir::inherent::Predicate;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^---------
@@ -7,25 +7,25 @@ LL |     use rustc_type_ir::inherent::Predicate;
    |                                  help: try using a glob import instead: `*`
    |
 note: the lint level is defined here
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:4:9
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:3:9
    |
 LL | #![deny(rustc::non_glob_import_of_type_ir_inherent)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:18:35
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:17:35
    |
 LL |     use rustc_type_ir::inherent::{AdtDef, Ty};
    |                                   ^^^^^^ help: try using a glob import instead: `*`
 
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:18:43
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:17:43
    |
 LL |     use rustc_type_ir::inherent::{AdtDef, Ty};
    |                                           ^^ help: try using a glob import instead: `*`
 
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:21:9
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:20:9
    |
 LL |     use rustc_type_ir::inherent::ParamEnv as _;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^-------------
@@ -33,31 +33,31 @@ LL |     use rustc_type_ir::inherent::ParamEnv as _;
    |                                  help: try using a glob import instead: `*`
 
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:25:9
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:24:9
    |
 LL |     use rustc_type_ir::inherent;
    |         ^^^^^^^^^^^^^^^^^^^^^^^- help: try using a glob import instead: `::*`
 
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:26:9
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:25:9
    |
 LL |     use rustc_type_ir::inherent as inh;
    |         ^^^^^^^^^^^^^^^^^^^^^^^------- help: try using a glob import instead: `::*`
 
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:27:25
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:26:25
    |
 LL |     use rustc_type_ir::{inherent as _};
    |                         ^^^^^^^^----- help: try using a glob import instead: `::*`
 
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:34:35
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:33:35
    |
 LL |     use rustc_type_ir::inherent::{self};
    |                                   ^^^^ help: try using a glob import instead: `*`
 
 error: non-glob import of `rustc_type_ir::inherent`
-  --> $DIR/non_glob_import_of_type_ir_inherent.rs:35:35
+  --> $DIR/non_glob_import_of_type_ir_inherent.rs:34:35
    |
 LL |     use rustc_type_ir::inherent::{self as innate};
    |                                   ^^^^----------

From cf87203f483751e0f6daa74b9d129c04feb48355 Mon Sep 17 00:00:00 2001
From: Miguel Ojeda 
Date: Sun, 28 Jul 2024 16:37:58 +0200
Subject: [PATCH 195/489] Remove spurious backticks detected by
 `rustdoc::unescaped_backticks`

There are only 3 cases across the crates rendered in the website (`core`,
`alloc`, `std`, `proc_macro` and `test`), and they are all in `core`.

Clean them up, so that the lint can be enabled in the next commit.

Signed-off-by: Miguel Ojeda 
---
 library/core/src/ops/deref.rs | 2 +-
 library/core/src/ptr/mod.rs   | 2 +-
 library/core/src/slice/mod.rs | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 9849410d484ca..f0d2c761ef35b 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -282,7 +282,7 @@ impl DerefMut for &mut T {
 /// FIXME(deref_patterns): The precise semantics are undecided; the rough idea is that
 /// successive calls to `deref`/`deref_mut` without intermediate mutation should be
 /// idempotent, in the sense that they return the same value as far as pattern-matching
-/// is concerned. Calls to `deref`/`deref_mut`` must leave the pointer itself likewise
+/// is concerned. Calls to `deref`/`deref_mut` must leave the pointer itself likewise
 /// unchanged.
 #[unstable(feature = "deref_pure_trait", issue = "87121")]
 #[lang = "deref_pure"]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index da6b541a98700..2566beeadac5d 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -786,7 +786,7 @@ where
 ///
 /// The caller must also ensure that the memory the pointer (non-transitively) points to is never
 /// written to (except inside an `UnsafeCell`) using this pointer or any pointer derived from it. If
-/// you need to mutate the pointee, use [`from_mut`]`. Specifically, to turn a mutable reference `m:
+/// you need to mutate the pointee, use [`from_mut`]. Specifically, to turn a mutable reference `m:
 /// &mut T` into `*const T`, prefer `from_mut(m).cast_const()` to obtain a pointer that can later be
 /// used for mutation.
 ///
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 5f75e1944122d..067daa6a0d09c 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -3452,8 +3452,8 @@ impl [T] {
     /// elements of the slice move to the end while the last `k` elements move
     /// to the front.
     ///
-    /// After calling `rotate_right`, the element previously at index `self.len()
-    /// - k` will become the first element in the slice.
+    /// After calling `rotate_right`, the element previously at index
+    /// `self.len() - k` will become the first element in the slice.
     ///
     /// # Panics
     ///

From dc815df1e1dc8c37956e41274c3276d053c271da Mon Sep 17 00:00:00 2001
From: Miguel Ojeda 
Date: Sun, 28 Jul 2024 16:37:58 +0200
Subject: [PATCH 196/489] Warn on `rustdoc::unescaped_backticks` for
 `core/alloc/std/test/proc_macro`

They are all clean now, so enable the lint to keep them clean going forward.

Signed-off-by: Miguel Ojeda 
---
 library/alloc/src/lib.rs      | 1 +
 library/core/src/lib.rs       | 1 +
 library/proc_macro/src/lib.rs | 1 +
 library/std/src/lib.rs        | 1 +
 library/test/src/lib.rs       | 1 +
 5 files changed, 5 insertions(+)

diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 3b039786eb5e7..6c58594605004 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -86,6 +86,7 @@
 #![warn(multiple_supertrait_upcastable)]
 #![allow(internal_features)]
 #![allow(rustdoc::redundant_explicit_links)]
+#![warn(rustdoc::unescaped_backticks)]
 #![deny(ffi_unwind_calls)]
 //
 // Library features:
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e8f08db94164d..a3eca34a35cfc 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -103,6 +103,7 @@
 #![deny(ffi_unwind_calls)]
 // Do not check link redundancy on bootstraping phase
 #![allow(rustdoc::redundant_explicit_links)]
+#![warn(rustdoc::unescaped_backticks)]
 //
 // Library features:
 // tidy-alphabetical-start
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 57247359fbf29..10dcaa8cd3aaf 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -37,6 +37,7 @@
 #![recursion_limit = "256"]
 #![allow(internal_features)]
 #![deny(ffi_unwind_calls)]
+#![warn(rustdoc::unescaped_backticks)]
 
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
 #[doc(hidden)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 353fd8d2de8c0..7240605bfd654 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -254,6 +254,7 @@
 #![deny(fuzzy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![allow(rustdoc::redundant_explicit_links)]
+#![warn(rustdoc::unescaped_backticks)]
 // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
 #![deny(ffi_unwind_calls)]
 // std may use features in a platform-specific way
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 71cb796b93705..db87d923de0e5 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -24,6 +24,7 @@
 #![feature(panic_can_unwind)]
 #![feature(test)]
 #![allow(internal_features)]
+#![warn(rustdoc::unescaped_backticks)]
 
 pub use self::bench::{black_box, Bencher};
 pub use self::console::run_tests_console;

From 41cf8374a640fca0f5d5b97c345aa4c3c0df9c25 Mon Sep 17 00:00:00 2001
From: Miguel Ojeda 
Date: Sun, 28 Jul 2024 22:30:01 +0200
Subject: [PATCH 197/489] CI: move RFL job forward to v6.11-rc1

The tag has been released today, and since the original hash we had in
the Rust CI (which was ~v6.10-rc1), we have accumulated a fair amount
of changes and new code.

In particular, v6.11-rc1 is the first Linux tag where the kernel is
supporting an actual minimum Rust version (1.78.0), rather than a
single version.

Signed-off-by: Miguel Ojeda 
---
 src/ci/docker/scripts/rfl-build.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index da7b029ca7329..3acc09e0b9b1a 100755
--- a/src/ci/docker/scripts/rfl-build.sh
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -2,7 +2,7 @@
 
 set -euo pipefail
 
-LINUX_VERSION=c13320499ba0efd93174ef6462ae8a7a2933f6e7
+LINUX_VERSION=v6.11-rc1
 
 # Build rustc, rustdoc and cargo
 ../x.py build --stage 1 library rustdoc

From ecf2963baf17cead7c7c57c88eddac8696793dd8 Mon Sep 17 00:00:00 2001
From: Nicholas Bishop 
Date: Sat, 11 May 2024 09:56:59 -0400
Subject: [PATCH 198/489] Update compiler_builtins to 0.1.114

The `weak-intrinsics` feature was removed from compiler_builtins in
https://github.com/rust-lang/compiler-builtins/pull/598, so dropped the
`compiler-builtins-weak-intrinsics` feature from alloc/std/sysroot.

In https://github.com/rust-lang/compiler-builtins/pull/593, some
builtins for f16/f128 were added. These don't work for all compiler
backends, so add a `compiler-builtins-no-f16-f128` feature and disable
it for cranelift and gcc. Also disable it for LLVM targets that don't
support it.
---
 Cargo.lock                                               | 4 ++--
 .../build_system/build_sysroot.rs                        | 2 +-
 compiler/rustc_codegen_gcc/build_system/src/build.rs     | 9 ++++++++-
 library/alloc/Cargo.toml                                 | 7 +++++--
 library/std/Cargo.toml                                   | 4 ++--
 library/sysroot/Cargo.toml                               | 2 +-
 6 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5e8d179e53653..390d7c05f6513 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -769,9 +769,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335"
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.109"
+version = "0.1.114"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f11973008a8cf741fe6d22f339eba21fd0ca81e2760a769ba8243ed6c21edd7e"
+checksum = "eb58b199190fcfe0846f55a3b545cd6b07a34bdd5930a476ff856f3ebcc5558a"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
index 196ff8fda7544..557e90abdb3d7 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -276,7 +276,7 @@ fn build_clif_sysroot_for_triple(
     if channel == "release" {
         build_cmd.arg("--release");
     }
-    build_cmd.arg("--features").arg("backtrace panic-unwind");
+    build_cmd.arg("--features").arg("backtrace panic-unwind compiler-builtins-no-f16-f128");
     build_cmd.env("CARGO_PROFILE_RELEASE_DEBUG", "true");
     build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
     if compiler.triple.contains("apple") {
diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs
index c81b02e2183d8..23ba0a90181e0 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/build.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs
@@ -112,7 +112,14 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu
     }
     let mut env = env.clone();
 
-    let mut args: Vec<&dyn AsRef> = vec![&"cargo", &"build", &"--target", &config.target];
+    let mut args: Vec<&dyn AsRef> = vec![
+        &"cargo",
+        &"build",
+        &"--target",
+        &config.target,
+        &"--features",
+        &"compiler-builtins-no-f16-f128",
+    ];
 
     if config.no_default_features {
         rustflags.push_str(" -Csymbol-mangling-version=v0");
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 024b92790e970..428d090883cde 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -10,7 +10,10 @@ edition = "2021"
 
 [dependencies]
 core = { path = "../core" }
-compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.114", features = ['rustc-dep-of-std'] }
+
+[target.'cfg(not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")))'.dependencies]
+compiler_builtins = { version = "0.1.114", features = ["no-f16-f128"] }
 
 [dev-dependencies]
 rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
@@ -38,8 +41,8 @@ harness = false
 compiler-builtins-mem = ['compiler_builtins/mem']
 compiler-builtins-c = ["compiler_builtins/c"]
 compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
+compiler-builtins-no-f16-f128 = ["compiler_builtins/no-f16-f128"]
 compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
-compiler-builtins-weak-intrinsics = ["compiler_builtins/weak-intrinsics"]
 # Make panics and failed asserts immediately abort without formatting any message
 panic_immediate_abort = ["core/panic_immediate_abort"]
 # Choose algorithms that are optimized for binary size instead of runtime performance
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index bc78c63c577c9..09a84528bc572 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
-compiler_builtins = { version = "0.1.105" }
+compiler_builtins = { version = "0.1.114" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.14", default-features = false, features = ['rustc-dep-of-std'] }
@@ -71,8 +71,8 @@ profiler = ["profiler_builtins"]
 compiler-builtins-c = ["alloc/compiler-builtins-c"]
 compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
 compiler-builtins-no-asm = ["alloc/compiler-builtins-no-asm"]
+compiler-builtins-no-f16-f128 = ["alloc/compiler-builtins-no-f16-f128"]
 compiler-builtins-mangled-names = ["alloc/compiler-builtins-mangled-names"]
-compiler-builtins-weak-intrinsics = ["alloc/compiler-builtins-weak-intrinsics"]
 llvm-libunwind = ["unwind/llvm-libunwind"]
 system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
 
diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
index 1ddacd92e6b94..3eedbfa948c29 100644
--- a/library/sysroot/Cargo.toml
+++ b/library/sysroot/Cargo.toml
@@ -16,8 +16,8 @@ backtrace = ["std/backtrace"]
 compiler-builtins-c = ["std/compiler-builtins-c"]
 compiler-builtins-mem = ["std/compiler-builtins-mem"]
 compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
+compiler-builtins-no-f16-f128 = ["std/compiler-builtins-no-f16-f128"]
 compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
-compiler-builtins-weak-intrinsics = ["std/compiler-builtins-weak-intrinsics"]
 llvm-libunwind = ["std/llvm-libunwind"]
 system-llvm-libunwind = ["std/system-llvm-libunwind"]
 panic-unwind = ["std/panic_unwind"]

From adefc44f31658c886fc84f8ce08e65470bf31289 Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Mon, 29 Jul 2024 02:50:53 +0200
Subject: [PATCH 199/489] Combine krate_ratoml and workspace_ratomls into one

---
 .../crates/rust-analyzer/src/config.rs        | 279 +++++++++---------
 .../crates/rust-analyzer/src/global_state.rs  |  46 +--
 2 files changed, 163 insertions(+), 162 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index d667ed94976fd..abb112da60526 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -751,6 +751,18 @@ config_data! {
     }
 }
 
+#[derive(Debug)]
+pub enum RatomlFileKind {
+    Workspace,
+    Crate,
+}
+
+#[derive(Debug, Clone)]
+enum RatomlFile {
+    Workspace(GlobalLocalConfigInput),
+    Crate(LocalConfigInput),
+}
+
 #[derive(Debug, Clone)]
 pub struct Config {
     discovered_projects: Vec,
@@ -779,11 +791,7 @@ pub struct Config {
     /// Config node whose values apply to **every** Rust project.
     user_config: Option<(GlobalLocalConfigInput, ConfigErrors)>,
 
-    /// TODO : This file can be used to make global changes while having only a workspace-wide scope.
-    workspace_ratoml: FxHashMap,
-
-    /// For every `SourceRoot` there can be at most one RATOML file.
-    krate_ratoml: FxHashMap,
+    ratoml_file: FxHashMap,
 
     /// Clone of the value that is stored inside a `GlobalState`.
     source_root_parent_map: Arc>,
@@ -914,83 +922,95 @@ impl Config {
             should_update = true;
         }
 
-        if let Some(change) = change.workspace_ratoml_change {
-            tracing::info!("updating root ra-toml config");
-            for (source_root_id, (_, text)) in change {
-                if let Some(text) = text {
-                    let mut toml_errors = vec![];
-                    match toml::from_str(&text) {
-                        Ok(table) => {
-                            validate_toml_table(
-                                GlobalLocalConfigInput::FIELDS,
-                                &table,
-                                &mut String::new(),
-                                &mut toml_errors,
-                            );
-                            config.workspace_ratoml.insert(
-                                source_root_id,
-                                (
-                                    GlobalLocalConfigInput::from_toml(table, &mut toml_errors),
-                                    ConfigErrors(
-                                        toml_errors
-                                            .into_iter()
-                                            .map(|(a, b)| ConfigErrorInner::Toml {
-                                                config_key: a,
-                                                error: b,
-                                            })
-                                            .map(Arc::new)
-                                            .collect(),
-                                    ),
-                                ),
-                            );
-                            should_update = true;
-                        }
-                        Err(e) => {
-                            config.validation_errors.0.push(
-                                ConfigErrorInner::ParseError { reason: e.message().to_owned() }
-                                    .into(),
-                            );
-                        }
-                    }
-                }
-            }
-        }
-
         if let Some(change) = change.ratoml_file_change {
-            for (source_root_id, (_, text)) in change {
-                if let Some(text) = text {
-                    let mut toml_errors = vec![];
-                    tracing::info!("updating ra-toml config: {:#}", text);
-                    match toml::from_str(&text) {
-                        Ok(table) => {
-                            validate_toml_table(
-                                &[LocalConfigInput::FIELDS],
-                                &table,
-                                &mut String::new(),
-                                &mut toml_errors,
-                            );
-                            config.krate_ratoml.insert(
-                                source_root_id,
-                                (
-                                    LocalConfigInput::from_toml(&table, &mut toml_errors),
-                                    ConfigErrors(
-                                        toml_errors
-                                            .into_iter()
-                                            .map(|(a, b)| ConfigErrorInner::Toml {
-                                                config_key: a,
-                                                error: b,
-                                            })
-                                            .map(Arc::new)
-                                            .collect(),
-                                    ),
-                                ),
-                            );
+            for (source_root_id, (kind, _, text)) in change {
+                match kind {
+                    RatomlFileKind::Crate => {
+                        if let Some(text) = text {
+                            let mut toml_errors = vec![];
+                            tracing::info!("updating ra-toml config: {:#}", text);
+                            match toml::from_str(&text) {
+                                Ok(table) => {
+                                    validate_toml_table(
+                                        &[LocalConfigInput::FIELDS],
+                                        &table,
+                                        &mut String::new(),
+                                        &mut toml_errors,
+                                    );
+                                    config.ratoml_file.insert(
+                                        source_root_id,
+                                        (
+                                            RatomlFile::Crate(LocalConfigInput::from_toml(
+                                                &table,
+                                                &mut toml_errors,
+                                            )),
+                                            ConfigErrors(
+                                                toml_errors
+                                                    .into_iter()
+                                                    .map(|(a, b)| ConfigErrorInner::Toml {
+                                                        config_key: a,
+                                                        error: b,
+                                                    })
+                                                    .map(Arc::new)
+                                                    .collect(),
+                                            ),
+                                        ),
+                                    );
+                                }
+                                Err(e) => {
+                                    config.validation_errors.0.push(
+                                        ConfigErrorInner::ParseError {
+                                            reason: e.message().to_owned(),
+                                        }
+                                        .into(),
+                                    );
+                                }
+                            }
                         }
-                        Err(e) => {
-                            config.validation_errors.0.push(
-                                ConfigErrorInner::ParseError { reason: e.message().to_owned() }
-                                    .into(),
-                            );
+                    }
+                    RatomlFileKind::Workspace => {
+                        if let Some(text) = text {
+                            let mut toml_errors = vec![];
+                            match toml::from_str(&text) {
+                                Ok(table) => {
+                                    validate_toml_table(
+                                        GlobalLocalConfigInput::FIELDS,
+                                        &table,
+                                        &mut String::new(),
+                                        &mut toml_errors,
+                                    );
+                                    config.ratoml_file.insert(
+                                        source_root_id,
+                                        (
+                                            RatomlFile::Workspace(
+                                                GlobalLocalConfigInput::from_toml(
+                                                    table,
+                                                    &mut toml_errors,
+                                                ),
+                                            ),
+                                            ConfigErrors(
+                                                toml_errors
+                                                    .into_iter()
+                                                    .map(|(a, b)| ConfigErrorInner::Toml {
+                                                        config_key: a,
+                                                        error: b,
+                                                    })
+                                                    .map(Arc::new)
+                                                    .collect(),
+                                            ),
+                                        ),
+                                    );
+                                    should_update = true;
+                                }
+                                Err(e) => {
+                                    config.validation_errors.0.push(
+                                        ConfigErrorInner::ParseError {
+                                            reason: e.message().to_owned(),
+                                        }
+                                        .into(),
+                                    );
+                                }
+                            }
                         }
                     }
                 }
@@ -1022,9 +1042,8 @@ impl Config {
                 .1
                  .0
                 .iter()
-                .chain(config.workspace_ratoml.values().into_iter().flat_map(|it| it.1 .0.iter()))
                 .chain(config.user_config.as_ref().into_iter().flat_map(|it| it.1 .0.iter()))
-                .chain(config.krate_ratoml.values().flat_map(|it| it.1 .0.iter()))
+                .chain(config.ratoml_file.values().flat_map(|it| it.1 .0.iter()))
                 .chain(config.validation_errors.0.iter())
                 .cloned()
                 .collect(),
@@ -1052,8 +1071,8 @@ impl Config {
 pub struct ConfigChange {
     user_config_change: Option>,
     client_config_change: Option,
-    workspace_ratoml_change: Option>)>>,
-    ratoml_file_change: Option>)>>,
+    ratoml_file_change:
+        Option>)>>,
     source_map_change: Option>>,
 }
 
@@ -1063,11 +1082,10 @@ impl ConfigChange {
         source_root: SourceRootId,
         vfs_path: VfsPath,
         content: Option>,
-    ) -> Option<(VfsPath, Option>)> {
-        dbg!("change_ratoml", &vfs_path);
+    ) -> Option<(RatomlFileKind, VfsPath, Option>)> {
         self.ratoml_file_change
             .get_or_insert_with(Default::default)
-            .insert(source_root, (vfs_path, content))
+            .insert(source_root, (RatomlFileKind::Crate, vfs_path, content))
     }
 
     pub fn change_user_config(&mut self, content: Option>) {
@@ -1080,11 +1098,10 @@ impl ConfigChange {
         source_root: SourceRootId,
         vfs_path: VfsPath,
         content: Option>,
-    ) -> Option<(VfsPath, Option>)> {
-        dbg!("change_workspace", &vfs_path);
-        self.workspace_ratoml_change
+    ) -> Option<(RatomlFileKind, VfsPath, Option>)> {
+        self.ratoml_file_change
             .get_or_insert_with(Default::default)
-            .insert(source_root, (vfs_path, content))
+            .insert(source_root, (RatomlFileKind::Workspace, vfs_path, content))
     }
 
     pub fn change_client_config(&mut self, change: serde_json::Value) {
@@ -1346,14 +1363,13 @@ impl Config {
             workspace_roots,
             visual_studio_code_version,
             client_config: (FullConfigInput::default(), ConfigErrors(vec![])),
-            krate_ratoml: FxHashMap::default(),
             default_config: DEFAULT_CONFIG_DATA.get_or_init(|| Box::leak(Box::default())),
             source_root_parent_map: Arc::new(FxHashMap::default()),
             user_config: None,
             user_config_path,
             detached_files: Default::default(),
             validation_errors: Default::default(),
-            workspace_ratoml: Default::default(),
+            ratoml_file: Default::default(),
         }
     }
 
@@ -1874,7 +1890,7 @@ impl Config {
     }
 
     pub fn rustfmt(&self, source_root_id: Option) -> RustfmtConfig {
-        match &self.rustfmt_overrideCommand(None) {
+        match &self.rustfmt_overrideCommand(source_root_id) {
             Some(args) if !args.is_empty() => {
                 let mut args = args.clone();
                 let command = args.remove(0);
@@ -2536,27 +2552,23 @@ macro_rules! _impl_for_config_data {
                 $($doc)*
                 #[allow(non_snake_case)]
                 $vis fn $field(&self, source_root: Option) -> &$ty {
-                    let follow = if stringify!($field) == "assist_emitMustUse" { dbg!("YEY"); true } else {false};
-                    let mut current: Option = None;
-                    let mut next: Option = source_root;
-                    if follow { dbg!(&self.krate_ratoml);}
-                    while let Some(source_root_id) = next {
-                        current = next;
-                        next = self.source_root_parent_map.get(&source_root_id).copied();
-                        if let Some((config, _)) = self.krate_ratoml.get(&source_root_id) {
-                            if let Some(value) = config.$field.as_ref() {
-                                return value;
-                            }
-                        }
-                    }
-
-                    if let Some(current) = current {
-                        if follow { dbg!(&self.workspace_ratoml);}
-                        if let Some((root_path_ratoml, _)) = self.workspace_ratoml.get(¤t).as_ref() {
-                            if let Some(v) = root_path_ratoml.local.$field.as_ref() {
-                                return &v;
+                    let mut source_root = source_root;
+                    while let Some(sr) = source_root {
+                        if let Some((file, _)) = self.ratoml_file.get(&sr) {
+                            match file {
+                                RatomlFile::Workspace(config) => {
+                                    if let Some(v) = config.local.$field.as_ref() {
+                                        return &v;
+                                    }
+                                },
+                                RatomlFile::Crate(config) => {
+                                    if let Some(value) = config.$field.as_ref() {
+                                        return value;
+                                    }
+                                }
                             }
                         }
+                        source_root = self.source_root_parent_map.get(&sr).copied();
                     }
 
                     if let Some(v) = self.client_config.0.local.$field.as_ref() {
@@ -2584,21 +2596,20 @@ macro_rules! _impl_for_config_data {
                 $($doc)*
                 #[allow(non_snake_case)]
                 $vis fn $field(&self, source_root : Option) -> &$ty {
-                    let follow = if stringify!($field) == "rustfmt_extraArgs" { dbg!("YEY"); true } else {false};
-                    let mut current: Option = None;
-                    let mut next: Option = source_root;
-                    while let Some(source_root_id) = next {
-                        current = next;
-                        next = self.source_root_parent_map.get(&source_root_id).copied();
-                    }
-
-                    if let Some(current) = current {
-                        if follow { dbg!(&self.workspace_ratoml);}
-                        if let Some((root_path_ratoml, _)) = self.workspace_ratoml.get(¤t).as_ref() {
-                            if let Some(v) = root_path_ratoml.global.$field.as_ref() {
-                                return &v;
+                    let mut source_root = source_root;
+                    while let Some(sr) = source_root {
+                        if let Some((file, _)) = self.ratoml_file.get(&sr) {
+                            match file {
+                                RatomlFile::Workspace(config) => {
+                                    if let Some(v) = config.global.$field.as_ref() {
+                                        return &v;
+                                    }
+                                },
+                                _ => ()
                             }
                         }
+
+                        source_root = self.source_root_parent_map.get(&sr).copied();
                     }
 
                     if let Some(v) = self.client_config.0.global.$field.as_ref() {
@@ -3667,21 +3678,7 @@ mod tests {
         let (_, e, _) = config.apply_change(change);
         expect_test::expect![[r#"
             ConfigErrors(
-                [
-                    Toml {
-                        config_key: "invalid/config/err",
-                        error: Error {
-                            inner: Error {
-                                inner: TomlError {
-                                    message: "unexpected field",
-                                    raw: None,
-                                    keys: [],
-                                    span: None,
-                                },
-                            },
-                        },
-                    },
-                ],
+                [],
             )
         "#]]
         .assert_debug_eq(&e);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index 5bfdb67af28a1..f1dde104fce4a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -26,13 +26,10 @@ use triomphe::Arc;
 use vfs::{AbsPathBuf, AnchoredPathBuf, ChangeKind, Vfs, VfsPath};
 
 use crate::{
-    config::{Config, ConfigChange, ConfigErrors},
+    config::{Config, ConfigChange, ConfigErrors, RatomlFileKind},
     diagnostics::{CheckFixes, DiagnosticCollection},
     line_index::{LineEndings, LineIndex},
-    lsp::{
-        from_proto::{self},
-        to_proto::url_from_abs_path,
-    },
+    lsp::{from_proto, to_proto::url_from_abs_path},
     lsp_ext,
     main_loop::Task,
     mem_docs::MemDocs,
@@ -411,27 +408,34 @@ impl GlobalState {
                     let sr_id = db.file_source_root(file_id);
                     let sr = db.source_root(sr_id);
 
-                    if workspace_ratoml_paths.contains(&vfs_path) {
-                        change.change_workspace_ratoml(
-                            sr_id,
-                            vfs_path,
-                            Some(db.file_text(file_id)),
-                        );
-                        continue;
-                    }
-
                     if !sr.is_library {
-                        if let Some((old_path, old_text)) = change.change_ratoml(
-                            sr_id,
-                            vfs_path.clone(),
-                            Some(db.file_text(file_id)),
-                        ) {
+                        let entry = if workspace_ratoml_paths.contains(&vfs_path) {
+                            change.change_workspace_ratoml(
+                                sr_id,
+                                vfs_path.clone(),
+                                Some(db.file_text(file_id)),
+                            )
+                        } else {
+                            change.change_ratoml(
+                                sr_id,
+                                vfs_path.clone(),
+                                Some(db.file_text(file_id)),
+                            )
+                        };
+
+                        if let Some((kind, old_path, old_text)) = entry {
                             // SourceRoot has more than 1 RATOML files. In this case lexicographically smaller wins.
                             if old_path < vfs_path {
-                                dbg!("HARBIDEN");
                                 span!(Level::ERROR, "Two `rust-analyzer.toml` files were found inside the same crate. {vfs_path} has no effect.");
                                 // Put the old one back in.
-                                change.change_ratoml(sr_id, old_path, old_text);
+                                match kind {
+                                    RatomlFileKind::Crate => {
+                                        change.change_ratoml(sr_id, old_path, old_text);
+                                    }
+                                    RatomlFileKind::Workspace => {
+                                        change.change_workspace_ratoml(sr_id, old_path, old_text);
+                                    }
+                                }
                             }
                         }
                     } else {

From 59c465b6e244e7f878d9c0d3a8785d9403818dcc Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Mon, 29 Jul 2024 03:43:27 +0200
Subject: [PATCH 200/489] add skip_slow_tests to ratoml tests

---
 .../rust-analyzer/tests/slow-tests/ratoml.rs  | 61 +++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
index 8c111723fb28e..c06ba9eee1477 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
@@ -10,6 +10,7 @@ use paths::Utf8PathBuf;
 
 use rust_analyzer::lsp::ext::{InternalTestingFetchConfig, InternalTestingFetchConfigParams};
 use serde_json::json;
+use test_utils::skip_slow_tests;
 
 enum QueryType {
     Local,
@@ -182,6 +183,10 @@ impl RatomlTest {
 /// the client config.
 #[test]
 fn ratoml_client_config_basic() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let server = RatomlTest::new(
         vec![
             r#"
@@ -283,6 +288,10 @@ enum Value {
 #[test]
 #[ignore = "the user config is currently not being watched on startup, fix this"]
 fn ratoml_user_config_detected() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let server = RatomlTest::new(
         vec![
             r#"
@@ -312,6 +321,10 @@ enum Value {
 #[test]
 #[ignore = "the user config is currently not being watched on startup, fix this"]
 fn ratoml_create_user_config() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"
@@ -343,6 +356,10 @@ enum Value {
 #[test]
 #[ignore = "the user config is currently not being watched on startup, fix this"]
 fn ratoml_modify_user_config() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"
@@ -373,6 +390,10 @@ assist.emitMustUse = true"#,
 #[test]
 #[ignore = "the user config is currently not being watched on startup, fix this"]
 fn ratoml_delete_user_config() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"
@@ -402,6 +423,10 @@ assist.emitMustUse = true"#,
 
 #[test]
 fn ratoml_inherit_config_from_ws_root() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let server = RatomlTest::new(
         vec![
             r#"
@@ -445,6 +470,10 @@ pub fn add(left: usize, right: usize) -> usize {
 
 #[test]
 fn ratoml_modify_ratoml_at_ws_root() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"
@@ -490,6 +519,10 @@ pub fn add(left: usize, right: usize) -> usize {
 
 #[test]
 fn ratoml_delete_ratoml_at_ws_root() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"
@@ -535,6 +568,10 @@ pub fn add(left: usize, right: usize) -> usize {
 
 #[test]
 fn ratoml_add_immediate_child_to_ws_root() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"
@@ -581,6 +618,10 @@ pub fn add(left: usize, right: usize) -> usize {
 #[test]
 #[ignore = "Root ratomls are not being looked for on startup. Fix this."]
 fn ratoml_rm_ws_root_ratoml_child_has_client_as_parent_now() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"
@@ -626,6 +667,10 @@ pub fn add(left: usize, right: usize) -> usize {
 
 #[test]
 fn ratoml_crates_both_roots() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let server = RatomlTest::new(
         vec![
             r#"
@@ -670,6 +715,10 @@ enum Value {
 
 #[test]
 fn ratoml_multiple_ratoml_in_single_source_root() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let server = RatomlTest::new(
         vec![
             r#"
@@ -778,6 +827,10 @@ fn ratoml_multiple_ratoml_in_single_source_root() {
 /// configuring global level configurations as well.
 #[test]
 fn ratoml_in_root_is_global() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let server = RatomlTest::new(
         vec![
             r#"
@@ -806,6 +859,10 @@ fn main() {
 
 #[test]
 fn ratoml_root_is_updateable() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"
@@ -836,6 +893,10 @@ fn main() {
 
 #[test]
 fn ratoml_root_is_deletable() {
+    if skip_slow_tests() {
+        return;
+    }
+
     let mut server = RatomlTest::new(
         vec![
             r#"

From 45ef4f2c32cb9a192b4cabfee8701eec42b64f20 Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Mon, 29 Jul 2024 03:46:02 +0200
Subject: [PATCH 201/489] Remove unnec copying of source_root_ids

---
 .../rust-analyzer/crates/rust-analyzer/src/config.rs      | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index abb112da60526..996f48482aa13 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -2552,7 +2552,7 @@ macro_rules! _impl_for_config_data {
                 $($doc)*
                 #[allow(non_snake_case)]
                 $vis fn $field(&self, source_root: Option) -> &$ty {
-                    let mut source_root = source_root;
+                    let mut source_root = source_root.as_ref();
                     while let Some(sr) = source_root {
                         if let Some((file, _)) = self.ratoml_file.get(&sr) {
                             match file {
@@ -2568,7 +2568,7 @@ macro_rules! _impl_for_config_data {
                                 }
                             }
                         }
-                        source_root = self.source_root_parent_map.get(&sr).copied();
+                        source_root = self.source_root_parent_map.get(&sr);
                     }
 
                     if let Some(v) = self.client_config.0.local.$field.as_ref() {
@@ -2596,7 +2596,7 @@ macro_rules! _impl_for_config_data {
                 $($doc)*
                 #[allow(non_snake_case)]
                 $vis fn $field(&self, source_root : Option) -> &$ty {
-                    let mut source_root = source_root;
+                    let mut source_root = source_root.as_ref();
                     while let Some(sr) = source_root {
                         if let Some((file, _)) = self.ratoml_file.get(&sr) {
                             match file {
@@ -2609,7 +2609,7 @@ macro_rules! _impl_for_config_data {
                             }
                         }
 
-                        source_root = self.source_root_parent_map.get(&sr).copied();
+                        source_root = self.source_root_parent_map.get(&sr);
                     }
 
                     if let Some(v) = self.client_config.0.global.$field.as_ref() {

From db05b0fd343e8204460b0e1f3e261cc4ae940e0a Mon Sep 17 00:00:00 2001
From: Zalathar 
Date: Sun, 28 Jul 2024 15:14:26 +1000
Subject: [PATCH 202/489] Encapsulate the printing of `WitnessPat`

This hides the fact that we print `WitnessPat` by converting it to `thir::Pat`
and then printing that.
---
 .../src/thir/pattern/check_match.rs                |  8 ++++----
 compiler/rustc_pattern_analysis/src/errors.rs      | 12 +++---------
 compiler/rustc_pattern_analysis/src/rustc.rs       | 14 +++++++++++---
 3 files changed, 18 insertions(+), 16 deletions(-)

diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 5e904057e732c..0632911671e12 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1077,7 +1077,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
     let suggested_arm = if suggest_the_witnesses {
         let pattern = witnesses
             .iter()
-            .map(|witness| cx.hoist_witness_pat(witness).to_string())
+            .map(|witness| cx.print_witness_pat(witness))
             .collect::>()
             .join(" | ");
         if witnesses.iter().all(|p| p.is_never_pattern()) && cx.tcx.features().never_patterns {
@@ -1195,13 +1195,13 @@ fn joined_uncovered_patterns<'p, 'tcx>(
     witnesses: &[WitnessPat<'p, 'tcx>],
 ) -> String {
     const LIMIT: usize = 3;
-    let pat_to_str = |pat: &WitnessPat<'p, 'tcx>| cx.hoist_witness_pat(pat).to_string();
+    let pat_to_str = |pat: &WitnessPat<'p, 'tcx>| cx.print_witness_pat(pat);
     match witnesses {
         [] => bug!(),
-        [witness] => format!("`{}`", cx.hoist_witness_pat(witness)),
+        [witness] => format!("`{}`", cx.print_witness_pat(witness)),
         [head @ .., tail] if head.len() < LIMIT => {
             let head: Vec<_> = head.iter().map(pat_to_str).collect();
-            format!("`{}` and `{}`", head.join("`, `"), cx.hoist_witness_pat(tail))
+            format!("`{}` and `{}`", head.join("`, `"), cx.print_witness_pat(tail))
         }
         _ => {
             let (head, tail) = witnesses.split_at(LIMIT);
diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs
index bad41ac77f098..1f7852e5190d2 100644
--- a/compiler/rustc_pattern_analysis/src/errors.rs
+++ b/compiler/rustc_pattern_analysis/src/errors.rs
@@ -26,19 +26,13 @@ impl Uncovered {
     where
         'tcx: 'p,
     {
-        let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap()).to_string();
+        let witness_1 = cx.print_witness_pat(witnesses.get(0).unwrap());
         Self {
             span,
             count: witnesses.len(),
             // Substitute dummy values if witnesses is smaller than 3. These will never be read.
-            witness_2: witnesses
-                .get(1)
-                .map(|w| cx.hoist_witness_pat(w).to_string())
-                .unwrap_or_default(),
-            witness_3: witnesses
-                .get(2)
-                .map(|w| cx.hoist_witness_pat(w).to_string())
-                .unwrap_or_default(),
+            witness_2: witnesses.get(1).map(|w| cx.print_witness_pat(w)).unwrap_or_default(),
+            witness_3: witnesses.get(2).map(|w| cx.print_witness_pat(w)).unwrap_or_default(),
             witness_1,
             remainder: witnesses.len().saturating_sub(3),
         }
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index ceddafa2f4ceb..b04c21a384c8c 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -744,7 +744,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
     /// Note: it is possible to get `isize/usize::MAX+1` here, as explained in the doc for
     /// [`IntRange::split`]. This cannot be represented as a `Const`, so we represent it with
     /// `PosInfinity`.
-    pub(crate) fn hoist_pat_range_bdy(
+    fn hoist_pat_range_bdy(
         &self,
         miint: MaybeInfiniteInt,
         ty: RevealedTy<'tcx>,
@@ -775,7 +775,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
     }
 
     /// Convert back to a `thir::Pat` for diagnostic purposes.
-    pub(crate) fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> Pat<'tcx> {
+    fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> Pat<'tcx> {
         use MaybeInfiniteInt::*;
         let cx = self;
         let kind = if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) {
@@ -811,9 +811,17 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
 
         Pat { ty: ty.inner(), span: DUMMY_SP, kind }
     }
+
+    /// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes.
+    pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String {
+        // This works by converting the witness pattern back to a `thir::Pat`
+        // and then printing that, but callers don't need to know that.
+        self.hoist_witness_pat(pat).to_string()
+    }
+
     /// Convert back to a `thir::Pat` for diagnostic purposes. This panics for patterns that don't
     /// appear in diagnostics, like float ranges.
-    pub fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'tcx> {
+    fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'tcx> {
         let cx = self;
         let is_wildcard = |pat: &Pat<'_>| matches!(pat.kind, PatKind::Wild);
         let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p)));

From ae0ec731a86ac6a2f6d8d08c4996bb8a438afdc2 Mon Sep 17 00:00:00 2001
From: Zalathar 
Date: Sun, 28 Jul 2024 14:02:41 +1000
Subject: [PATCH 203/489] Make `thir::Pat` not implement `fmt::Display`
 directly

This gives a clearer view of the (diagnostic) code that expects to be able to
print THIR patterns, and makes it possible to experiment with requiring some
kind of context (for ID lookup) when printing patterns.
---
 compiler/rustc_middle/src/thir.rs | 65 ++++++++++++++++++++++---------
 1 file changed, 46 insertions(+), 19 deletions(-)

diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 1300a06f37510..9b63b3980d20f 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -1073,8 +1073,33 @@ impl<'tcx> PatRangeBoundary<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Display for Pat<'tcx> {
+impl<'tcx> Pat<'tcx> {
+    /// Prints a [`Pat`] to an owned string, for user-facing diagnostics.
+    ///
+    /// If we ever switch over to storing subpatterns as `PatId`, this will also
+    /// need to take a context that can resolve IDs to subpatterns.
+    pub fn to_string(&self) -> String {
+        format!("{}", self.display())
+    }
+
+    /// Used internally by [`fmt::Display`] for [`PatDisplay`].
+    fn display(&self) -> PatDisplay<'_, 'tcx> {
+        PatDisplay { pat: self }
+    }
+}
+
+/// Wrapper around [`&Pat<'tcx>`][`Pat`] that implements [`fmt::Display`].
+///
+/// If we ever switch over to storing subpatterns as `PatId`, this will also
+/// need to hold a context that can resolve IDs to subpatterns.
+struct PatDisplay<'pat, 'tcx> {
+    pat: &'pat Pat<'tcx>,
+}
+
+impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let &Self { pat } = self;
+
         // Printing lists is a chore.
         let mut first = true;
         let mut start_or_continue = |s| {
@@ -1087,20 +1112,22 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
         };
         let mut start_or_comma = || start_or_continue(", ");
 
-        match self.kind {
+        match pat.kind {
             PatKind::Wild => write!(f, "_"),
             PatKind::Never => write!(f, "!"),
-            PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"),
+            PatKind::AscribeUserType { ref subpattern, .. } => {
+                write!(f, "{}: _", subpattern.display())
+            }
             PatKind::Binding { name, mode, ref subpattern, .. } => {
                 f.write_str(mode.prefix_str())?;
                 write!(f, "{name}")?;
                 if let Some(ref subpattern) = *subpattern {
-                    write!(f, " @ {subpattern}")?;
+                    write!(f, " @ {}", subpattern.display())?;
                 }
                 Ok(())
             }
             PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
-                let variant_and_name = match self.kind {
+                let variant_and_name = match pat.kind {
                     PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
                         let variant = adt_def.variant(variant_index);
                         let adt_did = adt_def.did();
@@ -1113,7 +1140,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
                         };
                         Some((variant, name))
                     }),
-                    _ => self.ty.ty_adt_def().and_then(|adt_def| {
+                    _ => pat.ty.ty_adt_def().and_then(|adt_def| {
                         if !adt_def.is_enum() {
                             ty::tls::with(|tcx| {
                                 Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
@@ -1138,11 +1165,11 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
                                 continue;
                             }
                             let name = variant.fields[p.field].name;
-                            write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?;
+                            write!(f, "{}{}: {}", start_or_comma(), name, p.pattern.display())?;
                             printed += 1;
                         }
 
-                        let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
+                        let is_union = pat.ty.ty_adt_def().is_some_and(|adt| adt.is_union());
                         if printed < variant.fields.len() && (!is_union || printed == 0) {
                             write!(f, "{}..", start_or_comma())?;
                         }
@@ -1161,14 +1188,14 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
                         // Common case: the field is where we expect it.
                         if let Some(p) = subpatterns.get(i) {
                             if p.field.index() == i {
-                                write!(f, "{}", p.pattern)?;
+                                write!(f, "{}", p.pattern.display())?;
                                 continue;
                             }
                         }
 
                         // Otherwise, we have to go looking for it.
                         if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
-                            write!(f, "{}", p.pattern)?;
+                            write!(f, "{}", p.pattern.display())?;
                         } else {
                             write!(f, "_")?;
                         }
@@ -1179,45 +1206,45 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
                 Ok(())
             }
             PatKind::Deref { ref subpattern } => {
-                match self.ty.kind() {
+                match pat.ty.kind() {
                     ty::Adt(def, _) if def.is_box() => write!(f, "box ")?,
                     ty::Ref(_, _, mutbl) => {
                         write!(f, "&{}", mutbl.prefix_str())?;
                     }
-                    _ => bug!("{} is a bad Deref pattern type", self.ty),
+                    _ => bug!("{} is a bad Deref pattern type", pat.ty),
                 }
-                write!(f, "{subpattern}")
+                write!(f, "{}", subpattern.display())
             }
             PatKind::DerefPattern { ref subpattern, .. } => {
-                write!(f, "deref!({subpattern})")
+                write!(f, "deref!({})", subpattern.display())
             }
             PatKind::Constant { value } => write!(f, "{value}"),
             PatKind::InlineConstant { def: _, ref subpattern } => {
-                write!(f, "{} (from inline const)", subpattern)
+                write!(f, "{} (from inline const)", subpattern.display())
             }
             PatKind::Range(ref range) => write!(f, "{range}"),
             PatKind::Slice { ref prefix, ref slice, ref suffix }
             | PatKind::Array { ref prefix, ref slice, ref suffix } => {
                 write!(f, "[")?;
                 for p in prefix.iter() {
-                    write!(f, "{}{}", start_or_comma(), p)?;
+                    write!(f, "{}{}", start_or_comma(), p.display())?;
                 }
                 if let Some(ref slice) = *slice {
                     write!(f, "{}", start_or_comma())?;
                     match slice.kind {
                         PatKind::Wild => {}
-                        _ => write!(f, "{slice}")?,
+                        _ => write!(f, "{}", slice.display())?,
                     }
                     write!(f, "..")?;
                 }
                 for p in suffix.iter() {
-                    write!(f, "{}{}", start_or_comma(), p)?;
+                    write!(f, "{}{}", start_or_comma(), p.display())?;
                 }
                 write!(f, "]")
             }
             PatKind::Or { ref pats } => {
                 for pat in pats.iter() {
-                    write!(f, "{}{}", start_or_continue(" | "), pat)?;
+                    write!(f, "{}{}", start_or_continue(" | "), pat.display())?;
                 }
                 Ok(())
             }

From 6e247195c644aa924a10c98cc8eb3a28e1a87929 Mon Sep 17 00:00:00 2001
From: onur-ozkan 
Date: Thu, 25 Jul 2024 15:59:25 +0300
Subject: [PATCH 204/489] handle no_std targets on std builds

This change unifies the `Step::run_make` logic and improves it by skipping
std specific crates for no_std targets.

Signed-off-by: onur-ozkan 
---
 src/bootstrap/src/core/build_steps/check.rs   |  4 ++--
 src/bootstrap/src/core/build_steps/clippy.rs  |  3 ++-
 src/bootstrap/src/core/build_steps/compile.rs | 23 +++++++++++++++----
 3 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 11ddae2aa2413..8b71300cf85e7 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -3,7 +3,7 @@
 use std::path::PathBuf;
 
 use crate::core::build_steps::compile::{
-    add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo,
+    add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
 };
 use crate::core::build_steps::tool::{prepare_tool_cargo, SourceType};
 use crate::core::builder::{
@@ -49,7 +49,7 @@ impl Step for Std {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        let crates = run.make_run_crates(Alias::Library);
+        let crates = std_crates_for_run_make(&run);
         run.builder.ensure(Std { target: run.target, crates, override_build_kind: None });
     }
 
diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs
index e45b44b82ded1..4ee9fbc314263 100644
--- a/src/bootstrap/src/core/build_steps/clippy.rs
+++ b/src/bootstrap/src/core/build_steps/clippy.rs
@@ -4,6 +4,7 @@ use super::compile::{librustc_stamp, libstd_stamp, run_cargo, rustc_cargo, std_c
 use super::tool::{prepare_tool_cargo, SourceType};
 use super::{check, compile};
 use crate::builder::{Builder, ShouldRun};
+use crate::core::build_steps::compile::std_crates_for_run_make;
 use crate::core::builder;
 use crate::core::builder::{crate_description, Alias, Kind, RunConfig, Step};
 use crate::{Mode, Subcommand, TargetSelection};
@@ -106,7 +107,7 @@ impl Step for Std {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        let crates = run.make_run_crates(Alias::Library);
+        let crates = std_crates_for_run_make(&run);
         run.builder.ensure(Std { target: run.target, crates });
     }
 
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index ce456a7200223..3164de8451ff2 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -123,11 +123,7 @@ impl Step for Std {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        // If the paths include "library", build the entire standard library.
-        let has_alias =
-            run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
-        let crates = if has_alias { Default::default() } else { run.cargo_crates_in_set() };
-
+        let crates = std_crates_for_run_make(&run);
         run.builder.ensure(Std {
             compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
             target: run.target,
@@ -425,6 +421,23 @@ fn copy_self_contained_objects(
     target_deps
 }
 
+/// Resolves standard library crates for `Std::run_make` for any build kind (like check, build, clippy, etc.).
+pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec {
+    let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
+    let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
+
+    // For no_std targets, do not add any additional crates to the compilation other than what `compile::std_cargo` already adds for no_std targets.
+    if target_is_no_std {
+        vec![]
+    }
+    // If the paths include "library", build the entire standard library.
+    else if has_alias {
+        run.make_run_crates(builder::Alias::Library)
+    } else {
+        run.cargo_crates_in_set()
+    }
+}
+
 /// Configure cargo to compile the standard library, adding appropriate env vars
 /// and such.
 pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) {

From 4c87e84f998378f125222f876ef454a71861a7f4 Mon Sep 17 00:00:00 2001
From: onur-ozkan 
Date: Thu, 25 Jul 2024 16:04:36 +0300
Subject: [PATCH 205/489] allow running `x doc` on std for no_std targets

Since we now handle library crates properly, there's no need to panic for `no_std`
targets anymore.

`x doc library` now generates documentation for the `alloc` crate from standard library.

Signed-off-by: onur-ozkan 
---
 src/bootstrap/src/core/build_steps/doc.rs | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 0b780dae9c29a..53925a3f54b8a 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -589,6 +589,7 @@ impl Step for Std {
     }
 
     fn make_run(run: RunConfig<'_>) {
+        let crates = compile::std_crates_for_run_make(&run);
         run.builder.ensure(Std {
             stage: run.builder.top_stage,
             target: run.target,
@@ -597,7 +598,7 @@ impl Step for Std {
             } else {
                 DocumentationFormat::Html
             },
-            crates: run.make_run_crates(Alias::Library),
+            crates,
         });
     }
 
@@ -695,13 +696,6 @@ fn doc_std(
     extra_args: &[&str],
     requested_crates: &[String],
 ) {
-    if builder.no_std(target) == Some(true) {
-        panic!(
-            "building std documentation for no_std target {target} is not supported\n\
-             Set `docs = false` in the config to disable documentation, or pass `--skip library`."
-        );
-    }
-
     let compiler = builder.compiler(stage, builder.config.build);
 
     let target_doc_dir_name = if format == DocumentationFormat::Json { "json-doc" } else { "doc" };

From d3aed2cdb4d4069ef7b6c5c74a3679817272a6ba Mon Sep 17 00:00:00 2001
From: onur-ozkan 
Date: Fri, 26 Jul 2024 08:48:46 +0300
Subject: [PATCH 206/489] remove the requirement of `Builder` arg in
 `doc::Std::new` function

`crates` field is handled in the `Step::make_run` just like in any other
`Std` implementation, so we don't need to resolve them in `Std::new`.

Signed-off-by: onur-ozkan 
---
 src/bootstrap/src/core/build_steps/dist.rs |  1 -
 src/bootstrap/src/core/build_steps/doc.rs  | 14 ++------------
 src/bootstrap/src/core/build_steps/test.rs |  1 -
 src/bootstrap/src/core/builder/tests.rs    |  4 ----
 4 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index f971bf115ee92..967ddbc0d3483 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -106,7 +106,6 @@ impl Step for JsonDocs {
         builder.ensure(crate::core::build_steps::doc::Std::new(
             builder.top_stage,
             host,
-            builder,
             DocumentationFormat::Json,
         ));
 
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 53925a3f54b8a..1541396bfdd98 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -564,18 +564,8 @@ pub struct Std {
 }
 
 impl Std {
-    pub(crate) fn new(
-        stage: u32,
-        target: TargetSelection,
-        builder: &Builder<'_>,
-        format: DocumentationFormat,
-    ) -> Self {
-        let crates = builder
-            .in_tree_crates("sysroot", Some(target))
-            .into_iter()
-            .map(|krate| krate.name.to_string())
-            .collect();
-        Std { stage, target, format, crates }
+    pub(crate) fn new(stage: u32, target: TargetSelection, format: DocumentationFormat) -> Self {
+        Std { stage, target, format, crates: vec![] }
     }
 }
 
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 79b7dd78810d2..ec96307deb285 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -847,7 +847,6 @@ impl Step for RustdocJSStd {
         builder.ensure(crate::core::build_steps::doc::Std::new(
             builder.top_stage,
             self.target,
-            builder,
             DocumentationFormat::Html,
         ));
         let _guard = builder.msg(
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index a295c89730acb..f19a4dd6d490f 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -79,13 +79,9 @@ macro_rules! std {
 
 macro_rules! doc_std {
     ($host:ident => $target:ident, stage = $stage:literal) => {{
-        let config = configure("doc", &["A-A"], &["A-A"]);
-        let build = Build::new(config);
-        let builder = Builder::new(&build);
         doc::Std::new(
             $stage,
             TargetSelection::from_user(concat!(stringify!($target), "-", stringify!($target))),
-            &builder,
             DocumentationFormat::Html,
         )
     }};

From f56d58e4a784b6429e742a411c2759900741894d Mon Sep 17 00:00:00 2001
From: onur-ozkan 
Date: Fri, 26 Jul 2024 08:54:55 +0300
Subject: [PATCH 207/489] ignore `crates` if running unit tests

Signed-off-by: onur-ozkan 
---
 src/bootstrap/src/core/build_steps/compile.rs | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 3164de8451ff2..268e89c7f6011 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -423,6 +423,11 @@ fn copy_self_contained_objects(
 
 /// Resolves standard library crates for `Std::run_make` for any build kind (like check, build, clippy, etc.).
 pub fn std_crates_for_run_make(run: &RunConfig<'_>) -> Vec {
+    // FIXME: Extend builder tests to cover the `crates` field of `Std` instances.
+    if cfg!(feature = "bootstrap-self-test") {
+        return vec![];
+    }
+
     let has_alias = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library"));
     let target_is_no_std = run.builder.no_std(run.target).unwrap_or(false);
 

From 9e05fb67a3360b9faf49b3484e2ac5cec27a6e78 Mon Sep 17 00:00:00 2001
From: Nadrieril 
Date: Sun, 23 Jun 2024 16:06:48 +0200
Subject: [PATCH 208/489] Small simplification

---
 .../rustc_mir_build/src/build/matches/mod.rs  | 34 +++++++++++--------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 6c34978a29c96..f56dad84cdbd1 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1199,6 +1199,17 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
             |_| {},
         );
     }
+
+    /// Visit the leaf candidates in reverse order.
+    fn visit_leaves_rev<'a>(&'a mut self, mut visit_leaf: impl FnMut(&'a mut Self)) {
+        traverse_candidate(
+            self,
+            &mut (),
+            &mut move |c, _| visit_leaf(c),
+            move |c, _| c.subcandidates.iter_mut().rev(),
+            |_| {},
+        );
+    }
 }
 
 /// A depth-first traversal of the `Candidate` and all of its recursive
@@ -1433,23 +1444,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let otherwise_block =
             self.match_candidates(match_start_span, scrutinee_span, block, candidates);
 
-        // Link each leaf candidate to the `false_edge_start_block` of the next one.
-        let mut previous_candidate: Option<&mut Candidate<'_, '_>> = None;
-        for candidate in candidates {
-            candidate.visit_leaves(|leaf_candidate| {
-                if let Some(ref mut prev) = previous_candidate {
-                    assert!(leaf_candidate.false_edge_start_block.is_some());
-                    prev.next_candidate_start_block = leaf_candidate.false_edge_start_block;
-                }
-                previous_candidate = Some(leaf_candidate);
+        // Link each leaf candidate to the `false_edge_start_block` of the next one. In the
+        // refutable case we also want a false edge to the failure block.
+        let mut next_candidate_start_block = if refutable { Some(otherwise_block) } else { None };
+        for candidate in candidates.iter_mut().rev() {
+            candidate.visit_leaves_rev(|leaf_candidate| {
+                leaf_candidate.next_candidate_start_block = next_candidate_start_block;
+                assert!(leaf_candidate.false_edge_start_block.is_some());
+                next_candidate_start_block = leaf_candidate.false_edge_start_block;
             });
         }
 
-        if refutable {
-            // In refutable cases there's always at least one candidate, and we want a false edge to
-            // the failure block.
-            previous_candidate.as_mut().unwrap().next_candidate_start_block = Some(otherwise_block)
-        } else {
+        if !refutable {
             // Match checking ensures `otherwise_block` is actually unreachable in irrefutable
             // cases.
             let source_info = self.source_info(scrutinee_span);

From e2fd9aa33e1887417375e94ec79b39ab4682c8b4 Mon Sep 17 00:00:00 2001
From: Nadrieril 
Date: Sun, 23 Jun 2024 15:54:42 +0200
Subject: [PATCH 209/489] Set up false edges in `lower_match_tree`

---
 .../rustc_mir_build/src/build/matches/mod.rs  |  61 ++++----
 .../rustc_mir_build/src/build/matches/util.rs |  19 ++-
 ...se_edges.full_tested_match.built.after.mir |  56 ++++----
 ...e_edges.full_tested_match2.built.after.mir |  44 +++---
 .../match_false_edges.main.built.after.mir    |  92 ++++++------
 ....constant_eq.SimplifyCfg-initial.after.mir |  40 +++---
 ...joint_ranges.SimplifyCfg-initial.after.mir |  30 ++--
 ...ch_match_arms.main.InstrumentCoverage.diff |  44 +++---
 ...mment_2.DeduplicateBlocks.panic-abort.diff |  28 ++--
 ...ment_2.DeduplicateBlocks.panic-unwind.diff |  28 ++--
 ...wise_branch.opt2.EarlyOtherwiseBranch.diff |  14 +-
 ...wise_branch.opt3.EarlyOtherwiseBranch.diff |  22 +--
 ...wise_branch.opt4.EarlyOtherwiseBranch.diff |  22 +--
 ...ement_tuple.opt1.EarlyOtherwiseBranch.diff |  14 +-
 ...ement_tuple.opt2.EarlyOtherwiseBranch.diff |  30 ++--
 ...ch_68867.try_sum.EarlyOtherwiseBranch.diff | 124 ++++++++--------
 ...nch_noopt.noopt1.EarlyOtherwiseBranch.diff |  26 ++--
 ...reading.dfa.JumpThreading.panic-abort.diff |  18 +--
 ...eading.dfa.JumpThreading.panic-unwind.diff |  18 +--
 tests/mir-opt/jump_threading.rs               |   6 +-
 ...fg-initial.after-ElaborateDrops.after.diff | 132 +++++++++---------
 ...fg-initial.after-ElaborateDrops.after.diff | 132 +++++++++---------
 ...h_i128_u128.MatchBranchSimplification.diff |   6 +-
 ...atch_i16_i8.MatchBranchSimplification.diff |   6 +-
 ...atch_i8_i16.MatchBranchSimplification.diff |   6 +-
 ..._i16_failed.MatchBranchSimplification.diff |   6 +-
 ...16_fallback.MatchBranchSimplification.diff |   6 +-
 ...atch_u8_u16.MatchBranchSimplification.diff |   6 +-
 ...ut_second_or.SimplifyCfg-initial.after.mir |  30 ++--
 ...le_switchint.SimplifyCfg-initial.after.mir |  16 +--
 ...tch_const.SingleUseConsts.panic-abort.diff |   8 +-
 ...ch_const.SingleUseConsts.panic-unwind.diff |   8 +-
 ...nst_debug.SingleUseConsts.panic-abort.diff |   8 +-
 ...st_debug.SingleUseConsts.panic-unwind.diff |   8 +-
 ..._fallthrough.UnreachableEnumBranching.diff |   8 +-
 ..._fallthrough.UnreachableEnumBranching.diff |   8 +-
 ....UnreachableEnumBranching.panic-abort.diff |  28 ++--
 ...UnreachableEnumBranching.panic-unwind.diff |  28 ++--
 ....UnreachableEnumBranching.panic-abort.diff |  12 +-
 ...UnreachableEnumBranching.panic-unwind.diff |  12 +-
 ....UnreachableEnumBranching.panic-abort.diff |  12 +-
 ...UnreachableEnumBranching.panic-unwind.diff |  12 +-
 ....UnreachableEnumBranching.panic-abort.diff |  12 +-
 ...UnreachableEnumBranching.panic-unwind.diff |  12 +-
 ....UnreachableEnumBranching.panic-abort.diff |  14 +-
 ...UnreachableEnumBranching.panic-unwind.diff |  14 +-
 ....UnreachableEnumBranching.panic-abort.diff |  32 ++---
 ...UnreachableEnumBranching.panic-unwind.diff |  32 ++---
 ....UnreachableEnumBranching.panic-abort.diff |  14 +-
 ...UnreachableEnumBranching.panic-unwind.diff |  14 +-
 tests/mir-opt/unreachable_enum_branching.rs   |  12 +-
 ....UnreachableEnumBranching.panic-abort.diff |  12 +-
 ...UnreachableEnumBranching.panic-unwind.diff |  12 +-
 .../ui/stable-mir-print/basic_function.stdout |   6 +-
 54 files changed, 720 insertions(+), 700 deletions(-)

diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index f56dad84cdbd1..0a55013ae20cd 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -1152,8 +1152,6 @@ struct Candidate<'pat, 'tcx> {
     /// The earliest block that has only candidates >= this one as descendents. Used for false
     /// edges, see the doc for [`Builder::match_expr`].
     false_edge_start_block: Option,
-    /// The `false_edge_start_block` of the next candidate.
-    next_candidate_start_block: Option,
 }
 
 impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
@@ -1179,7 +1177,6 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
             otherwise_block: None,
             pre_binding_block: None,
             false_edge_start_block: None,
-            next_candidate_start_block: None,
         }
     }
 
@@ -1444,12 +1441,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let otherwise_block =
             self.match_candidates(match_start_span, scrutinee_span, block, candidates);
 
-        // Link each leaf candidate to the `false_edge_start_block` of the next one. In the
-        // refutable case we also want a false edge to the failure block.
+        // Set up false edges so that the borrow-checker cannot make use of the specific CFG we
+        // generated. We falsely branch from each candidate to the one below it to make it as if we
+        // were testing match branches one by one in order. In the refutable case we also want a
+        // false edge to the final failure block.
         let mut next_candidate_start_block = if refutable { Some(otherwise_block) } else { None };
         for candidate in candidates.iter_mut().rev() {
+            let has_guard = candidate.has_guard;
             candidate.visit_leaves_rev(|leaf_candidate| {
-                leaf_candidate.next_candidate_start_block = next_candidate_start_block;
+                if let Some(next_candidate_start_block) = next_candidate_start_block {
+                    let source_info = self.source_info(leaf_candidate.extra_data.span);
+                    // Falsely branch to `next_candidate_start_block` before reaching pre_binding.
+                    let old_pre_binding = leaf_candidate.pre_binding_block.unwrap();
+                    let new_pre_binding = self.cfg.start_new_block();
+                    self.false_edges(
+                        old_pre_binding,
+                        new_pre_binding,
+                        next_candidate_start_block,
+                        source_info,
+                    );
+                    leaf_candidate.pre_binding_block = Some(new_pre_binding);
+                    if has_guard {
+                        // Falsely branch to `next_candidate_start_block` also if the guard fails.
+                        let new_otherwise = self.cfg.start_new_block();
+                        let old_otherwise = leaf_candidate.otherwise_block.unwrap();
+                        self.false_edges(
+                            new_otherwise,
+                            old_otherwise,
+                            next_candidate_start_block,
+                            source_info,
+                        );
+                        leaf_candidate.otherwise_block = Some(new_otherwise);
+                    }
+                }
                 assert!(leaf_candidate.false_edge_start_block.is_some());
                 next_candidate_start_block = leaf_candidate.false_edge_start_block;
             });
@@ -2302,20 +2326,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         debug_assert!(candidate.match_pairs.is_empty());
 
-        let candidate_source_info = self.source_info(candidate.extra_data.span);
-
-        let mut block = candidate.pre_binding_block.unwrap();
-
-        if candidate.next_candidate_start_block.is_some() {
-            let fresh_block = self.cfg.start_new_block();
-            self.false_edges(
-                block,
-                fresh_block,
-                candidate.next_candidate_start_block,
-                candidate_source_info,
-            );
-            block = fresh_block;
-        }
+        let block = candidate.pre_binding_block.unwrap();
 
         if candidate.extra_data.is_never {
             // This arm has a dummy body, we don't need to generate code for it. `block` is already
@@ -2382,16 +2393,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(temp));
             }
 
-            let otherwise_block = candidate.otherwise_block.unwrap_or_else(|| {
-                let unreachable = self.cfg.start_new_block();
-                self.cfg.terminate(unreachable, source_info, TerminatorKind::Unreachable);
-                unreachable
-            });
-            self.false_edges(
+            self.cfg.goto(
                 otherwise_post_guard_block,
-                otherwise_block,
-                candidate.next_candidate_start_block,
                 source_info,
+                candidate.otherwise_block.unwrap(),
             );
 
             // We want to ensure that the matched candidates are bound
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index c80204c4ad171..1848ab7a20be7 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -18,18 +18,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         from_block: BasicBlock,
         real_target: BasicBlock,
-        imaginary_target: Option,
+        imaginary_target: BasicBlock,
         source_info: SourceInfo,
     ) {
-        match imaginary_target {
-            Some(target) if target != real_target => {
-                self.cfg.terminate(
-                    from_block,
-                    source_info,
-                    TerminatorKind::FalseEdge { real_target, imaginary_target: target },
-                );
-            }
-            _ => self.cfg.goto(from_block, source_info, real_target),
+        if imaginary_target != real_target {
+            self.cfg.terminate(
+                from_block,
+                source_info,
+                TerminatorKind::FalseEdge { real_target, imaginary_target },
+            );
+        } else {
+            self.cfg.goto(from_block, source_info, real_target)
         }
     }
 }
diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
index 9ebfff18f4830..a93743edfac73 100644
--- a/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match.built.after.mir
@@ -37,11 +37,11 @@ fn full_tested_match() -> () {
     }
 
     bb2: {
-        falseEdge -> [real: bb7, imaginary: bb3];
+        falseEdge -> [real: bb8, imaginary: bb3];
     }
 
     bb3: {
-        falseEdge -> [real: bb12, imaginary: bb5];
+        falseEdge -> [real: bb7, imaginary: bb5];
     }
 
     bb4: {
@@ -50,7 +50,7 @@ fn full_tested_match() -> () {
 
     bb5: {
         _1 = (const 3_i32, const 3_i32);
-        goto -> bb13;
+        goto -> bb14;
     }
 
     bb6: {
@@ -58,18 +58,33 @@ fn full_tested_match() -> () {
     }
 
     bb7: {
+        StorageLive(_9);
+        _9 = ((_2 as Some).0: i32);
+        StorageLive(_10);
+        _10 = _9;
+        _1 = (const 2_i32, move _10);
+        StorageDead(_10);
+        StorageDead(_9);
+        goto -> bb14;
+    }
+
+    bb8: {
         StorageLive(_6);
         _6 = &((_2 as Some).0: i32);
         _3 = &fake shallow _2;
         StorageLive(_7);
-        _7 = guard() -> [return: bb8, unwind: bb15];
+        _7 = guard() -> [return: bb10, unwind: bb16];
     }
 
-    bb8: {
-        switchInt(move _7) -> [0: bb10, otherwise: bb9];
+    bb9: {
+        goto -> bb3;
     }
 
-    bb9: {
+    bb10: {
+        switchInt(move _7) -> [0: bb12, otherwise: bb11];
+    }
+
+    bb11: {
         StorageDead(_7);
         FakeRead(ForMatchGuard, _3);
         FakeRead(ForGuardBinding, _6);
@@ -81,31 +96,20 @@ fn full_tested_match() -> () {
         StorageDead(_8);
         StorageDead(_5);
         StorageDead(_6);
-        goto -> bb13;
+        goto -> bb14;
     }
 
-    bb10: {
-        goto -> bb11;
+    bb12: {
+        goto -> bb13;
     }
 
-    bb11: {
+    bb13: {
         StorageDead(_7);
         StorageDead(_6);
-        goto -> bb3;
-    }
-
-    bb12: {
-        StorageLive(_9);
-        _9 = ((_2 as Some).0: i32);
-        StorageLive(_10);
-        _10 = _9;
-        _1 = (const 2_i32, move _10);
-        StorageDead(_10);
-        StorageDead(_9);
-        goto -> bb13;
+        goto -> bb9;
     }
 
-    bb13: {
+    bb14: {
         PlaceMention(_1);
         StorageDead(_2);
         StorageDead(_1);
@@ -113,12 +117,12 @@ fn full_tested_match() -> () {
         return;
     }
 
-    bb14: {
+    bb15: {
         FakeRead(ForMatchedPlace(None), _1);
         unreachable;
     }
 
-    bb15 (cleanup): {
+    bb16 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
index 4d2989ea93ece..0d0ea2be1b005 100644
--- a/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.full_tested_match2.built.after.mir
@@ -37,7 +37,7 @@ fn full_tested_match2() -> () {
     }
 
     bb2: {
-        falseEdge -> [real: bb7, imaginary: bb5];
+        falseEdge -> [real: bb8, imaginary: bb5];
     }
 
     bb3: {
@@ -48,7 +48,7 @@ fn full_tested_match2() -> () {
         _1 = (const 2_i32, move _10);
         StorageDead(_10);
         StorageDead(_9);
-        goto -> bb13;
+        goto -> bb14;
     }
 
     bb4: {
@@ -56,7 +56,7 @@ fn full_tested_match2() -> () {
     }
 
     bb5: {
-        falseEdge -> [real: bb12, imaginary: bb3];
+        falseEdge -> [real: bb7, imaginary: bb3];
     }
 
     bb6: {
@@ -64,18 +64,27 @@ fn full_tested_match2() -> () {
     }
 
     bb7: {
+        _1 = (const 3_i32, const 3_i32);
+        goto -> bb14;
+    }
+
+    bb8: {
         StorageLive(_6);
         _6 = &((_2 as Some).0: i32);
         _3 = &fake shallow _2;
         StorageLive(_7);
-        _7 = guard() -> [return: bb8, unwind: bb15];
+        _7 = guard() -> [return: bb10, unwind: bb16];
     }
 
-    bb8: {
-        switchInt(move _7) -> [0: bb10, otherwise: bb9];
+    bb9: {
+        falseEdge -> [real: bb3, imaginary: bb5];
     }
 
-    bb9: {
+    bb10: {
+        switchInt(move _7) -> [0: bb12, otherwise: bb11];
+    }
+
+    bb11: {
         StorageDead(_7);
         FakeRead(ForMatchGuard, _3);
         FakeRead(ForGuardBinding, _6);
@@ -87,25 +96,20 @@ fn full_tested_match2() -> () {
         StorageDead(_8);
         StorageDead(_5);
         StorageDead(_6);
-        goto -> bb13;
+        goto -> bb14;
     }
 
-    bb10: {
-        goto -> bb11;
+    bb12: {
+        goto -> bb13;
     }
 
-    bb11: {
+    bb13: {
         StorageDead(_7);
         StorageDead(_6);
-        falseEdge -> [real: bb3, imaginary: bb5];
-    }
-
-    bb12: {
-        _1 = (const 3_i32, const 3_i32);
-        goto -> bb13;
+        goto -> bb9;
     }
 
-    bb13: {
+    bb14: {
         PlaceMention(_1);
         StorageDead(_2);
         StorageDead(_1);
@@ -113,12 +117,12 @@ fn full_tested_match2() -> () {
         return;
     }
 
-    bb14: {
+    bb15: {
         FakeRead(ForMatchedPlace(None), _1);
         unreachable;
     }
 
-    bb15 (cleanup): {
+    bb16 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
index 4ed9361070662..87b7e29848f74 100644
--- a/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
+++ b/tests/mir-opt/building/match/match_false_edges.main.built.after.mir
@@ -43,11 +43,11 @@ fn main() -> () {
     }
 
     bb1: {
-        falseEdge -> [real: bb14, imaginary: bb4];
+        falseEdge -> [real: bb11, imaginary: bb4];
     }
 
     bb2: {
-        falseEdge -> [real: bb9, imaginary: bb1];
+        falseEdge -> [real: bb12, imaginary: bb1];
     }
 
     bb3: {
@@ -64,11 +64,11 @@ fn main() -> () {
         _14 = _2;
         _1 = const 4_i32;
         StorageDead(_14);
-        goto -> bb20;
+        goto -> bb22;
     }
 
     bb6: {
-        falseEdge -> [real: bb15, imaginary: bb5];
+        falseEdge -> [real: bb9, imaginary: bb5];
     }
 
     bb7: {
@@ -81,62 +81,70 @@ fn main() -> () {
     }
 
     bb9: {
-        StorageLive(_7);
-        _7 = &((_2 as Some).0: i32);
+        StorageLive(_11);
+        _11 = &((_2 as Some).0: i32);
         _3 = &fake shallow _2;
-        StorageLive(_8);
-        _8 = guard() -> [return: bb10, unwind: bb22];
+        StorageLive(_12);
+        StorageLive(_13);
+        _13 = (*_11);
+        _12 = guard2(move _13) -> [return: bb18, unwind: bb24];
     }
 
     bb10: {
-        switchInt(move _8) -> [0: bb12, otherwise: bb11];
+        falseEdge -> [real: bb7, imaginary: bb5];
     }
 
     bb11: {
-        StorageDead(_8);
-        FakeRead(ForMatchGuard, _3);
-        FakeRead(ForGuardBinding, _7);
-        StorageLive(_6);
-        _6 = ((_2 as Some).0: i32);
-        _1 = const 1_i32;
-        StorageDead(_6);
-        StorageDead(_7);
-        goto -> bb20;
+        StorageLive(_9);
+        _9 = _2;
+        _1 = const 2_i32;
+        StorageDead(_9);
+        goto -> bb22;
     }
 
     bb12: {
-        goto -> bb13;
+        StorageLive(_7);
+        _7 = &((_2 as Some).0: i32);
+        _3 = &fake shallow _2;
+        StorageLive(_8);
+        _8 = guard() -> [return: bb14, unwind: bb24];
     }
 
     bb13: {
-        StorageDead(_8);
-        StorageDead(_7);
         falseEdge -> [real: bb3, imaginary: bb1];
     }
 
     bb14: {
-        StorageLive(_9);
-        _9 = _2;
-        _1 = const 2_i32;
-        StorageDead(_9);
-        goto -> bb20;
+        switchInt(move _8) -> [0: bb16, otherwise: bb15];
     }
 
     bb15: {
-        StorageLive(_11);
-        _11 = &((_2 as Some).0: i32);
-        _3 = &fake shallow _2;
-        StorageLive(_12);
-        StorageLive(_13);
-        _13 = (*_11);
-        _12 = guard2(move _13) -> [return: bb16, unwind: bb22];
+        StorageDead(_8);
+        FakeRead(ForMatchGuard, _3);
+        FakeRead(ForGuardBinding, _7);
+        StorageLive(_6);
+        _6 = ((_2 as Some).0: i32);
+        _1 = const 1_i32;
+        StorageDead(_6);
+        StorageDead(_7);
+        goto -> bb22;
     }
 
     bb16: {
-        switchInt(move _12) -> [0: bb18, otherwise: bb17];
+        goto -> bb17;
     }
 
     bb17: {
+        StorageDead(_8);
+        StorageDead(_7);
+        goto -> bb13;
+    }
+
+    bb18: {
+        switchInt(move _12) -> [0: bb20, otherwise: bb19];
+    }
+
+    bb19: {
         StorageDead(_13);
         StorageDead(_12);
         FakeRead(ForMatchGuard, _3);
@@ -146,21 +154,21 @@ fn main() -> () {
         _1 = const 3_i32;
         StorageDead(_10);
         StorageDead(_11);
-        goto -> bb20;
+        goto -> bb22;
     }
 
-    bb18: {
-        goto -> bb19;
+    bb20: {
+        goto -> bb21;
     }
 
-    bb19: {
+    bb21: {
         StorageDead(_13);
         StorageDead(_12);
         StorageDead(_11);
-        falseEdge -> [real: bb7, imaginary: bb5];
+        goto -> bb10;
     }
 
-    bb20: {
+    bb22: {
         PlaceMention(_1);
         StorageDead(_2);
         StorageDead(_1);
@@ -168,12 +176,12 @@ fn main() -> () {
         return;
     }
 
-    bb21: {
+    bb23: {
         FakeRead(ForMatchedPlace(None), _1);
         unreachable;
     }
 
-    bb22 (cleanup): {
+    bb24 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
index 2b5dbacc2d928..2bce79a3ae799 100644
--- a/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/sort_candidates.constant_eq.SimplifyCfg-initial.after.mir
@@ -31,7 +31,7 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
     }
 
     bb2: {
-        falseEdge -> [real: bb12, imaginary: bb5];
+        falseEdge -> [real: bb15, imaginary: bb5];
     }
 
     bb3: {
@@ -39,7 +39,7 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
     }
 
     bb4: {
-        falseEdge -> [real: bb16, imaginary: bb1];
+        falseEdge -> [real: bb13, imaginary: bb1];
     }
 
     bb5: {
@@ -51,7 +51,7 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
     }
 
     bb7: {
-        falseEdge -> [real: bb15, imaginary: bb3];
+        falseEdge -> [real: bb14, imaginary: bb3];
     }
 
     bb8: {
@@ -68,43 +68,43 @@ fn constant_eq(_1: &str, _2: bool) -> u32 {
     }
 
     bb11: {
-        falseEdge -> [real: bb17, imaginary: bb10];
+        falseEdge -> [real: bb12, imaginary: bb10];
     }
 
     bb12: {
-        _6 = &fake shallow (_3.0: &str);
-        _7 = &fake shallow (_3.1: bool);
-        StorageLive(_10);
-        _10 = const true;
-        switchInt(move _10) -> [0: bb14, otherwise: bb13];
+        _0 = const 4_u32;
+        goto -> bb18;
     }
 
     bb13: {
-        StorageDead(_10);
-        FakeRead(ForMatchGuard, _6);
-        FakeRead(ForMatchGuard, _7);
-        _0 = const 1_u32;
+        _0 = const 3_u32;
         goto -> bb18;
     }
 
     bb14: {
-        StorageDead(_10);
-        falseEdge -> [real: bb3, imaginary: bb5];
+        _0 = const 2_u32;
+        goto -> bb18;
     }
 
     bb15: {
-        _0 = const 2_u32;
-        goto -> bb18;
+        _6 = &fake shallow (_3.0: &str);
+        _7 = &fake shallow (_3.1: bool);
+        StorageLive(_10);
+        _10 = const true;
+        switchInt(move _10) -> [0: bb17, otherwise: bb16];
     }
 
     bb16: {
-        _0 = const 3_u32;
+        StorageDead(_10);
+        FakeRead(ForMatchGuard, _6);
+        FakeRead(ForMatchGuard, _7);
+        _0 = const 1_u32;
         goto -> bb18;
     }
 
     bb17: {
-        _0 = const 4_u32;
-        goto -> bb18;
+        StorageDead(_10);
+        falseEdge -> [real: bb3, imaginary: bb5];
     }
 
     bb18: {
diff --git a/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir b/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
index 07daa3eddfa2c..e521fb4509aa1 100644
--- a/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/building/match/sort_candidates.disjoint_ranges.SimplifyCfg-initial.after.mir
@@ -23,7 +23,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
     }
 
     bb2: {
-        falseEdge -> [real: bb9, imaginary: bb3];
+        falseEdge -> [real: bb11, imaginary: bb3];
     }
 
     bb3: {
@@ -32,7 +32,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
     }
 
     bb4: {
-        falseEdge -> [real: bb12, imaginary: bb5];
+        falseEdge -> [real: bb10, imaginary: bb5];
     }
 
     bb5: {
@@ -40,7 +40,7 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
     }
 
     bb6: {
-        falseEdge -> [real: bb13, imaginary: bb1];
+        falseEdge -> [real: bb9, imaginary: bb1];
     }
 
     bb7: {
@@ -54,32 +54,32 @@ fn disjoint_ranges(_1: i32, _2: bool) -> u32 {
     }
 
     bb9: {
-        _3 = &fake shallow _1;
-        StorageLive(_8);
-        _8 = _2;
-        switchInt(move _8) -> [0: bb11, otherwise: bb10];
+        _0 = const 2_u32;
+        goto -> bb14;
     }
 
     bb10: {
-        StorageDead(_8);
-        FakeRead(ForMatchGuard, _3);
-        _0 = const 0_u32;
+        _0 = const 1_u32;
         goto -> bb14;
     }
 
     bb11: {
-        StorageDead(_8);
-        falseEdge -> [real: bb1, imaginary: bb3];
+        _3 = &fake shallow _1;
+        StorageLive(_8);
+        _8 = _2;
+        switchInt(move _8) -> [0: bb13, otherwise: bb12];
     }
 
     bb12: {
-        _0 = const 1_u32;
+        StorageDead(_8);
+        FakeRead(ForMatchGuard, _3);
+        _0 = const 0_u32;
         goto -> bb14;
     }
 
     bb13: {
-        _0 = const 2_u32;
-        goto -> bb14;
+        StorageDead(_8);
+        falseEdge -> [real: bb1, imaginary: bb3];
     }
 
     bb14: {
diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
index e60f71f47b1ed..3d791734f4626 100644
--- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
@@ -55,17 +55,17 @@
   
       bb2: {
 +         Coverage::CounterIncrement(3);
-          falseEdge -> [real: bb6, imaginary: bb3];
+          falseEdge -> [real: bb8, imaginary: bb3];
       }
   
       bb3: {
 +         Coverage::CounterIncrement(2);
-          falseEdge -> [real: bb8, imaginary: bb4];
+          falseEdge -> [real: bb7, imaginary: bb4];
       }
   
       bb4: {
 +         Coverage::CounterIncrement(1);
-          falseEdge -> [real: bb10, imaginary: bb5];
+          falseEdge -> [real: bb6, imaginary: bb5];
       }
   
       bb5: {
@@ -78,39 +78,39 @@
       }
   
       bb6: {
-          StorageLive(_3);
-          _3 = ((_1 as D).0: u32);
-          StorageLive(_4);
-          _4 = _3;
-          _0 = consume(move _4) -> [return: bb7, unwind: bb14];
+          StorageLive(_7);
+          _7 = ((_1 as B).0: u32);
+          StorageLive(_8);
+          _8 = _7;
+          _0 = consume(move _8) -> [return: bb11, unwind: bb14];
       }
   
       bb7: {
-          StorageDead(_4);
-          StorageDead(_3);
-          goto -> bb13;
-      }
-  
-      bb8: {
           StorageLive(_5);
           _5 = ((_1 as C).0: u32);
           StorageLive(_6);
           _6 = _5;
-          _0 = consume(move _6) -> [return: bb9, unwind: bb14];
+          _0 = consume(move _6) -> [return: bb10, unwind: bb14];
+      }
+  
+      bb8: {
+          StorageLive(_3);
+          _3 = ((_1 as D).0: u32);
+          StorageLive(_4);
+          _4 = _3;
+          _0 = consume(move _4) -> [return: bb9, unwind: bb14];
       }
   
       bb9: {
-          StorageDead(_6);
-          StorageDead(_5);
+          StorageDead(_4);
+          StorageDead(_3);
           goto -> bb13;
       }
   
       bb10: {
-          StorageLive(_7);
-          _7 = ((_1 as B).0: u32);
-          StorageLive(_8);
-          _8 = _7;
-          _0 = consume(move _8) -> [return: bb11, unwind: bb14];
+          StorageDead(_6);
+          StorageDead(_5);
+          goto -> bb13;
       }
   
       bb11: {
diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff
index 3a5762e4f3d1e..efb28ba344b2b 100644
--- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff
+++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff
@@ -33,7 +33,7 @@
           _8 = const 3_usize;
           _9 = Ge(move _7, move _8);
 -         switchInt(move _9) -> [0: bb7, otherwise: bb8];
-+         switchInt(move _9) -> [0: bb10, otherwise: bb7];
++         switchInt(move _9) -> [0: bb11, otherwise: bb7];
       }
   
       bb3: {
@@ -49,48 +49,48 @@
       }
   
       bb6: {
--         switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
-+         switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2];
+-         switchInt((*_2)[3 of 4]) -> [47: bb13, otherwise: bb2];
++         switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
       }
   
       bb7: {
 -         _0 = const false;
 -         goto -> bb14;
-+         switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10];
++         switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb11];
       }
   
       bb8: {
 -         switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
-+         switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10];
++         switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb11];
       }
   
       bb9: {
 -         switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
-+         switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10];
++         switchInt((*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11];
       }
   
       bb10: {
--         switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb7];
+-         switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7];
 -     }
 - 
 -     bb11: {
-          _0 = const false;
+          _0 = const true;
 -         goto -> bb14;
 +         goto -> bb12;
       }
   
 -     bb12: {
+-         _0 = const true;
+-         goto -> bb14;
+-     }
+- 
+-     bb13: {
 +     bb11: {
-          _0 = const true;
+          _0 = const false;
 -         goto -> bb14;
 +         goto -> bb12;
       }
   
--     bb13: {
--         _0 = const true;
--         goto -> bb14;
--     }
-- 
 -     bb14: {
 +     bb12: {
           StorageDead(_2);
diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff
index 21b197d2f270c..c6e2d3a551259 100644
--- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff
+++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff
@@ -33,7 +33,7 @@
           _8 = const 3_usize;
           _9 = Ge(move _7, move _8);
 -         switchInt(move _9) -> [0: bb7, otherwise: bb8];
-+         switchInt(move _9) -> [0: bb10, otherwise: bb7];
++         switchInt(move _9) -> [0: bb11, otherwise: bb7];
       }
   
       bb3: {
@@ -49,48 +49,48 @@
       }
   
       bb6: {
--         switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
-+         switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb2];
+-         switchInt((*_2)[3 of 4]) -> [47: bb13, otherwise: bb2];
++         switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
       }
   
       bb7: {
 -         _0 = const false;
 -         goto -> bb14;
-+         switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10];
++         switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb11];
       }
   
       bb8: {
 -         switchInt((*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
-+         switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10];
++         switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb11];
       }
   
       bb9: {
 -         switchInt((*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
-+         switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10];
++         switchInt((*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11];
       }
   
       bb10: {
--         switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb7];
+-         switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7];
 -     }
 - 
 -     bb11: {
-          _0 = const false;
+          _0 = const true;
 -         goto -> bb14;
 +         goto -> bb12;
       }
   
 -     bb12: {
+-         _0 = const true;
+-         goto -> bb14;
+-     }
+- 
+-     bb13: {
 +     bb11: {
-          _0 = const true;
+          _0 = const false;
 -         goto -> bb14;
 +         goto -> bb12;
       }
   
--     bb13: {
--         _0 = const true;
--         goto -> bb14;
--     }
-- 
 -     bb14: {
 +     bb12: {
           StorageDead(_2);
diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
index 7776ff0fde794..41ae2fd3af3f4 100644
--- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
@@ -38,15 +38,20 @@
   
       bb2: {
           _6 = discriminant((_3.1: std::option::Option));
-          switchInt(move _6) -> [1: bb4, 0: bb1, otherwise: bb7];
+          switchInt(move _6) -> [1: bb5, 0: bb1, otherwise: bb7];
       }
   
       bb3: {
           _7 = discriminant((_3.1: std::option::Option));
-          switchInt(move _7) -> [0: bb5, 1: bb1, otherwise: bb7];
+          switchInt(move _7) -> [0: bb4, 1: bb1, otherwise: bb7];
       }
   
       bb4: {
+          _0 = const 2_u32;
+          goto -> bb6;
+      }
+  
+      bb5: {
           StorageLive(_9);
           _9 = (((_3.0: std::option::Option) as Some).0: u32);
           StorageLive(_10);
@@ -57,11 +62,6 @@
           goto -> bb6;
       }
   
-      bb5: {
-          _0 = const 2_u32;
-          goto -> bb6;
-      }
-  
       bb6: {
           StorageDead(_3);
           return;
diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
index b41e952d80f5a..302fd0bfded4b 100644
--- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
@@ -49,7 +49,7 @@
   
       bb2: {
 -         _6 = discriminant((_3.1: Option2));
--         switchInt(move _6) -> [0: bb5, otherwise: bb1];
+-         switchInt(move _6) -> [0: bb7, otherwise: bb1];
 -     }
 - 
 -     bb3: {
@@ -59,17 +59,11 @@
 - 
 -     bb4: {
 -         _8 = discriminant((_3.1: Option2));
--         switchInt(move _8) -> [2: bb7, otherwise: bb1];
+-         switchInt(move _8) -> [2: bb5, otherwise: bb1];
 -     }
 - 
 -     bb5: {
-          StorageLive(_10);
-          _10 = (((_3.0: Option2) as Some).0: u32);
-          StorageLive(_11);
-          _11 = (((_3.1: Option2) as Some).0: bool);
-          _0 = const 0_u32;
-          StorageDead(_11);
-          StorageDead(_10);
+          _0 = const 3_u32;
 -         goto -> bb8;
 +         goto -> bb5;
       }
@@ -83,7 +77,13 @@
   
 -     bb7: {
 +     bb4: {
-          _0 = const 3_u32;
+          StorageLive(_10);
+          _10 = (((_3.0: Option2) as Some).0: u32);
+          StorageLive(_11);
+          _11 = (((_3.1: Option2) as Some).0: bool);
+          _0 = const 0_u32;
+          StorageDead(_11);
+          StorageDead(_10);
 -         goto -> bb8;
 +         goto -> bb5;
       }
@@ -101,7 +101,7 @@
 + 
 +     bb7: {
 +         StorageDead(_13);
-+         switchInt(_9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb6];
++         switchInt(_9) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb6];
       }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
index 18dea56f4307c..eef4fb3278c1c 100644
--- a/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt4.EarlyOtherwiseBranch.diff
@@ -49,7 +49,7 @@
   
       bb2: {
 -         _6 = discriminant((_3.1: Option2));
--         switchInt(move _6) -> [0: bb5, otherwise: bb1];
+-         switchInt(move _6) -> [0: bb7, otherwise: bb1];
 -     }
 - 
 -     bb3: {
@@ -59,17 +59,11 @@
 - 
 -     bb4: {
 -         _8 = discriminant((_3.1: Option2));
--         switchInt(move _8) -> [2: bb7, otherwise: bb1];
+-         switchInt(move _8) -> [2: bb5, otherwise: bb1];
 -     }
 - 
 -     bb5: {
-          StorageLive(_10);
-          _10 = (((_3.0: Option2) as Some).0: u32);
-          StorageLive(_11);
-          _11 = (((_3.1: Option2) as Some).0: u32);
-          _0 = const 0_u32;
-          StorageDead(_11);
-          StorageDead(_10);
+          _0 = const 3_u32;
 -         goto -> bb8;
 +         goto -> bb5;
       }
@@ -83,7 +77,13 @@
   
 -     bb7: {
 +     bb4: {
-          _0 = const 3_u32;
+          StorageLive(_10);
+          _10 = (((_3.0: Option2) as Some).0: u32);
+          StorageLive(_11);
+          _11 = (((_3.1: Option2) as Some).0: u32);
+          _0 = const 0_u32;
+          StorageDead(_11);
+          StorageDead(_10);
 -         goto -> bb8;
 +         goto -> bb5;
       }
@@ -101,7 +101,7 @@
 + 
 +     bb7: {
 +         StorageDead(_13);
-+         switchInt(_9) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb6];
++         switchInt(_9) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb6];
       }
   }
   
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
index 4c3c717b52251..cb03e2697ccd3 100644
--- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
@@ -52,7 +52,7 @@
   
       bb3: {
           _8 = discriminant((_4.2: std::option::Option));
-          switchInt(move _8) -> [1: bb6, 0: bb1, otherwise: bb9];
+          switchInt(move _8) -> [1: bb7, 0: bb1, otherwise: bb9];
       }
   
       bb4: {
@@ -62,10 +62,15 @@
   
       bb5: {
           _10 = discriminant((_4.2: std::option::Option));
-          switchInt(move _10) -> [0: bb7, 1: bb1, otherwise: bb9];
+          switchInt(move _10) -> [0: bb6, 1: bb1, otherwise: bb9];
       }
   
       bb6: {
+          _0 = const 2_u32;
+          goto -> bb8;
+      }
+  
+      bb7: {
           StorageLive(_13);
           _13 = (((_4.0: std::option::Option) as Some).0: u32);
           StorageLive(_14);
@@ -79,11 +84,6 @@
           goto -> bb8;
       }
   
-      bb7: {
-          _0 = const 2_u32;
-          goto -> bb8;
-      }
-  
       bb8: {
           StorageDead(_4);
           return;
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
index 0ea7a10baaadc..5634df253a5d0 100644
--- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt2.EarlyOtherwiseBranch.diff
@@ -64,8 +64,8 @@
 - 
 -     bb3: {
           _8 = discriminant((_4.2: Option2));
--         switchInt(move _8) -> [0: bb8, otherwise: bb1];
-+         switchInt(move _8) -> [0: bb5, otherwise: bb1];
+-         switchInt(move _8) -> [0: bb10, otherwise: bb1];
++         switchInt(move _8) -> [0: bb7, otherwise: bb1];
       }
   
 -     bb4: {
@@ -88,22 +88,13 @@
 -     bb7: {
 +     bb4: {
           _12 = discriminant((_4.2: Option2));
--         switchInt(move _12) -> [2: bb10, otherwise: bb1];
-+         switchInt(move _12) -> [2: bb7, otherwise: bb1];
+-         switchInt(move _12) -> [2: bb8, otherwise: bb1];
++         switchInt(move _12) -> [2: bb5, otherwise: bb1];
       }
   
 -     bb8: {
 +     bb5: {
-          StorageLive(_15);
-          _15 = (((_4.0: Option2) as Some).0: u32);
-          StorageLive(_16);
-          _16 = (((_4.1: Option2) as Some).0: u32);
-          StorageLive(_17);
-          _17 = (((_4.2: Option2) as Some).0: u32);
-          _0 = const 0_u32;
-          StorageDead(_17);
-          StorageDead(_16);
-          StorageDead(_15);
+          _0 = const 3_u32;
 -         goto -> bb11;
 +         goto -> bb8;
       }
@@ -117,7 +108,16 @@
   
 -     bb10: {
 +     bb7: {
-          _0 = const 3_u32;
+          StorageLive(_15);
+          _15 = (((_4.0: Option2) as Some).0: u32);
+          StorageLive(_16);
+          _16 = (((_4.1: Option2) as Some).0: u32);
+          StorageLive(_17);
+          _17 = (((_4.2: Option2) as Some).0: u32);
+          _0 = const 0_u32;
+          StorageDead(_17);
+          StorageDead(_16);
+          StorageDead(_15);
 -         goto -> bb11;
 +         goto -> bb8;
       }
diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
index de12fe8f120a7..8179d9dd11505 100644
--- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
@@ -94,78 +94,56 @@
       bb2: {
           _35 = deref_copy (_4.1: &ViewportPercentageLength);
           _7 = discriminant((*_35));
-          switchInt(move _7) -> [0: bb6, otherwise: bb1];
+          switchInt(move _7) -> [0: bb9, otherwise: bb1];
       }
   
       bb3: {
           _36 = deref_copy (_4.1: &ViewportPercentageLength);
           _8 = discriminant((*_36));
-          switchInt(move _8) -> [1: bb7, otherwise: bb1];
+          switchInt(move _8) -> [1: bb8, otherwise: bb1];
       }
   
       bb4: {
           _37 = deref_copy (_4.1: &ViewportPercentageLength);
           _9 = discriminant((*_37));
-          switchInt(move _9) -> [2: bb8, otherwise: bb1];
+          switchInt(move _9) -> [2: bb7, otherwise: bb1];
       }
   
       bb5: {
           _38 = deref_copy (_4.1: &ViewportPercentageLength);
           _10 = discriminant((*_38));
-          switchInt(move _10) -> [3: bb9, otherwise: bb1];
+          switchInt(move _10) -> [3: bb6, otherwise: bb1];
       }
   
       bb6: {
-          StorageLive(_12);
+          StorageLive(_27);
           _39 = deref_copy (_4.0: &ViewportPercentageLength);
-          _12 = (((*_39) as Vw).0: f32);
-          StorageLive(_13);
+          _27 = (((*_39) as Vmax).0: f32);
+          StorageLive(_28);
           _40 = deref_copy (_4.1: &ViewportPercentageLength);
-          _13 = (((*_40) as Vw).0: f32);
-          StorageLive(_14);
-          StorageLive(_15);
-          _15 = _12;
-          StorageLive(_16);
-          _16 = _13;
-          _14 = Add(move _15, move _16);
-          StorageDead(_16);
-          StorageDead(_15);
-          _3 = ViewportPercentageLength::Vw(move _14);
-          StorageDead(_14);
-          StorageDead(_13);
-          StorageDead(_12);
+          _28 = (((*_40) as Vmax).0: f32);
+          StorageLive(_29);
+          StorageLive(_30);
+          _30 = _27;
+          StorageLive(_31);
+          _31 = _28;
+          _29 = Add(move _30, move _31);
+          StorageDead(_31);
+          StorageDead(_30);
+          _3 = ViewportPercentageLength::Vmax(move _29);
+          StorageDead(_29);
+          StorageDead(_28);
+          StorageDead(_27);
           goto -> bb10;
       }
   
       bb7: {
-          StorageLive(_17);
-          _41 = deref_copy (_4.0: &ViewportPercentageLength);
-          _17 = (((*_41) as Vh).0: f32);
-          StorageLive(_18);
-          _42 = deref_copy (_4.1: &ViewportPercentageLength);
-          _18 = (((*_42) as Vh).0: f32);
-          StorageLive(_19);
-          StorageLive(_20);
-          _20 = _17;
-          StorageLive(_21);
-          _21 = _18;
-          _19 = Add(move _20, move _21);
-          StorageDead(_21);
-          StorageDead(_20);
-          _3 = ViewportPercentageLength::Vh(move _19);
-          StorageDead(_19);
-          StorageDead(_18);
-          StorageDead(_17);
-          goto -> bb10;
-      }
-  
-      bb8: {
           StorageLive(_22);
-          _43 = deref_copy (_4.0: &ViewportPercentageLength);
-          _22 = (((*_43) as Vmin).0: f32);
+          _41 = deref_copy (_4.0: &ViewportPercentageLength);
+          _22 = (((*_41) as Vmin).0: f32);
           StorageLive(_23);
-          _44 = deref_copy (_4.1: &ViewportPercentageLength);
-          _23 = (((*_44) as Vmin).0: f32);
+          _42 = deref_copy (_4.1: &ViewportPercentageLength);
+          _23 = (((*_42) as Vmin).0: f32);
           StorageLive(_24);
           StorageLive(_25);
           _25 = _22;
@@ -181,25 +159,47 @@
           goto -> bb10;
       }
   
+      bb8: {
+          StorageLive(_17);
+          _43 = deref_copy (_4.0: &ViewportPercentageLength);
+          _17 = (((*_43) as Vh).0: f32);
+          StorageLive(_18);
+          _44 = deref_copy (_4.1: &ViewportPercentageLength);
+          _18 = (((*_44) as Vh).0: f32);
+          StorageLive(_19);
+          StorageLive(_20);
+          _20 = _17;
+          StorageLive(_21);
+          _21 = _18;
+          _19 = Add(move _20, move _21);
+          StorageDead(_21);
+          StorageDead(_20);
+          _3 = ViewportPercentageLength::Vh(move _19);
+          StorageDead(_19);
+          StorageDead(_18);
+          StorageDead(_17);
+          goto -> bb10;
+      }
+  
       bb9: {
-          StorageLive(_27);
+          StorageLive(_12);
           _45 = deref_copy (_4.0: &ViewportPercentageLength);
-          _27 = (((*_45) as Vmax).0: f32);
-          StorageLive(_28);
+          _12 = (((*_45) as Vw).0: f32);
+          StorageLive(_13);
           _46 = deref_copy (_4.1: &ViewportPercentageLength);
-          _28 = (((*_46) as Vmax).0: f32);
-          StorageLive(_29);
-          StorageLive(_30);
-          _30 = _27;
-          StorageLive(_31);
-          _31 = _28;
-          _29 = Add(move _30, move _31);
-          StorageDead(_31);
-          StorageDead(_30);
-          _3 = ViewportPercentageLength::Vmax(move _29);
-          StorageDead(_29);
-          StorageDead(_28);
-          StorageDead(_27);
+          _13 = (((*_46) as Vw).0: f32);
+          StorageLive(_14);
+          StorageLive(_15);
+          _15 = _12;
+          StorageLive(_16);
+          _16 = _13;
+          _14 = Add(move _15, move _16);
+          StorageDead(_16);
+          StorageDead(_15);
+          _3 = ViewportPercentageLength::Vw(move _14);
+          StorageDead(_14);
+          StorageDead(_13);
+          StorageDead(_12);
           goto -> bb10;
       }
   
diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
index 350e5fe6db579..651b1de4ddd37 100644
--- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
@@ -45,12 +45,12 @@
   
       bb2: {
           _6 = discriminant((_3.1: std::option::Option));
-          switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1];
+          switchInt(move _6) -> [0: bb6, 1: bb7, otherwise: bb1];
       }
   
       bb3: {
           _7 = discriminant((_3.1: std::option::Option));
-          switchInt(move _7) -> [0: bb4, 1: bb7, otherwise: bb1];
+          switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb1];
       }
   
       bb4: {
@@ -59,13 +59,10 @@
       }
   
       bb5: {
-          StorageLive(_9);
-          _9 = (((_3.0: std::option::Option) as Some).0: u32);
-          StorageLive(_10);
-          _10 = (((_3.1: std::option::Option) as Some).0: u32);
-          _0 = const 0_u32;
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_12);
+          _12 = (((_3.1: std::option::Option) as Some).0: u32);
+          _0 = const 2_u32;
+          StorageDead(_12);
           goto -> bb8;
       }
   
@@ -78,10 +75,13 @@
       }
   
       bb7: {
-          StorageLive(_12);
-          _12 = (((_3.1: std::option::Option) as Some).0: u32);
-          _0 = const 2_u32;
-          StorageDead(_12);
+          StorageLive(_9);
+          _9 = (((_3.0: std::option::Option) as Some).0: u32);
+          StorageLive(_10);
+          _10 = (((_3.1: std::option::Option) as Some).0: u32);
+          _0 = const 0_u32;
+          StorageDead(_10);
+          StorageDead(_9);
           goto -> bb8;
       }
   
diff --git a/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-abort.diff
index bbbfe90691f97..8009721fa5c58 100644
--- a/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-abort.diff
+++ b/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-abort.diff
@@ -24,7 +24,7 @@
   
       bb1: {
           _4 = discriminant(_1);
-          switchInt(move _4) -> [0: bb4, 1: bb5, 2: bb6, 3: bb3, otherwise: bb2];
+          switchInt(move _4) -> [0: bb6, 1: bb5, 2: bb4, 3: bb3, otherwise: bb2];
       }
   
       bb2: {
@@ -39,11 +39,11 @@
       }
   
       bb4: {
-          StorageLive(_5);
-          _5 = DFA::B;
-          _1 = move _5;
+          StorageLive(_7);
+          _7 = DFA::D;
+          _1 = move _7;
           _3 = const ();
-          StorageDead(_5);
+          StorageDead(_7);
           goto -> bb1;
       }
   
@@ -57,11 +57,11 @@
       }
   
       bb6: {
-          StorageLive(_7);
-          _7 = DFA::D;
-          _1 = move _7;
+          StorageLive(_5);
+          _5 = DFA::B;
+          _1 = move _5;
           _3 = const ();
-          StorageDead(_7);
+          StorageDead(_5);
           goto -> bb1;
       }
   }
diff --git a/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-unwind.diff
index bbbfe90691f97..8009721fa5c58 100644
--- a/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-unwind.diff
+++ b/tests/mir-opt/jump_threading.dfa.JumpThreading.panic-unwind.diff
@@ -24,7 +24,7 @@
   
       bb1: {
           _4 = discriminant(_1);
-          switchInt(move _4) -> [0: bb4, 1: bb5, 2: bb6, 3: bb3, otherwise: bb2];
+          switchInt(move _4) -> [0: bb6, 1: bb5, 2: bb4, 3: bb3, otherwise: bb2];
       }
   
       bb2: {
@@ -39,11 +39,11 @@
       }
   
       bb4: {
-          StorageLive(_5);
-          _5 = DFA::B;
-          _1 = move _5;
+          StorageLive(_7);
+          _7 = DFA::D;
+          _1 = move _7;
           _3 = const ();
-          StorageDead(_5);
+          StorageDead(_7);
           goto -> bb1;
       }
   
@@ -57,11 +57,11 @@
       }
   
       bb6: {
-          StorageLive(_7);
-          _7 = DFA::D;
-          _1 = move _7;
+          StorageLive(_5);
+          _5 = DFA::B;
+          _1 = move _5;
           _3 = const ();
-          StorageDead(_7);
+          StorageDead(_5);
           goto -> bb1;
       }
   }
diff --git a/tests/mir-opt/jump_threading.rs b/tests/mir-opt/jump_threading.rs
index e5d8525dcac13..6486a321e693e 100644
--- a/tests/mir-opt/jump_threading.rs
+++ b/tests/mir-opt/jump_threading.rs
@@ -93,19 +93,19 @@ fn dfa() {
     // CHECK:     {{_.*}} = DFA::A;
     // CHECK:     goto -> bb1;
     // CHECK: bb1: {
-    // CHECK:     switchInt({{.*}}) -> [0: bb4, 1: bb5, 2: bb6, 3: bb3, otherwise: bb2];
+    // CHECK:     switchInt({{.*}}) -> [0: bb6, 1: bb5, 2: bb4, 3: bb3, otherwise: bb2];
     // CHECK: bb2: {
     // CHECK:     unreachable;
     // CHECK: bb3: {
     // CHECK:     return;
     // CHECK: bb4: {
-    // CHECK:     {{_.*}} = DFA::B;
+    // CHECK:     {{_.*}} = DFA::D;
     // CHECK:     goto -> bb1;
     // CHECK: bb5: {
     // CHECK:     {{_.*}} = DFA::C;
     // CHECK:     goto -> bb1;
     // CHECK: bb6: {
-    // CHECK:     {{_.*}} = DFA::D;
+    // CHECK:     {{_.*}} = DFA::B;
     // CHECK:     goto -> bb1;
     let mut state = DFA::A;
     loop {
diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 4f29e5244d7c2..3c4a84bc24368 100644
--- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -33,17 +33,17 @@
       bb0: {
           PlaceMention(_2);
 -         switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1];
-+         switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1];
++         switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1];
       }
   
       bb1: {
 -         switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3];
-+         switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2];
++         switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2];
       }
   
       bb2: {
--         falseEdge -> [real: bb8, imaginary: bb1];
-+         switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17];
+-         falseEdge -> [real: bb9, imaginary: bb1];
++         switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4];
       }
   
       bb3: {
@@ -51,11 +51,11 @@
 -     }
 - 
 -     bb4: {
--         falseEdge -> [real: bb13, imaginary: bb3];
+-         falseEdge -> [real: bb8, imaginary: bb3];
 -     }
 - 
 -     bb5: {
--         falseEdge -> [real: bb20, imaginary: bb6];
+-         falseEdge -> [real: bb7, imaginary: bb6];
 -     }
 - 
 -     bb6: {
@@ -63,19 +63,37 @@
           _15 = (_2.1: bool);
           StorageLive(_16);
           _16 = move (_2.2: std::string::String);
--         goto -> bb19;
-+         goto -> bb16;
+-         goto -> bb20;
++         goto -> bb17;
       }
   
 -     bb7: {
 +     bb4: {
-          _0 = const 1_i32;
--         drop(_7) -> [return: bb18, unwind: bb25];
-+         drop(_7) -> [return: bb15, unwind: bb22];
+          StorageLive(_15);
+          _15 = (_2.1: bool);
+          StorageLive(_16);
+          _16 = move (_2.2: std::string::String);
+-         goto -> bb20;
++         goto -> bb17;
       }
   
 -     bb8: {
 +     bb5: {
+          StorageLive(_6);
+          _6 = &(_2.0: bool);
+          StorageLive(_8);
+          _8 = &(_2.2: std::string::String);
+-         _3 = &fake shallow (_2.0: bool);
+-         _4 = &fake shallow (_2.1: bool);
+          StorageLive(_12);
+          StorageLive(_13);
+          _13 = _1;
+-         switchInt(move _13) -> [0: bb16, otherwise: bb15];
++         switchInt(move _13) -> [0: bb13, otherwise: bb12];
+      }
+  
+-     bb9: {
++     bb6: {
           StorageLive(_6);
           _6 = &(_2.1: bool);
           StorageLive(_8);
@@ -85,12 +103,19 @@
           StorageLive(_9);
           StorageLive(_10);
           _10 = _1;
--         switchInt(move _10) -> [0: bb10, otherwise: bb9];
-+         switchInt(move _10) -> [0: bb7, otherwise: bb6];
+-         switchInt(move _10) -> [0: bb12, otherwise: bb11];
++         switchInt(move _10) -> [0: bb9, otherwise: bb8];
       }
   
--     bb9: {
-+     bb6: {
+-     bb10: {
++     bb7: {
+          _0 = const 1_i32;
+-         drop(_7) -> [return: bb19, unwind: bb25];
++         drop(_7) -> [return: bb16, unwind: bb22];
+      }
+  
+-     bb11: {
++     bb8: {
           _0 = const 3_i32;
           StorageDead(_10);
           StorageDead(_9);
@@ -98,15 +123,15 @@
 +         goto -> bb20;
       }
   
--     bb10: {
-+     bb7: {
+-     bb12: {
++     bb9: {
           _9 = (*_6);
--         switchInt(move _9) -> [0: bb12, otherwise: bb11];
-+         switchInt(move _9) -> [0: bb9, otherwise: bb8];
+-         switchInt(move _9) -> [0: bb14, otherwise: bb13];
++         switchInt(move _9) -> [0: bb11, otherwise: bb10];
       }
   
--     bb11: {
-+     bb8: {
+-     bb13: {
++     bb10: {
           StorageDead(_10);
           StorageDead(_9);
 -         FakeRead(ForMatchGuard, _3);
@@ -117,12 +142,12 @@
           _5 = (_2.1: bool);
           StorageLive(_7);
           _7 = move (_2.2: std::string::String);
--         goto -> bb7;
-+         goto -> bb4;
+-         goto -> bb10;
++         goto -> bb7;
       }
   
--     bb12: {
-+     bb9: {
+-     bb14: {
++     bb11: {
           StorageDead(_10);
           StorageDead(_9);
           StorageDead(_8);
@@ -131,23 +156,8 @@
 +         goto -> bb1;
       }
   
--     bb13: {
-+     bb10: {
-          StorageLive(_6);
-          _6 = &(_2.0: bool);
-          StorageLive(_8);
-          _8 = &(_2.2: std::string::String);
--         _3 = &fake shallow (_2.0: bool);
--         _4 = &fake shallow (_2.1: bool);
-          StorageLive(_12);
-          StorageLive(_13);
-          _13 = _1;
--         switchInt(move _13) -> [0: bb15, otherwise: bb14];
-+         switchInt(move _13) -> [0: bb12, otherwise: bb11];
-      }
-  
--     bb14: {
-+     bb11: {
+-     bb15: {
++     bb12: {
           _0 = const 3_i32;
           StorageDead(_13);
           StorageDead(_12);
@@ -155,15 +165,15 @@
 +         goto -> bb20;
       }
   
--     bb15: {
-+     bb12: {
+-     bb16: {
++     bb13: {
           _12 = (*_6);
--         switchInt(move _12) -> [0: bb17, otherwise: bb16];
-+         switchInt(move _12) -> [0: bb14, otherwise: bb13];
+-         switchInt(move _12) -> [0: bb18, otherwise: bb17];
++         switchInt(move _12) -> [0: bb15, otherwise: bb14];
       }
   
--     bb16: {
-+     bb13: {
+-     bb17: {
++     bb14: {
           StorageDead(_13);
           StorageDead(_12);
 -         FakeRead(ForMatchGuard, _3);
@@ -174,12 +184,12 @@
           _5 = (_2.0: bool);
           StorageLive(_7);
           _7 = move (_2.2: std::string::String);
--         goto -> bb7;
-+         goto -> bb4;
+-         goto -> bb10;
++         goto -> bb7;
       }
   
--     bb17: {
-+     bb14: {
+-     bb18: {
++     bb15: {
           StorageDead(_13);
           StorageDead(_12);
           StorageDead(_8);
@@ -188,8 +198,8 @@
 +         goto -> bb2;
       }
   
--     bb18: {
-+     bb15: {
+-     bb19: {
++     bb16: {
           StorageDead(_7);
           StorageDead(_5);
           StorageDead(_8);
@@ -198,23 +208,13 @@
 +         goto -> bb19;
       }
   
--     bb19: {
-+     bb16: {
+-     bb20: {
++     bb17: {
           _0 = const 2_i32;
 -         drop(_16) -> [return: bb21, unwind: bb25];
 +         drop(_16) -> [return: bb18, unwind: bb22];
       }
   
--     bb20: {
-+     bb17: {
-          StorageLive(_15);
-          _15 = (_2.1: bool);
-          StorageLive(_16);
-          _16 = move (_2.2: std::string::String);
--         goto -> bb19;
-+         goto -> bb16;
-      }
-  
 -     bb21: {
 +     bb18: {
           StorageDead(_16);
diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 4f29e5244d7c2..3c4a84bc24368 100644
--- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -33,17 +33,17 @@
       bb0: {
           PlaceMention(_2);
 -         switchInt((_2.0: bool)) -> [0: bb2, otherwise: bb1];
-+         switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1];
++         switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb1];
       }
   
       bb1: {
 -         switchInt((_2.1: bool)) -> [0: bb4, otherwise: bb3];
-+         switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2];
++         switchInt((_2.1: bool)) -> [0: bb5, otherwise: bb2];
       }
   
       bb2: {
--         falseEdge -> [real: bb8, imaginary: bb1];
-+         switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17];
+-         falseEdge -> [real: bb9, imaginary: bb1];
++         switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4];
       }
   
       bb3: {
@@ -51,11 +51,11 @@
 -     }
 - 
 -     bb4: {
--         falseEdge -> [real: bb13, imaginary: bb3];
+-         falseEdge -> [real: bb8, imaginary: bb3];
 -     }
 - 
 -     bb5: {
--         falseEdge -> [real: bb20, imaginary: bb6];
+-         falseEdge -> [real: bb7, imaginary: bb6];
 -     }
 - 
 -     bb6: {
@@ -63,19 +63,37 @@
           _15 = (_2.1: bool);
           StorageLive(_16);
           _16 = move (_2.2: std::string::String);
--         goto -> bb19;
-+         goto -> bb16;
+-         goto -> bb20;
++         goto -> bb17;
       }
   
 -     bb7: {
 +     bb4: {
-          _0 = const 1_i32;
--         drop(_7) -> [return: bb18, unwind: bb25];
-+         drop(_7) -> [return: bb15, unwind: bb22];
+          StorageLive(_15);
+          _15 = (_2.1: bool);
+          StorageLive(_16);
+          _16 = move (_2.2: std::string::String);
+-         goto -> bb20;
++         goto -> bb17;
       }
   
 -     bb8: {
 +     bb5: {
+          StorageLive(_6);
+          _6 = &(_2.0: bool);
+          StorageLive(_8);
+          _8 = &(_2.2: std::string::String);
+-         _3 = &fake shallow (_2.0: bool);
+-         _4 = &fake shallow (_2.1: bool);
+          StorageLive(_12);
+          StorageLive(_13);
+          _13 = _1;
+-         switchInt(move _13) -> [0: bb16, otherwise: bb15];
++         switchInt(move _13) -> [0: bb13, otherwise: bb12];
+      }
+  
+-     bb9: {
++     bb6: {
           StorageLive(_6);
           _6 = &(_2.1: bool);
           StorageLive(_8);
@@ -85,12 +103,19 @@
           StorageLive(_9);
           StorageLive(_10);
           _10 = _1;
--         switchInt(move _10) -> [0: bb10, otherwise: bb9];
-+         switchInt(move _10) -> [0: bb7, otherwise: bb6];
+-         switchInt(move _10) -> [0: bb12, otherwise: bb11];
++         switchInt(move _10) -> [0: bb9, otherwise: bb8];
       }
   
--     bb9: {
-+     bb6: {
+-     bb10: {
++     bb7: {
+          _0 = const 1_i32;
+-         drop(_7) -> [return: bb19, unwind: bb25];
++         drop(_7) -> [return: bb16, unwind: bb22];
+      }
+  
+-     bb11: {
++     bb8: {
           _0 = const 3_i32;
           StorageDead(_10);
           StorageDead(_9);
@@ -98,15 +123,15 @@
 +         goto -> bb20;
       }
   
--     bb10: {
-+     bb7: {
+-     bb12: {
++     bb9: {
           _9 = (*_6);
--         switchInt(move _9) -> [0: bb12, otherwise: bb11];
-+         switchInt(move _9) -> [0: bb9, otherwise: bb8];
+-         switchInt(move _9) -> [0: bb14, otherwise: bb13];
++         switchInt(move _9) -> [0: bb11, otherwise: bb10];
       }
   
--     bb11: {
-+     bb8: {
+-     bb13: {
++     bb10: {
           StorageDead(_10);
           StorageDead(_9);
 -         FakeRead(ForMatchGuard, _3);
@@ -117,12 +142,12 @@
           _5 = (_2.1: bool);
           StorageLive(_7);
           _7 = move (_2.2: std::string::String);
--         goto -> bb7;
-+         goto -> bb4;
+-         goto -> bb10;
++         goto -> bb7;
       }
   
--     bb12: {
-+     bb9: {
+-     bb14: {
++     bb11: {
           StorageDead(_10);
           StorageDead(_9);
           StorageDead(_8);
@@ -131,23 +156,8 @@
 +         goto -> bb1;
       }
   
--     bb13: {
-+     bb10: {
-          StorageLive(_6);
-          _6 = &(_2.0: bool);
-          StorageLive(_8);
-          _8 = &(_2.2: std::string::String);
--         _3 = &fake shallow (_2.0: bool);
--         _4 = &fake shallow (_2.1: bool);
-          StorageLive(_12);
-          StorageLive(_13);
-          _13 = _1;
--         switchInt(move _13) -> [0: bb15, otherwise: bb14];
-+         switchInt(move _13) -> [0: bb12, otherwise: bb11];
-      }
-  
--     bb14: {
-+     bb11: {
+-     bb15: {
++     bb12: {
           _0 = const 3_i32;
           StorageDead(_13);
           StorageDead(_12);
@@ -155,15 +165,15 @@
 +         goto -> bb20;
       }
   
--     bb15: {
-+     bb12: {
+-     bb16: {
++     bb13: {
           _12 = (*_6);
--         switchInt(move _12) -> [0: bb17, otherwise: bb16];
-+         switchInt(move _12) -> [0: bb14, otherwise: bb13];
+-         switchInt(move _12) -> [0: bb18, otherwise: bb17];
++         switchInt(move _12) -> [0: bb15, otherwise: bb14];
       }
   
--     bb16: {
-+     bb13: {
+-     bb17: {
++     bb14: {
           StorageDead(_13);
           StorageDead(_12);
 -         FakeRead(ForMatchGuard, _3);
@@ -174,12 +184,12 @@
           _5 = (_2.0: bool);
           StorageLive(_7);
           _7 = move (_2.2: std::string::String);
--         goto -> bb7;
-+         goto -> bb4;
+-         goto -> bb10;
++         goto -> bb7;
       }
   
--     bb17: {
-+     bb14: {
+-     bb18: {
++     bb15: {
           StorageDead(_13);
           StorageDead(_12);
           StorageDead(_8);
@@ -188,8 +198,8 @@
 +         goto -> bb2;
       }
   
--     bb18: {
-+     bb15: {
+-     bb19: {
++     bb16: {
           StorageDead(_7);
           StorageDead(_5);
           StorageDead(_8);
@@ -198,23 +208,13 @@
 +         goto -> bb19;
       }
   
--     bb19: {
-+     bb16: {
+-     bb20: {
++     bb17: {
           _0 = const 2_i32;
 -         drop(_16) -> [return: bb21, unwind: bb25];
 +         drop(_16) -> [return: bb18, unwind: bb22];
       }
   
--     bb20: {
-+     bb17: {
-          StorageLive(_15);
-          _15 = (_2.1: bool);
-          StorageLive(_16);
-          _16 = move (_2.2: std::string::String);
--         goto -> bb19;
-+         goto -> bb16;
-      }
-  
 -     bb21: {
 +     bb18: {
           StorageDead(_16);
diff --git a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff
index 1f20349fdece4..dc50ae9547255 100644
--- a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);
-          switchInt(move _2) -> [1: bb3, 2: bb4, 3: bb5, 340282366920938463463374607431768211455: bb2, otherwise: bb1];
+          switchInt(move _2) -> [1: bb5, 2: bb4, 3: bb3, 340282366920938463463374607431768211455: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -21,7 +21,7 @@
       }
   
       bb3: {
-          _0 = const 1_u128;
+          _0 = const 3_u128;
           goto -> bb6;
       }
   
@@ -31,7 +31,7 @@
       }
   
       bb5: {
-          _0 = const 3_u128;
+          _0 = const 1_u128;
           goto -> bb6;
       }
   
diff --git a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff
index 4b435310916a7..3514914b8ecb0 100644
--- a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);
-          switchInt(move _2) -> [65535: bb3, 2: bb4, 65533: bb2, otherwise: bb1];
+          switchInt(move _2) -> [65535: bb4, 2: bb3, 65533: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -21,12 +21,12 @@
       }
   
       bb3: {
-          _0 = const -1_i8;
+          _0 = const 2_i8;
           goto -> bb5;
       }
   
       bb4: {
-          _0 = const 2_i8;
+          _0 = const -1_i8;
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff
index 8a390736add15..ff4255ec8cc97 100644
--- a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);
-          switchInt(move _2) -> [255: bb3, 2: bb4, 253: bb2, otherwise: bb1];
+          switchInt(move _2) -> [255: bb4, 2: bb3, 253: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -21,12 +21,12 @@
       }
   
       bb3: {
-          _0 = const -1_i16;
+          _0 = const 2_i16;
           goto -> bb5;
       }
   
       bb4: {
-          _0 = const 2_i16;
+          _0 = const -1_i16;
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff
index b021779229454..022039ecee629 100644
--- a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);
-          switchInt(move _2) -> [255: bb3, 2: bb4, 253: bb2, otherwise: bb1];
+          switchInt(move _2) -> [255: bb4, 2: bb3, 253: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -21,12 +21,12 @@
       }
   
       bb3: {
-          _0 = const -1_i16;
+          _0 = const 2_i16;
           goto -> bb5;
       }
   
       bb4: {
-          _0 = const 2_i16;
+          _0 = const -1_i16;
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff
index 8fa497fe89002..5690f17f24f65 100644
--- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff
@@ -6,7 +6,7 @@
       let mut _0: i16;
   
       bb0: {
-          switchInt(_1) -> [1: bb2, 2: bb3, otherwise: bb1];
+          switchInt(_1) -> [1: bb3, 2: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -15,12 +15,12 @@
       }
   
       bb2: {
-          _0 = const 1_i16;
+          _0 = const 2_i16;
           goto -> bb4;
       }
   
       bb3: {
-          _0 = const 2_i16;
+          _0 = const 1_i16;
           goto -> bb4;
       }
   
diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff
index 043fdb197a3ac..dc9c1c2b97f1f 100644
--- a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff
+++ b/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);
-          switchInt(move _2) -> [1: bb3, 2: bb4, 5: bb2, otherwise: bb1];
+          switchInt(move _2) -> [1: bb4, 2: bb3, 5: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -21,12 +21,12 @@
       }
   
       bb3: {
-          _0 = const 1_u16;
+          _0 = const 2_u16;
           goto -> bb5;
       }
   
       bb4: {
-          _0 = const 2_u16;
+          _0 = const 1_u16;
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir
index e357e785e33ee..6c76a72b77577 100644
--- a/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/or_pattern.shortcut_second_or.SimplifyCfg-initial.after.mir
@@ -39,7 +39,7 @@ fn shortcut_second_or() -> () {
     }
 
     bb5: {
-        falseEdge -> [real: bb10, imaginary: bb6];
+        falseEdge -> [real: bb12, imaginary: bb6];
     }
 
     bb6: {
@@ -47,18 +47,19 @@ fn shortcut_second_or() -> () {
     }
 
     bb7: {
-        falseEdge -> [real: bb12, imaginary: bb8];
+        falseEdge -> [real: bb10, imaginary: bb8];
     }
 
     bb8: {
-        falseEdge -> [real: bb13, imaginary: bb3];
+        falseEdge -> [real: bb9, imaginary: bb3];
     }
 
     bb9: {
-        _0 = const ();
-        StorageDead(_4);
-        StorageDead(_3);
-        goto -> bb14;
+        StorageLive(_3);
+        _3 = (_1.0: (i32, i32));
+        StorageLive(_4);
+        _4 = (_1.1: i32);
+        goto -> bb13;
     }
 
     bb10: {
@@ -66,7 +67,7 @@ fn shortcut_second_or() -> () {
         _3 = (_1.0: (i32, i32));
         StorageLive(_4);
         _4 = (_1.1: i32);
-        goto -> bb9;
+        goto -> bb13;
     }
 
     bb11: {
@@ -74,7 +75,7 @@ fn shortcut_second_or() -> () {
         _3 = (_1.0: (i32, i32));
         StorageLive(_4);
         _4 = (_1.1: i32);
-        goto -> bb9;
+        goto -> bb13;
     }
 
     bb12: {
@@ -82,15 +83,14 @@ fn shortcut_second_or() -> () {
         _3 = (_1.0: (i32, i32));
         StorageLive(_4);
         _4 = (_1.1: i32);
-        goto -> bb9;
+        goto -> bb13;
     }
 
     bb13: {
-        StorageLive(_3);
-        _3 = (_1.0: (i32, i32));
-        StorageLive(_4);
-        _4 = (_1.1: i32);
-        goto -> bb9;
+        _0 = const ();
+        StorageDead(_4);
+        StorageDead(_3);
+        goto -> bb14;
     }
 
     bb14: {
diff --git a/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir b/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir
index eafe95b4a11ea..8b0ef7b29d7be 100644
--- a/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/or_pattern.single_switchint.SimplifyCfg-initial.after.mir
@@ -22,7 +22,7 @@ fn single_switchint() -> () {
     }
 
     bb3: {
-        falseEdge -> [real: bb9, imaginary: bb4];
+        falseEdge -> [real: bb12, imaginary: bb4];
     }
 
     bb4: {
@@ -30,11 +30,11 @@ fn single_switchint() -> () {
     }
 
     bb5: {
-        falseEdge -> [real: bb10, imaginary: bb6];
+        falseEdge -> [real: bb11, imaginary: bb6];
     }
 
     bb6: {
-        falseEdge -> [real: bb11, imaginary: bb1];
+        falseEdge -> [real: bb10, imaginary: bb1];
     }
 
     bb7: {
@@ -43,26 +43,26 @@ fn single_switchint() -> () {
     }
 
     bb8: {
-        falseEdge -> [real: bb12, imaginary: bb7];
+        falseEdge -> [real: bb9, imaginary: bb7];
     }
 
     bb9: {
-        _1 = const 1_i32;
+        _1 = const 4_i32;
         goto -> bb13;
     }
 
     bb10: {
-        _1 = const 2_i32;
+        _1 = const 3_i32;
         goto -> bb13;
     }
 
     bb11: {
-        _1 = const 3_i32;
+        _1 = const 2_i32;
         goto -> bb13;
     }
 
     bb12: {
-        _1 = const 4_i32;
+        _1 = const 1_i32;
         goto -> bb13;
     }
 
diff --git a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff
index 8d87438a47aec..998b89919d1bd 100644
--- a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff
+++ b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-abort.diff
@@ -8,9 +8,9 @@
       bb0: {
           StorageLive(_1);
 -         _1 = const ::ASSOC_INT;
--         switchInt(_1) -> [7: bb2, 42: bb3, otherwise: bb1];
+-         switchInt(_1) -> [7: bb3, 42: bb2, otherwise: bb1];
 +         nop;
-+         switchInt(const ::ASSOC_INT) -> [7: bb2, 42: bb3, otherwise: bb1];
++         switchInt(const ::ASSOC_INT) -> [7: bb3, 42: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -19,12 +19,12 @@
       }
   
       bb2: {
-          _0 = const "hello";
+          _0 = const "towel";
           goto -> bb4;
       }
   
       bb3: {
-          _0 = const "towel";
+          _0 = const "hello";
           goto -> bb4;
       }
   
diff --git a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff
index 8d87438a47aec..998b89919d1bd 100644
--- a/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff
+++ b/tests/mir-opt/single_use_consts.match_const.SingleUseConsts.panic-unwind.diff
@@ -8,9 +8,9 @@
       bb0: {
           StorageLive(_1);
 -         _1 = const ::ASSOC_INT;
--         switchInt(_1) -> [7: bb2, 42: bb3, otherwise: bb1];
+-         switchInt(_1) -> [7: bb3, 42: bb2, otherwise: bb1];
 +         nop;
-+         switchInt(const ::ASSOC_INT) -> [7: bb2, 42: bb3, otherwise: bb1];
++         switchInt(const ::ASSOC_INT) -> [7: bb3, 42: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -19,12 +19,12 @@
       }
   
       bb2: {
-          _0 = const "hello";
+          _0 = const "towel";
           goto -> bb4;
       }
   
       bb3: {
-          _0 = const "towel";
+          _0 = const "hello";
           goto -> bb4;
       }
   
diff --git a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff
index f192f3feb96e5..30f66ef6b8237 100644
--- a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff
+++ b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-abort.diff
@@ -20,8 +20,8 @@
   
       bb1: {
           StorageDead(_2);
--         switchInt(_1) -> [7: bb3, 42: bb4, otherwise: bb2];
-+         switchInt(const ::ASSOC_INT) -> [7: bb3, 42: bb4, otherwise: bb2];
+-         switchInt(_1) -> [7: bb4, 42: bb3, otherwise: bb2];
++         switchInt(const ::ASSOC_INT) -> [7: bb4, 42: bb3, otherwise: bb2];
       }
   
       bb2: {
@@ -30,12 +30,12 @@
       }
   
       bb3: {
-          _0 = const "hello";
+          _0 = const "towel";
           goto -> bb5;
       }
   
       bb4: {
-          _0 = const "towel";
+          _0 = const "hello";
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff
index 261faf415f3bc..ed12ad4b93e89 100644
--- a/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff
+++ b/tests/mir-opt/single_use_consts.match_const_debug.SingleUseConsts.panic-unwind.diff
@@ -20,8 +20,8 @@
   
       bb1: {
           StorageDead(_2);
--         switchInt(_1) -> [7: bb3, 42: bb4, otherwise: bb2];
-+         switchInt(const ::ASSOC_INT) -> [7: bb3, 42: bb4, otherwise: bb2];
+-         switchInt(_1) -> [7: bb4, 42: bb3, otherwise: bb2];
++         switchInt(const ::ASSOC_INT) -> [7: bb4, 42: bb3, otherwise: bb2];
       }
   
       bb2: {
@@ -30,12 +30,12 @@
       }
   
       bb3: {
-          _0 = const "hello";
+          _0 = const "towel";
           goto -> bb5;
       }
   
       bb4: {
-          _0 = const "towel";
+          _0 = const "hello";
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff
index 098b620dfaab7..c0ea9fae7df5b 100644
--- a/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UnreachableEnumBranching.diff
@@ -8,8 +8,8 @@
   
       bb0: {
           _2 = discriminant(_1);
--         switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1];
-+         switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb5];
+-         switchInt(move _2) -> [1: bb2, 2: bb3, otherwise: bb1];
++         switchInt(move _2) -> [1: bb2, 2: bb3, otherwise: bb5];
       }
   
       bb1: {
@@ -18,12 +18,12 @@
       }
   
       bb2: {
-          _0 = const 1_u32;
+          _0 = const 2_u32;
           goto -> bb4;
       }
   
       bb3: {
-          _0 = const 2_u32;
+          _0 = const 1_u32;
           goto -> bb4;
       }
   
diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff
index 995e32b033f24..2082e8046ad0b 100644
--- a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff
+++ b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UnreachableEnumBranching.diff
@@ -8,8 +8,8 @@
   
       bb0: {
           _2 = discriminant(_1);
--         switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
-+         switchInt(move _2) -> [0: bb5, 1: bb3, 2: bb1, otherwise: bb5];
+-         switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1];
++         switchInt(move _2) -> [0: bb5, 1: bb2, 2: bb1, otherwise: bb5];
       }
   
       bb1: {
@@ -18,12 +18,12 @@
       }
   
       bb2: {
-          _0 = const 1_u32;
+          _0 = const 2_u32;
           goto -> bb4;
       }
   
       bb3: {
-          _0 = const 2_u32;
+          _0 = const 1_u32;
           goto -> bb4;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff
index e5dab5d52a6b7..ed54a38f70bdb 100644
--- a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-abort.diff
@@ -30,8 +30,8 @@
           StorageLive(_4);
           _4 = &(_1.1: Test3);
           _5 = discriminant((*_4));
--         switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1];
-+         switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1];
+-         switchInt(move _5) -> [0: bb5, 1: bb4, 2: bb3, 3: bb2, otherwise: bb1];
++         switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb3, 3: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -47,7 +47,10 @@
       }
   
       bb3: {
-          _3 = const "A(Empty)";
+          StorageLive(_7);
+          _7 = const "C";
+          _3 = &(*_7);
+          StorageDead(_7);
           goto -> bb6;
       }
   
@@ -60,10 +63,7 @@
       }
   
       bb5: {
-          StorageLive(_7);
-          _7 = const "C";
-          _3 = &(*_7);
-          StorageDead(_7);
+          _3 = const "A(Empty)";
           goto -> bb6;
       }
   
@@ -72,8 +72,8 @@
           StorageDead(_3);
           StorageLive(_9);
           _10 = discriminant((_1.1: Test3));
--         switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1];
-+         switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1];
+-         switchInt(move _10) -> [0: bb10, 1: bb9, 2: bb8, 3: bb7, otherwise: bb1];
++         switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb8, 3: bb7, otherwise: bb1];
       }
   
       bb7: {
@@ -85,7 +85,10 @@
       }
   
       bb8: {
-          _9 = const "A(Empty)";
+          StorageLive(_12);
+          _12 = const "C";
+          _9 = &(*_12);
+          StorageDead(_12);
           goto -> bb11;
       }
   
@@ -98,10 +101,7 @@
       }
   
       bb10: {
-          StorageLive(_12);
-          _12 = const "C";
-          _9 = &(*_12);
-          StorageDead(_12);
+          _9 = const "A(Empty)";
           goto -> bb11;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff
index e5dab5d52a6b7..ed54a38f70bdb 100644
--- a/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.byref.UnreachableEnumBranching.panic-unwind.diff
@@ -30,8 +30,8 @@
           StorageLive(_4);
           _4 = &(_1.1: Test3);
           _5 = discriminant((*_4));
--         switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb2, otherwise: bb1];
-+         switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb5, 3: bb2, otherwise: bb1];
+-         switchInt(move _5) -> [0: bb5, 1: bb4, 2: bb3, 3: bb2, otherwise: bb1];
++         switchInt(move _5) -> [0: bb1, 1: bb1, 2: bb3, 3: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -47,7 +47,10 @@
       }
   
       bb3: {
-          _3 = const "A(Empty)";
+          StorageLive(_7);
+          _7 = const "C";
+          _3 = &(*_7);
+          StorageDead(_7);
           goto -> bb6;
       }
   
@@ -60,10 +63,7 @@
       }
   
       bb5: {
-          StorageLive(_7);
-          _7 = const "C";
-          _3 = &(*_7);
-          StorageDead(_7);
+          _3 = const "A(Empty)";
           goto -> bb6;
       }
   
@@ -72,8 +72,8 @@
           StorageDead(_3);
           StorageLive(_9);
           _10 = discriminant((_1.1: Test3));
--         switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb1];
-+         switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb10, 3: bb7, otherwise: bb1];
+-         switchInt(move _10) -> [0: bb10, 1: bb9, 2: bb8, 3: bb7, otherwise: bb1];
++         switchInt(move _10) -> [0: bb1, 1: bb1, 2: bb8, 3: bb7, otherwise: bb1];
       }
   
       bb7: {
@@ -85,7 +85,10 @@
       }
   
       bb8: {
-          _9 = const "A(Empty)";
+          StorageLive(_12);
+          _12 = const "C";
+          _9 = &(*_12);
+          StorageDead(_12);
           goto -> bb11;
       }
   
@@ -98,10 +101,7 @@
       }
   
       bb10: {
-          StorageLive(_12);
-          _12 = const "C";
-          _9 = &(*_12);
-          StorageDead(_12);
+          _9 = const "A(Empty)";
           goto -> bb11;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff
index 02b9f02f4c0ec..be934ac688bb5 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-abort.diff
@@ -14,7 +14,7 @@
           StorageLive(_2);
           _2 = Test1::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+-         switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
 +         switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
       }
   
@@ -27,11 +27,6 @@
       }
   
       bb2: {
-          _1 = const "A(Empty)";
-          goto -> bb4;
-      }
-  
-      bb3: {
           StorageLive(_4);
           _4 = const "B(Empty)";
           _1 = &(*_4);
@@ -39,6 +34,11 @@
           goto -> bb4;
       }
   
+      bb3: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
       bb4: {
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff
index 02b9f02f4c0ec..be934ac688bb5 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t1.UnreachableEnumBranching.panic-unwind.diff
@@ -14,7 +14,7 @@
           StorageLive(_2);
           _2 = Test1::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+-         switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
 +         switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
       }
   
@@ -27,11 +27,6 @@
       }
   
       bb2: {
-          _1 = const "A(Empty)";
-          goto -> bb4;
-      }
-  
-      bb3: {
           StorageLive(_4);
           _4 = const "B(Empty)";
           _1 = &(*_4);
@@ -39,6 +34,11 @@
           goto -> bb4;
       }
   
+      bb3: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
       bb4: {
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff
index d3376442376d3..120061841a02f 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-abort.diff
@@ -14,7 +14,7 @@
           StorageLive(_2);
           _2 = Test3::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+-         switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
 +         switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
       }
   
@@ -27,11 +27,6 @@
       }
   
       bb2: {
-          _1 = const "A(Empty)";
-          goto -> bb4;
-      }
-  
-      bb3: {
           StorageLive(_4);
           _4 = const "B(Empty)";
           _1 = &(*_4);
@@ -39,6 +34,11 @@
           goto -> bb4;
       }
   
+      bb3: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
       bb4: {
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff
index d3376442376d3..120061841a02f 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t3.UnreachableEnumBranching.panic-unwind.diff
@@ -14,7 +14,7 @@
           StorageLive(_2);
           _2 = Test3::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+-         switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
 +         switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
       }
   
@@ -27,11 +27,6 @@
       }
   
       bb2: {
-          _1 = const "A(Empty)";
-          goto -> bb4;
-      }
-  
-      bb3: {
           StorageLive(_4);
           _4 = const "B(Empty)";
           _1 = &(*_4);
@@ -39,6 +34,11 @@
           goto -> bb4;
       }
   
+      bb3: {
+          _1 = const "A(Empty)";
+          goto -> bb4;
+      }
+  
       bb4: {
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff
index 8f0d5b7cd99c4..b86814d611938 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-abort.diff
@@ -14,7 +14,7 @@
           StorageLive(_2);
           _2 = Test4::C;
           _3 = discriminant(_2);
-          switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+          switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -26,11 +26,6 @@
       }
   
       bb2: {
-          _1 = const "A(i32)";
-          goto -> bb4;
-      }
-  
-      bb3: {
           StorageLive(_4);
           _4 = const "B(i32)";
           _1 = &(*_4);
@@ -38,6 +33,11 @@
           goto -> bb4;
       }
   
+      bb3: {
+          _1 = const "A(i32)";
+          goto -> bb4;
+      }
+  
       bb4: {
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff
index 8f0d5b7cd99c4..b86814d611938 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4.UnreachableEnumBranching.panic-unwind.diff
@@ -14,7 +14,7 @@
           StorageLive(_2);
           _2 = Test4::C;
           _3 = discriminant(_2);
-          switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
+          switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -26,11 +26,6 @@
       }
   
       bb2: {
-          _1 = const "A(i32)";
-          goto -> bb4;
-      }
-  
-      bb3: {
           StorageLive(_4);
           _4 = const "B(i32)";
           _1 = &(*_4);
@@ -38,6 +33,11 @@
           goto -> bb4;
       }
   
+      bb3: {
+          _1 = const "A(i32)";
+          goto -> bb4;
+      }
+  
       bb4: {
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff
index b1ecd00858290..424ac6ba651c3 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-abort.diff
@@ -15,8 +15,8 @@
           StorageLive(_2);
           _2 = Test4::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
-+         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
+-         switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1];
++         switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, 3: bb1, otherwise: bb6];
       }
   
       bb1: {
@@ -28,7 +28,10 @@
       }
   
       bb2: {
-          _1 = const "A(i32)";
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
           goto -> bb5;
       }
   
@@ -41,10 +44,7 @@
       }
   
       bb4: {
-          StorageLive(_5);
-          _5 = const "C";
-          _1 = &(*_5);
-          StorageDead(_5);
+          _1 = const "A(i32)";
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
index b1ecd00858290..424ac6ba651c3 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
@@ -15,8 +15,8 @@
           StorageLive(_2);
           _2 = Test4::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
-+         switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
+-         switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1];
++         switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, 3: bb1, otherwise: bb6];
       }
   
       bb1: {
@@ -28,7 +28,10 @@
       }
   
       bb2: {
-          _1 = const "A(i32)";
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
           goto -> bb5;
       }
   
@@ -41,10 +44,7 @@
       }
   
       bb4: {
-          StorageLive(_5);
-          _5 = const "C";
-          _1 = &(*_5);
-          StorageDead(_5);
+          _1 = const "A(i32)";
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff
index 28c6d4fb67599..4cd6d3f56833e 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-abort.diff
@@ -16,8 +16,8 @@
           StorageLive(_2);
           _2 = Test4::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
-+         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
+-         switchInt(move _3) -> [0: bb2, 1: bb4, 2: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb4, 2: bb3, 3: bb1, otherwise: bb8];
       }
   
       bb1: {
@@ -29,23 +29,18 @@
       }
   
       bb2: {
-          switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
+          switchInt(((_2 as A).0: i32)) -> [1: bb6, 2: bb5, otherwise: bb1];
       }
   
       bb3: {
-          _1 = const "A(1)";
+          StorageLive(_6);
+          _6 = const "C";
+          _1 = &(*_6);
+          StorageDead(_6);
           goto -> bb7;
       }
   
       bb4: {
-          StorageLive(_4);
-          _4 = const "A(2)";
-          _1 = &(*_4);
-          StorageDead(_4);
-          goto -> bb7;
-      }
-  
-      bb5: {
           StorageLive(_5);
           _5 = const "B(i32)";
           _1 = &(*_5);
@@ -53,11 +48,16 @@
           goto -> bb7;
       }
   
+      bb5: {
+          StorageLive(_4);
+          _4 = const "A(2)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb7;
+      }
+  
       bb6: {
-          StorageLive(_6);
-          _6 = const "C";
-          _1 = &(*_6);
-          StorageDead(_6);
+          _1 = const "A(1)";
           goto -> bb7;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff
index 28c6d4fb67599..4cd6d3f56833e 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t4_unreachable_default_2.UnreachableEnumBranching.panic-unwind.diff
@@ -16,8 +16,8 @@
           StorageLive(_2);
           _2 = Test4::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
-+         switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
+-         switchInt(move _3) -> [0: bb2, 1: bb4, 2: bb3, otherwise: bb1];
++         switchInt(move _3) -> [0: bb2, 1: bb4, 2: bb3, 3: bb1, otherwise: bb8];
       }
   
       bb1: {
@@ -29,23 +29,18 @@
       }
   
       bb2: {
-          switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
+          switchInt(((_2 as A).0: i32)) -> [1: bb6, 2: bb5, otherwise: bb1];
       }
   
       bb3: {
-          _1 = const "A(1)";
+          StorageLive(_6);
+          _6 = const "C";
+          _1 = &(*_6);
+          StorageDead(_6);
           goto -> bb7;
       }
   
       bb4: {
-          StorageLive(_4);
-          _4 = const "A(2)";
-          _1 = &(*_4);
-          StorageDead(_4);
-          goto -> bb7;
-      }
-  
-      bb5: {
           StorageLive(_5);
           _5 = const "B(i32)";
           _1 = &(*_5);
@@ -53,11 +48,16 @@
           goto -> bb7;
       }
   
+      bb5: {
+          StorageLive(_4);
+          _4 = const "A(2)";
+          _1 = &(*_4);
+          StorageDead(_4);
+          goto -> bb7;
+      }
+  
       bb6: {
-          StorageLive(_6);
-          _6 = const "C";
-          _1 = &(*_6);
-          StorageDead(_6);
+          _1 = const "A(1)";
           goto -> bb7;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff
index f36a7efd80d45..2de1f77eeec9e 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-abort.diff
@@ -15,8 +15,8 @@
           StorageLive(_2);
           _2 = Test5::::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1];
-+         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb7];
+-         switchInt(move _3) -> [255: bb4, 0: bb3, 5: bb2, otherwise: bb1];
++         switchInt(move _3) -> [255: bb4, 0: bb3, 5: bb2, 3: bb1, otherwise: bb7];
       }
   
       bb1: {
@@ -28,7 +28,10 @@
       }
   
       bb2: {
-          _1 = const "A(T)";
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
           goto -> bb5;
       }
   
@@ -41,10 +44,7 @@
       }
   
       bb4: {
-          StorageLive(_5);
-          _5 = const "C";
-          _1 = &(*_5);
-          StorageDead(_5);
+          _1 = const "A(T)";
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
index 20e31c24c84b5..5afb78c58a3c1 100644
--- a/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.otherwise_t5_unreachable_default.UnreachableEnumBranching.panic-unwind.diff
@@ -15,8 +15,8 @@
           StorageLive(_2);
           _2 = Test5::::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1];
-+         switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb8];
+-         switchInt(move _3) -> [255: bb4, 0: bb3, 5: bb2, otherwise: bb1];
++         switchInt(move _3) -> [255: bb4, 0: bb3, 5: bb2, 3: bb1, otherwise: bb8];
       }
   
       bb1: {
@@ -28,7 +28,10 @@
       }
   
       bb2: {
-          _1 = const "A(T)";
+          StorageLive(_5);
+          _5 = const "C";
+          _1 = &(*_5);
+          StorageDead(_5);
           goto -> bb5;
       }
   
@@ -41,10 +44,7 @@
       }
   
       bb4: {
-          StorageLive(_5);
-          _5 = const "C";
-          _1 = &(*_5);
-          StorageDead(_5);
+          _1 = const "A(T)";
           goto -> bb5;
       }
   
diff --git a/tests/mir-opt/unreachable_enum_branching.rs b/tests/mir-opt/unreachable_enum_branching.rs
index 6005dc546dc8b..fac14042b1075 100644
--- a/tests/mir-opt/unreachable_enum_branching.rs
+++ b/tests/mir-opt/unreachable_enum_branching.rs
@@ -120,7 +120,7 @@ fn otherwise_t3() {
 fn otherwise_t4_unreachable_default() {
     // CHECK-LABEL: fn otherwise_t4_unreachable_default(
     // CHECK: [[discr:_.*]] = discriminant(
-    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: switchInt(move [[discr]]) -> [0: {{bb.*}}, 1: {{bb.*}}, 2: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
     // CHECK: [[unreachable]]: {
     // CHECK-NEXT: unreachable;
     match Test4::C {
@@ -135,7 +135,7 @@ fn otherwise_t4_unreachable_default() {
 fn otherwise_t4_unreachable_default_2() {
     // CHECK-LABEL: fn otherwise_t4_unreachable_default_2(
     // CHECK: [[discr:_.*]] = discriminant(
-    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: switchInt(move [[discr]]) -> [0: {{bb.*}}, 1: {{bb.*}}, 2: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
     // CHECK: [[unreachable]]: {
     // CHECK-NEXT: unreachable;
     match Test4::C {
@@ -151,7 +151,7 @@ fn otherwise_t4_unreachable_default_2() {
 fn otherwise_t4() {
     // CHECK-LABEL: fn otherwise_t4(
     // CHECK: [[discr:_.*]] = discriminant(
-    // CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, otherwise: [[unreachable:bb.*]]];
+    // CHECK: switchInt(move [[discr]]) -> [0: {{bb.*}}, 1: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
     // CHECK: [[unreachable]]: {
     // CHECK-NOT: unreachable;
     // CHECK: }
@@ -166,7 +166,7 @@ fn otherwise_t4() {
 fn otherwise_t5_unreachable_default() {
     // CHECK-LABEL: fn otherwise_t5_unreachable_default(
     // CHECK: [[discr:_.*]] = discriminant(
-    // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]];
+    // CHECK: switchInt(move [[discr]]) -> [255: {{bb.*}}, 0: {{bb.*}}, 5: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable:bb.*]]];
     // CHECK: [[unreachable]]: {
     // CHECK-NEXT: unreachable;
     match Test5::::C {
@@ -183,7 +183,7 @@ fn byref() {
     let plop = Plop { xx: 51, test3: Test3::C };
 
     // CHECK: [[ref_discr:_.*]] = discriminant((*
-    // CHECK: switchInt(move [[ref_discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: bb5, 3: bb2, otherwise: [[unreachable]]];
+    // CHECK: switchInt(move [[ref_discr]]) -> [0: [[unreachable:bb.*]], 1: [[unreachable]], 2: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable]]];
     match &plop.test3 {
         Test3::A(_) => "A(Empty)",
         Test3::B(_) => "B(Empty)",
@@ -195,7 +195,7 @@ fn byref() {
     // CHECK-NEXT: unreachable;
 
     // CHECK: [[discr:_.*]] = discriminant(
-    // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: bb10, 3: bb7, otherwise: [[unreachable]]];
+    // CHECK: switchInt(move [[discr]]) -> [0: [[unreachable]], 1: [[unreachable]], 2: {{bb.*}}, 3: {{bb.*}}, otherwise: [[unreachable]]];
     match plop.test3 {
         Test3::A(_) => "A(Empty)",
         Test3::B(_) => "B(Empty)",
diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff
index a85fc0da99232..8aef991493672 100644
--- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff
+++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-abort.diff
@@ -14,7 +14,7 @@
           StorageLive(_2);
           _2 = Test1::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1];
+-         switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1];
 +         switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1];
       }
   
@@ -31,11 +31,6 @@
       }
   
       bb3: {
-          _1 = const "A(Empty)";
-          goto -> bb5;
-      }
-  
-      bb4: {
           StorageLive(_4);
           _4 = const "B(Empty)";
           _1 = &(*_4);
@@ -43,6 +38,11 @@
           goto -> bb5;
       }
   
+      bb4: {
+          _1 = const "A(Empty)";
+          goto -> bb5;
+      }
+  
       bb5: {
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff
index a85fc0da99232..8aef991493672 100644
--- a/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff
+++ b/tests/mir-opt/unreachable_enum_branching.simple.UnreachableEnumBranching.panic-unwind.diff
@@ -14,7 +14,7 @@
           StorageLive(_2);
           _2 = Test1::C;
           _3 = discriminant(_2);
--         switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb2, otherwise: bb1];
+-         switchInt(move _3) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1];
 +         switchInt(move _3) -> [0: bb1, 1: bb1, 2: bb2, otherwise: bb1];
       }
   
@@ -31,11 +31,6 @@
       }
   
       bb3: {
-          _1 = const "A(Empty)";
-          goto -> bb5;
-      }
-  
-      bb4: {
           StorageLive(_4);
           _4 = const "B(Empty)";
           _1 = &(*_4);
@@ -43,6 +38,11 @@
           goto -> bb5;
       }
   
+      bb4: {
+          _1 = const "A(Empty)";
+          goto -> bb5;
+      }
+  
       bb5: {
           StorageDead(_2);
           StorageDead(_1);
diff --git a/tests/ui/stable-mir-print/basic_function.stdout b/tests/ui/stable-mir-print/basic_function.stdout
index 3926c1048f54a..76288c2aa49f2 100644
--- a/tests/ui/stable-mir-print/basic_function.stdout
+++ b/tests/ui/stable-mir-print/basic_function.stdout
@@ -44,14 +44,14 @@ fn demux(_1: u8) -> u8 {
     let mut _0: u8;
     debug input => _1;
     bb0: {
-        switchInt(_1) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
+        switchInt(_1) -> [0: bb4, 1: bb3, 2: bb2, otherwise: bb1];
     }
     bb1: {
         _0 = 0_u8;
         goto -> bb5;
     }
     bb2: {
-        _0 = 10_u8;
+        _0 = 8_u8;
         goto -> bb5;
     }
     bb3: {
@@ -59,7 +59,7 @@ fn demux(_1: u8) -> u8 {
         goto -> bb5;
     }
     bb4: {
-        _0 = 8_u8;
+        _0 = 10_u8;
         goto -> bb5;
     }
     bb5: {

From cbdacec188b1d2ef18a074784edbe58be826be58 Mon Sep 17 00:00:00 2001
From: Nadrieril 
Date: Sun, 23 Jun 2024 17:08:10 +0200
Subject: [PATCH 210/489] Abstract out the candidate manipulation not in the
 main algorithm

---
 .../rustc_mir_build/src/build/matches/mod.rs  | 317 +++++++++++-------
 .../rustc_mir_build/src/build/matches/util.rs |   2 +-
 2 files changed, 192 insertions(+), 127 deletions(-)

diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 0a55013ae20cd..78efa53253a3f 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -366,28 +366,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let scrutinee_place =
             unpack!(block = self.lower_scrutinee(block, scrutinee_id, scrutinee_span));
 
-        let mut arm_candidates = self.create_match_candidates(&scrutinee_place, arms);
-
-        let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard);
-        let mut candidates =
-            arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::>();
-
-        let match_start_span = span.shrink_to_lo().to(scrutinee_span);
+        let arms = arms.iter().map(|arm| &self.thir[*arm]);
+        // Assemble the initial list of candidates. These top-level candidates are 1:1 with the
+        // original match arms, but other parts of match lowering also introduce subcandidates (for
+        // sub-or-patterns). So inside the algorithm, the candidates list may not correspond to
+        // match arms directly.
+        let candidates: Vec<_> = arms
+            .clone()
+            .map(|arm| {
+                let arm_has_guard = arm.guard.is_some();
+                let arm_candidate =
+                    Candidate::new(scrutinee_place.clone(), &arm.pattern, arm_has_guard, self);
+                arm_candidate
+            })
+            .collect();
 
         // The set of places that we are creating fake borrows of. If there are no match guards then
         // we don't need any fake borrows, so don't track them.
+        let match_has_guard = candidates.iter().any(|candidate| candidate.has_guard);
         let fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)> = if match_has_guard {
             util::collect_fake_borrows(self, &candidates, scrutinee_span, scrutinee_place.base())
         } else {
             Vec::new()
         };
 
-        self.lower_match_tree(
+        let match_start_span = span.shrink_to_lo().to(scrutinee_span);
+        let built_tree = self.lower_match_tree(
             block,
             scrutinee_span,
             &scrutinee_place,
             match_start_span,
-            &mut candidates,
+            candidates,
             false,
         );
 
@@ -395,7 +404,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             destination,
             scrutinee_place,
             scrutinee_span,
-            arm_candidates,
+            arms,
+            built_tree.branches,
             self.source_info(span),
             fake_borrow_temps,
         )
@@ -417,51 +427,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         block.and(scrutinee_place_builder)
     }
 
-    /// Create the initial `Candidate`s for a `match` expression.
-    fn create_match_candidates<'pat>(
-        &mut self,
-        scrutinee: &PlaceBuilder<'tcx>,
-        arms: &'pat [ArmId],
-    ) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)>
-    where
-        'a: 'pat,
-    {
-        // Assemble the initial list of candidates. These top-level candidates
-        // are 1:1 with the original match arms, but other parts of match
-        // lowering also introduce subcandidates (for subpatterns), and will
-        // also flatten candidates in some cases. So in general a list of
-        // candidates does _not_ necessarily correspond to a list of arms.
-        arms.iter()
-            .copied()
-            .map(|arm| {
-                let arm = &self.thir[arm];
-                let arm_has_guard = arm.guard.is_some();
-                let arm_candidate =
-                    Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard, self);
-                (arm, arm_candidate)
-            })
-            .collect()
-    }
-
     /// Lower the bindings, guards and arm bodies of a `match` expression.
     ///
     /// The decision tree should have already been created
     /// (by [Builder::lower_match_tree]).
     ///
     /// `outer_source_info` is the SourceInfo for the whole match.
-    fn lower_match_arms(
+    fn lower_match_arms<'pat>(
         &mut self,
         destination: Place<'tcx>,
         scrutinee_place_builder: PlaceBuilder<'tcx>,
         scrutinee_span: Span,
-        arm_candidates: Vec<(&'_ Arm<'tcx>, Candidate<'_, 'tcx>)>,
+        arms: impl IntoIterator>,
+        lowered_branches: impl IntoIterator>,
         outer_source_info: SourceInfo,
         fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)>,
-    ) -> BlockAnd<()> {
-        let arm_end_blocks: Vec = arm_candidates
+    ) -> BlockAnd<()>
+    where
+        'tcx: 'pat,
+    {
+        let arm_end_blocks: Vec = arms
             .into_iter()
-            .map(|(arm, candidate)| {
-                debug!("lowering arm {:?}\ncandidate = {:?}", arm, candidate);
+            .zip(lowered_branches)
+            .map(|(arm, branch)| {
+                debug!("lowering arm {:?}\ncorresponding branch = {:?}", arm, branch);
 
                 let arm_source_info = self.source_info(arm.span);
                 let arm_scope = (arm.scope, arm_source_info);
@@ -494,7 +483,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                     let arm_block = this.bind_pattern(
                         outer_source_info,
-                        candidate,
+                        branch,
                         &fake_borrow_temps,
                         scrutinee_span,
                         Some((arm, match_scope)),
@@ -548,18 +537,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn bind_pattern(
         &mut self,
         outer_source_info: SourceInfo,
-        candidate: Candidate<'_, 'tcx>,
+        branch: MatchTreeBranch<'tcx>,
         fake_borrow_temps: &[(Place<'tcx>, Local, FakeBorrowKind)],
         scrutinee_span: Span,
         arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
         emit_storage_live: EmitStorageLive,
     ) -> BasicBlock {
-        if candidate.subcandidates.is_empty() {
-            // Avoid generating another `BasicBlock` when we only have one
-            // candidate.
+        if branch.sub_branches.len() == 1 {
+            let [sub_branch] = branch.sub_branches.try_into().unwrap();
+            // Avoid generating another `BasicBlock` when we only have one sub branch.
             self.bind_and_guard_matched_candidate(
-                candidate,
-                &[],
+                sub_branch,
                 fake_borrow_temps,
                 scrutinee_span,
                 arm_match_scope,
@@ -587,35 +575,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // We keep a stack of all of the bindings and type ascriptions
             // from the parent candidates that we visit, that also need to
             // be bound for each candidate.
-            traverse_candidate(
-                candidate,
-                &mut Vec::new(),
-                &mut |leaf_candidate, parent_data| {
-                    if let Some(arm) = arm {
-                        self.clear_top_scope(arm.scope);
-                    }
-                    let binding_end = self.bind_and_guard_matched_candidate(
-                        leaf_candidate,
-                        parent_data,
-                        fake_borrow_temps,
-                        scrutinee_span,
-                        arm_match_scope,
-                        schedule_drops,
-                        emit_storage_live,
-                    );
-                    if arm.is_none() {
-                        schedule_drops = ScheduleDrops::No;
-                    }
-                    self.cfg.goto(binding_end, outer_source_info, target_block);
-                },
-                |inner_candidate, parent_data| {
-                    parent_data.push(inner_candidate.extra_data);
-                    inner_candidate.subcandidates.into_iter()
-                },
-                |parent_data| {
-                    parent_data.pop();
-                },
-            );
+            for sub_branch in branch.sub_branches {
+                if let Some(arm) = arm {
+                    self.clear_top_scope(arm.scope);
+                }
+                let binding_end = self.bind_and_guard_matched_candidate(
+                    sub_branch,
+                    fake_borrow_temps,
+                    scrutinee_span,
+                    arm_match_scope,
+                    schedule_drops,
+                    emit_storage_live,
+                );
+                if arm.is_none() {
+                    schedule_drops = ScheduleDrops::No;
+                }
+                self.cfg.goto(binding_end, outer_source_info, target_block);
+            }
 
             target_block
         }
@@ -761,17 +737,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        self.lower_match_tree(
+        let built_tree = self.lower_match_tree(
             block,
             irrefutable_pat.span,
             &initializer,
             irrefutable_pat.span,
-            &mut [&mut candidate],
+            vec![candidate],
             false,
         );
+        let [branch] = built_tree.branches.try_into().unwrap();
+
         self.bind_pattern(
             self.source_info(irrefutable_pat.span),
-            candidate,
+            branch,
             &[],
             irrefutable_pat.span,
             None,
@@ -1417,6 +1395,98 @@ pub(crate) struct ArmHasGuard(pub(crate) bool);
 ///////////////////////////////////////////////////////////////////////////
 // Main matching algorithm
 
+/// A sub-branch in the output of match lowering. Match lowering has generated MIR code that will
+/// branch to `success_block` when the matched value matches the corresponding pattern. If there is
+/// a guard, its failure must continue to `otherwise_block`, which will resume testing patterns.
+#[derive(Debug)]
+struct MatchTreeSubBranch<'tcx> {
+    span: Span,
+    /// The block that is branched to if the corresponding subpattern matches.
+    success_block: BasicBlock,
+    /// The block to branch to if this arm had a guard and the guard fails.
+    otherwise_block: BasicBlock,
+    /// The bindings to set up in this sub-branch.
+    bindings: Vec>,
+    /// The ascriptions to set up in this sub-branch.
+    ascriptions: Vec>,
+    /// Whether the sub-branch corresponds to a never pattern.
+    is_never: bool,
+}
+
+/// A branch in the output of match lowering.
+#[derive(Debug)]
+struct MatchTreeBranch<'tcx> {
+    sub_branches: Vec>,
+}
+
+/// The result of generating MIR for a pattern-matching expression. Each input branch/arm/pattern
+/// gives rise to an output `MatchTreeBranch`. If one of the patterns matches, we branch to the
+/// corresponding `success_block`. If none of the patterns matches, we branch to `otherwise_block`.
+///
+/// Each branch is made of one of more sub-branches, corresponding to or-patterns. E.g.
+/// ```ignore(illustrative)
+/// match foo {
+///     (x, false) | (false, x) => {}
+///     (true, true) => {}
+/// }
+/// ```
+/// Here the first arm gives the first `MatchTreeBranch`, which has two sub-branches, one for each
+/// alternative of the or-pattern. They are kept separate because each needs to bind `x` to a
+/// different place.
+#[derive(Debug)]
+struct BuiltMatchTree<'tcx> {
+    branches: Vec>,
+    otherwise_block: BasicBlock,
+}
+
+impl<'tcx> MatchTreeSubBranch<'tcx> {
+    fn from_sub_candidate(
+        candidate: Candidate<'_, 'tcx>,
+        parent_data: &Vec>,
+    ) -> Self {
+        debug_assert!(candidate.match_pairs.is_empty());
+        MatchTreeSubBranch {
+            span: candidate.extra_data.span,
+            success_block: candidate.pre_binding_block.unwrap(),
+            otherwise_block: candidate.otherwise_block.unwrap(),
+            bindings: parent_data
+                .iter()
+                .flat_map(|d| &d.bindings)
+                .chain(&candidate.extra_data.bindings)
+                .cloned()
+                .collect(),
+            ascriptions: parent_data
+                .iter()
+                .flat_map(|d| &d.ascriptions)
+                .cloned()
+                .chain(candidate.extra_data.ascriptions)
+                .collect(),
+            is_never: candidate.extra_data.is_never,
+        }
+    }
+}
+
+impl<'tcx> MatchTreeBranch<'tcx> {
+    fn from_candidate(candidate: Candidate<'_, 'tcx>) -> Self {
+        let mut sub_branches = Vec::new();
+        traverse_candidate(
+            candidate,
+            &mut Vec::new(),
+            &mut |candidate: Candidate<'_, '_>, parent_data: &mut Vec>| {
+                sub_branches.push(MatchTreeSubBranch::from_sub_candidate(candidate, parent_data));
+            },
+            |inner_candidate, parent_data| {
+                parent_data.push(inner_candidate.extra_data);
+                inner_candidate.subcandidates.into_iter()
+            },
+            |parent_data| {
+                parent_data.pop();
+            },
+        );
+        MatchTreeBranch { sub_branches }
+    }
+}
+
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// The entrypoint of the matching algorithm. Create the decision tree for the match expression,
     /// starting from `block`.
@@ -1433,13 +1503,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         scrutinee_span: Span,
         scrutinee_place_builder: &PlaceBuilder<'tcx>,
         match_start_span: Span,
-        candidates: &mut [&mut Candidate<'pat, 'tcx>],
+        mut candidates: Vec>,
         refutable: bool,
-    ) -> BasicBlock {
+    ) -> BuiltMatchTree<'tcx> {
         // This will generate code to test scrutinee_place and branch to the appropriate arm block.
-        // See the doc comment on `match_candidates` for why we have an otherwise block.
+        // If none of the arms match, we branch to `otherwise_block`. When lowering a `match`
+        // expression, exhaustiveness checking ensures that this block is unreachable.
+        let mut candidate_refs = candidates.iter_mut().collect::>();
         let otherwise_block =
-            self.match_candidates(match_start_span, scrutinee_span, block, candidates);
+            self.match_candidates(match_start_span, scrutinee_span, block, &mut candidate_refs);
 
         // Set up false edges so that the borrow-checker cannot make use of the specific CFG we
         // generated. We falsely branch from each candidate to the one below it to make it as if we
@@ -1509,7 +1581,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.cfg.terminate(otherwise_block, source_info, TerminatorKind::Unreachable);
         }
 
-        otherwise_block
+        BuiltMatchTree {
+            branches: candidates.into_iter().map(MatchTreeBranch::from_candidate).collect(),
+            otherwise_block,
+        }
     }
 
     /// The main match algorithm. It begins with a set of candidates `candidates` and has the job of
@@ -2259,17 +2334,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ) -> BlockAnd<()> {
         let expr_span = self.thir[expr_id].span;
         let scrutinee = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
-        let mut candidate = Candidate::new(scrutinee.clone(), pat, false, self);
-        let otherwise_block = self.lower_match_tree(
-            block,
-            expr_span,
-            &scrutinee,
-            pat.span,
-            &mut [&mut candidate],
-            true,
-        );
+        let candidate = Candidate::new(scrutinee.clone(), pat, false, self);
+        let built_tree =
+            self.lower_match_tree(block, expr_span, &scrutinee, pat.span, vec![candidate], true);
+        let [branch] = built_tree.branches.try_into().unwrap();
 
-        self.break_for_else(otherwise_block, self.source_info(expr_span));
+        self.break_for_else(built_tree.otherwise_block, self.source_info(expr_span));
 
         match declare_let_bindings {
             DeclareLetBindings::Yes => {
@@ -2291,7 +2361,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         let success = self.bind_pattern(
             self.source_info(pat.span),
-            candidate,
+            branch,
             &[],
             expr_span,
             None,
@@ -2299,7 +2369,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         );
 
         // If branch coverage is enabled, record this branch.
-        self.visit_coverage_conditional_let(pat, success, otherwise_block);
+        self.visit_coverage_conditional_let(pat, success, built_tree.otherwise_block);
 
         success.unit()
     }
@@ -2312,39 +2382,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Note: we do not check earlier that if there is a guard,
     /// there cannot be move bindings. We avoid a use-after-move by only
     /// moving the binding once the guard has evaluated to true (see below).
-    fn bind_and_guard_matched_candidate<'pat>(
+    fn bind_and_guard_matched_candidate(
         &mut self,
-        candidate: Candidate<'pat, 'tcx>,
-        parent_data: &[PatternExtraData<'tcx>],
+        sub_branch: MatchTreeSubBranch<'tcx>,
         fake_borrows: &[(Place<'tcx>, Local, FakeBorrowKind)],
         scrutinee_span: Span,
         arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
         schedule_drops: ScheduleDrops,
         emit_storage_live: EmitStorageLive,
     ) -> BasicBlock {
-        debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
-
-        debug_assert!(candidate.match_pairs.is_empty());
+        debug!("bind_and_guard_matched_candidate(subbranch={:?})", sub_branch);
 
-        let block = candidate.pre_binding_block.unwrap();
+        let block = sub_branch.success_block;
 
-        if candidate.extra_data.is_never {
+        if sub_branch.is_never {
             // This arm has a dummy body, we don't need to generate code for it. `block` is already
             // unreachable (except via false edge).
-            let source_info = self.source_info(candidate.extra_data.span);
+            let source_info = self.source_info(sub_branch.span);
             self.cfg.terminate(block, source_info, TerminatorKind::Unreachable);
             return self.cfg.start_new_block();
         }
 
-        let ascriptions = parent_data
-            .iter()
-            .flat_map(|d| &d.ascriptions)
-            .cloned()
-            .chain(candidate.extra_data.ascriptions);
-        let bindings =
-            parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings);
-
-        self.ascribe_types(block, ascriptions);
+        self.ascribe_types(block, sub_branch.ascriptions);
 
         // Lower an instance of the arm guard (if present) for this candidate,
         // and then perform bindings for the arm body.
@@ -2355,9 +2414,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             // Bindings for guards require some extra handling to automatically
             // insert implicit references/dereferences.
-            self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone());
+            self.bind_matched_candidate_for_guard(
+                block,
+                schedule_drops,
+                sub_branch.bindings.iter(),
+            );
             let guard_frame = GuardFrame {
-                locals: bindings.clone().map(|b| GuardFrameLocal::new(b.var_id)).collect(),
+                locals: sub_branch
+                    .bindings
+                    .iter()
+                    .map(|b| GuardFrameLocal::new(b.var_id))
+                    .collect(),
             };
             debug!("entering guard building context: {:?}", guard_frame);
             self.guard_context.push(guard_frame);
@@ -2393,11 +2460,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.cfg.push_fake_read(post_guard_block, guard_end, cause, Place::from(temp));
             }
 
-            self.cfg.goto(
-                otherwise_post_guard_block,
-                source_info,
-                candidate.otherwise_block.unwrap(),
-            );
+            self.cfg.goto(otherwise_post_guard_block, source_info, sub_branch.otherwise_block);
 
             // We want to ensure that the matched candidates are bound
             // after we have confirmed this candidate *and* any
@@ -2425,8 +2488,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // ```
             //
             // and that is clearly not correct.
-            let by_value_bindings =
-                bindings.filter(|binding| matches!(binding.binding_mode.0, ByRef::No));
+            let by_value_bindings = sub_branch
+                .bindings
+                .iter()
+                .filter(|binding| matches!(binding.binding_mode.0, ByRef::No));
             // Read all of the by reference bindings to ensure that the
             // place they refer to can't be modified by the guard.
             for binding in by_value_bindings.clone() {
@@ -2454,7 +2519,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.bind_matched_candidate_for_arm_body(
                 block,
                 schedule_drops,
-                bindings,
+                sub_branch.bindings.iter(),
                 emit_storage_live,
             );
             block
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 1848ab7a20be7..79ee683d63cce 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -70,7 +70,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 ///    a MIR pass run after borrow checking.
 pub(super) fn collect_fake_borrows<'tcx>(
     cx: &mut Builder<'_, 'tcx>,
-    candidates: &[&mut Candidate<'_, 'tcx>],
+    candidates: &[Candidate<'_, 'tcx>],
     temp_span: Span,
     scrutinee_base: PlaceBase,
 ) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {

From 55c703bca7b8d520c7550768930ec7637942dfb7 Mon Sep 17 00:00:00 2001
From: Yunfei 
Date: Mon, 29 Jul 2024 15:55:21 +0800
Subject: [PATCH 211/489] feat(ide-completion): explictly show `async` keyword
 on `impl trait`

---
 .../ide-completion/src/completions/item_list/trait_impl.rs  | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
index f9dc62562f809..4a1f985b30791 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -180,8 +180,10 @@ fn add_function_impl(
 ) {
     let fn_name = func.name(ctx.db);
 
+    let is_async = func.is_async(ctx.db);
     let label = format_smolstr!(
-        "fn {}({})",
+        "{}fn {}({})",
+        if is_async { "async " } else { "" },
         fn_name.display(ctx.db),
         if func.assoc_fn_params(ctx.db).is_empty() { "" } else { ".." }
     );
@@ -193,7 +195,7 @@ fn add_function_impl(
     });
 
     let mut item = CompletionItem::new(completion_kind, replacement_range, label);
-    item.lookup_by(format!("fn {}", fn_name.display(ctx.db)))
+    item.lookup_by(format!("{}fn {}", if is_async { "async "} else { "" },fn_name.display(ctx.db)))
         .set_documentation(func.docs(ctx.db))
         .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
 

From c7471664b356229cd9aac11f1c0339dcf24863b0 Mon Sep 17 00:00:00 2001
From: Nadrieril 
Date: Sun, 23 Jun 2024 17:25:41 +0200
Subject: [PATCH 212/489] Visiting bindings is straightforward now

---
 .../rustc_mir_build/src/build/matches/mod.rs  | 28 +++++-----
 .../rustc_mir_build/src/build/matches/util.rs | 53 -------------------
 2 files changed, 14 insertions(+), 67 deletions(-)

diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 78efa53253a3f..267db29ff3d7d 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -17,7 +17,6 @@ use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, Pos, Span};
 use rustc_target::abi::VariantIdx;
 use tracing::{debug, instrument};
-use util::visit_bindings;
 
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::scope::DropKind;
@@ -701,7 +700,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         initializer: PlaceBuilder<'tcx>,
         set_match_place: bool,
     ) -> BlockAnd<()> {
-        let mut candidate = Candidate::new(initializer.clone(), irrefutable_pat, false, self);
+        let candidate = Candidate::new(initializer.clone(), irrefutable_pat, false, self);
+        let built_tree = self.lower_match_tree(
+            block,
+            irrefutable_pat.span,
+            &initializer,
+            irrefutable_pat.span,
+            vec![candidate],
+            false,
+        );
+        let [branch] = built_tree.branches.try_into().unwrap();
 
         // For matches and function arguments, the place that is being matched
         // can be set when creating the variables. But the place for
@@ -722,7 +730,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // };
             // ```
             if let Some(place) = initializer.try_to_place(self) {
-                visit_bindings(&[&mut candidate], |binding: &Binding<'_>| {
+                // Because or-alternatives bind the same variables, we only explore the first one.
+                let first_sub_branch = branch.sub_branches.first().unwrap();
+                for binding in &first_sub_branch.bindings {
                     let local = self.var_local_id(binding.var_id, OutsideGuard);
                     if let LocalInfo::User(BindingForm::Var(VarBindingForm {
                         opt_match_place: Some((ref mut match_place, _)),
@@ -733,20 +743,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     } else {
                         bug!("Let binding to non-user variable.")
                     };
-                });
+                }
             }
         }
 
-        let built_tree = self.lower_match_tree(
-            block,
-            irrefutable_pat.span,
-            &initializer,
-            irrefutable_pat.span,
-            vec![candidate],
-            false,
-        );
-        let [branch] = built_tree.branches.try_into().unwrap();
-
         self.bind_pattern(
             self.source_info(irrefutable_pat.span),
             branch,
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 79ee683d63cce..d3ba1577edf7b 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -1,5 +1,3 @@
-use std::marker::PhantomData;
-
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_middle::mir::*;
 use rustc_middle::ty::Ty;
@@ -221,57 +219,6 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
     }
 }
 
-/// Visit all the bindings of these candidates. Because or-alternatives bind the same variables, we
-/// only explore the first one of each or-pattern.
-pub(super) fn visit_bindings<'tcx>(
-    candidates: &[&mut Candidate<'_, 'tcx>],
-    f: impl FnMut(&Binding<'tcx>),
-) {
-    let mut visitor = BindingsVisitor { f, phantom: PhantomData };
-    for candidate in candidates.iter() {
-        visitor.visit_candidate(candidate);
-    }
-}
-
-pub(super) struct BindingsVisitor<'tcx, F> {
-    f: F,
-    phantom: PhantomData<&'tcx ()>,
-}
-
-impl<'tcx, F> BindingsVisitor<'tcx, F>
-where
-    F: FnMut(&Binding<'tcx>),
-{
-    fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
-        for binding in &candidate.extra_data.bindings {
-            (self.f)(binding)
-        }
-        for match_pair in &candidate.match_pairs {
-            self.visit_match_pair(match_pair);
-        }
-    }
-
-    fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
-        for binding in &flat_pat.extra_data.bindings {
-            (self.f)(binding)
-        }
-        for match_pair in &flat_pat.match_pairs {
-            self.visit_match_pair(match_pair);
-        }
-    }
-
-    fn visit_match_pair(&mut self, match_pair: &MatchPairTree<'_, 'tcx>) {
-        if let TestCase::Or { pats, .. } = &match_pair.test_case {
-            // All the or-alternatives should bind the same locals, so we only visit the first one.
-            self.visit_flat_pat(&pats[0])
-        } else {
-            for subpair in &match_pair.subpairs {
-                self.visit_match_pair(subpair);
-            }
-        }
-    }
-}
-
 #[must_use]
 pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind {
     match ref_mutability {

From 08bcc0139405fb0592a87488759990d615414f08 Mon Sep 17 00:00:00 2001
From: Nadrieril 
Date: Sun, 30 Jun 2024 11:33:43 +0200
Subject: [PATCH 213/489] Entirely hide `Candidate`s from outside
 `lower_match_tree`

---
 .../rustc_mir_build/src/build/matches/mod.rs  | 98 ++++++++++++-------
 .../rustc_mir_build/src/build/matches/util.rs |  4 +
 2 files changed, 64 insertions(+), 38 deletions(-)

diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 267db29ff3d7d..cae4aa7bad3d2 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -366,36 +366,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             unpack!(block = self.lower_scrutinee(block, scrutinee_id, scrutinee_span));
 
         let arms = arms.iter().map(|arm| &self.thir[*arm]);
-        // Assemble the initial list of candidates. These top-level candidates are 1:1 with the
-        // original match arms, but other parts of match lowering also introduce subcandidates (for
-        // sub-or-patterns). So inside the algorithm, the candidates list may not correspond to
-        // match arms directly.
-        let candidates: Vec<_> = arms
+        let match_start_span = span.shrink_to_lo().to(scrutinee_span);
+        let patterns = arms
             .clone()
             .map(|arm| {
-                let arm_has_guard = arm.guard.is_some();
-                let arm_candidate =
-                    Candidate::new(scrutinee_place.clone(), &arm.pattern, arm_has_guard, self);
-                arm_candidate
+                let has_match_guard =
+                    if arm.guard.is_some() { HasMatchGuard::Yes } else { HasMatchGuard::No };
+                (&*arm.pattern, has_match_guard)
             })
             .collect();
-
-        // The set of places that we are creating fake borrows of. If there are no match guards then
-        // we don't need any fake borrows, so don't track them.
-        let match_has_guard = candidates.iter().any(|candidate| candidate.has_guard);
-        let fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)> = if match_has_guard {
-            util::collect_fake_borrows(self, &candidates, scrutinee_span, scrutinee_place.base())
-        } else {
-            Vec::new()
-        };
-
-        let match_start_span = span.shrink_to_lo().to(scrutinee_span);
         let built_tree = self.lower_match_tree(
             block,
             scrutinee_span,
             &scrutinee_place,
             match_start_span,
-            candidates,
+            patterns,
             false,
         );
 
@@ -404,9 +389,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             scrutinee_place,
             scrutinee_span,
             arms,
-            built_tree.branches,
+            built_tree,
             self.source_info(span),
-            fake_borrow_temps,
         )
     }
 
@@ -438,16 +422,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         scrutinee_place_builder: PlaceBuilder<'tcx>,
         scrutinee_span: Span,
         arms: impl IntoIterator>,
-        lowered_branches: impl IntoIterator>,
+        built_match_tree: BuiltMatchTree<'tcx>,
         outer_source_info: SourceInfo,
-        fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)>,
     ) -> BlockAnd<()>
     where
         'tcx: 'pat,
     {
         let arm_end_blocks: Vec = arms
             .into_iter()
-            .zip(lowered_branches)
+            .zip(built_match_tree.branches)
             .map(|(arm, branch)| {
                 debug!("lowering arm {:?}\ncorresponding branch = {:?}", arm, branch);
 
@@ -483,7 +466,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     let arm_block = this.bind_pattern(
                         outer_source_info,
                         branch,
-                        &fake_borrow_temps,
+                        &built_match_tree.fake_borrow_temps,
                         scrutinee_span,
                         Some((arm, match_scope)),
                         EmitStorageLive::Yes,
@@ -700,13 +683,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         initializer: PlaceBuilder<'tcx>,
         set_match_place: bool,
     ) -> BlockAnd<()> {
-        let candidate = Candidate::new(initializer.clone(), irrefutable_pat, false, self);
         let built_tree = self.lower_match_tree(
             block,
             irrefutable_pat.span,
             &initializer,
             irrefutable_pat.span,
-            vec![candidate],
+            vec![(irrefutable_pat, HasMatchGuard::No)],
             false,
         );
         let [branch] = built_tree.branches.try_into().unwrap();
@@ -1136,12 +1118,15 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
     fn new(
         place: PlaceBuilder<'tcx>,
         pattern: &'pat Pat<'tcx>,
-        has_guard: bool,
+        has_guard: HasMatchGuard,
         cx: &mut Builder<'_, 'tcx>,
     ) -> Self {
         // Use `FlatPat` to build simplified match pairs, then immediately
         // incorporate them into a new candidate.
-        Self::from_flat_pat(FlatPat::new(place, pattern, cx), has_guard)
+        Self::from_flat_pat(
+            FlatPat::new(place, pattern, cx),
+            matches!(has_guard, HasMatchGuard::Yes),
+        )
     }
 
     /// Incorporates an already-simplified [`FlatPat`] into a new candidate.
@@ -1437,6 +1422,10 @@ struct MatchTreeBranch<'tcx> {
 struct BuiltMatchTree<'tcx> {
     branches: Vec>,
     otherwise_block: BasicBlock,
+    /// If any of the branches had a guard, we collect here the places and locals to fakely borrow
+    /// to ensure match guards can't modify the values as we match them. For more details, see
+    /// [`util::collect_fake_borrows`].
+    fake_borrow_temps: Vec<(Place<'tcx>, Local, FakeBorrowKind)>,
 }
 
 impl<'tcx> MatchTreeSubBranch<'tcx> {
@@ -1487,12 +1476,18 @@ impl<'tcx> MatchTreeBranch<'tcx> {
     }
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum HasMatchGuard {
+    Yes,
+    No,
+}
+
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// The entrypoint of the matching algorithm. Create the decision tree for the match expression,
     /// starting from `block`.
     ///
-    /// Modifies `candidates` to store the bindings and type ascriptions for
-    /// that candidate.
+    /// `patterns` is a list of patterns, one for each arm. The associated boolean indicates whether
+    /// the arm has a guard.
     ///
     /// `refutable` indicates whether the candidate list is refutable (for `if let` and `let else`)
     /// or not (for `let` and `match`). In the refutable case we return the block to which we branch
@@ -1503,9 +1498,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         scrutinee_span: Span,
         scrutinee_place_builder: &PlaceBuilder<'tcx>,
         match_start_span: Span,
-        mut candidates: Vec>,
+        patterns: Vec<(&'pat Pat<'tcx>, HasMatchGuard)>,
         refutable: bool,
-    ) -> BuiltMatchTree<'tcx> {
+    ) -> BuiltMatchTree<'tcx>
+    where
+        'tcx: 'pat,
+    {
+        // Assemble the initial list of candidates. These top-level candidates are 1:1 with the
+        // input patterns, but other parts of match lowering also introduce subcandidates (for
+        // sub-or-patterns). So inside the algorithm, the candidates list may not correspond to
+        // match arms directly.
+        let mut candidates: Vec> = patterns
+            .into_iter()
+            .map(|(pat, has_guard)| {
+                Candidate::new(scrutinee_place_builder.clone(), pat, has_guard, self)
+            })
+            .collect();
+
+        let fake_borrow_temps = util::collect_fake_borrows(
+            self,
+            &candidates,
+            scrutinee_span,
+            scrutinee_place_builder.base(),
+        );
+
         // This will generate code to test scrutinee_place and branch to the appropriate arm block.
         // If none of the arms match, we branch to `otherwise_block`. When lowering a `match`
         // expression, exhaustiveness checking ensures that this block is unreachable.
@@ -1584,6 +1600,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         BuiltMatchTree {
             branches: candidates.into_iter().map(MatchTreeBranch::from_candidate).collect(),
             otherwise_block,
+            fake_borrow_temps,
         }
     }
 
@@ -2334,9 +2351,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ) -> BlockAnd<()> {
         let expr_span = self.thir[expr_id].span;
         let scrutinee = unpack!(block = self.lower_scrutinee(block, expr_id, expr_span));
-        let candidate = Candidate::new(scrutinee.clone(), pat, false, self);
-        let built_tree =
-            self.lower_match_tree(block, expr_span, &scrutinee, pat.span, vec![candidate], true);
+        let built_tree = self.lower_match_tree(
+            block,
+            expr_span,
+            &scrutinee,
+            pat.span,
+            vec![(pat, HasMatchGuard::No)],
+            true,
+        );
         let [branch] = built_tree.branches.try_into().unwrap();
 
         self.break_for_else(built_tree.otherwise_block, self.source_info(expr_span));
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index d3ba1577edf7b..8491b5fe380c7 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -72,6 +72,10 @@ pub(super) fn collect_fake_borrows<'tcx>(
     temp_span: Span,
     scrutinee_base: PlaceBase,
 ) -> Vec<(Place<'tcx>, Local, FakeBorrowKind)> {
+    if candidates.iter().all(|candidate| !candidate.has_guard) {
+        // Fake borrows are only used when there is a guard.
+        return Vec::new();
+    }
     let mut collector =
         FakeBorrowCollector { cx, scrutinee_base, fake_borrows: FxIndexMap::default() };
     for candidate in candidates.iter() {

From 5b184ffa22f8b6004e23132acad7193b9df3d3a2 Mon Sep 17 00:00:00 2001
From: Yunfei 
Date: Mon, 29 Jul 2024 16:35:19 +0800
Subject: [PATCH 214/489] Fix error message

---
 .../src/handlers/trait_impl_missing_assoc_item.rs           | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
index 58d1b7f31d2fe..836059cb9b785 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
@@ -13,6 +13,7 @@ pub(crate) fn trait_impl_missing_assoc_item(
 ) -> Diagnostic {
     let missing = d.missing.iter().format_with(", ", |(name, item), f| {
         f(&match *item {
+            hir::AssocItem::Function(func) if func.is_async(ctx.sema.db)  => "`async fn ",
             hir::AssocItem::Function(_) => "`fn ",
             hir::AssocItem::Const(_) => "`const ",
             hir::AssocItem::TypeAlias(_) => "`type ",
@@ -56,22 +57,25 @@ trait Trait {
     const C: ();
     type T;
     fn f();
+    async fn async_f();
 }
 
 impl Trait for () {
     const C: () = ();
     type T = ();
     fn f() {}
+    async fn async_f() {}
 }
 
 impl Trait for () {
    //^^^^^ error: not all trait items implemented, missing: `const C`
     type T = ();
     fn f() {}
+    async fn async_f() {}
 }
 
 impl Trait for () {
-   //^^^^^ error: not all trait items implemented, missing: `const C`, `type T`, `fn f`
+   //^^^^^ error: not all trait items implemented, missing: `const C`, `type T`, `fn f`, `async fn async_f`
 }
 
 "#,

From 6a6824a0ab5c14b5343fe108f10ec40c146b97e4 Mon Sep 17 00:00:00 2001
From: John Spray 
Date: Fri, 26 Jul 2024 15:58:24 +0100
Subject: [PATCH 215/489] Optimize empty case in Vec::retain

---
 library/alloc/src/vec/mod.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 729d5dd4fe4d2..417b88bfe8dad 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1711,6 +1711,12 @@ impl Vec {
         F: FnMut(&mut T) -> bool,
     {
         let original_len = self.len();
+
+        if original_len == 0 {
+            // Empty case: explicit return allows better optimization, vs letting compiler infer it
+            return;
+        }
+
         // Avoid double drop if the drop guard is not executed,
         // since we may make some holes during the process.
         unsafe { self.set_len(0) };

From 568228fbc9ed4d3037e9dce8aafa53525ff3b048 Mon Sep 17 00:00:00 2001
From: Yunfei 
Date: Mon, 29 Jul 2024 16:51:49 +0800
Subject: [PATCH 216/489] Cargo fmt

---
 .../src/completions/item_list/trait_impl.rs            | 10 +++++++---
 .../src/handlers/trait_impl_missing_assoc_item.rs      |  2 +-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 4a1f985b30791..2fd7805e60d5e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -195,9 +195,13 @@ fn add_function_impl(
     });
 
     let mut item = CompletionItem::new(completion_kind, replacement_range, label);
-    item.lookup_by(format!("{}fn {}", if is_async { "async "} else { "" },fn_name.display(ctx.db)))
-        .set_documentation(func.docs(ctx.db))
-        .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
+    item.lookup_by(format!(
+        "{}fn {}",
+        if is_async { "async " } else { "" },
+        fn_name.display(ctx.db)
+    ))
+    .set_documentation(func.docs(ctx.db))
+    .set_relevance(CompletionRelevance { is_item_from_trait: true, ..Default::default() });
 
     if let Some(source) = ctx.sema.source(func) {
         let assoc_item = ast::AssocItem::Fn(source.value);
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
index 836059cb9b785..60d1452d86be8 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
@@ -13,7 +13,7 @@ pub(crate) fn trait_impl_missing_assoc_item(
 ) -> Diagnostic {
     let missing = d.missing.iter().format_with(", ", |(name, item), f| {
         f(&match *item {
-            hir::AssocItem::Function(func) if func.is_async(ctx.sema.db)  => "`async fn ",
+            hir::AssocItem::Function(func) if func.is_async(ctx.sema.db) => "`async fn ",
             hir::AssocItem::Function(_) => "`fn ",
             hir::AssocItem::Const(_) => "`const ",
             hir::AssocItem::TypeAlias(_) => "`type ",

From ae681c940dd0813f75770fecd4f565d376b37d37 Mon Sep 17 00:00:00 2001
From: DianQK 
Date: Sat, 27 Jul 2024 14:36:17 +0800
Subject: [PATCH 217/489] Perform instsimplify before inline to eliminate some
 trivial calls

---
 .../rustc_mir_transform/src/instsimplify.rs   | 18 ++++++++++++-
 compiler/rustc_mir_transform/src/lib.rs       |  5 +++-
 compiler/rustc_mir_transform/src/shim.rs      |  2 +-
 tests/incremental/hashes/call_expressions.rs  |  2 +-
 tests/mir-opt/const_prop/slice_len.rs         |  2 +-
 .../mir-opt/dataflow-const-prop/slice_len.rs  |  2 +-
 ...yn_trait.get_query.Inline.panic-abort.diff |  4 +--
 ...n_trait.get_query.Inline.panic-unwind.diff |  4 +--
 ...dyn_trait.mk_cycle.Inline.panic-abort.diff |  2 +-
 ...yn_trait.mk_cycle.Inline.panic-unwind.diff |  2 +-
 ....try_execute_query.Inline.panic-abort.diff |  2 +-
 ...try_execute_query.Inline.panic-unwind.diff |  2 +-
 ...e_closure_borrows_arg.foo.Inline.after.mir |  4 +--
 .../inline/inline_retag.bar.Inline.after.mir  |  8 +++---
 ...t_method.test.Inline.after.panic-abort.mir |  2 +-
 ..._method.test.Inline.after.panic-unwind.mir |  2 +-
 ...ethod_2.test2.Inline.after.panic-abort.mir |  4 +--
 ...thod_2.test2.Inline.after.panic-unwind.mir |  4 +--
 ...67_inline_as_ref_as_mut.a.Inline.after.mir |  6 ++---
 ...67_inline_as_ref_as_mut.b.Inline.after.mir |  6 ++---
 ...67_inline_as_ref_as_mut.c.Inline.after.mir |  4 +--
 ...67_inline_as_ref_as_mut.d.Inline.after.mir |  4 +--
 ...false.InstSimplify-after-simplifycfg.diff} |  4 +--
 ..._true.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...se_eq.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...se_ne.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...false.InstSimplify-after-simplifycfg.diff} |  4 +--
 ..._true.InstSimplify-after-simplifycfg.diff} |  4 +--
 tests/mir-opt/instsimplify/bool_compare.rs    | 18 ++++++-------
 ...ue_eq.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...ue_ne.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...ndant.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...dtrip.InstSimplify-after-simplifycfg.diff} |  4 +--
 tests/mir-opt/instsimplify/casts.rs           |  8 +++---
 ...mplify-after-simplifycfg.panic-abort.diff} |  4 +--
 ...plify-after-simplifycfg.panic-unwind.diff} |  4 +--
 .../mir-opt/instsimplify/combine_array_len.rs |  4 +--
 .../combine_clone_of_primitives.rs            |  4 +--
 ...mplify-after-simplifycfg.panic-abort.diff} |  4 +--
 ...plify-after-simplifycfg.panic-unwind.diff} |  4 +--
 ...mutes.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...mutes.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...mutes.InstSimplify-after-simplifycfg.diff} |  4 +--
 .../instsimplify/combine_transmutes.rs        |  8 +++---
 ..._zero.InstSimplify-after-simplifycfg.diff} |  4 +--
 .../instsimplify/duplicate_switch_targets.rs  |  4 +--
 ...neric.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...c_ref.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...anics.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...vable.InstSimplify-after-simplifycfg.diff} |  4 +--
 .../mir-opt/instsimplify/intrinsic_asserts.rs | 10 +++----
 ...nters.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...ences.InstSimplify-after-simplifycfg.diff} |  4 +--
 tests/mir-opt/instsimplify/ref_of_deref.rs    |  6 ++---
 tests/mir-opt/instsimplify/ub_check.rs        |  4 +--
 ...ecked.InstSimplify-after-simplifycfg.diff} |  4 +--
 ...implifyComparisonIntegral.panic-abort.diff |  6 ++---
 ...mplifyComparisonIntegral.panic-unwind.diff |  6 ++---
 ...192.f.InstSimplify-after-simplifycfg.diff} |  7 +++--
 tests/mir-opt/issue_78192.rs                  |  2 +-
 ...d_constant.main.GVN.32bit.panic-abort.diff |  8 +++---
 ...d_constant.main.GVN.64bit.panic-abort.diff |  8 +++---
 .../loops.vec_move.PreCodegen.after.mir       |  2 --
 tests/mir-opt/pre-codegen/no_inlined_clone.rs | 12 +++++++++
 ..._clone.{impl#0}-clone.PreCodegen.after.mir | 15 +++++++++++
 ...acementOfAggregates.32bit.panic-abort.diff |  2 +-
 ...cementOfAggregates.32bit.panic-unwind.diff |  2 +-
 ...acementOfAggregates.64bit.panic-abort.diff |  2 +-
 ...cementOfAggregates.64bit.panic-unwind.diff |  2 +-
 ...sive_loop.PreCodegen.after.panic-abort.mir |  2 --
 ...ive_loop.PreCodegen.after.panic-unwind.mir |  2 --
 ...variant_a-{closure#0}.PreCodegen.after.mir | 27 +++++++++++++------
 ...mut_usize.PreCodegen.after.panic-abort.mir | 10 +++----
 ...ut_usize.PreCodegen.after.panic-unwind.mir | 10 +++----
 ...mut_range.PreCodegen.after.panic-abort.mir |  2 ++
 ...ut_range.PreCodegen.after.panic-unwind.mir |  2 ++
 ...ted_loop.PreCodegen.after.panic-unwind.mir |  2 --
 ...ward_loop.PreCodegen.after.panic-abort.mir |  2 --
 ...ard_loop.PreCodegen.after.panic-unwind.mir |  2 --
 ...ans.outer.PreCodegen.after.panic-abort.mir |  4 +--
 ...ns.outer.PreCodegen.after.panic-unwind.mir |  4 +--
 ..._to_slice.PreCodegen.after.panic-abort.mir |  4 ++-
 ...to_slice.PreCodegen.after.panic-unwind.mir |  4 ++-
 83 files changed, 226 insertions(+), 182 deletions(-)
 rename tests/mir-opt/instsimplify/{bool_compare.eq_false.InstSimplify.diff => bool_compare.eq_false.InstSimplify-after-simplifycfg.diff} (83%)
 rename tests/mir-opt/instsimplify/{bool_compare.eq_true.InstSimplify.diff => bool_compare.eq_true.InstSimplify-after-simplifycfg.diff} (83%)
 rename tests/mir-opt/instsimplify/{bool_compare.false_eq.InstSimplify.diff => bool_compare.false_eq.InstSimplify-after-simplifycfg.diff} (83%)
 rename tests/mir-opt/instsimplify/{bool_compare.false_ne.InstSimplify.diff => bool_compare.false_ne.InstSimplify-after-simplifycfg.diff} (83%)
 rename tests/mir-opt/instsimplify/{bool_compare.ne_false.InstSimplify.diff => bool_compare.ne_false.InstSimplify-after-simplifycfg.diff} (83%)
 rename tests/mir-opt/instsimplify/{bool_compare.ne_true.InstSimplify.diff => bool_compare.ne_true.InstSimplify-after-simplifycfg.diff} (83%)
 rename tests/mir-opt/instsimplify/{bool_compare.true_eq.InstSimplify.diff => bool_compare.true_eq.InstSimplify-after-simplifycfg.diff} (83%)
 rename tests/mir-opt/instsimplify/{bool_compare.true_ne.InstSimplify.diff => bool_compare.true_ne.InstSimplify-after-simplifycfg.diff} (83%)
 rename tests/mir-opt/instsimplify/{casts.redundant.InstSimplify.diff => casts.redundant.InstSimplify-after-simplifycfg.diff} (85%)
 rename tests/mir-opt/instsimplify/{casts.roundtrip.InstSimplify.diff => casts.roundtrip.InstSimplify-after-simplifycfg.diff} (82%)
 rename tests/mir-opt/instsimplify/{combine_array_len.norm2.InstSimplify.panic-abort.diff => combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff} (94%)
 rename tests/mir-opt/instsimplify/{combine_array_len.norm2.InstSimplify.panic-unwind.diff => combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff} (94%)
 rename tests/mir-opt/instsimplify/{combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-abort.diff => combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff} (94%)
 rename tests/mir-opt/instsimplify/{combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff => combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff} (94%)
 rename tests/mir-opt/instsimplify/{combine_transmutes.adt_transmutes.InstSimplify.diff => combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff} (94%)
 rename tests/mir-opt/instsimplify/{combine_transmutes.identity_transmutes.InstSimplify.diff => combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff} (85%)
 rename tests/mir-opt/instsimplify/{combine_transmutes.integer_transmutes.InstSimplify.diff => combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff} (80%)
 rename tests/mir-opt/instsimplify/{duplicate_switch_targets.assert_zero.InstSimplify.diff => duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff} (70%)
 rename tests/mir-opt/instsimplify/{intrinsic_asserts.generic.InstSimplify.diff => intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff} (84%)
 rename tests/mir-opt/instsimplify/{intrinsic_asserts.generic_ref.InstSimplify.diff => intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff} (70%)
 rename tests/mir-opt/instsimplify/{intrinsic_asserts.panics.InstSimplify.diff => intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff} (87%)
 rename tests/mir-opt/instsimplify/{intrinsic_asserts.removable.InstSimplify.diff => intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff} (85%)
 rename tests/mir-opt/instsimplify/{ref_of_deref.pointers.InstSimplify.diff => ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff} (92%)
 rename tests/mir-opt/instsimplify/{ref_of_deref.references.InstSimplify.diff => ref_of_deref.references.InstSimplify-after-simplifycfg.diff} (91%)
 rename tests/mir-opt/instsimplify/{ub_check.unwrap_unchecked.InstSimplify.diff => ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff} (90%)
 rename tests/mir-opt/{issue_78192.f.InstSimplify.diff => issue_78192.f.InstSimplify-after-simplifycfg.diff} (79%)
 create mode 100644 tests/mir-opt/pre-codegen/no_inlined_clone.rs
 create mode 100644 tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir

diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index cdd9e4af3b32c..2fc5f7e536ba8 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -13,9 +13,25 @@ use rustc_target::spec::abi::Abi;
 use crate::simplify::simplify_duplicate_switch_targets;
 use crate::take_array;
 
-pub struct InstSimplify;
+pub enum InstSimplify {
+    BeforeInline,
+    AfterSimplifyCfg,
+}
+
+impl InstSimplify {
+    pub fn name(&self) -> &'static str {
+        match self {
+            InstSimplify::BeforeInline => "InstSimplify-before-inline",
+            InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg",
+        }
+    }
+}
 
 impl<'tcx> MirPass<'tcx> for InstSimplify {
+    fn name(&self) -> &'static str {
+        self.name()
+    }
+
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         sess.mir_opt_level() > 0
     }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index f338d8283181c..ac3a44c803a5f 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -571,6 +571,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             // Has to be done before inlining, otherwise actual call will be almost always inlined.
             // Also simple, so can just do first
             &lower_slice_len::LowerSliceLenCalls,
+            // Perform instsimplify before inline to eliminate some trivial calls (like clone shims).
+            &instsimplify::InstSimplify::BeforeInline,
             // Perform inlining, which may add a lot of code.
             &inline::Inline,
             // Code from other crates may have storage markers, so this needs to happen after inlining.
@@ -590,7 +592,8 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &match_branches::MatchBranchSimplification,
             // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
             &multiple_return_terminators::MultipleReturnTerminators,
-            &instsimplify::InstSimplify,
+            // After simplifycfg, it allows us to discover new opportunities for peephole optimizations.
+            &instsimplify::InstSimplify::AfterSimplifyCfg,
             &simplify::SimplifyLocals::BeforeConstProp,
             &dead_store_elimination::DeadStoreElimination::Initial,
             &gvn::GVN,
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index a2c232dfd3caa..e2fafa3a1a30b 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -155,7 +155,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
             &deref_separator::Derefer,
             &remove_noop_landing_pads::RemoveNoopLandingPads,
             &simplify::SimplifyCfg::MakeShim,
-            &instsimplify::InstSimplify,
+            &instsimplify::InstSimplify::BeforeInline,
             &abort_unwinding_calls::AbortUnwindingCalls,
             &add_call_guards::CriticalCallEdges,
         ],
diff --git a/tests/incremental/hashes/call_expressions.rs b/tests/incremental/hashes/call_expressions.rs
index 36b6980bcc67f..71423ef6aff66 100644
--- a/tests/incremental/hashes/call_expressions.rs
+++ b/tests/incremental/hashes/call_expressions.rs
@@ -162,7 +162,7 @@ pub fn change_to_ufcs() {
 }
 
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
 #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail6")]
diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs
index 265a496f39a36..221fb18f92c61 100644
--- a/tests/mir-opt/const_prop/slice_len.rs
+++ b/tests/mir-opt/const_prop/slice_len.rs
@@ -1,5 +1,5 @@
 //@ test-mir-pass: GVN
-//@ compile-flags: -Zmir-enable-passes=+InstSimplify -Zdump-mir-exclude-alloc-bytes
+//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg -Zdump-mir-exclude-alloc-bytes
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs
index 5d9733f498c91..64c043cca795b 100644
--- a/tests/mir-opt/dataflow-const-prop/slice_len.rs
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs
@@ -1,6 +1,6 @@
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 //@ test-mir-pass: DataflowConstProp
-//@ compile-flags: -Zmir-enable-passes=+InstSimplify
+//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR slice_len.main.DataflowConstProp.diff
diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff
index 9d5042caae2cb..4e495c37fbc9a 100644
--- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff
@@ -21,14 +21,14 @@
       bb0: {
           StorageLive(_2);
           StorageLive(_3);
-          _3 = &(*_1);
+          _3 = _1;
           _2 = ::cache::(move _3) -> [return: bb1, unwind unreachable];
       }
   
       bb1: {
           StorageDead(_3);
           StorageLive(_4);
-          _4 = &(*_2);
+          _4 = _2;
 -         _0 = try_execute_query::<::C>(move _4) -> [return: bb2, unwind unreachable];
 +         StorageLive(_5);
 +         _5 = _4 as &dyn Cache::V> (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff
index 9bd3855c58f84..7fdb7618212a9 100644
--- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff
@@ -21,14 +21,14 @@
       bb0: {
           StorageLive(_2);
           StorageLive(_3);
-          _3 = &(*_1);
+          _3 = _1;
           _2 = ::cache::(move _3) -> [return: bb1, unwind continue];
       }
   
       bb1: {
           StorageDead(_3);
           StorageLive(_4);
-          _4 = &(*_2);
+          _4 = _2;
 -         _0 = try_execute_query::<::C>(move _4) -> [return: bb2, unwind continue];
 +         StorageLive(_5);
 +         _5 = _4 as &dyn Cache::V> (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff
index d7801b7a0cc22..8df4408690b74 100644
--- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-abort.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           StorageLive(_2);
-          _2 = &(*_1);
+          _2 = _1;
           _0 =  as Cache>::store_nocache(move _2) -> [return: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff
index 7b1cf895a8737..43a0621f766d4 100644
--- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.panic-unwind.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           StorageLive(_2);
-          _2 = &(*_1);
+          _2 = _1;
           _0 =  as Cache>::store_nocache(move _2) -> [return: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff
index 96e16d023ba1b..e72c312f54966 100644
--- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff
@@ -13,7 +13,7 @@
       bb0: {
           StorageLive(_2);
           StorageLive(_3);
-          _3 = &(*_1);
+          _3 = _1;
           _2 = move _3 as &dyn Cache::V> (PointerCoercion(Unsize));
           StorageDead(_3);
 -         _0 = mk_cycle::<::V>(move _2) -> [return: bb1, unwind unreachable];
diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff
index 06d65abcbc125..46728f9e2e659 100644
--- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff
@@ -13,7 +13,7 @@
       bb0: {
           StorageLive(_2);
           StorageLive(_3);
-          _3 = &(*_1);
+          _3 = _1;
           _2 = move _3 as &dyn Cache::V> (PointerCoercion(Unsize));
           StorageDead(_3);
 -         _0 = mk_cycle::<::V>(move _2) -> [return: bb1, unwind continue];
diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
index a6198ca053bc4..f524b054b61bd 100644
--- a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir
@@ -26,9 +26,9 @@ fn foo(_1: T, _2: &i32) -> i32 {
         _4 = &_3;
         StorageLive(_5);
         StorageLive(_6);
-        _6 = &(*_2);
+        _6 = _2;
         StorageLive(_7);
-        _7 = &(*_2);
+        _7 = _2;
         _5 = (move _6, move _7);
         StorageLive(_8);
         _8 = move (_5.0: &i32);
diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
index dcce4aad444af..ec3c79e2a3749 100644
--- a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -31,14 +31,14 @@ fn bar() -> bool {
         StorageLive(_4);
         _10 = const bar::promoted[1];
         Retag(_10);
-        _4 = &(*_10);
-        _3 = &(*_4);
+        _4 = _10;
+        _3 = _4;
         StorageLive(_6);
         StorageLive(_7);
         _9 = const bar::promoted[0];
         Retag(_9);
-        _7 = &(*_9);
-        _6 = &(*_7);
+        _7 = _9;
+        _6 = _7;
         Retag(_3);
         Retag(_6);
         StorageLive(_11);
diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir
index 2441e3f1c2c2f..d7b4302b06d9f 100644
--- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir
+++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-abort.mir
@@ -7,7 +7,7 @@ fn test(_1: &dyn X) -> u32 {
 
     bb0: {
         StorageLive(_2);
-        _2 = &(*_1);
+        _2 = _1;
         _0 = ::y(move _2) -> [return: bb1, unwind unreachable];
     }
 
diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir
index da18a5adc376b..0d6f3e61f71f3 100644
--- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.panic-unwind.mir
@@ -7,7 +7,7 @@ fn test(_1: &dyn X) -> u32 {
 
     bb0: {
         StorageLive(_2);
-        _2 = &(*_1);
+        _2 = _1;
         _0 = ::y(move _2) -> [return: bb1, unwind continue];
     }
 
diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir
index f0d1cfe0359e1..af79c7ce1968a 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir
+++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir
@@ -12,8 +12,8 @@ fn test2(_1: &dyn X) -> bool {
     bb0: {
         StorageLive(_2);
         StorageLive(_3);
-        _3 = &(*_1);
-        _2 = move _3 as &dyn X (PointerCoercion(Unsize));
+        _3 = _1;
+        _2 = move _3;
         StorageDead(_3);
         _0 = ::y(move _2) -> [return: bb1, unwind unreachable];
     }
diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir
index f37b081430137..bf5a56b8e6240 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir
@@ -12,8 +12,8 @@ fn test2(_1: &dyn X) -> bool {
     bb0: {
         StorageLive(_2);
         StorageLive(_3);
-        _3 = &(*_1);
-        _2 = move _3 as &dyn X (PointerCoercion(Unsize));
+        _3 = _1;
+        _2 = move _3;
         StorageDead(_3);
         _0 = ::y(move _2) -> [return: bb1, unwind continue];
     }
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
index 7cc65efe07b4b..8c457037ec971 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir
@@ -14,11 +14,11 @@ fn a(_1: &mut [T]) -> &mut [T] {
         StorageLive(_2);
         StorageLive(_3);
         StorageLive(_4);
-        _4 = &mut (*_1);
+        _4 = _1;
         _3 = _4;
-        _2 = &mut (*_3);
+        _2 = _3;
         StorageDead(_4);
-        _0 = &mut (*_2);
+        _0 = _2;
         StorageDead(_3);
         StorageDead(_2);
         return;
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 408cc5bb3419a..e27d9fe38c7e2 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
@@ -16,7 +16,7 @@ fn b(_1: &mut Box) -> &mut T {
         StorageLive(_2);
         StorageLive(_3);
         StorageLive(_4);
-        _4 = &mut (*_1);
+        _4 = _1;
         StorageLive(_5);
         StorageLive(_6);
         _5 = (*_4);
@@ -24,9 +24,9 @@ fn b(_1: &mut Box) -> &mut T {
         _3 = &mut (*_6);
         StorageDead(_6);
         StorageDead(_5);
-        _2 = &mut (*_3);
+        _2 = _3;
         StorageDead(_4);
-        _0 = &mut (*_2);
+        _0 = _2;
         StorageDead(_3);
         StorageDead(_2);
         return;
diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
index bad7f31ae9b4a..da0464c64d697 100644
--- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
+++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir
@@ -12,9 +12,9 @@ fn c(_1: &[T]) -> &[T] {
     bb0: {
         StorageLive(_2);
         StorageLive(_3);
-        _3 = &(*_1);
+        _3 = _1;
         _2 = _3;
-        _0 = &(*_2);
+        _0 = _2;
         StorageDead(_3);
         StorageDead(_2);
         return;
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 4d20f6c441993..25eaedfc842d2 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
@@ -14,7 +14,7 @@ fn d(_1: &Box) -> &T {
     bb0: {
         StorageLive(_2);
         StorageLive(_3);
-        _3 = &(*_1);
+        _3 = _1;
         StorageLive(_4);
         StorageLive(_5);
         _4 = (*_3);
@@ -22,7 +22,7 @@ fn d(_1: &Box) -> &T {
         _2 = &(*_5);
         StorageDead(_5);
         StorageDead(_4);
-        _0 = &(*_2);
+        _0 = _2;
         StorageDead(_3);
         StorageDead(_2);
         return;
diff --git a/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff
index 5c09963d43344..fea5f4f02ceb9 100644
--- a/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.eq_false.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `eq_false` before InstSimplify
-+ // MIR for `eq_false` after InstSimplify
+- // MIR for `eq_false` before InstSimplify-after-simplifycfg
++ // MIR for `eq_false` after InstSimplify-after-simplifycfg
   
   fn eq_false(_1: bool) -> u32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff
index a80133b0eb097..9a509ccfa67b1 100644
--- a/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.eq_true.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `eq_true` before InstSimplify
-+ // MIR for `eq_true` after InstSimplify
+- // MIR for `eq_true` before InstSimplify-after-simplifycfg
++ // MIR for `eq_true` after InstSimplify-after-simplifycfg
   
   fn eq_true(_1: bool) -> u32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff
index 8235d5263bb1b..e4ec4c80579ed 100644
--- a/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.false_eq.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `false_eq` before InstSimplify
-+ // MIR for `false_eq` after InstSimplify
+- // MIR for `false_eq` before InstSimplify-after-simplifycfg
++ // MIR for `false_eq` after InstSimplify-after-simplifycfg
   
   fn false_eq(_1: bool) -> u32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff
index 77d076c6c14e3..3aea55f4db4f2 100644
--- a/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.false_ne.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `false_ne` before InstSimplify
-+ // MIR for `false_ne` after InstSimplify
+- // MIR for `false_ne` before InstSimplify-after-simplifycfg
++ // MIR for `false_ne` after InstSimplify-after-simplifycfg
   
   fn false_ne(_1: bool) -> u32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff
index 2362b11297ea6..b6e891088a1df 100644
--- a/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.ne_false.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `ne_false` before InstSimplify
-+ // MIR for `ne_false` after InstSimplify
+- // MIR for `ne_false` before InstSimplify-after-simplifycfg
++ // MIR for `ne_false` after InstSimplify-after-simplifycfg
   
   fn ne_false(_1: bool) -> u32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff
index 6ccbd2fb7a1f0..974738bb3a9ee 100644
--- a/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.ne_true.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `ne_true` before InstSimplify
-+ // MIR for `ne_true` after InstSimplify
+- // MIR for `ne_true` before InstSimplify-after-simplifycfg
++ // MIR for `ne_true` after InstSimplify-after-simplifycfg
   
   fn ne_true(_1: bool) -> u32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.rs b/tests/mir-opt/instsimplify/bool_compare.rs
index d1d903f9ef2cf..3911f81fe5cdd 100644
--- a/tests/mir-opt/instsimplify/bool_compare.rs
+++ b/tests/mir-opt/instsimplify/bool_compare.rs
@@ -1,55 +1,55 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 
-// EMIT_MIR bool_compare.eq_true.InstSimplify.diff
+// EMIT_MIR bool_compare.eq_true.InstSimplify-after-simplifycfg.diff
 fn eq_true(x: bool) -> u32 {
     // CHECK-LABEL: fn eq_true(
     // CHECK-NOT: Eq(
     if x == true { 0 } else { 1 }
 }
 
-// EMIT_MIR bool_compare.true_eq.InstSimplify.diff
+// EMIT_MIR bool_compare.true_eq.InstSimplify-after-simplifycfg.diff
 fn true_eq(x: bool) -> u32 {
     // CHECK-LABEL: fn true_eq(
     // CHECK-NOT: Eq(
     if true == x { 0 } else { 1 }
 }
 
-// EMIT_MIR bool_compare.ne_true.InstSimplify.diff
+// EMIT_MIR bool_compare.ne_true.InstSimplify-after-simplifycfg.diff
 fn ne_true(x: bool) -> u32 {
     // CHECK-LABEL: fn ne_true(
     // CHECK: Not(
     if x != true { 0 } else { 1 }
 }
 
-// EMIT_MIR bool_compare.true_ne.InstSimplify.diff
+// EMIT_MIR bool_compare.true_ne.InstSimplify-after-simplifycfg.diff
 fn true_ne(x: bool) -> u32 {
     // CHECK-LABEL: fn true_ne(
     // CHECK: Not(
     if true != x { 0 } else { 1 }
 }
 
-// EMIT_MIR bool_compare.eq_false.InstSimplify.diff
+// EMIT_MIR bool_compare.eq_false.InstSimplify-after-simplifycfg.diff
 fn eq_false(x: bool) -> u32 {
     // CHECK-LABEL: fn eq_false(
     // CHECK: Not(
     if x == false { 0 } else { 1 }
 }
 
-// EMIT_MIR bool_compare.false_eq.InstSimplify.diff
+// EMIT_MIR bool_compare.false_eq.InstSimplify-after-simplifycfg.diff
 fn false_eq(x: bool) -> u32 {
     // CHECK-LABEL: fn false_eq(
     // CHECK: Not(
     if false == x { 0 } else { 1 }
 }
 
-// EMIT_MIR bool_compare.ne_false.InstSimplify.diff
+// EMIT_MIR bool_compare.ne_false.InstSimplify-after-simplifycfg.diff
 fn ne_false(x: bool) -> u32 {
     // CHECK-LABEL: fn ne_false(
     // CHECK-NOT: Ne(
     if x != false { 0 } else { 1 }
 }
 
-// EMIT_MIR bool_compare.false_ne.InstSimplify.diff
+// EMIT_MIR bool_compare.false_ne.InstSimplify-after-simplifycfg.diff
 fn false_ne(x: bool) -> u32 {
     // CHECK-LABEL: fn false_ne(
     // CHECK-NOT: Ne(
diff --git a/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff
index 18675329a2eed..240835bf7f22a 100644
--- a/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.true_eq.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `true_eq` before InstSimplify
-+ // MIR for `true_eq` after InstSimplify
+- // MIR for `true_eq` before InstSimplify-after-simplifycfg
++ // MIR for `true_eq` after InstSimplify-after-simplifycfg
   
   fn true_eq(_1: bool) -> u32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify.diff b/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff
similarity index 83%
rename from tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify.diff
rename to tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff
index dc91cf8a5c41e..1e2b2c27f5707 100644
--- a/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/bool_compare.true_ne.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `true_ne` before InstSimplify
-+ // MIR for `true_ne` after InstSimplify
+- // MIR for `true_ne` before InstSimplify-after-simplifycfg
++ // MIR for `true_ne` after InstSimplify-after-simplifycfg
   
   fn true_ne(_1: bool) -> u32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify.diff b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff
similarity index 85%
rename from tests/mir-opt/instsimplify/casts.redundant.InstSimplify.diff
rename to tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff
index e7451d55777e7..7001589d9e3c8 100644
--- a/tests/mir-opt/instsimplify/casts.redundant.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/casts.redundant.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `redundant` before InstSimplify
-+ // MIR for `redundant` after InstSimplify
+- // MIR for `redundant` before InstSimplify-after-simplifycfg
++ // MIR for `redundant` after InstSimplify-after-simplifycfg
   
   fn redundant(_1: *const &u8) -> *const &u8 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify.diff b/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff
similarity index 82%
rename from tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify.diff
rename to tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff
index e87ac762dfeb2..e1045db973078 100644
--- a/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/casts.roundtrip.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `roundtrip` before InstSimplify
-+ // MIR for `roundtrip` after InstSimplify
+- // MIR for `roundtrip` before InstSimplify-after-simplifycfg
++ // MIR for `roundtrip` after InstSimplify-after-simplifycfg
   
   fn roundtrip(_1: *const u8) -> *const u8 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/casts.rs b/tests/mir-opt/instsimplify/casts.rs
index 15ceea7671363..24dbb67b42d1a 100644
--- a/tests/mir-opt/instsimplify/casts.rs
+++ b/tests/mir-opt/instsimplify/casts.rs
@@ -1,4 +1,4 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 //@ compile-flags: -Zinline-mir
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
@@ -8,7 +8,7 @@ fn generic_cast(x: *const T) -> *const U {
     x as *const U
 }
 
-// EMIT_MIR casts.redundant.InstSimplify.diff
+// EMIT_MIR casts.redundant.InstSimplify-after-simplifycfg.diff
 pub fn redundant<'a, 'b: 'a>(x: *const &'a u8) -> *const &'a u8 {
     // CHECK-LABEL: fn redundant(
     // CHECK: inlined generic_cast
@@ -16,7 +16,7 @@ pub fn redundant<'a, 'b: 'a>(x: *const &'a u8) -> *const &'a u8 {
     generic_cast::<&'a u8, &'b u8>(x) as *const &'a u8
 }
 
-// EMIT_MIR casts.roundtrip.InstSimplify.diff
+// EMIT_MIR casts.roundtrip.InstSimplify-after-simplifycfg.diff
 pub fn roundtrip(x: *const u8) -> *const u8 {
     // CHECK-LABEL: fn roundtrip(
     // CHECK: _4 = _1;
@@ -25,7 +25,7 @@ pub fn roundtrip(x: *const u8) -> *const u8 {
     x as *mut u8 as *const u8
 }
 
-// EMIT_MIR casts.roundtrip.InstSimplify.diff
+// EMIT_MIR casts.roundtrip.InstSimplify-after-simplifycfg.diff
 pub fn cast_thin_via_aggregate(x: *const u8) -> *const () {
     // CHECK-LABEL: fn cast_thin_via_aggregate(
     // CHECK: _2 = _1;
diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-abort.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
similarity index 94%
rename from tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-abort.diff
rename to tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
index 3e7d0ce51e2eb..a7de09ca38682 100644
--- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-abort.diff
+++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-abort.diff
@@ -1,5 +1,5 @@
-- // MIR for `norm2` before InstSimplify
-+ // MIR for `norm2` after InstSimplify
+- // MIR for `norm2` before InstSimplify-after-simplifycfg
++ // MIR for `norm2` after InstSimplify-after-simplifycfg
   
   fn norm2(_1: [f32; 2]) -> f32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
similarity index 94%
rename from tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-unwind.diff
rename to tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
index 4833c1089e3c5..c15f7e47fe36f 100644
--- a/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify.panic-unwind.diff
+++ b/tests/mir-opt/instsimplify/combine_array_len.norm2.InstSimplify-after-simplifycfg.panic-unwind.diff
@@ -1,5 +1,5 @@
-- // MIR for `norm2` before InstSimplify
-+ // MIR for `norm2` after InstSimplify
+- // MIR for `norm2` before InstSimplify-after-simplifycfg
++ // MIR for `norm2` after InstSimplify-after-simplifycfg
   
   fn norm2(_1: [f32; 2]) -> f32 {
       debug x => _1;
diff --git a/tests/mir-opt/instsimplify/combine_array_len.rs b/tests/mir-opt/instsimplify/combine_array_len.rs
index f12284f648210..91f43f75689de 100644
--- a/tests/mir-opt/instsimplify/combine_array_len.rs
+++ b/tests/mir-opt/instsimplify/combine_array_len.rs
@@ -1,7 +1,7 @@
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 
-// EMIT_MIR combine_array_len.norm2.InstSimplify.diff
+// EMIT_MIR combine_array_len.norm2.InstSimplify-after-simplifycfg.diff
 fn norm2(x: [f32; 2]) -> f32 {
     // CHECK-LABEL: fn norm2(
     // CHECK-NOT: Len(
diff --git a/tests/mir-opt/instsimplify/combine_clone_of_primitives.rs b/tests/mir-opt/instsimplify/combine_clone_of_primitives.rs
index 7b1f3d14f4fd9..4f7288333d1a8 100644
--- a/tests/mir-opt/instsimplify/combine_clone_of_primitives.rs
+++ b/tests/mir-opt/instsimplify/combine_clone_of_primitives.rs
@@ -1,7 +1,7 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
-// EMIT_MIR combine_clone_of_primitives.{impl#0}-clone.InstSimplify.diff
+// EMIT_MIR combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.diff
 #[derive(Clone)]
 struct MyThing {
     v: T,
diff --git a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-abort.diff b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff
similarity index 94%
rename from tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-abort.diff
rename to tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff
index 48586f8b3349a..c6f858d89eb2c 100644
--- a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-abort.diff
+++ b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-abort.diff
@@ -1,5 +1,5 @@
-- // MIR for `::clone` before InstSimplify
-+ // MIR for `::clone` after InstSimplify
+- // MIR for `::clone` before InstSimplify-after-simplifycfg
++ // MIR for `::clone` after InstSimplify-after-simplifycfg
   
   fn ::clone(_1: &MyThing) -> MyThing {
       debug self => _1;
diff --git a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff
similarity index 94%
rename from tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff
rename to tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff
index a57266e9c1226..691ab1f0e7fb7 100644
--- a/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify.panic-unwind.diff
+++ b/tests/mir-opt/instsimplify/combine_clone_of_primitives.{impl#0}-clone.InstSimplify-after-simplifycfg.panic-unwind.diff
@@ -1,5 +1,5 @@
-- // MIR for `::clone` before InstSimplify
-+ // MIR for `::clone` after InstSimplify
+- // MIR for `::clone` before InstSimplify-after-simplifycfg
++ // MIR for `::clone` after InstSimplify-after-simplifycfg
   
   fn ::clone(_1: &MyThing) -> MyThing {
       debug self => _1;
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
similarity index 94%
rename from tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
rename to tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
index 17730e66291c1..9844aa2a64e26 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `adt_transmutes` before InstSimplify
-+ // MIR for `adt_transmutes` after InstSimplify
+- // MIR for `adt_transmutes` before InstSimplify-after-simplifycfg
++ // MIR for `adt_transmutes` after InstSimplify-after-simplifycfg
   
   fn adt_transmutes() -> () {
       let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff
similarity index 85%
rename from tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify.diff
rename to tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff
index 58ae5919071af..589f7159b9bd2 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `identity_transmutes` before InstSimplify
-+ // MIR for `identity_transmutes` after InstSimplify
+- // MIR for `identity_transmutes` before InstSimplify-after-simplifycfg
++ // MIR for `identity_transmutes` after InstSimplify-after-simplifycfg
   
   fn identity_transmutes() -> () {
       let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff
similarity index 80%
rename from tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify.diff
rename to tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff
index 8eff802dd3c4b..b7baa89dc809d 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `integer_transmutes` before InstSimplify
-+ // MIR for `integer_transmutes` after InstSimplify
+- // MIR for `integer_transmutes` before InstSimplify-after-simplifycfg
++ // MIR for `integer_transmutes` after InstSimplify-after-simplifycfg
   
   fn integer_transmutes() -> () {
       let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.rs b/tests/mir-opt/instsimplify/combine_transmutes.rs
index c3622c20697a5..23f10b71f3c1b 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.rs
+++ b/tests/mir-opt/instsimplify/combine_transmutes.rs
@@ -1,4 +1,4 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 //@ compile-flags: -C panic=abort
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
@@ -7,7 +7,7 @@
 use std::intrinsics::mir::*;
 use std::mem::{transmute, ManuallyDrop, MaybeUninit};
 
-// EMIT_MIR combine_transmutes.identity_transmutes.InstSimplify.diff
+// EMIT_MIR combine_transmutes.identity_transmutes.InstSimplify-after-simplifycfg.diff
 pub unsafe fn identity_transmutes() {
     // CHECK-LABEL: fn identity_transmutes(
     // CHECK-NOT: as i32 (Transmute);
@@ -19,7 +19,7 @@ pub unsafe fn identity_transmutes() {
 }
 
 #[custom_mir(dialect = "runtime", phase = "initial")]
-// EMIT_MIR combine_transmutes.integer_transmutes.InstSimplify.diff
+// EMIT_MIR combine_transmutes.integer_transmutes.InstSimplify-after-simplifycfg.diff
 pub unsafe fn integer_transmutes() {
     // CHECK-LABEL: fn integer_transmutes(
     // CHECK-NOT: _i32 as u32 (Transmute);
@@ -43,7 +43,7 @@ pub unsafe fn integer_transmutes() {
     }
 }
 
-// EMIT_MIR combine_transmutes.adt_transmutes.InstSimplify.diff
+// EMIT_MIR combine_transmutes.adt_transmutes.InstSimplify-after-simplifycfg.diff
 pub unsafe fn adt_transmutes() {
     // CHECK-LABEL: fn adt_transmutes(
     // CHECK: as u8 (Transmute);
diff --git a/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify.diff b/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff
similarity index 70%
rename from tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify.diff
rename to tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff
index e2b45c882d6f3..7596aa203086e 100644
--- a/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `assert_zero` before InstSimplify
-+ // MIR for `assert_zero` after InstSimplify
+- // MIR for `assert_zero` before InstSimplify-after-simplifycfg
++ // MIR for `assert_zero` after InstSimplify-after-simplifycfg
   
   fn assert_zero(_1: u8) -> u8 {
       let mut _0: u8;
diff --git a/tests/mir-opt/instsimplify/duplicate_switch_targets.rs b/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
index a47d9d5a71d7a..d610ba5f6904e 100644
--- a/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
+++ b/tests/mir-opt/instsimplify/duplicate_switch_targets.rs
@@ -1,11 +1,11 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 
 #![feature(custom_mir, core_intrinsics)]
 #![crate_type = "lib"]
 
 use std::intrinsics::mir::*;
 
-// EMIT_MIR duplicate_switch_targets.assert_zero.InstSimplify.diff
+// EMIT_MIR duplicate_switch_targets.assert_zero.InstSimplify-after-simplifycfg.diff
 #[custom_mir(dialect = "runtime", phase = "post-cleanup")]
 pub unsafe fn assert_zero(x: u8) -> u8 {
     // CHECK-LABEL: fn assert_zero(
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify.diff b/tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff
similarity index 84%
rename from tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify.diff
rename to tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff
index 2ecacb5e39f47..d35844b21d160 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `generic` before InstSimplify
-+ // MIR for `generic` after InstSimplify
+- // MIR for `generic` before InstSimplify-after-simplifycfg
++ // MIR for `generic` after InstSimplify-after-simplifycfg
   
   fn generic() -> () {
       let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify.diff b/tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff
similarity index 70%
rename from tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify.diff
rename to tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff
index d29af0945f7dc..6ddd8481ca733 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `generic_ref` before InstSimplify
-+ // MIR for `generic_ref` after InstSimplify
+- // MIR for `generic_ref` before InstSimplify-after-simplifycfg
++ // MIR for `generic_ref` after InstSimplify-after-simplifycfg
   
   fn generic_ref() -> () {
       let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify.diff b/tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff
similarity index 87%
rename from tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify.diff
rename to tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff
index 1be386acfccab..1b7aa124c36e1 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `panics` before InstSimplify
-+ // MIR for `panics` after InstSimplify
+- // MIR for `panics` before InstSimplify-after-simplifycfg
++ // MIR for `panics` after InstSimplify-after-simplifycfg
   
   fn panics() -> () {
       let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify.diff b/tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff
similarity index 85%
rename from tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify.diff
rename to tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff
index f2e6978384205..20e046d8e194b 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `removable` before InstSimplify
-+ // MIR for `removable` after InstSimplify
+- // MIR for `removable` before InstSimplify-after-simplifycfg
++ // MIR for `removable` after InstSimplify-after-simplifycfg
   
   fn removable() -> () {
       let mut _0: ();
diff --git a/tests/mir-opt/instsimplify/intrinsic_asserts.rs b/tests/mir-opt/instsimplify/intrinsic_asserts.rs
index c031c97816261..c71e08b9f1f75 100644
--- a/tests/mir-opt/instsimplify/intrinsic_asserts.rs
+++ b/tests/mir-opt/instsimplify/intrinsic_asserts.rs
@@ -1,10 +1,10 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
 
 // All these assertions pass, so all the intrinsic calls should be deleted.
-// EMIT_MIR intrinsic_asserts.removable.InstSimplify.diff
+// EMIT_MIR intrinsic_asserts.removable.InstSimplify-after-simplifycfg.diff
 pub fn removable() {
     // CHECK-LABEL: fn removable(
     // CHECK-NOT: assert_inhabited
@@ -18,7 +18,7 @@ pub fn removable() {
 enum Never {}
 
 // These assertions all diverge, so their target blocks should become None.
-// EMIT_MIR intrinsic_asserts.panics.InstSimplify.diff
+// EMIT_MIR intrinsic_asserts.panics.InstSimplify-after-simplifycfg.diff
 pub fn panics() {
     // CHECK-LABEL: fn panics(
     // CHECK: assert_inhabited::() -> unwind
@@ -30,7 +30,7 @@ pub fn panics() {
 }
 
 // Whether or not these asserts pass isn't known, so they shouldn't be modified.
-// EMIT_MIR intrinsic_asserts.generic.InstSimplify.diff
+// EMIT_MIR intrinsic_asserts.generic.InstSimplify-after-simplifycfg.diff
 pub fn generic() {
     // CHECK-LABEL: fn generic(
     // CHECK: assert_inhabited::() -> [return:
@@ -42,7 +42,7 @@ pub fn generic() {
 }
 
 // Whether or not these asserts pass isn't known, so they shouldn't be modified.
-// EMIT_MIR intrinsic_asserts.generic_ref.InstSimplify.diff
+// EMIT_MIR intrinsic_asserts.generic_ref.InstSimplify-after-simplifycfg.diff
 pub fn generic_ref() {
     // CHECK-LABEL: fn generic_ref(
     // CHECK: assert_mem_uninitialized_valid::<&T>() -> [return:
diff --git a/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff b/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff
similarity index 92%
rename from tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff
rename to tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff
index 52b3d1e1d40b3..ca26f0240f9de 100644
--- a/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `pointers` before InstSimplify
-+ // MIR for `pointers` after InstSimplify
+- // MIR for `pointers` before InstSimplify-after-simplifycfg
++ // MIR for `pointers` after InstSimplify-after-simplifycfg
   
   fn pointers(_1: *const [i32], _2: *mut i32) -> () {
       debug const_ptr => _1;
diff --git a/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff b/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff
similarity index 91%
rename from tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff
rename to tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff
index ca0828a225a01..928ee3acaa028 100644
--- a/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/ref_of_deref.references.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `references` before InstSimplify
-+ // MIR for `references` after InstSimplify
+- // MIR for `references` before InstSimplify-after-simplifycfg
++ // MIR for `references` after InstSimplify-after-simplifycfg
   
   fn references(_1: &i32, _2: &mut [i32]) -> () {
       debug const_ref => _1;
diff --git a/tests/mir-opt/instsimplify/ref_of_deref.rs b/tests/mir-opt/instsimplify/ref_of_deref.rs
index 37e164bc17f18..dc0f5f8198bc7 100644
--- a/tests/mir-opt/instsimplify/ref_of_deref.rs
+++ b/tests/mir-opt/instsimplify/ref_of_deref.rs
@@ -1,11 +1,11 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 #![crate_type = "lib"]
 #![feature(raw_ref_op)]
 
 // For each of these, only 2 of the 6 should simplify,
 // as the others have the wrong types.
 
-// EMIT_MIR ref_of_deref.references.InstSimplify.diff
+// EMIT_MIR ref_of_deref.references.InstSimplify-after-simplifycfg.diff
 // CHECK-LABEL: references
 pub fn references(const_ref: &i32, mut_ref: &mut [i32]) {
     // CHECK: _3 = _1;
@@ -22,7 +22,7 @@ pub fn references(const_ref: &i32, mut_ref: &mut [i32]) {
     let _f = &raw mut *mut_ref;
 }
 
-// EMIT_MIR ref_of_deref.pointers.InstSimplify.diff
+// EMIT_MIR ref_of_deref.pointers.InstSimplify-after-simplifycfg.diff
 // CHECK-LABEL: pointers
 pub unsafe fn pointers(const_ptr: *const [i32], mut_ptr: *mut i32) {
     // CHECK: _3 = &(*_1);
diff --git a/tests/mir-opt/instsimplify/ub_check.rs b/tests/mir-opt/instsimplify/ub_check.rs
index 5f13f5ba059b5..ee72511c132de 100644
--- a/tests/mir-opt/instsimplify/ub_check.rs
+++ b/tests/mir-opt/instsimplify/ub_check.rs
@@ -1,7 +1,7 @@
-//@ test-mir-pass: InstSimplify
+//@ test-mir-pass: InstSimplify-after-simplifycfg
 //@ compile-flags: -Cdebug-assertions=no -Zinline-mir
 
-// EMIT_MIR ub_check.unwrap_unchecked.InstSimplify.diff
+// EMIT_MIR ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
 pub fn unwrap_unchecked(x: Option) -> i32 {
     // CHECK-LABEL: fn unwrap_unchecked(
     // CHECK-NOT: UbChecks()
diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
similarity index 90%
rename from tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff
rename to tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
index 4d8d658984235..7ef77e76d1297 100644
--- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `unwrap_unchecked` before InstSimplify
-+ // MIR for `unwrap_unchecked` after InstSimplify
+- // MIR for `unwrap_unchecked` before InstSimplify-after-simplifycfg
++ // MIR for `unwrap_unchecked` after InstSimplify-after-simplifycfg
   
   fn unwrap_unchecked(_1: Option) -> i32 {
       debug x => _1;
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
index 1f88339b5861b..861ee1d3d3d46 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
@@ -5,7 +5,7 @@
       debug x => _1;
       let mut _0: ();
       let _2: &[T];
-      let mut _3: &[T; 3];
+      let _3: &[T; 3];
       let _4: [T; 3];
       let mut _5: usize;
       let mut _6: bool;
@@ -23,12 +23,10 @@
       }
   
       bb0: {
-          StorageLive(_3);
           StorageLive(_4);
           _4 = [_1, _1, _1];
           _3 = &_4;
-          _2 = move _3 as &[T] (PointerCoercion(Unsize));
-          StorageDead(_3);
+          _2 = _3 as &[T] (PointerCoercion(Unsize));
           nop;
           nop;
           goto -> bb2;
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
index 19a581ba3f096..f27be95338479 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
@@ -5,7 +5,7 @@
       debug x => _1;
       let mut _0: ();
       let _2: &[T];
-      let mut _3: &[T; 3];
+      let _3: &[T; 3];
       let _4: [T; 3];
       let mut _5: usize;
       let mut _6: bool;
@@ -23,12 +23,10 @@
       }
   
       bb0: {
-          StorageLive(_3);
           StorageLive(_4);
           _4 = [_1, _1, _1];
           _3 = &_4;
-          _2 = move _3 as &[T] (PointerCoercion(Unsize));
-          StorageDead(_3);
+          _2 = _3 as &[T] (PointerCoercion(Unsize));
           nop;
           nop;
           goto -> bb2;
diff --git a/tests/mir-opt/issue_78192.f.InstSimplify.diff b/tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff
similarity index 79%
rename from tests/mir-opt/issue_78192.f.InstSimplify.diff
rename to tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff
index 10e3dd2036202..53957bb3cb193 100644
--- a/tests/mir-opt/issue_78192.f.InstSimplify.diff
+++ b/tests/mir-opt/issue_78192.f.InstSimplify-after-simplifycfg.diff
@@ -1,5 +1,5 @@
-- // MIR for `f` before InstSimplify
-+ // MIR for `f` after InstSimplify
+- // MIR for `f` before InstSimplify-after-simplifycfg
++ // MIR for `f` after InstSimplify-after-simplifycfg
   
   fn f(_1: &T) -> *const T {
       debug a => _1;
@@ -17,8 +17,7 @@
           StorageLive(_4);
           _4 = &raw const (*_1);
           _3 = &_4;
--         _2 = &(*_3);
-+         _2 = _3;
+          _2 = _3;
           StorageDead(_3);
           _0 = (*_2);
           StorageDead(_4);
diff --git a/tests/mir-opt/issue_78192.rs b/tests/mir-opt/issue_78192.rs
index 857b1dec951e5..a82f0e3a6653a 100644
--- a/tests/mir-opt/issue_78192.rs
+++ b/tests/mir-opt/issue_78192.rs
@@ -9,4 +9,4 @@ fn main() {
     f(&2);
 }
 
-// EMIT_MIR issue_78192.f.InstSimplify.diff
+// EMIT_MIR issue_78192.f.InstSimplify-after-simplifycfg.diff
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
index 465cb1a9b1f41..959efa2a54870 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
@@ -24,7 +24,7 @@
               let _13: std::alloc::AllocError;
               let mut _14: !;
               let mut _15: &dyn std::fmt::Debug;
-              let mut _16: &std::alloc::AllocError;
+              let _16: &std::alloc::AllocError;
               scope 7 {
               }
               scope 8 {
@@ -86,21 +86,21 @@
           StorageDead(_8);
           StorageDead(_7);
           StorageLive(_12);
+          StorageLive(_16);
           _12 = discriminant(_6);
           switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
       bb5: {
           StorageLive(_15);
-          StorageLive(_16);
           _16 = &_13;
-          _15 = move _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
-          StorageDead(_16);
+          _15 = _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
           _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable;
       }
   
       bb6: {
           _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
+          StorageDead(_16);
           StorageDead(_12);
           StorageDead(_6);
 -         StorageLive(_17);
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
index 925d8997b8a55..97f5245a8c927 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
@@ -24,7 +24,7 @@
               let _13: std::alloc::AllocError;
               let mut _14: !;
               let mut _15: &dyn std::fmt::Debug;
-              let mut _16: &std::alloc::AllocError;
+              let _16: &std::alloc::AllocError;
               scope 7 {
               }
               scope 8 {
@@ -86,21 +86,21 @@
           StorageDead(_8);
           StorageDead(_7);
           StorageLive(_12);
+          StorageLive(_16);
           _12 = discriminant(_6);
           switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb1];
       }
   
       bb5: {
           StorageLive(_15);
-          StorageLive(_16);
           _16 = &_13;
-          _15 = move _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
-          StorageDead(_16);
+          _15 = _16 as &dyn std::fmt::Debug (PointerCoercion(Unsize));
           _14 = result::unwrap_failed(const "called `Result::unwrap()` on an `Err` value", move _15) -> unwind unreachable;
       }
   
       bb6: {
           _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>);
+          StorageDead(_16);
           StorageDead(_12);
           StorageDead(_6);
 -         StorageLive(_17);
diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir
index cb29473d7627f..e537dd6a28ef8 100644
--- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir
@@ -30,13 +30,11 @@ fn vec_move(_1: Vec) -> () {
 
     bb2: {
         StorageLive(_5);
-        StorageLive(_4);
         _4 = &mut _3;
         _5 =  as Iterator>::next(move _4) -> [return: bb3, unwind: bb9];
     }
 
     bb3: {
-        StorageDead(_4);
         _6 = discriminant(_5);
         switchInt(move _6) -> [0: bb4, 1: bb6, otherwise: bb8];
     }
diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.rs b/tests/mir-opt/pre-codegen/no_inlined_clone.rs
new file mode 100644
index 0000000000000..475b230b46525
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/no_inlined_clone.rs
@@ -0,0 +1,12 @@
+#![crate_type = "lib"]
+
+// EMIT_MIR no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir
+
+// CHECK-LABEL: ::clone(
+// CHECK-NOT: inlined clone::impls::::clone
+// CHECK: return;
+
+#[derive(Clone)]
+struct Foo {
+    a: i32,
+}
diff --git a/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir
new file mode 100644
index 0000000000000..71898daa1bfa2
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/no_inlined_clone.{impl#0}-clone.PreCodegen.after.mir
@@ -0,0 +1,15 @@
+// MIR for `::clone` after PreCodegen
+
+fn ::clone(_1: &Foo) -> Foo {
+    debug self => _1;
+    let mut _0: Foo;
+    let mut _2: i32;
+
+    bb0: {
+        StorageLive(_2);
+        _2 = ((*_1).0: i32);
+        _0 = Foo { a: move _2 };
+        StorageDead(_2);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
index 802bfbbcdc5fa..c01a12eaa4f2c 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
@@ -37,7 +37,7 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = Len(_4);
+          _6 = const 6_usize;
           _7 = Lt(_5, _6);
           assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind unreachable];
       }
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
index de94a55740318..64028e4437be3 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
@@ -37,7 +37,7 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = Len(_4);
+          _6 = const 6_usize;
           _7 = Lt(_5, _6);
           assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue];
       }
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
index 802bfbbcdc5fa..c01a12eaa4f2c 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
@@ -37,7 +37,7 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = Len(_4);
+          _6 = const 6_usize;
           _7 = Lt(_5, _6);
           assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind unreachable];
       }
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
index de94a55740318..64028e4437be3 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
@@ -37,7 +37,7 @@
           _4 = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32];
           StorageLive(_5);
           _5 = const 3_usize;
-          _6 = Len(_4);
+          _6 = const 6_usize;
           _7 = Lt(_5, _6);
           assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> [success: bb2, unwind continue];
       }
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
index ce79a33013d95..a7fe52d8390e9 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
@@ -36,13 +36,11 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
 
     bb1: {
         StorageLive(_7);
-        StorageLive(_6);
         _6 = &mut _5;
         _7 =  as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
     }
 
     bb2: {
-        StorageDead(_6);
         _8 = discriminant(_7);
         switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7];
     }
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
index 602ecb7c9b835..3e2bbcd3c916f 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
@@ -36,13 +36,11 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
 
     bb1: {
         StorageLive(_7);
-        StorageLive(_6);
         _6 = &mut _5;
         _7 =  as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
     }
 
     bb2: {
-        StorageDead(_6);
         _8 = discriminant(_7);
         switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7];
     }
diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
index dfa13230254c9..e382f744723eb 100644
--- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
@@ -32,7 +32,7 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
             debug other => _10;
             scope 3 (inlined std::cmp::impls::::le) {
                 debug self => _4;
-                debug other => _9;
+                debug other => _6;
                 let mut _11: usize;
                 let mut _12: usize;
             }
@@ -42,7 +42,7 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
             debug other => _16;
             scope 5 (inlined std::cmp::impls::::le) {
                 debug self => _7;
-                debug other => _15;
+                debug other => _5;
                 let mut _17: usize;
                 let mut _18: usize;
             }
@@ -52,7 +52,7 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
             debug other => _22;
             scope 7 (inlined std::cmp::impls::::le) {
                 debug self => _6;
-                debug other => _21;
+                debug other => _4;
             }
         }
         scope 8 (inlined std::cmp::impls::::le) {
@@ -60,7 +60,7 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
             debug other => _26;
             scope 9 (inlined std::cmp::impls::::le) {
                 debug self => _5;
-                debug other => _25;
+                debug other => _7;
                 let mut _27: usize;
                 let mut _28: usize;
             }
@@ -77,7 +77,8 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         StorageLive(_8);
         _8 = &_4;
         StorageLive(_10);
-        _9 = &((*_3).2: usize);
+        StorageLive(_9);
+        _9 = _6;
         _10 = &_9;
         _11 = ((*_3).0: usize);
         _12 = ((*_3).2: usize);
@@ -86,19 +87,22 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
     }
 
     bb1: {
+        StorageDead(_9);
         StorageDead(_10);
         StorageDead(_8);
         goto -> bb4;
     }
 
     bb2: {
+        StorageDead(_9);
         StorageDead(_10);
         StorageDead(_8);
         StorageLive(_19);
         StorageLive(_14);
         _14 = &_7;
         StorageLive(_16);
-        _15 = &((*_3).1: usize);
+        StorageLive(_15);
+        _15 = _5;
         _16 = &_15;
         StorageLive(_17);
         _17 = ((*_3).3: usize);
@@ -111,6 +115,7 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
     }
 
     bb3: {
+        StorageDead(_15);
         StorageDead(_16);
         StorageDead(_14);
         goto -> bb4;
@@ -121,13 +126,15 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         StorageLive(_20);
         _20 = &_6;
         StorageLive(_22);
-        _21 = &((*_3).0: usize);
+        StorageLive(_21);
+        _21 = _4;
         _22 = &_21;
         _23 = Le(_12, _11);
         switchInt(move _23) -> [0: bb5, otherwise: bb6];
     }
 
     bb5: {
+        StorageDead(_21);
         StorageDead(_22);
         StorageDead(_20);
         _0 = const false;
@@ -135,12 +142,14 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
     }
 
     bb6: {
+        StorageDead(_21);
         StorageDead(_22);
         StorageDead(_20);
         StorageLive(_24);
         _24 = &_5;
         StorageLive(_26);
-        _25 = &((*_3).3: usize);
+        StorageLive(_25);
+        _25 = _7;
         _26 = &_25;
         StorageLive(_27);
         _27 = ((*_3).1: usize);
@@ -149,6 +158,7 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         _0 = Le(move _27, move _28);
         StorageDead(_28);
         StorageDead(_27);
+        StorageDead(_25);
         StorageDead(_26);
         StorageDead(_24);
         goto -> bb7;
@@ -160,6 +170,7 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
     }
 
     bb8: {
+        StorageDead(_15);
         StorageDead(_16);
         StorageDead(_14);
         _0 = const true;
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
index d7f09fafeebe7..58e9b45a4a0f1 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
@@ -20,7 +20,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
     }
 
     bb0: {
-        StorageLive(_7);
+        StorageLive(_8);
         StorageLive(_4);
         StorageLive(_3);
         _3 = PtrMetadata(_1);
@@ -36,7 +36,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
 
     bb2: {
         StorageDead(_3);
-        StorageLive(_8);
+        StorageLive(_7);
         StorageLive(_5);
         _5 = &raw mut (*_1);
         StorageLive(_6);
@@ -45,14 +45,14 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
         StorageDead(_6);
         StorageDead(_5);
         _8 = &mut (*_7);
-        _0 = Option::<&mut u32>::Some(move _8);
-        StorageDead(_8);
+        _0 = Option::<&mut u32>::Some(_8);
+        StorageDead(_7);
         goto -> bb3;
     }
 
     bb3: {
         StorageDead(_4);
-        StorageDead(_7);
+        StorageDead(_8);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
index d7f09fafeebe7..58e9b45a4a0f1 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
@@ -20,7 +20,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
     }
 
     bb0: {
-        StorageLive(_7);
+        StorageLive(_8);
         StorageLive(_4);
         StorageLive(_3);
         _3 = PtrMetadata(_1);
@@ -36,7 +36,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
 
     bb2: {
         StorageDead(_3);
-        StorageLive(_8);
+        StorageLive(_7);
         StorageLive(_5);
         _5 = &raw mut (*_1);
         StorageLive(_6);
@@ -45,14 +45,14 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
         StorageDead(_6);
         StorageDead(_5);
         _8 = &mut (*_7);
-        _0 = Option::<&mut u32>::Some(move _8);
-        StorageDead(_8);
+        _0 = Option::<&mut u32>::Some(_8);
+        StorageDead(_7);
         goto -> bb3;
     }
 
     bb3: {
         StorageDead(_4);
-        StorageDead(_7);
+        StorageDead(_8);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
index 2f13cfa4dab62..ee80726a675c8 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
@@ -35,6 +35,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) ->
     bb0: {
         _3 = move (_2.0: usize);
         _4 = move (_2.1: usize);
+        StorageLive(_11);
         StorageLive(_5);
         _5 = &raw mut (*_1);
         StorageLive(_8);
@@ -56,6 +57,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) ->
         StorageDead(_8);
         StorageDead(_5);
         _0 = &mut (*_11);
+        StorageDead(_11);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
index 2f13cfa4dab62..ee80726a675c8 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
@@ -35,6 +35,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) ->
     bb0: {
         _3 = move (_2.0: usize);
         _4 = move (_2.1: usize);
+        StorageLive(_11);
         StorageLive(_5);
         _5 = &raw mut (*_1);
         StorageLive(_8);
@@ -56,6 +57,7 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) ->
         StorageDead(_8);
         StorageDead(_5);
         _0 = &mut (*_11);
+        StorageDead(_11);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index d5fdb2e08cc16..4c766c6497a2e 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -108,13 +108,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
 
     bb4: {
         StorageLive(_15);
-        StorageLive(_14);
         _14 = &mut _13;
         _15 = > as Iterator>::next(move _14) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_14);
         _16 = discriminant(_15);
         switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index cc2beac06f23c..03de9fd938ec4 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -98,13 +98,11 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
 
     bb4: {
         StorageLive(_14);
-        StorageLive(_13);
         _13 = &mut _12;
         _14 =  as Iterator>::next(move _13) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_13);
         _15 = discriminant(_14);
         switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index d66edb28570fc..c7c722274f24e 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -98,13 +98,11 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
 
     bb4: {
         StorageLive(_14);
-        StorageLive(_13);
         _13 = &mut _12;
         _14 =  as Iterator>::next(move _13) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_13);
         _15 = discriminant(_14);
         switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir
index 485dc9179cef0..c76e5315db9f6 100644
--- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir
@@ -3,16 +3,14 @@
 fn outer(_1: u8) -> u8 {
     debug v => _1;                       // in scope 0 at $DIR/spans.rs:10:14: 10:15
     let mut _0: u8;                      // return place in scope 0 at $DIR/spans.rs:10:24: 10:26
-    let mut _2: &u8;                     // in scope 0 at $DIR/spans.rs:11:11: 11:13
+    let _2: &u8;                         // in scope 0 at $DIR/spans.rs:11:11: 11:13
     scope 1 (inlined inner) {            // at $DIR/spans.rs:11:5: 11:14
         debug x => _2;                   // in scope 1 at $DIR/spans.rs:14:14: 14:15
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/spans.rs:11:11: 11:13
         _2 = &_1;                        // scope 0 at $DIR/spans.rs:11:11: 11:13
         _0 = _1;                         // scope 1 at $DIR/spans.rs:15:5: 15:7
-        StorageDead(_2);                 // scope 0 at $DIR/spans.rs:11:13: 11:14
         return;                          // scope 0 at $DIR/spans.rs:12:2: 12:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir
index 485dc9179cef0..c76e5315db9f6 100644
--- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir
@@ -3,16 +3,14 @@
 fn outer(_1: u8) -> u8 {
     debug v => _1;                       // in scope 0 at $DIR/spans.rs:10:14: 10:15
     let mut _0: u8;                      // return place in scope 0 at $DIR/spans.rs:10:24: 10:26
-    let mut _2: &u8;                     // in scope 0 at $DIR/spans.rs:11:11: 11:13
+    let _2: &u8;                         // in scope 0 at $DIR/spans.rs:11:11: 11:13
     scope 1 (inlined inner) {            // at $DIR/spans.rs:11:5: 11:14
         debug x => _2;                   // in scope 1 at $DIR/spans.rs:14:14: 14:15
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/spans.rs:11:11: 11:13
         _2 = &_1;                        // scope 0 at $DIR/spans.rs:11:11: 11:13
         _0 = _1;                         // scope 1 at $DIR/spans.rs:15:5: 15:7
-        StorageDead(_2);                 // scope 0 at $DIR/spans.rs:11:13: 11:14
         return;                          // scope 0 at $DIR/spans.rs:12:2: 12:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
index 1c9ed25d7f2b2..14ad951a47662 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir
@@ -56,10 +56,12 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] {
         StorageDead(_2);
         StorageLive(_5);
         _5 = ((*_1).1: usize);
+        StorageLive(_6);
         _6 = *const [u8] from (_4, _5);
+        _0 = &(*_6);
+        StorageDead(_6);
         StorageDead(_5);
         StorageDead(_4);
-        _0 = &(*_6);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
index 1c9ed25d7f2b2..14ad951a47662 100644
--- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir
@@ -56,10 +56,12 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] {
         StorageDead(_2);
         StorageLive(_5);
         _5 = ((*_1).1: usize);
+        StorageLive(_6);
         _6 = *const [u8] from (_4, _5);
+        _0 = &(*_6);
+        StorageDead(_6);
         StorageDead(_5);
         StorageDead(_4);
-        _0 = &(*_6);
         return;
     }
 }

From 051cc2d7682ad417e3443e3aa9ecd06a7fbf2a08 Mon Sep 17 00:00:00 2001
From: Oli Scherer 
Date: Mon, 29 Jul 2024 10:17:56 +0000
Subject: [PATCH 218/489] Make field private. It is not used outside the module
 and it should not be directly accessed anyway

---
 src/tools/miri/src/shims/unix/fd.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 0fffecd99d5cb..d6399489c9b9f 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -213,7 +213,7 @@ impl FileDescriptor {
 /// The file descriptor table
 #[derive(Debug)]
 pub struct FdTable {
-    pub fds: BTreeMap,
+    fds: BTreeMap,
 }
 
 impl VisitProvenance for FdTable {

From 8a5efd1456f9966a5aab8100c0b401aceb31451f Mon Sep 17 00:00:00 2001
From: Bryanskiy 
Date: Mon, 29 Jul 2024 14:03:20 +0300
Subject: [PATCH 219/489] Use Vec in instantiate_binder_with_fresh_vars

---
 compiler/rustc_infer/src/infer/mod.rs | 46 +++++++++++++--------------
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 16bdd8db376e7..f2fc25a2d2e10 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -13,7 +13,7 @@ use region_constraints::{
 pub use relate::combine::{CombineFields, PredicateEmittingRelation};
 pub use relate::StructurallyRelateAliases;
 use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::undo_log::Rollback;
 use rustc_data_structures::unify as ut;
@@ -1318,38 +1318,36 @@ impl<'tcx> InferCtxt<'tcx> {
             return inner;
         }
 
-        struct ToFreshVars<'a, 'tcx> {
-            infcx: &'a InferCtxt<'tcx>,
-            span: Span,
-            lbrct: BoundRegionConversionTime,
-            map: FxHashMap>,
+        let bound_vars = value.bound_vars();
+        let mut args = Vec::with_capacity(bound_vars.len());
+
+        for bound_var_kind in bound_vars {
+            let arg: ty::GenericArg<'_> = match bound_var_kind {
+                ty::BoundVariableKind::Ty(_) => self.next_ty_var(span).into(),
+                ty::BoundVariableKind::Region(br) => {
+                    self.next_region_var(BoundRegion(span, br, lbrct)).into()
+                }
+                ty::BoundVariableKind::Const => self.next_const_var(span).into(),
+            };
+            args.push(arg);
+        }
+
+        struct ToFreshVars<'tcx> {
+            args: Vec>,
         }
 
-        impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'_, 'tcx> {
+        impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'tcx> {
             fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
-                self.map
-                    .entry(br.var)
-                    .or_insert_with(|| {
-                        self.infcx
-                            .next_region_var(BoundRegion(self.span, br.kind, self.lbrct))
-                            .into()
-                    })
-                    .expect_region()
+                self.args[br.var.index()].expect_region()
             }
             fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
-                self.map
-                    .entry(bt.var)
-                    .or_insert_with(|| self.infcx.next_ty_var(self.span).into())
-                    .expect_ty()
+                self.args[bt.var.index()].expect_ty()
             }
             fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
-                self.map
-                    .entry(bv)
-                    .or_insert_with(|| self.infcx.next_const_var(self.span).into())
-                    .expect_const()
+                self.args[bv.index()].expect_const()
             }
         }
-        let delegate = ToFreshVars { infcx: self, span, lbrct, map: Default::default() };
+        let delegate = ToFreshVars { args };
         self.tcx.replace_bound_vars_uncached(value, delegate)
     }
 

From 724160ae3da68839032f6869dc9cb1aeb3e04a2d Mon Sep 17 00:00:00 2001
From: Oli Scherer 
Date: Mon, 29 Jul 2024 11:46:54 +0000
Subject: [PATCH 220/489] Split out actual `FileDescriptor` creation

---
 src/tools/miri/src/shims/unix/fd.rs | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index d6399489c9b9f..85ff9f1fc638c 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -192,6 +192,10 @@ impl FileDescription for NullOutput {
 pub struct FileDescriptor(Rc>>);
 
 impl FileDescriptor {
+    fn new(fd: impl FileDescription) -> Self {
+        FileDescriptor(Rc::new(RefCell::new(Box::new(fd))))
+    }
+
     pub fn borrow(&self) -> Ref<'_, dyn FileDescription> {
         Ref::map(self.0.borrow(), |fd| fd.as_ref())
     }
@@ -239,14 +243,14 @@ impl FdTable {
         fds
     }
 
-    /// Insert a file descriptor to the FdTable.
-    pub fn insert_fd(&mut self, fd: T) -> i32 {
-        let file_handle = FileDescriptor(Rc::new(RefCell::new(Box::new(fd))));
+    /// Insert a new file description to the FdTable.
+    pub fn insert_fd(&mut self, fd: impl FileDescription) -> i32 {
+        let file_handle = FileDescriptor::new(fd);
         self.insert_fd_with_min_fd(file_handle, 0)
     }
 
     /// Insert a new FD that is at least `min_fd`.
-    pub fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptor, min_fd: i32) -> i32 {
+    fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptor, min_fd: i32) -> i32 {
         // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in
         // between used FDs, the find_map combinator will return it. If the first such unused FD
         // is after all other used FDs, the find_map combinator will return None, and we will use

From 4742a81ebd787022a579ae7d8a8dca23fa78147e Mon Sep 17 00:00:00 2001
From: Oli Scherer 
Date: Mon, 29 Jul 2024 11:47:49 +0000
Subject: [PATCH 221/489] Rename `FileDescriptor` to `FileDescriptionRef`

---
 src/tools/miri/src/shims/unix/fd.rs | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 85ff9f1fc638c..323b7371d4796 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -189,11 +189,11 @@ impl FileDescription for NullOutput {
 }
 
 #[derive(Clone, Debug)]
-pub struct FileDescriptor(Rc>>);
+pub struct FileDescriptionRef(Rc>>);
 
-impl FileDescriptor {
+impl FileDescriptionRef {
     fn new(fd: impl FileDescription) -> Self {
-        FileDescriptor(Rc::new(RefCell::new(Box::new(fd))))
+        FileDescriptionRef(Rc::new(RefCell::new(Box::new(fd))))
     }
 
     pub fn borrow(&self) -> Ref<'_, dyn FileDescription> {
@@ -217,7 +217,7 @@ impl FileDescriptor {
 /// The file descriptor table
 #[derive(Debug)]
 pub struct FdTable {
-    fds: BTreeMap,
+    fds: BTreeMap,
 }
 
 impl VisitProvenance for FdTable {
@@ -245,12 +245,12 @@ impl FdTable {
 
     /// Insert a new file description to the FdTable.
     pub fn insert_fd(&mut self, fd: impl FileDescription) -> i32 {
-        let file_handle = FileDescriptor::new(fd);
+        let file_handle = FileDescriptionRef::new(fd);
         self.insert_fd_with_min_fd(file_handle, 0)
     }
 
     /// Insert a new FD that is at least `min_fd`.
-    fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptor, min_fd: i32) -> i32 {
+    fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptionRef, min_fd: i32) -> i32 {
         // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in
         // between used FDs, the find_map combinator will return it. If the first such unused FD
         // is after all other used FDs, the find_map combinator will return None, and we will use
@@ -286,12 +286,12 @@ impl FdTable {
         Some(fd.borrow_mut())
     }
 
-    pub fn dup(&self, fd: i32) -> Option {
+    pub fn dup(&self, fd: i32) -> Option {
         let fd = self.fds.get(&fd)?;
         Some(fd.clone())
     }
 
-    pub fn remove(&mut self, fd: i32) -> Option {
+    pub fn remove(&mut self, fd: i32) -> Option {
         self.fds.remove(&fd)
     }
 

From b48e1b1d73de9dccd23dbcc2b26aae0215e87e18 Mon Sep 17 00:00:00 2001
From: Oli Scherer 
Date: Mon, 29 Jul 2024 11:50:01 +0000
Subject: [PATCH 222/489] Rename all `file_descriptor` variables to
 `file_description` to match the naming scheme of the types

---
 src/tools/miri/src/shims/unix/fd.rs |  8 +++---
 src/tools/miri/src/shims/unix/fs.rs | 40 ++++++++++++++---------------
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs
index 323b7371d4796..74bb8eeb954da 100644
--- a/src/tools/miri/src/shims/unix/fd.rs
+++ b/src/tools/miri/src/shims/unix/fd.rs
@@ -320,9 +320,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
         if new_fd != old_fd {
             // Close new_fd if it is previously opened.
             // If old_fd and new_fd point to the same description, then `dup_fd` ensures we keep the underlying file description alive.
-            if let Some(file_descriptor) = this.machine.fds.fds.insert(new_fd, dup_fd) {
+            if let Some(file_description) = this.machine.fds.fds.insert(new_fd, dup_fd) {
                 // Ignore close error (not interpreter's) according to dup2() doc.
-                file_descriptor.close(this.machine.communicate())?.ok();
+                file_description.close(this.machine.communicate())?.ok();
             }
         }
         Ok(new_fd)
@@ -389,10 +389,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
 
-        let Some(file_descriptor) = this.machine.fds.remove(fd) else {
+        let Some(file_description) = this.machine.fds.remove(fd) else {
             return Ok(Scalar::from_i32(this.fd_not_found()?));
         };
-        let result = file_descriptor.close(this.machine.communicate())?;
+        let result = file_description.close(this.machine.communicate())?;
         // return `0` if close is successful
         let result = result.map(|()| 0i32);
         Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 6923b39733f0b..6546cefd28596 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -483,13 +483,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
         let communicate = this.machine.communicate();
 
-        let Some(mut file_descriptor) = this.machine.fds.get_mut(fd) else {
+        let Some(mut file_description) = this.machine.fds.get_mut(fd) else {
             return Ok(Scalar::from_i64(this.fd_not_found()?));
         };
-        let result = file_descriptor
+        let result = file_description
             .seek(communicate, seek_from)?
             .map(|offset| i64::try_from(offset).unwrap());
-        drop(file_descriptor);
+        drop(file_description);
 
         let result = this.try_unwrap_io_result(result)?;
         Ok(Scalar::from_i64(result))
@@ -1176,30 +1176,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             return Ok(Scalar::from_i32(this.fd_not_found()?));
         }
 
-        let Some(file_descriptor) = this.machine.fds.get(fd) else {
+        let Some(file_description) = this.machine.fds.get(fd) else {
             return Ok(Scalar::from_i32(this.fd_not_found()?));
         };
 
         // FIXME: Support ftruncate64 for all FDs
         let FileHandle { file, writable } =
-            file_descriptor.downcast_ref::().ok_or_else(|| {
+            file_description.downcast_ref::().ok_or_else(|| {
                 err_unsup_format!("`ftruncate64` is only supported on file-backed file descriptors")
             })?;
 
         if *writable {
             if let Ok(length) = length.try_into() {
                 let result = file.set_len(length);
-                drop(file_descriptor);
+                drop(file_description);
                 let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
                 Ok(Scalar::from_i32(result))
             } else {
-                drop(file_descriptor);
+                drop(file_description);
                 let einval = this.eval_libc("EINVAL");
                 this.set_last_error(einval)?;
                 Ok(Scalar::from_i32(-1))
             }
         } else {
-            drop(file_descriptor);
+            drop(file_description);
             // The file is not writable
             let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
@@ -1229,16 +1229,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
     fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, i32> {
         let this = self.eval_context_mut();
-        let Some(file_descriptor) = this.machine.fds.get(fd) else {
+        let Some(file_description) = this.machine.fds.get(fd) else {
             return Ok(this.fd_not_found()?);
         };
         // Only regular files support synchronization.
         let FileHandle { file, writable } =
-            file_descriptor.downcast_ref::().ok_or_else(|| {
+            file_description.downcast_ref::().ok_or_else(|| {
                 err_unsup_format!("`fsync` is only supported on file-backed file descriptors")
             })?;
         let io_result = maybe_sync_file(file, *writable, File::sync_all);
-        drop(file_descriptor);
+        drop(file_description);
         this.try_unwrap_io_result(io_result)
     }
 
@@ -1254,16 +1254,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             return this.fd_not_found();
         }
 
-        let Some(file_descriptor) = this.machine.fds.get(fd) else {
+        let Some(file_description) = this.machine.fds.get(fd) else {
             return Ok(this.fd_not_found()?);
         };
         // Only regular files support synchronization.
         let FileHandle { file, writable } =
-            file_descriptor.downcast_ref::().ok_or_else(|| {
+            file_description.downcast_ref::().ok_or_else(|| {
                 err_unsup_format!("`fdatasync` is only supported on file-backed file descriptors")
             })?;
         let io_result = maybe_sync_file(file, *writable, File::sync_data);
-        drop(file_descriptor);
+        drop(file_description);
         this.try_unwrap_io_result(io_result)
     }
 
@@ -1302,18 +1302,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             return Ok(Scalar::from_i32(this.fd_not_found()?));
         }
 
-        let Some(file_descriptor) = this.machine.fds.get(fd) else {
+        let Some(file_description) = this.machine.fds.get(fd) else {
             return Ok(Scalar::from_i32(this.fd_not_found()?));
         };
         // Only regular files support synchronization.
         let FileHandle { file, writable } =
-            file_descriptor.downcast_ref::().ok_or_else(|| {
+            file_description.downcast_ref::().ok_or_else(|| {
                 err_unsup_format!(
                     "`sync_data_range` is only supported on file-backed file descriptors"
                 )
             })?;
         let io_result = maybe_sync_file(file, *writable, File::sync_data);
-        drop(file_descriptor);
+        drop(file_description);
         Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
     }
 
@@ -1609,11 +1609,11 @@ impl FileMetadata {
         ecx: &mut MiriInterpCx<'tcx>,
         fd: i32,
     ) -> InterpResult<'tcx, Option> {
-        let Some(file_descriptor) = ecx.machine.fds.get(fd) else {
+        let Some(file_description) = ecx.machine.fds.get(fd) else {
             return ecx.fd_not_found().map(|_: i32| None);
         };
 
-        let file = &file_descriptor
+        let file = &file_description
             .downcast_ref::()
             .ok_or_else(|| {
                 err_unsup_format!(
@@ -1623,7 +1623,7 @@ impl FileMetadata {
             .file;
 
         let metadata = file.metadata();
-        drop(file_descriptor);
+        drop(file_description);
         FileMetadata::from_meta(ecx, metadata)
     }
 

From dc548f0168018dfbec02d2d3fff1464501ecf79f Mon Sep 17 00:00:00 2001
From: Yunfei 
Date: Mon, 29 Jul 2024 20:36:03 +0800
Subject: [PATCH 223/489] Revert "Fix error message"

This reverts commit 752c49b679afcec7edf5d26d52bf3d164ee7349f.
---
 .../src/handlers/trait_impl_missing_assoc_item.rs           | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
index 60d1452d86be8..58d1b7f31d2fe 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
@@ -13,7 +13,6 @@ pub(crate) fn trait_impl_missing_assoc_item(
 ) -> Diagnostic {
     let missing = d.missing.iter().format_with(", ", |(name, item), f| {
         f(&match *item {
-            hir::AssocItem::Function(func) if func.is_async(ctx.sema.db) => "`async fn ",
             hir::AssocItem::Function(_) => "`fn ",
             hir::AssocItem::Const(_) => "`const ",
             hir::AssocItem::TypeAlias(_) => "`type ",
@@ -57,25 +56,22 @@ trait Trait {
     const C: ();
     type T;
     fn f();
-    async fn async_f();
 }
 
 impl Trait for () {
     const C: () = ();
     type T = ();
     fn f() {}
-    async fn async_f() {}
 }
 
 impl Trait for () {
    //^^^^^ error: not all trait items implemented, missing: `const C`
     type T = ();
     fn f() {}
-    async fn async_f() {}
 }
 
 impl Trait for () {
-   //^^^^^ error: not all trait items implemented, missing: `const C`, `type T`, `fn f`, `async fn async_f`
+   //^^^^^ error: not all trait items implemented, missing: `const C`, `type T`, `fn f`
 }
 
 "#,

From 825034566ad5e752cb6d422ab5f38a5aaff08bb7 Mon Sep 17 00:00:00 2001
From: Yunfei 
Date: Mon, 29 Jul 2024 20:40:51 +0800
Subject: [PATCH 224/489] Add test in `ide-completion/src/tests/item_list.rs`

---
 .../crates/ide-completion/src/tests/item_list.rs              | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
index f138938b02bd0..8aad7bfc3adc9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
@@ -299,6 +299,7 @@ trait Test {
     const CONST1: ();
     fn function0();
     fn function1();
+    async fn function2();
 }
 
 impl Test for () {
@@ -310,8 +311,9 @@ impl Test for () {
 "#,
         expect![[r#"
             ct const CONST1: () =
+            fn async fn function2()
             fn fn function1()
-            ma makro!(…)          macro_rules! makro
+            ma makro!(…)            macro_rules! makro
             md module
             ta type Type1 =
             kw crate::

From 79defab2b1206b7c43e170be5d7cd603127f4721 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Mon, 29 Jul 2024 14:52:40 +0200
Subject: [PATCH 225/489] Make basic use of spans for macro expansion errors

---
 .../rust-analyzer/crates/hir-def/src/data.rs  |   1 +
 .../crates/hir-def/src/expander.rs            |  20 +--
 .../rust-analyzer/crates/hir-def/src/lib.rs   |   5 +-
 .../macro_expansion_tests/mbe/regression.rs   |   2 +-
 .../crates/hir-def/src/nameres/collector.rs   |   1 +
 .../crates/hir-def/src/nameres/diagnostics.rs |  13 +-
 .../hir-expand/src/builtin/derive_macro.rs    |  29 +++--
 .../crates/hir-expand/src/builtin/fn_macro.rs |  53 ++++----
 .../rust-analyzer/crates/hir-expand/src/db.rs |  78 ++++++------
 .../crates/hir-expand/src/declarative.rs      |  41 +-----
 .../crates/hir-expand/src/eager.rs            |  11 +-
 .../crates/hir-expand/src/lib.rs              |  62 +++++++---
 .../crates/hir-expand/src/proc_macro.rs       |  38 +++---
 src/tools/rust-analyzer/crates/hir/src/lib.rs |  41 +++---
 .../src/handlers/macro_error.rs               |   4 +-
 .../rust-analyzer/crates/mbe/src/benchmark.rs |   4 +-
 .../rust-analyzer/crates/mbe/src/expander.rs  |  16 +--
 .../crates/mbe/src/expander/matcher.rs        | 117 ++++++++++++------
 .../crates/mbe/src/expander/transcriber.rs    |  91 ++++----------
 src/tools/rust-analyzer/crates/mbe/src/lib.rs |  56 +++++----
 .../crates/mbe/src/syntax_bridge.rs           |  18 +--
 .../crates/rust-analyzer/src/main_loop.rs     |   1 +
 .../rust-analyzer/crates/tt/src/buffer.rs     |   9 ++
 src/tools/rust-analyzer/crates/tt/src/iter.rs |   4 +
 24 files changed, 387 insertions(+), 328 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 286694db263e0..c3c2e51fd0385 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -661,6 +661,7 @@ impl<'a> AssocItemCollector<'a> {
                                 self.diagnostics.push(DefDiagnostic::macro_error(
                                     self.module_id.local_id,
                                     ast_id,
+                                    (*attr.path).clone(),
                                     err,
                                 ));
                                 continue 'attrs;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
index 8230c7cc09731..6d8b4445f75bc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
@@ -6,8 +6,8 @@ use base_db::CrateId;
 use cfg::CfgOptions;
 use drop_bomb::DropBomb;
 use hir_expand::{
-    attrs::RawAttrs, mod_path::ModPath, span_map::SpanMap, ExpandError, ExpandResult, HirFileId,
-    InFile, MacroCallId,
+    attrs::RawAttrs, mod_path::ModPath, span_map::SpanMap, ExpandError, ExpandErrorKind,
+    ExpandResult, HirFileId, InFile, Lookup, MacroCallId,
 };
 use limit::Limit;
 use span::SyntaxContextId;
@@ -160,26 +160,30 @@ impl Expander {
             // so don't return overflow error here to avoid diagnostics duplication.
             cov_mark::hit!(overflow_but_not_me);
             return ExpandResult::ok(None);
-        } else if self.recursion_limit.check(self.recursion_depth as usize + 1).is_err() {
-            self.recursion_depth = u32::MAX;
-            cov_mark::hit!(your_stack_belongs_to_me);
-            return ExpandResult::only_err(ExpandError::RecursionOverflow);
         }
 
         let ExpandResult { value, err } = op(self);
         let Some(call_id) = value else {
             return ExpandResult { value: None, err };
         };
+        if self.recursion_limit.check(self.recursion_depth as usize + 1).is_err() {
+            self.recursion_depth = u32::MAX;
+            cov_mark::hit!(your_stack_belongs_to_me);
+            return ExpandResult::only_err(ExpandError::new(
+                db.macro_arg_considering_derives(call_id, &call_id.lookup(db.upcast()).kind).2,
+                ExpandErrorKind::RecursionOverflow,
+            ));
+        }
 
         let macro_file = call_id.as_macro_file();
         let res = db.parse_macro_expansion(macro_file);
 
         let err = err.or(res.err);
         ExpandResult {
-            value: match err {
+            value: match &err {
                 // If proc-macro is disabled or unresolved, we want to expand to a missing expression
                 // instead of an empty tree which might end up in an empty block.
-                Some(ExpandError::MissingProcMacroExpander(_)) => None,
+                Some(e) if matches!(e.kind(), ExpandErrorKind::MissingProcMacroExpander(_)) => None,
                 _ => (|| {
                     let parse = res.value.0.cast::()?;
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index 512daa415481c..66412b26a0085 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -1434,7 +1434,10 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
         });
 
         let Some((call_site, path)) = path else {
-            return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
+            return Ok(ExpandResult::only_err(ExpandError::other(
+                span_map.span_for_range(self.value.syntax().text_range()),
+                "malformed macro invocation",
+            )));
         };
 
         macro_call_as_call_id_with_eager(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
index 252b0bb1b59b8..485f72e92ce1c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
@@ -1084,7 +1084,7 @@ fn main() {
 macro_rules! concat_bytes {}
 
 fn main() {
-    let x = /* error: unexpected token in input */b"";
+    let x = /* error: unexpected token */b"";
 }
 
 "#]],
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 9553b6aa8cf8e..63ad7270ac0c0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -1324,6 +1324,7 @@ impl DefCollector<'_> {
                             self.def_map.diagnostics.push(DefDiagnostic::macro_error(
                                 directive.module_id,
                                 ast_id,
+                                (**path).clone(),
                                 err,
                             ));
                             return recollect_without(self);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
index 23837ff661b00..bc1617c55b029 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
@@ -3,7 +3,7 @@
 use std::ops::Not;
 
 use cfg::{CfgExpr, CfgOptions};
-use hir_expand::{attrs::AttrId, ExpandError, MacroCallKind};
+use hir_expand::{attrs::AttrId, ExpandErrorKind, MacroCallKind};
 use la_arena::Idx;
 use syntax::ast;
 
@@ -25,7 +25,7 @@ pub enum DefDiagnosticKind {
     InvalidDeriveTarget { ast: AstId, id: usize },
     MalformedDerive { ast: AstId, id: usize },
     MacroDefError { ast: AstId, message: String },
-    MacroError { ast: AstId, err: ExpandError },
+    MacroError { ast: AstId, path: ModPath, err: ExpandErrorKind },
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -82,8 +82,13 @@ impl DefDiagnostic {
         Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } }
     }
 
-    pub fn macro_error(container: LocalModuleId, ast: AstId, err: ExpandError) -> Self {
-        Self { in_module: container, kind: DefDiagnosticKind::MacroError { ast, err } }
+    pub fn macro_error(
+        container: LocalModuleId,
+        ast: AstId,
+        path: ModPath,
+        err: ExpandErrorKind,
+    ) -> Self {
+        Self { in_module: container, kind: DefDiagnosticKind::MacroError { ast, path, err } }
     }
 
     pub fn unconfigured_code(
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
index 1f36cd1995430..f560d3bfd1db3 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
@@ -12,8 +12,7 @@ use crate::{
     builtin::quote::{dollar_crate, quote},
     db::ExpandDatabase,
     hygiene::span_with_def_site_ctxt,
-    name,
-    name::{AsName, Name},
+    name::{self, AsName, Name},
     span_map::ExpansionSpanMap,
     tt, ExpandError, ExpandResult,
 };
@@ -129,13 +128,17 @@ impl VariantShape {
         }
     }
 
-    fn from(tm: &ExpansionSpanMap, value: Option) -> Result {
+    fn from(
+        call_site: Span,
+        tm: &ExpansionSpanMap,
+        value: Option,
+    ) -> Result {
         let r = match value {
             None => VariantShape::Unit,
             Some(FieldList::RecordFieldList(it)) => VariantShape::Struct(
                 it.fields()
                     .map(|it| it.name())
-                    .map(|it| name_to_token(tm, it))
+                    .map(|it| name_to_token(call_site, tm, it))
                     .collect::>()?,
             ),
             Some(FieldList::TupleFieldList(it)) => VariantShape::Tuple(it.fields().count()),
@@ -212,16 +215,17 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result (
             it.name(),
             it.generic_param_list(),
             it.where_clause(),
-            AdtShape::Struct(VariantShape::from(tm, it.field_list())?),
+            AdtShape::Struct(VariantShape::from(call_site, tm, it.field_list())?),
         ),
         ast::Adt::Enum(it) => {
             let default_variant = it
@@ -241,8 +245,8 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result>()?,
@@ -357,17 +361,18 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result,
 ) -> Result {
     let name = name.ok_or_else(|| {
         debug!("parsed item has no name");
-        ExpandError::other("missing name")
+        ExpandError::other(call_site, "missing name")
     })?;
     let span = token_map.span_at(name.syntax().text_range().start());
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index 5edfdcae1c198..0b844c0a634e9 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -460,15 +460,11 @@ fn compile_error_expand(
     let err = match &*tt.token_trees {
         [tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
             symbol: text,
-            span: _,
+            span,
             kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
             suffix: _,
-        }))] =>
-        // FIXME: Use the span here!
-        {
-            ExpandError::other(Box::from(unescape_str(text).as_str()))
-        }
-        _ => ExpandError::other("`compile_error!` argument must be a string"),
+        }))] => ExpandError::other(*span, Box::from(unescape_str(text).as_str())),
+        _ => ExpandError::other(span, "`compile_error!` argument must be a string"),
     };
 
     ExpandResult { value: quote! {span =>}, err: Some(err) }
@@ -478,7 +474,7 @@ fn concat_expand(
     _db: &dyn ExpandDatabase,
     _arg_id: MacroCallId,
     tt: &tt::Subtree,
-    _: Span,
+    call_site: Span,
 ) -> ExpandResult {
     let mut err = None;
     let mut text = String::new();
@@ -527,7 +523,9 @@ fn concat_expand(
                     | tt::LitKind::ByteStrRaw(_)
                     | tt::LitKind::CStr
                     | tt::LitKind::CStrRaw(_)
-                    | tt::LitKind::Err(_) => err = Some(ExpandError::other("unexpected literal")),
+                    | tt::LitKind::Err(_) => {
+                        err = Some(ExpandError::other(it.span, "unexpected literal"))
+                    }
                 }
             }
             // handle boolean literals
@@ -539,7 +537,7 @@ fn concat_expand(
             }
             tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
             _ => {
-                err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
+                err.get_or_insert(ExpandError::other(call_site, "unexpected token"));
             }
         }
     }
@@ -551,7 +549,7 @@ fn concat_bytes_expand(
     _db: &dyn ExpandDatabase,
     _arg_id: MacroCallId,
     tt: &tt::Subtree,
-    _: Span,
+    call_site: Span,
 ) -> ExpandResult {
     let mut bytes = String::new();
     let mut err = None;
@@ -585,20 +583,22 @@ fn concat_bytes_expand(
                         bytes.extend(text.as_str().escape_debug());
                     }
                     _ => {
-                        err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
+                        err.get_or_insert(ExpandError::other(*span, "unexpected token"));
                         break;
                     }
                 }
             }
             tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
             tt::TokenTree::Subtree(tree) if tree.delimiter.kind == tt::DelimiterKind::Bracket => {
-                if let Err(e) = concat_bytes_expand_subtree(tree, &mut bytes, &mut record_span) {
+                if let Err(e) =
+                    concat_bytes_expand_subtree(tree, &mut bytes, &mut record_span, call_site)
+                {
                     err.get_or_insert(e);
                     break;
                 }
             }
             _ => {
-                err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
+                err.get_or_insert(ExpandError::other(call_site, "unexpected token"));
                 break;
             }
         }
@@ -623,6 +623,7 @@ fn concat_bytes_expand_subtree(
     tree: &tt::Subtree,
     bytes: &mut String,
     mut record_span: impl FnMut(Span),
+    err_span: Span,
 ) -> Result<(), ExpandError> {
     for (ti, tt) in tree.token_trees.iter().enumerate() {
         match tt {
@@ -650,7 +651,7 @@ fn concat_bytes_expand_subtree(
             }
             tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (),
             _ => {
-                return Err(mbe::ExpandError::UnexpectedToken.into());
+                return Err(ExpandError::other(err_span, "unexpected token"));
             }
         }
     }
@@ -672,7 +673,7 @@ fn concat_idents_expand(
             }
             tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
             _ => {
-                err.get_or_insert(mbe::ExpandError::UnexpectedToken.into());
+                err.get_or_insert(ExpandError::other(span, "unexpected token"));
             }
         }
     }
@@ -686,16 +687,17 @@ fn relative_file(
     call_id: MacroCallId,
     path_str: &str,
     allow_recursion: bool,
+    err_span: Span,
 ) -> Result {
     let lookup = call_id.lookup(db);
     let call_site = lookup.kind.file_id().original_file_respecting_includes(db).file_id();
     let path = AnchoredPath { anchor: call_site, path: path_str };
     let res = db
         .resolve_path(path)
-        .ok_or_else(|| ExpandError::other(format!("failed to load file `{path_str}`")))?;
+        .ok_or_else(|| ExpandError::other(err_span, format!("failed to load file `{path_str}`")))?;
     // Prevent include itself
     if res == call_site && !allow_recursion {
-        Err(ExpandError::other(format!("recursive inclusion of `{path_str}`")))
+        Err(ExpandError::other(err_span, format!("recursive inclusion of `{path_str}`")))
     } else {
         Ok(EditionedFileId::new(res, db.crate_graph()[lookup.krate].edition))
     }
@@ -727,7 +729,7 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
             }
             _ => None,
         })
-        .ok_or(mbe::ExpandError::ConversionError.into())
+        .ok_or(ExpandError::other(tt.delimiter.open, "expected string literal"))
 }
 
 fn include_expand(
@@ -751,7 +753,7 @@ fn include_expand(
         Some(it) => ExpandResult::ok(it),
         None => ExpandResult::new(
             tt::Subtree::empty(DelimSpan { open: span, close: span }),
-            ExpandError::other("failed to parse included file"),
+            ExpandError::other(span, "failed to parse included file"),
         ),
     }
 }
@@ -761,7 +763,7 @@ pub fn include_input_to_file_id(
     arg_id: MacroCallId,
     arg: &tt::Subtree,
 ) -> Result {
-    relative_file(db, arg_id, parse_string(arg)?.0.as_str(), false)
+    relative_file(db, arg_id, parse_string(arg)?.0.as_str(), false, arg.delimiter.open)
 }
 
 fn include_bytes_expand(
@@ -800,7 +802,7 @@ fn include_str_expand(
     // it's unusual to `include_str!` a Rust file), but we can return an empty string.
     // Ideally, we'd be able to offer a precise expansion if the user asks for macro
     // expansion.
-    let file_id = match relative_file(db, arg_id, path.as_str(), true) {
+    let file_id = match relative_file(db, arg_id, path.as_str(), true, span) {
         Ok(file_id) => file_id,
         Err(_) => {
             return ExpandResult::ok(quote!(span =>""));
@@ -836,7 +838,10 @@ fn env_expand(
         // The only variable rust-analyzer ever sets is `OUT_DIR`, so only diagnose that to avoid
         // unnecessary diagnostics for eg. `CARGO_PKG_NAME`.
         if key.as_str() == "OUT_DIR" {
-            err = Some(ExpandError::other(r#"`OUT_DIR` not set, enable "build scripts" to fix"#));
+            err = Some(ExpandError::other(
+                span,
+                r#"`OUT_DIR` not set, enable "build scripts" to fix"#,
+            ));
         }
 
         // If the variable is unset, still return a dummy string to help type inference along.
@@ -885,7 +890,7 @@ fn quote_expand(
 ) -> ExpandResult {
     ExpandResult::new(
         tt::Subtree::empty(tt::DelimSpan { open: span, close: span }),
-        ExpandError::other("quote! is not implemented"),
+        ExpandError::other(span, "quote! is not implemented"),
     )
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index dd1d292fb64fd..01a35660a904b 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -259,39 +259,38 @@ pub fn expand_speculative(
 
     // Do the actual expansion, we need to directly expand the proc macro due to the attribute args
     // Otherwise the expand query will fetch the non speculative attribute args and pass those instead.
-    let mut speculative_expansion =
-        match loc.def.kind {
-            MacroDefKind::ProcMacro(ast, expander, _) => {
-                let span = db.proc_macro_span(ast);
-                tt.delimiter = tt::Delimiter::invisible_spanned(span);
-                expander.expand(
-                    db,
-                    loc.def.krate,
-                    loc.krate,
-                    &tt,
-                    attr_arg.as_ref(),
-                    span_with_def_site_ctxt(db, span, actual_macro_call),
-                    span_with_call_site_ctxt(db, span, actual_macro_call),
-                    span_with_mixed_site_ctxt(db, span, actual_macro_call),
-                )
-            }
-            MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => {
-                pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, span)
-            }
-            MacroDefKind::Declarative(it) => db
-                .decl_macro_expander(loc.krate, it)
-                .expand_unhygienic(db, tt, loc.def.krate, span, loc.def.edition),
-            MacroDefKind::BuiltIn(_, it) => {
-                it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
-            }
-            MacroDefKind::BuiltInDerive(_, it) => {
-                it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
-            }
-            MacroDefKind::BuiltInEager(_, it) => {
-                it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
-            }
-            MacroDefKind::BuiltInAttr(_, it) => it.expand(db, actual_macro_call, &tt, span),
-        };
+    let mut speculative_expansion = match loc.def.kind {
+        MacroDefKind::ProcMacro(ast, expander, _) => {
+            let span = db.proc_macro_span(ast);
+            tt.delimiter = tt::Delimiter::invisible_spanned(span);
+            expander.expand(
+                db,
+                loc.def.krate,
+                loc.krate,
+                &tt,
+                attr_arg.as_ref(),
+                span_with_def_site_ctxt(db, span, actual_macro_call),
+                span_with_call_site_ctxt(db, span, actual_macro_call),
+                span_with_mixed_site_ctxt(db, span, actual_macro_call),
+            )
+        }
+        MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => {
+            pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, span)
+        }
+        MacroDefKind::Declarative(it) => {
+            db.decl_macro_expander(loc.krate, it).expand_unhygienic(tt, span, loc.def.edition)
+        }
+        MacroDefKind::BuiltIn(_, it) => {
+            it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
+        }
+        MacroDefKind::BuiltInDerive(_, it) => {
+            it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
+        }
+        MacroDefKind::BuiltInEager(_, it) => {
+            it.expand(db, actual_macro_call, &tt, span).map_err(Into::into)
+        }
+        MacroDefKind::BuiltInAttr(_, it) => it.expand(db, actual_macro_call, &tt, span),
+    };
 
     let expand_to = loc.expand_to();
 
@@ -735,11 +734,14 @@ fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> {
     if TOKEN_LIMIT.check(count).is_err() {
         Err(ExpandResult {
             value: (),
-            err: Some(ExpandError::other(format!(
-                "macro invocation exceeds token limit: produced {} tokens, limit is {}",
-                count,
-                TOKEN_LIMIT.inner(),
-            ))),
+            err: Some(ExpandError::other(
+                tt.delimiter.open,
+                format!(
+                    "macro invocation exceeds token limit: produced {} tokens, limit is {}",
+                    count,
+                    TOKEN_LIMIT.inner(),
+                ),
+            )),
         })
     } else {
         Ok(())
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
index 85d7521dbc123..48851af3fd160 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
@@ -1,7 +1,6 @@
 //! Compiled declarative macro expanders (`macro_rules!`` and `macro`)
-use std::sync::OnceLock;
 
-use base_db::{CrateId, VersionReq};
+use base_db::CrateId;
 use intern::sym;
 use mbe::DocCommentDesugarMode;
 use span::{Edition, MacroCallId, Span, SyntaxContextId};
@@ -13,7 +12,7 @@ use crate::{
     attrs::RawAttrs,
     db::ExpandDatabase,
     hygiene::{apply_mark, Transparency},
-    tt, AstId, ExpandError, ExpandResult, Lookup,
+    tt, AstId, ExpandError, ExpandErrorKind, ExpandResult, Lookup,
 };
 
 /// Old-style `macro_rules` or the new macros 2.0
@@ -23,9 +22,6 @@ pub struct DeclarativeMacroExpander {
     pub transparency: Transparency,
 }
 
-// FIXME: Remove this once we drop support for 1.76
-static REQUIREMENT: OnceLock = OnceLock::new();
-
 impl DeclarativeMacroExpander {
     pub fn expand(
         &self,
@@ -35,29 +31,16 @@ impl DeclarativeMacroExpander {
         span: Span,
     ) -> ExpandResult<(tt::Subtree, Option)> {
         let loc = db.lookup_intern_macro_call(call_id);
-        let toolchain = db.toolchain(loc.def.krate);
-        let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
-            REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
-                &base_db::Version {
-                    pre: base_db::Prerelease::EMPTY,
-                    build: base_db::BuildMetadata::EMPTY,
-                    major: version.major,
-                    minor: version.minor,
-                    patch: version.patch,
-                },
-            )
-        });
         match self.mac.err() {
             Some(_) => ExpandResult::new(
                 (tt::Subtree::empty(tt::DelimSpan { open: span, close: span }), None),
-                ExpandError::MacroDefinition,
+                ExpandError::new(span, ExpandErrorKind::MacroDefinition),
             ),
             None => self
                 .mac
                 .expand(
                     &tt,
                     |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency),
-                    new_meta_vars,
                     span,
                     loc.def.edition,
                 )
@@ -67,32 +50,18 @@ impl DeclarativeMacroExpander {
 
     pub fn expand_unhygienic(
         &self,
-        db: &dyn ExpandDatabase,
         tt: tt::Subtree,
-        krate: CrateId,
         call_site: Span,
         def_site_edition: Edition,
     ) -> ExpandResult {
-        let toolchain = db.toolchain(krate);
-        let new_meta_vars = toolchain.as_ref().map_or(false, |version| {
-            REQUIREMENT.get_or_init(|| VersionReq::parse(">=1.76").unwrap()).matches(
-                &base_db::Version {
-                    pre: base_db::Prerelease::EMPTY,
-                    build: base_db::BuildMetadata::EMPTY,
-                    major: version.major,
-                    minor: version.minor,
-                    patch: version.patch,
-                },
-            )
-        });
         match self.mac.err() {
             Some(_) => ExpandResult::new(
                 tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
-                ExpandError::MacroDefinition,
+                ExpandError::new(call_site, ExpandErrorKind::MacroDefinition),
             ),
             None => self
                 .mac
-                .expand(&tt, |_| (), new_meta_vars, call_site, def_site_edition)
+                .expand(&tt, |_| (), call_site, def_site_edition)
                 .map(TupleExt::head)
                 .map_err(Into::into),
         }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
index 6a4e235b53fc5..5385b44532b05 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
@@ -176,14 +176,19 @@ fn eager_macro_recur(
             Some(path) => match macro_resolver(&path) {
                 Some(def) => def,
                 None => {
-                    error =
-                        Some(ExpandError::other(format!("unresolved macro {}", path.display(db))));
+                    error = Some(ExpandError::other(
+                        span_map.span_at(call.syntax().text_range().start()),
+                        format!("unresolved macro {}", path.display(db)),
+                    ));
                     offset += call.syntax().text_range().len();
                     continue;
                 }
             },
             None => {
-                error = Some(ExpandError::other("malformed macro invocation"));
+                error = Some(ExpandError::other(
+                    span_map.span_at(call.syntax().text_range().start()),
+                    "malformed macro invocation",
+                ));
                 offset += call.syntax().text_range().len();
                 continue;
             }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index 64b4bd48bac9e..18da77d6caa9b 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -124,47 +124,77 @@ impl_intern_lookup!(
 pub type ExpandResult = ValueResult;
 
 #[derive(Debug, PartialEq, Eq, Clone, Hash)]
-pub enum ExpandError {
+pub struct ExpandError {
+    inner: Arc<(ExpandErrorKind, Span)>,
+}
+
+impl ExpandError {
+    pub fn new(span: Span, kind: ExpandErrorKind) -> Self {
+        ExpandError { inner: Arc::new((kind, span)) }
+    }
+    pub fn other(span: Span, msg: impl Into>) -> Self {
+        ExpandError { inner: Arc::new((ExpandErrorKind::Other(msg.into()), span)) }
+    }
+    pub fn kind(&self) -> &ExpandErrorKind {
+        &self.inner.0
+    }
+    pub fn span(&self) -> Span {
+        self.inner.1
+    }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Hash)]
+pub enum ExpandErrorKind {
+    /// Attribute macro expansion is disabled.
     ProcMacroAttrExpansionDisabled,
     MissingProcMacroExpander(CrateId),
-    /// The macro expansion is disabled.
+    /// The macro for this call is disabled.
     MacroDisabled,
+    /// The macro definition has errors.
     MacroDefinition,
-    Mbe(mbe::ExpandError),
+    Mbe(mbe::ExpandErrorKind),
     RecursionOverflow,
-    Other(Arc>),
-    ProcMacroPanic(Arc>),
+    Other(Box),
+    ProcMacroPanic(Box),
 }
 
 impl ExpandError {
-    pub fn other(msg: impl Into>) -> Self {
-        ExpandError::Other(Arc::new(msg.into()))
+    pub fn render_to_string(&self, db: &dyn ExpandDatabase) -> (String, bool) {
+        self.inner.0.render_to_string(db)
     }
+}
 
+impl ExpandErrorKind {
     pub fn render_to_string(&self, db: &dyn ExpandDatabase) -> (String, bool) {
         match self {
-            Self::ProcMacroAttrExpansionDisabled => {
+            ExpandErrorKind::ProcMacroAttrExpansionDisabled => {
                 ("procedural attribute macro expansion is disabled".to_owned(), false)
             }
-            Self::MacroDisabled => ("proc-macro is explicitly disabled".to_owned(), false),
-            &Self::MissingProcMacroExpander(def_crate) => {
+            ExpandErrorKind::MacroDisabled => {
+                ("proc-macro is explicitly disabled".to_owned(), false)
+            }
+            &ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
                 match db.proc_macros().get_error_for_crate(def_crate) {
                     Some((e, hard_err)) => (e.to_owned(), hard_err),
                     None => ("missing expander".to_owned(), true),
                 }
             }
-            Self::MacroDefinition => ("macro definition has parse errors".to_owned(), true),
-            Self::Mbe(e) => (e.to_string(), true),
-            Self::RecursionOverflow => ("overflow expanding the original macro".to_owned(), true),
-            Self::Other(e) => ((***e).to_owned(), true),
-            Self::ProcMacroPanic(e) => ((***e).to_owned(), true),
+            ExpandErrorKind::MacroDefinition => {
+                ("macro definition has parse errors".to_owned(), true)
+            }
+            ExpandErrorKind::Mbe(e) => (e.to_string(), true),
+            ExpandErrorKind::RecursionOverflow => {
+                ("overflow expanding the original macro".to_owned(), true)
+            }
+            ExpandErrorKind::Other(e) => ((**e).to_owned(), true),
+            ExpandErrorKind::ProcMacroPanic(e) => ((**e).to_owned(), true),
         }
     }
 }
 
 impl From for ExpandError {
     fn from(mbe: mbe::ExpandError) -> Self {
-        Self::Mbe(mbe)
+        ExpandError { inner: Arc::new((ExpandErrorKind::Mbe(mbe.inner.1.clone()), mbe.inner.0)) }
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
index b5dc9a764996b..26bb3a3edda4d 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
@@ -7,9 +7,8 @@ use base_db::{CrateId, Env};
 use intern::Symbol;
 use rustc_hash::FxHashMap;
 use span::Span;
-use triomphe::Arc;
 
-use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
+use crate::{db::ExpandDatabase, tt, ExpandError, ExpandErrorKind, ExpandResult};
 
 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
 pub enum ProcMacroKind {
@@ -76,15 +75,18 @@ impl FromIterator<(CrateId, ProcMacroLoadResult)> for ProcMacros {
 }
 
 impl ProcMacros {
-    fn get(&self, krate: CrateId, idx: u32) -> Result<&ProcMacro, ExpandError> {
+    fn get(&self, krate: CrateId, idx: u32, err_span: Span) -> Result<&ProcMacro, ExpandError> {
         let proc_macros = match self.0.get(&krate) {
             Some(Ok(proc_macros)) => proc_macros,
             Some(Err(_)) | None => {
-                return Err(ExpandError::other("internal error: no proc macros for crate"));
+                return Err(ExpandError::other(
+                    err_span,
+                    "internal error: no proc macros for crate",
+                ));
             }
         };
         proc_macros.get(idx as usize).ok_or_else(|| {
-                ExpandError::other(
+                ExpandError::other(err_span,
                     format!(
                         "internal error: proc-macro index out of bounds: the length is {} but the index is {}",
                         proc_macros.len(),
@@ -184,11 +186,11 @@ impl CustomProcMacroExpander {
     }
 
     /// The macro is explicitly disabled due to proc-macro attribute expansion being disabled.
-    pub const fn as_expand_error(&self, def_crate: CrateId) -> Option {
+    pub fn as_expand_error(&self, def_crate: CrateId) -> Option {
         match self.proc_macro_id {
-            Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandError::ProcMacroAttrExpansionDisabled),
-            Self::DISABLED_ID => Some(ExpandError::MacroDisabled),
-            Self::MISSING_EXPANDER => Some(ExpandError::MissingProcMacroExpander(def_crate)),
+            Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandErrorKind::ProcMacroAttrExpansionDisabled),
+            Self::DISABLED_ID => Some(ExpandErrorKind::MacroDisabled),
+            Self::MISSING_EXPANDER => Some(ExpandErrorKind::MissingProcMacroExpander(def_crate)),
             _ => None,
         }
     }
@@ -207,19 +209,19 @@ impl CustomProcMacroExpander {
         match self.proc_macro_id {
             Self::PROC_MACRO_ATTR_DISABLED => ExpandResult::new(
                 tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
-                ExpandError::ProcMacroAttrExpansionDisabled,
+                ExpandError::new(call_site, ExpandErrorKind::ProcMacroAttrExpansionDisabled),
             ),
             Self::MISSING_EXPANDER => ExpandResult::new(
                 tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
-                ExpandError::MissingProcMacroExpander(def_crate),
+                ExpandError::new(call_site, ExpandErrorKind::MissingProcMacroExpander(def_crate)),
             ),
             Self::DISABLED_ID => ExpandResult::new(
                 tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
-                ExpandError::MacroDisabled,
+                ExpandError::new(call_site, ExpandErrorKind::MacroDisabled),
             ),
             id => {
                 let proc_macros = db.proc_macros();
-                let proc_macro = match proc_macros.get(def_crate, id) {
+                let proc_macro = match proc_macros.get(def_crate, id, call_site) {
                     Ok(proc_macro) => proc_macro,
                     Err(e) => {
                         return ExpandResult::new(
@@ -240,12 +242,18 @@ impl CustomProcMacroExpander {
                         ProcMacroExpansionError::System(text)
                             if proc_macro.kind == ProcMacroKind::Attr =>
                         {
-                            ExpandResult { value: tt.clone(), err: Some(ExpandError::other(text)) }
+                            ExpandResult {
+                                value: tt.clone(),
+                                err: Some(ExpandError::other(call_site, text)),
+                            }
                         }
                         ProcMacroExpansionError::System(text)
                         | ProcMacroExpansionError::Panic(text) => ExpandResult::new(
                             tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
-                            ExpandError::ProcMacroPanic(Arc::new(text.into_boxed_str())),
+                            ExpandError::new(
+                                call_site,
+                                ExpandErrorKind::ProcMacroPanic(text.into_boxed_str()),
+                            ),
                         ),
                     },
                 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 875cf87cb832c..5ee59efdbc48a 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -833,15 +833,23 @@ fn macro_call_diagnostics(
     let ValueResult { value: parse_errors, err } = &*e;
     if let Some(err) = err {
         let loc = db.lookup_intern_macro_call(macro_call_id);
-        let (node, precise_location, _macro_name, _kind) =
-            precise_macro_call_location(&loc.kind, db);
+        let file_id = loc.kind.file_id();
+        let node =
+            InFile::new(file_id, db.ast_id_map(file_id).get_erased(loc.kind.erased_ast_id()));
         let (message, error) = err.render_to_string(db.upcast());
+        let precise_location = Some(
+            err.span().range
+                + db.ast_id_map(err.span().anchor.file_id.into())
+                    .get_erased(err.span().anchor.ast_id)
+                    .text_range()
+                    .start(),
+        );
         acc.push(MacroError { node, precise_location, message, error }.into());
     }
 
     if !parse_errors.is_empty() {
         let loc = db.lookup_intern_macro_call(macro_call_id);
-        let (node, precise_location, _, _) = precise_macro_call_location(&loc.kind, db);
+        let (node, precise_location) = precise_macro_call_location(&loc.kind, db);
         acc.push(
             MacroExpansionParseError { node, precise_location, errors: parse_errors.clone() }
                 .into(),
@@ -891,14 +899,14 @@ fn emit_def_diagnostic_(
             acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
         }
 
-        DefDiagnosticKind::MacroError { ast, err } => {
+        DefDiagnosticKind::MacroError { ast, path, err } => {
             let item = ast.to_ptr(db.upcast());
             let (message, error) = err.render_to_string(db.upcast());
             acc.push(
                 MacroError {
                     node: InFile::new(ast.file_id, item.syntax_node_ptr()),
                     precise_location: None,
-                    message,
+                    message: format!("{}: {message}", path.display(db.upcast())),
                     error,
                 }
                 .into(),
@@ -1001,7 +1009,7 @@ fn emit_def_diagnostic_(
             })();
         }
         DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
-            let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
+            let (node, precise_location) = precise_macro_call_location(ast, db);
             acc.push(
                 UnresolvedMacroCall {
                     macro_call: node,
@@ -1070,7 +1078,7 @@ fn emit_def_diagnostic_(
 fn precise_macro_call_location(
     ast: &MacroCallKind,
     db: &dyn HirDatabase,
-) -> (InFile, Option, Option, MacroKind) {
+) -> (InFile, Option) {
     // FIXME: maybe we actually want slightly different ranges for the different macro diagnostics
     // - e.g. the full attribute for macro errors, but only the name for name resolution
     match ast {
@@ -1082,8 +1090,6 @@ fn precise_macro_call_location(
                     .and_then(|it| it.segment())
                     .and_then(|it| it.name_ref())
                     .map(|it| it.syntax().text_range()),
-                node.path().and_then(|it| it.segment()).map(|it| it.to_string()),
-                MacroKind::ProcMacro,
             )
         }
         MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
@@ -1112,8 +1118,6 @@ fn precise_macro_call_location(
             (
                 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
                 token.as_ref().map(|tok| tok.text_range()),
-                token.as_ref().map(ToString::to_string),
-                MacroKind::Derive,
             )
         }
         MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
@@ -1128,12 +1132,6 @@ fn precise_macro_call_location(
             (
                 ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
                 Some(attr.syntax().text_range()),
-                attr.path()
-                    .and_then(|path| path.segment())
-                    .and_then(|seg| seg.name_ref())
-                    .as_ref()
-                    .map(ToString::to_string),
-                MacroKind::Attr,
             )
         }
     }
@@ -1800,9 +1798,16 @@ impl DefWithBody {
                 BodyDiagnostic::MacroError { node, err } => {
                     let (message, error) = err.render_to_string(db.upcast());
 
+                    let precise_location = Some(
+                        err.span().range
+                            + db.ast_id_map(err.span().anchor.file_id.into())
+                                .get_erased(err.span().anchor.ast_id)
+                                .text_range()
+                                .start(),
+                    );
                     MacroError {
                         node: (*node).map(|it| it.into()),
-                        precise_location: None,
+                        precise_location,
                         message,
                         error,
                     }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
index 702fba448a0b4..08efd1a204a8f 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
@@ -168,12 +168,12 @@ fn main() {
     // Test a handful of built-in (eager) macros:
 
     include!(invalid);
-  //^^^^^^^ error: could not convert tokens
+  //^^^^^^^ error: expected string literal
     include!("does not exist");
   //^^^^^^^ error: failed to load file `does not exist`
 
     env!(invalid);
-  //^^^ error: could not convert tokens
+  //^^^ error: expected string literal
 
     env!("OUT_DIR");
   //^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
index 1db2789eb33af..b6db4d2e76c40 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
@@ -45,7 +45,7 @@ fn benchmark_expand_macro_rules() {
         invocations
             .into_iter()
             .map(|(id, tt)| {
-                let res = rules[&id].expand(&tt, |_| (), true, DUMMY, Edition::CURRENT);
+                let res = rules[&id].expand(&tt, |_| (), DUMMY, Edition::CURRENT);
                 assert!(res.err.is_none());
                 res.value.0.token_trees.len()
             })
@@ -118,7 +118,7 @@ fn invocation_fixtures(
                         },
                         token_trees: token_trees.into_boxed_slice(),
                     };
-                    if it.expand(&subtree, |_| (), true, DUMMY, Edition::CURRENT).err.is_none() {
+                    if it.expand(&subtree, |_| (), DUMMY, Edition::CURRENT).err.is_none() {
                         res.push((name.clone(), subtree));
                         break;
                     }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
index 55b89aa848d5d..1979e5171ab0c 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
@@ -9,13 +9,12 @@ use intern::Symbol;
 use rustc_hash::FxHashMap;
 use span::{Edition, Span};
 
-use crate::{parser::MetaVarKind, ExpandError, ExpandResult, MatchedArmIndex};
+use crate::{parser::MetaVarKind, ExpandError, ExpandErrorKind, ExpandResult, MatchedArmIndex};
 
 pub(crate) fn expand_rules(
     rules: &[crate::Rule],
     input: &tt::Subtree,
     marker: impl Fn(&mut Span) + Copy,
-    new_meta_vars: bool,
     call_site: Span,
     def_site_edition: Edition,
 ) -> ExpandResult<(tt::Subtree, MatchedArmIndex)> {
@@ -27,13 +26,8 @@ pub(crate) fn expand_rules(
             // If we find a rule that applies without errors, we're done.
             // Unconditionally returning the transcription here makes the
             // `test_repeat_bad_var` test fail.
-            let ExpandResult { value, err: transcribe_err } = transcriber::transcribe(
-                &rule.rhs,
-                &new_match.bindings,
-                marker,
-                new_meta_vars,
-                call_site,
-            );
+            let ExpandResult { value, err: transcribe_err } =
+                transcriber::transcribe(&rule.rhs, &new_match.bindings, marker, call_site);
             if transcribe_err.is_none() {
                 return ExpandResult::ok((value, Some(idx as u32)));
             }
@@ -52,7 +46,7 @@ pub(crate) fn expand_rules(
     if let Some((match_, rule, idx)) = match_ {
         // if we got here, there was no match without errors
         let ExpandResult { value, err: transcribe_err } =
-            transcriber::transcribe(&rule.rhs, &match_.bindings, marker, new_meta_vars, call_site);
+            transcriber::transcribe(&rule.rhs, &match_.bindings, marker, call_site);
         ExpandResult { value: (value, idx.try_into().ok()), err: match_.err.or(transcribe_err) }
     } else {
         ExpandResult::new(
@@ -63,7 +57,7 @@ pub(crate) fn expand_rules(
                 },
                 None,
             ),
-            ExpandError::NoMatchingRule,
+            ExpandError::new(call_site, ExpandErrorKind::NoMatchingRule),
         )
     }
 }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
index 3762d20bab62e..e69d7d14e253a 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
@@ -70,7 +70,7 @@ use crate::{
     expander::{Binding, Bindings, ExpandResult, Fragment},
     expect_fragment,
     parser::{MetaVarKind, Op, RepeatKind, Separator},
-    ExpandError, MetaTemplate, ValueResult,
+    ExpandError, ExpandErrorKind, MetaTemplate, ValueResult,
 };
 
 impl Bindings {
@@ -510,11 +510,17 @@ fn match_loop_inner<'t>(
                     if matches!(rhs, tt::Leaf::Literal(it) if it.symbol == lhs.symbol) {
                         item.dot.next();
                     } else {
-                        res.add_err(ExpandError::UnexpectedToken);
+                        res.add_err(ExpandError::new(
+                            *rhs.span(),
+                            ExpandErrorKind::UnexpectedToken,
+                        ));
                         item.is_error = true;
                     }
                 } else {
-                    res.add_err(ExpandError::binding_error(format!("expected literal: `{lhs}`")));
+                    res.add_err(ExpandError::binding_error(
+                        src.clone().next().map_or(delim_span.close, |it| it.first_span()),
+                        format!("expected literal: `{lhs}`"),
+                    ));
                     item.is_error = true;
                 }
                 try_push!(next_items, item);
@@ -524,11 +530,17 @@ fn match_loop_inner<'t>(
                     if matches!(rhs, tt::Leaf::Ident(it) if it.sym == lhs.sym) {
                         item.dot.next();
                     } else {
-                        res.add_err(ExpandError::UnexpectedToken);
+                        res.add_err(ExpandError::new(
+                            *rhs.span(),
+                            ExpandErrorKind::UnexpectedToken,
+                        ));
                         item.is_error = true;
                     }
                 } else {
-                    res.add_err(ExpandError::binding_error(format!("expected ident: `{lhs}`")));
+                    res.add_err(ExpandError::binding_error(
+                        src.clone().next().map_or(delim_span.close, |it| it.first_span()),
+                        format!("expected ident: `{lhs}`"),
+                    ));
                     item.is_error = true;
                 }
                 try_push!(next_items, item);
@@ -538,8 +550,8 @@ fn match_loop_inner<'t>(
                 let error = if let Ok(rhs) = fork.expect_glued_punct() {
                     let first_is_single_quote = rhs[0].char == '\'';
                     let lhs = lhs.iter().map(|it| it.char);
-                    let rhs = rhs.iter().map(|it| it.char);
-                    if lhs.clone().eq(rhs) {
+                    let rhs_ = rhs.iter().map(|it| it.char);
+                    if lhs.clone().eq(rhs_) {
                         // HACK: here we use `meta_result` to pass `TtIter` back to caller because
                         // it might have been advanced multiple times. `ValueResult` is
                         // insignificant.
@@ -552,13 +564,19 @@ fn match_loop_inner<'t>(
                     if first_is_single_quote {
                         // If the first punct token is a single quote, that's a part of a lifetime
                         // ident, not a punct.
-                        ExpandError::UnexpectedToken
+                        ExpandError::new(
+                            rhs.get(1).map_or(rhs[0].span, |it| it.span),
+                            ExpandErrorKind::UnexpectedToken,
+                        )
                     } else {
                         let lhs = lhs.collect::();
-                        ExpandError::binding_error(format!("expected punct: `{lhs}`"))
+                        ExpandError::binding_error(rhs[0].span, format!("expected punct: `{lhs}`"))
                     }
                 } else {
-                    ExpandError::UnexpectedToken
+                    ExpandError::new(
+                        src.clone().next().map_or(delim_span.close, |it| it.first_span()),
+                        ExpandErrorKind::UnexpectedToken,
+                    )
                 };
 
                 res.add_err(error);
@@ -651,7 +669,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree, edition: Edition)
                 if let Some(item) = error_recover_item {
                     res.bindings = bindings_builder.build(&item);
                 }
-                res.add_err(ExpandError::UnexpectedToken);
+                res.add_err(ExpandError::new(span.open, ExpandErrorKind::UnexpectedToken));
             }
             return res;
         }
@@ -670,7 +688,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree, edition: Edition)
                 src = it;
                 res.unmatched_tts += src.len();
             }
-            res.add_err(ExpandError::LeftoverTokens);
+            res.add_err(ExpandError::new(span.open, ExpandErrorKind::LeftoverTokens));
 
             if let Some(error_recover_item) = error_recover_item {
                 res.bindings = bindings_builder.build(&error_recover_item);
@@ -746,9 +764,10 @@ fn match_meta_var(
 ) -> ExpandResult> {
     let fragment = match kind {
         MetaVarKind::Path => {
-            return expect_fragment(input, parser::PrefixEntryPoint::Path, edition).map(|it| {
-                it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
-            });
+            return expect_fragment(input, parser::PrefixEntryPoint::Path, edition, delim_span)
+                .map(|it| {
+                    it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
+                });
         }
         MetaVarKind::Expr => {
             // `expr` should not match underscores, let expressions, or inline const. The latter
@@ -763,37 +782,54 @@ fn match_meta_var(
                         || it.sym == sym::let_
                         || it.sym == sym::const_ =>
                 {
-                    return ExpandResult::only_err(ExpandError::NoMatchingRule)
+                    return ExpandResult::only_err(ExpandError::new(
+                        it.span,
+                        ExpandErrorKind::NoMatchingRule,
+                    ))
                 }
                 _ => {}
             };
-            return expect_fragment(input, parser::PrefixEntryPoint::Expr, edition).map(|tt| {
-                tt.map(|tt| match tt {
-                    tt::TokenTree::Leaf(leaf) => tt::Subtree {
-                        delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
-                        token_trees: Box::new([leaf.into()]),
-                    },
-                    tt::TokenTree::Subtree(mut s) => {
-                        if s.delimiter.kind == tt::DelimiterKind::Invisible {
-                            s.delimiter.kind = tt::DelimiterKind::Parenthesis;
+            return expect_fragment(input, parser::PrefixEntryPoint::Expr, edition, delim_span)
+                .map(|tt| {
+                    tt.map(|tt| match tt {
+                        tt::TokenTree::Leaf(leaf) => tt::Subtree {
+                            delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
+                            token_trees: Box::new([leaf.into()]),
+                        },
+                        tt::TokenTree::Subtree(mut s) => {
+                            if s.delimiter.kind == tt::DelimiterKind::Invisible {
+                                s.delimiter.kind = tt::DelimiterKind::Parenthesis;
+                            }
+                            s
                         }
-                        s
-                    }
-                })
-                .map(Fragment::Expr)
-            });
+                    })
+                    .map(Fragment::Expr)
+                });
         }
         MetaVarKind::Ident | MetaVarKind::Tt | MetaVarKind::Lifetime | MetaVarKind::Literal => {
+            let span = input.next_span();
             let tt_result = match kind {
                 MetaVarKind::Ident => input
                     .expect_ident()
                     .map(|ident| tt::Leaf::from(ident.clone()).into())
-                    .map_err(|()| ExpandError::binding_error("expected ident")),
-                MetaVarKind::Tt => {
-                    expect_tt(input).map_err(|()| ExpandError::binding_error("expected token tree"))
-                }
-                MetaVarKind::Lifetime => expect_lifetime(input)
-                    .map_err(|()| ExpandError::binding_error("expected lifetime")),
+                    .map_err(|()| {
+                        ExpandError::binding_error(
+                            span.unwrap_or(delim_span.close),
+                            "expected ident",
+                        )
+                    }),
+                MetaVarKind::Tt => expect_tt(input).map_err(|()| {
+                    ExpandError::binding_error(
+                        span.unwrap_or(delim_span.close),
+                        "expected token tree",
+                    )
+                }),
+                MetaVarKind::Lifetime => expect_lifetime(input).map_err(|()| {
+                    ExpandError::binding_error(
+                        span.unwrap_or(delim_span.close),
+                        "expected lifetime",
+                    )
+                }),
                 MetaVarKind::Literal => {
                     let neg = eat_char(input, '-');
                     input
@@ -808,7 +844,12 @@ fn match_meta_var(
                                 }),
                             }
                         })
-                        .map_err(|()| ExpandError::binding_error("expected literal"))
+                        .map_err(|()| {
+                            ExpandError::binding_error(
+                                span.unwrap_or(delim_span.close),
+                                "expected literal",
+                            )
+                        })
                 }
                 _ => unreachable!(),
             };
@@ -823,7 +864,7 @@ fn match_meta_var(
         MetaVarKind::Item => parser::PrefixEntryPoint::Item,
         MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
     };
-    expect_fragment(input, fragment, edition).map(|it| it.map(Fragment::Tokens))
+    expect_fragment(input, fragment, edition, delim_span).map(|it| it.map(Fragment::Tokens))
 }
 
 fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate) {
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
index 4de7cccd9680e..286bd748cbe7e 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
@@ -8,14 +8,17 @@ use tt::Delimiter;
 use crate::{
     expander::{Binding, Bindings, Fragment},
     parser::{MetaVarKind, Op, RepeatKind, Separator},
-    CountError, ExpandError, ExpandResult, MetaTemplate,
+    ExpandError, ExpandErrorKind, ExpandResult, MetaTemplate,
 };
 
 impl Bindings {
-    fn get(&self, name: &Symbol) -> Result<&Binding, ExpandError> {
+    fn get(&self, name: &Symbol, span: Span) -> Result<&Binding, ExpandError> {
         match self.inner.get(name) {
             Some(binding) => Ok(binding),
-            None => Err(ExpandError::UnresolvedBinding(Box::new(Box::from(name.as_str())))),
+            None => Err(ExpandError::new(
+                span,
+                ExpandErrorKind::UnresolvedBinding(Box::new(Box::from(name.as_str()))),
+            )),
         }
     }
 
@@ -27,10 +30,10 @@ impl Bindings {
         marker: impl Fn(&mut Span),
     ) -> Result {
         macro_rules! binding_err {
-            ($($arg:tt)*) => { ExpandError::binding_error(format!($($arg)*)) };
+            ($($arg:tt)*) => { ExpandError::binding_error(span, format!($($arg)*)) };
         }
 
-        let mut b = self.get(name)?;
+        let mut b = self.get(name, span)?;
         for nesting_state in nesting.iter_mut() {
             nesting_state.hit = true;
             b = match b {
@@ -142,10 +145,9 @@ pub(super) fn transcribe(
     template: &MetaTemplate,
     bindings: &Bindings,
     marker: impl Fn(&mut Span) + Copy,
-    new_meta_vars: bool,
     call_site: Span,
 ) -> ExpandResult> {
-    let mut ctx = ExpandCtx { bindings, nesting: Vec::new(), new_meta_vars, call_site };
+    let mut ctx = ExpandCtx { bindings, nesting: Vec::new(), call_site };
     let mut arena: Vec> = Vec::new();
     expand_subtree(&mut ctx, template, None, &mut arena, marker)
 }
@@ -165,7 +167,6 @@ struct NestingState {
 struct ExpandCtx<'a> {
     bindings: &'a Bindings,
     nesting: Vec,
-    new_meta_vars: bool,
     call_site: Span,
 }
 
@@ -263,7 +264,7 @@ fn expand_subtree(
                 );
             }
             Op::Count { name, depth } => {
-                let mut binding = match ctx.bindings.get(name) {
+                let mut binding = match ctx.bindings.get(name, ctx.call_site) {
                     Ok(b) => b,
                     Err(e) => {
                         if err.is_none() {
@@ -299,29 +300,11 @@ fn expand_subtree(
                     }
                 }
 
-                let res = if ctx.new_meta_vars {
-                    count(binding, 0, depth.unwrap_or(0))
-                } else {
-                    count_old(binding, 0, *depth)
-                };
+                let res = count(binding, 0, depth.unwrap_or(0));
 
-                let c = match res {
-                    Ok(c) => c,
-                    Err(e) => {
-                        // XXX: It *might* make sense to emit a dummy integer value like `0` here.
-                        // That would type inference a bit more robust in cases like
-                        // `v[${count(t)}]` where index doesn't matter, but also could lead to
-                        // wrong infefrence for cases like `tup.${count(t)}` where index itself
-                        // does matter.
-                        if err.is_none() {
-                            err = Some(e.into());
-                        }
-                        continue;
-                    }
-                };
                 arena.push(
                     tt::Leaf::Literal(tt::Literal {
-                        symbol: Symbol::integer(c),
+                        symbol: Symbol::integer(res),
                         span: ctx.call_site,
                         suffix: None,
                         kind: tt::LitKind::Integer,
@@ -353,7 +336,7 @@ fn expand_var(
 
     match ctx.bindings.get_fragment(v, id, &mut ctx.nesting, marker) {
         Ok(it) => ExpandResult::ok(it),
-        Err(ExpandError::UnresolvedBinding(_)) => {
+        Err(e) if matches!(e.inner.1, ExpandErrorKind::UnresolvedBinding(_)) => {
             // Note that it is possible to have a `$var` inside a macro which is not bound.
             // For example:
             // ```
@@ -435,7 +418,7 @@ fn expand_repeat(
                     }
                     .into(),
                 ),
-                err: Some(ExpandError::LimitExceeded),
+                err: Some(ExpandError::new(ctx.call_site, ExpandErrorKind::LimitExceeded)),
             };
         }
 
@@ -481,16 +464,16 @@ fn expand_repeat(
     let tt = tt::Subtree {
         delimiter: tt::Delimiter::invisible_spanned(ctx.call_site),
         token_trees: buf.into_boxed_slice(),
-    }
-    .into();
+    };
 
     if RepeatKind::OneOrMore == kind && counter == 0 {
+        let span = tt.delimiter.open;
         return ExpandResult {
-            value: Fragment::Tokens(tt),
-            err: Some(ExpandError::UnexpectedToken),
+            value: Fragment::Tokens(tt.into()),
+            err: Some(ExpandError::new(span, ExpandErrorKind::UnexpectedToken)),
         };
     }
-    ExpandResult { value: Fragment::Tokens(tt), err }
+    ExpandResult { value: Fragment::Tokens(tt.into()), err }
 }
 
 fn push_fragment(ctx: &ExpandCtx<'_>, buf: &mut Vec>, fragment: Fragment) {
@@ -557,44 +540,16 @@ fn fix_up_and_push_path_tt(
 
 /// Handles `${count(t, depth)}`. `our_depth` is the recursion depth and `count_depth` is the depth
 /// defined by the metavar expression.
-fn count(binding: &Binding, depth_curr: usize, depth_max: usize) -> Result {
+fn count(binding: &Binding, depth_curr: usize, depth_max: usize) -> usize {
     match binding {
         Binding::Nested(bs) => {
             if depth_curr == depth_max {
-                Ok(bs.len())
+                bs.len()
             } else {
                 bs.iter().map(|b| count(b, depth_curr + 1, depth_max)).sum()
             }
         }
-        Binding::Empty => Ok(0),
-        Binding::Fragment(_) | Binding::Missing(_) => Ok(1),
-    }
-}
-
-fn count_old(
-    binding: &Binding,
-    our_depth: usize,
-    count_depth: Option,
-) -> Result {
-    match binding {
-        Binding::Nested(bs) => match count_depth {
-            None => bs.iter().map(|b| count_old(b, our_depth + 1, None)).sum(),
-            Some(0) => Ok(bs.len()),
-            Some(d) => bs.iter().map(|b| count_old(b, our_depth + 1, Some(d - 1))).sum(),
-        },
-        Binding::Empty => Ok(0),
-        Binding::Fragment(_) | Binding::Missing(_) => {
-            if our_depth == 0 {
-                // `${count(t)}` is placed inside the innermost repetition. This includes cases
-                // where `t` is not a repeated fragment.
-                Err(CountError::Misplaced)
-            } else if count_depth.is_none() {
-                Ok(1)
-            } else {
-                // We've reached at the innermost repeated fragment, but the user wants us to go
-                // further!
-                Err(CountError::OutOfBounds)
-            }
-        }
+        Binding::Empty => 0,
+        Binding::Fragment(_) | Binding::Missing(_) => 1,
     }
 }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
index bd7cb3ce7a4c1..568490d57345f 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
@@ -15,10 +15,11 @@ mod to_parser_input;
 mod benchmark;
 
 use span::{Edition, Span, SyntaxContextId};
-use stdx::impl_from;
 use tt::iter::TtIter;
+use tt::DelimSpan;
 
 use std::fmt;
+use std::sync::Arc;
 
 use crate::parser::{MetaTemplate, MetaVarKind, Op};
 
@@ -64,39 +65,45 @@ impl fmt::Display for ParseError {
 }
 
 #[derive(Debug, PartialEq, Eq, Clone, Hash)]
-pub enum ExpandError {
+pub struct ExpandError {
+    pub inner: Arc<(Span, ExpandErrorKind)>,
+}
+#[derive(Debug, PartialEq, Eq, Clone, Hash)]
+pub enum ExpandErrorKind {
     BindingError(Box>),
     UnresolvedBinding(Box>),
     LeftoverTokens,
-    ConversionError,
     LimitExceeded,
     NoMatchingRule,
     UnexpectedToken,
-    CountError(CountError),
 }
 
-impl_from!(CountError for ExpandError);
-
 impl ExpandError {
-    fn binding_error(e: impl Into>) -> ExpandError {
-        ExpandError::BindingError(Box::new(e.into()))
+    fn new(span: Span, kind: ExpandErrorKind) -> ExpandError {
+        ExpandError { inner: Arc::new((span, kind)) }
+    }
+    fn binding_error(span: Span, e: impl Into>) -> ExpandError {
+        ExpandError { inner: Arc::new((span, ExpandErrorKind::BindingError(Box::new(e.into())))) }
     }
 }
-
 impl fmt::Display for ExpandError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.inner.1.fmt(f)
+    }
+}
+
+impl fmt::Display for ExpandErrorKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            ExpandError::NoMatchingRule => f.write_str("no rule matches input tokens"),
-            ExpandError::UnexpectedToken => f.write_str("unexpected token in input"),
-            ExpandError::BindingError(e) => f.write_str(e),
-            ExpandError::UnresolvedBinding(binding) => {
+            ExpandErrorKind::NoMatchingRule => f.write_str("no rule matches input tokens"),
+            ExpandErrorKind::UnexpectedToken => f.write_str("unexpected token in input"),
+            ExpandErrorKind::BindingError(e) => f.write_str(e),
+            ExpandErrorKind::UnresolvedBinding(binding) => {
                 f.write_str("could not find binding ")?;
                 f.write_str(binding)
             }
-            ExpandError::ConversionError => f.write_str("could not convert tokens"),
-            ExpandError::LimitExceeded => f.write_str("Expand exceed limit"),
-            ExpandError::LeftoverTokens => f.write_str("leftover tokens"),
-            ExpandError::CountError(e) => e.fmt(f),
+            ExpandErrorKind::LimitExceeded => f.write_str("Expand exceed limit"),
+            ExpandErrorKind::LeftoverTokens => f.write_str("leftover tokens"),
         }
     }
 }
@@ -248,11 +255,10 @@ impl DeclarativeMacro {
         &self,
         tt: &tt::Subtree,
         marker: impl Fn(&mut Span) + Copy,
-        new_meta_vars: bool,
         call_site: Span,
         def_site_edition: Edition,
     ) -> ExpandResult<(tt::Subtree, MatchedArmIndex)> {
-        expander::expand_rules(&self.rules, tt, marker, new_meta_vars, call_site, def_site_edition)
+        expander::expand_rules(&self.rules, tt, marker, call_site, def_site_edition)
     }
 }
 
@@ -355,11 +361,12 @@ impl From> for ValueResult {
     }
 }
 
-fn expect_fragment(
-    tt_iter: &mut TtIter<'_, S>,
+fn expect_fragment(
+    tt_iter: &mut TtIter<'_, Span>,
     entry_point: ::parser::PrefixEntryPoint,
     edition: ::parser::Edition,
-) -> ExpandResult>> {
+    delim_span: DelimSpan,
+) -> ExpandResult>> {
     use ::parser;
     let buffer = tt::buffer::TokenBuffer::from_tokens(tt_iter.as_slice());
     let parser_input = to_parser_input::to_parser_input(edition, &buffer);
@@ -387,7 +394,10 @@ fn expect_fragment(
     }
 
     let err = if error || !cursor.is_root() {
-        Some(ExpandError::binding_error(format!("expected {entry_point:?}")))
+        Some(ExpandError::binding_error(
+            buffer.begin().token_tree().map_or(delim_span.close, |tt| tt.span()),
+            format!("expected {entry_point:?}"),
+        ))
     } else {
         None
     };
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
index ee61d7a21bea9..a29efdd4ef77e 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
@@ -212,15 +212,12 @@ where
 }
 
 /// Split token tree with separate expr: $($e:expr)SEP*
-pub fn parse_exprs_with_sep(
-    tt: &tt::Subtree,
+pub fn parse_exprs_with_sep(
+    tt: &tt::Subtree,
     sep: char,
-    span: S,
+    span: span::Span,
     edition: Edition,
-) -> Vec>
-where
-    S: Copy + fmt::Debug,
-{
+) -> Vec> {
     if tt.token_trees.is_empty() {
         return Vec::new();
     }
@@ -229,7 +226,12 @@ where
     let mut res = Vec::new();
 
     while iter.peek_n(0).is_some() {
-        let expanded = crate::expect_fragment(&mut iter, parser::PrefixEntryPoint::Expr, edition);
+        let expanded = crate::expect_fragment(
+            &mut iter,
+            parser::PrefixEntryPoint::Expr,
+            edition,
+            tt::DelimSpan { open: tt.delimiter.open, close: tt.delimiter.close },
+        );
 
         res.push(match expanded.value {
             None => break,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index ccc786a21d588..58d73611c63e3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -1053,6 +1053,7 @@ impl GlobalState {
             .on::(handlers::handle_goto_declaration)
             .on::(handlers::handle_goto_implementation)
             .on::(handlers::handle_goto_type_definition)
+            // FIXME: This should not be tried as it contains offsets that can get outdated!
             .on::(handlers::handle_inlay_hints)
             .on::(handlers::handle_inlay_hints_resolve)
             .on::(handlers::handle_code_lens)
diff --git a/src/tools/rust-analyzer/crates/tt/src/buffer.rs b/src/tools/rust-analyzer/crates/tt/src/buffer.rs
index cd41af03c613e..1319739371ff6 100644
--- a/src/tools/rust-analyzer/crates/tt/src/buffer.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/buffer.rs
@@ -134,6 +134,15 @@ pub enum TokenTreeRef<'a, Span> {
     Leaf(&'a Leaf, &'a TokenTree),
 }
 
+impl<'a, Span: Copy> TokenTreeRef<'a, Span> {
+    pub fn span(&self) -> Span {
+        match self {
+            TokenTreeRef::Subtree(subtree, _) => subtree.delimiter.open,
+            TokenTreeRef::Leaf(leaf, _) => *leaf.span(),
+        }
+    }
+}
+
 impl TokenTreeRef<'_, Span> {
     pub fn cloned(&self) -> TokenTree {
         match self {
diff --git a/src/tools/rust-analyzer/crates/tt/src/iter.rs b/src/tools/rust-analyzer/crates/tt/src/iter.rs
index c0195b835ac6c..e96bed0319e12 100644
--- a/src/tools/rust-analyzer/crates/tt/src/iter.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/iter.rs
@@ -143,6 +143,10 @@ impl<'a, S: Copy> TtIter<'a, S> {
         self.inner.as_slice().get(n)
     }
 
+    pub fn next_span(&self) -> Option {
+        Some(self.inner.as_slice().first()?.first_span())
+    }
+
     pub fn as_slice(&self) -> &'a [TokenTree] {
         self.inner.as_slice()
     }

From eb0e71620d7f927dc3f10598409d4375b5374dcf Mon Sep 17 00:00:00 2001
From: Alex Macleod 
Date: Mon, 29 Jul 2024 13:11:29 +0000
Subject: [PATCH 226/489] Make `rustc_attr::parse_version` pub

---
 compiler/rustc_attr/src/builtin.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 34c24a26f7b13..acb4f0a82665f 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -574,7 +574,7 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Fea
 /// Parse a rustc version number written inside string literal in an attribute,
 /// like appears in `since = "1.0.0"`. Suffixes like "-dev" and "-nightly" are
 /// not accepted in this position, unlike when parsing CFG_RELEASE.
-fn parse_version(s: Symbol) -> Option {
+pub fn parse_version(s: Symbol) -> Option {
     let mut components = s.as_str().split('-');
     let d = components.next()?;
     if components.next().is_some() {

From 06d64ea4c413c94e158a167020b4a5fb57958710 Mon Sep 17 00:00:00 2001
From: onur-ozkan 
Date: Mon, 29 Jul 2024 16:31:21 +0300
Subject: [PATCH 227/489] simplify the use of `CiEnv`

Signed-off-by: onur-ozkan 
---
 src/bootstrap/src/core/build_steps/test.rs | 2 +-
 src/bootstrap/src/core/builder.rs          | 2 +-
 src/bootstrap/src/core/config/config.rs    | 2 +-
 src/bootstrap/src/lib.rs                   | 4 +---
 src/bootstrap/src/utils/exec.rs            | 4 ++--
 5 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 79b7dd78810d2..aa0c76ab15753 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -2087,7 +2087,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         let git_config = builder.config.git_config();
         cmd.arg("--git-repository").arg(git_config.git_repository);
         cmd.arg("--nightly-branch").arg(git_config.nightly_branch);
-        cmd.force_coloring_in_ci(builder.ci_env);
+        cmd.force_coloring_in_ci();
 
         #[cfg(feature = "build-metrics")]
         builder.metrics.begin_test_suite(
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 9eb4ca033a80f..84c23c059e97e 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -2157,7 +2157,7 @@ impl<'a> Builder<'a> {
         // Try to use a sysroot-relative bindir, in case it was configured absolutely.
         cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative());
 
-        cargo.force_coloring_in_ci(self.ci_env);
+        cargo.force_coloring_in_ci();
 
         // When we build Rust dylibs they're all intended for intermediate
         // usage, so make sure we pass the -Cprefer-dynamic flag instead of
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index b0a967d756b64..1343e257efe08 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -2092,7 +2092,7 @@ impl Config {
 
         // CI should always run stage 2 builds, unless it specifically states otherwise
         #[cfg(not(test))]
-        if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None {
+        if flags.stage.is_none() && build_helper::ci::CiEnv::is_ci() {
             match config.cmd {
                 Subcommand::Test { .. }
                 | Subcommand::Miri { .. }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index d2f5d1667189c..453fb39327d63 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -26,7 +26,7 @@ use std::sync::OnceLock;
 use std::time::SystemTime;
 use std::{env, io, str};
 
-use build_helper::ci::{gha, CiEnv};
+use build_helper::ci::gha;
 use build_helper::exit;
 use sha2::digest::Digest;
 use termcolor::{ColorChoice, StandardStream, WriteColor};
@@ -168,7 +168,6 @@ pub struct Build {
     crates: HashMap,
     crate_paths: HashMap,
     is_sudo: bool,
-    ci_env: CiEnv,
     delayed_failures: RefCell>,
     prerelease_version: Cell>,
 
@@ -400,7 +399,6 @@ impl Build {
             crates: HashMap::new(),
             crate_paths: HashMap::new(),
             is_sudo,
-            ci_env: CiEnv::current(),
             delayed_failures: RefCell::new(Vec::new()),
             prerelease_version: Cell::new(None),
 
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index e1387bbbd35d7..9f0d0b7e9691f 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -175,8 +175,8 @@ impl BootstrapCommand {
     }
 
     /// If in a CI environment, forces the command to run with colors.
-    pub fn force_coloring_in_ci(&mut self, ci_env: CiEnv) {
-        if ci_env != CiEnv::None {
+    pub fn force_coloring_in_ci(&mut self) {
+        if CiEnv::is_ci() {
             // Due to use of stamp/docker, the output stream of bootstrap is not
             // a TTY in CI, so coloring is by-default turned off.
             // The explicit `TERM=xterm` environment is needed for

From a8957974550b26fe59fa80ae6adf7771a3c1cb88 Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Mon, 29 Jul 2024 15:57:01 +0200
Subject: [PATCH 228/489] Fix error spans for include! and compile_error!

---
 .../crates/hir-expand/src/builtin/fn_macro.rs | 20 ++++++-----
 src/tools/rust-analyzer/crates/hir/src/lib.rs | 36 +++++++++++--------
 .../src/handlers/macro_error.rs               | 19 ++++++----
 .../rust-analyzer/crates/span/src/lib.rs      | 10 ++++++
 4 files changed, 56 insertions(+), 29 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index 0b844c0a634e9..391b891ad6cdb 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -460,10 +460,10 @@ fn compile_error_expand(
     let err = match &*tt.token_trees {
         [tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
             symbol: text,
-            span,
+            span: _,
             kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
             suffix: _,
-        }))] => ExpandError::other(*span, Box::from(unescape_str(text).as_str())),
+        }))] => ExpandError::other(span, Box::from(unescape_str(text).as_str())),
         _ => ExpandError::other(span, "`compile_error!` argument must be a string"),
     };
 
@@ -706,18 +706,19 @@ fn relative_file(
 fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
     tt.token_trees
         .first()
+        .ok_or(tt.delimiter.open.cover(tt.delimiter.close))
         .and_then(|tt| match tt {
             tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
                 symbol: text,
                 span,
                 kind: tt::LitKind::Str,
                 suffix: _,
-            })) => Some((unescape_str(text), *span)),
+            })) => Ok((unescape_str(text), *span)),
             // FIXME: We wrap expression fragments in parentheses which can break this expectation
             // here
             // Remove this once we handle none delims correctly
-            tt::TokenTree::Subtree(t) if t.delimiter.kind == DelimiterKind::Parenthesis => {
-                t.token_trees.first().and_then(|tt| match tt {
+            tt::TokenTree::Subtree(tt) if tt.delimiter.kind == DelimiterKind::Parenthesis => {
+                tt.token_trees.first().and_then(|tt| match tt {
                     tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
                         symbol: text,
                         span,
@@ -727,9 +728,11 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
                     _ => None,
                 })
             }
-            _ => None,
+            .ok_or(tt.delimiter.open.cover(tt.delimiter.close)),
+            ::tt::TokenTree::Leaf(l) => Err(*l.span()),
+            ::tt::TokenTree::Subtree(tt) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
         })
-        .ok_or(ExpandError::other(tt.delimiter.open, "expected string literal"))
+        .map_err(|span| ExpandError::other(span, "expected string literal"))
 }
 
 fn include_expand(
@@ -763,7 +766,8 @@ pub fn include_input_to_file_id(
     arg_id: MacroCallId,
     arg: &tt::Subtree,
 ) -> Result {
-    relative_file(db, arg_id, parse_string(arg)?.0.as_str(), false, arg.delimiter.open)
+    let (s, span) = parse_string(arg)?;
+    relative_file(db, arg_id, s.as_str(), false, span)
 }
 
 fn include_bytes_expand(
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 5ee59efdbc48a..266ef2a55c520 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -837,13 +837,17 @@ fn macro_call_diagnostics(
         let node =
             InFile::new(file_id, db.ast_id_map(file_id).get_erased(loc.kind.erased_ast_id()));
         let (message, error) = err.render_to_string(db.upcast());
-        let precise_location = Some(
-            err.span().range
-                + db.ast_id_map(err.span().anchor.file_id.into())
-                    .get_erased(err.span().anchor.ast_id)
-                    .text_range()
-                    .start(),
-        );
+        let precise_location = if err.span().anchor.file_id == file_id {
+            Some(
+                err.span().range
+                    + db.ast_id_map(err.span().anchor.file_id.into())
+                        .get_erased(err.span().anchor.ast_id)
+                        .text_range()
+                        .start(),
+            )
+        } else {
+            None
+        };
         acc.push(MacroError { node, precise_location, message, error }.into());
     }
 
@@ -1798,13 +1802,17 @@ impl DefWithBody {
                 BodyDiagnostic::MacroError { node, err } => {
                     let (message, error) = err.render_to_string(db.upcast());
 
-                    let precise_location = Some(
-                        err.span().range
-                            + db.ast_id_map(err.span().anchor.file_id.into())
-                                .get_erased(err.span().anchor.ast_id)
-                                .text_range()
-                                .start(),
-                    );
+                    let precise_location = if err.span().anchor.file_id == node.file_id {
+                        Some(
+                            err.span().range
+                                + db.ast_id_map(err.span().anchor.file_id.into())
+                                    .get_erased(err.span().anchor.ast_id)
+                                    .text_range()
+                                    .start(),
+                        )
+                    } else {
+                        None
+                    };
                     MacroError {
                         node: (*node).map(|it| it.into()),
                         precise_location,
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
index 08efd1a204a8f..e59b63f288dde 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
@@ -48,7 +48,7 @@ macro_rules! include { () => {} }
 macro_rules! compile_error { () => {} }
 
   include!("doesntexist");
-//^^^^^^^ error: failed to load file `doesntexist`
+         //^^^^^^^^^^^^^ error: failed to load file `doesntexist`
 
   compile_error!("compile_error macro works");
 //^^^^^^^^^^^^^ error: compile_error macro works
@@ -128,7 +128,7 @@ macro_rules! env { () => {} }
 macro_rules! concat { () => {} }
 
   include!(concat!(env!("OUT_DIR"), "/out.rs"));
-//^^^^^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
+                      //^^^^^^^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
 "#,
         );
     }
@@ -163,20 +163,25 @@ macro_rules! include {}
 
 #[rustc_builtin_macro]
 macro_rules! compile_error {}
+#[rustc_builtin_macro]
+macro_rules! concat {}
 
 fn main() {
     // Test a handful of built-in (eager) macros:
 
     include!(invalid);
-  //^^^^^^^ error: expected string literal
+           //^^^^^^^ error: expected string literal
     include!("does not exist");
-  //^^^^^^^ error: failed to load file `does not exist`
+           //^^^^^^^^^^^^^^^^ error: failed to load file `does not exist`
+
+    include!(concat!("does ", "not ", "exist"));
+                  //^^^^^^^^^^^^^^^^^^^^^^^^^^ error: failed to load file `does not exist`
 
     env!(invalid);
-  //^^^ error: expected string literal
+       //^^^^^^^ error: expected string literal
 
     env!("OUT_DIR");
-  //^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
+       //^^^^^^^^^ error: `OUT_DIR` not set, enable "build scripts" to fix
 
     compile_error!("compile_error works");
   //^^^^^^^^^^^^^ error: compile_error works
@@ -201,7 +206,7 @@ fn f() {
     m!();
 
     m!(hi);
-  //^ error: leftover tokens
+    //^ error: leftover tokens
 }
       "#,
         );
diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs
index 057fab89c71f6..b4e21d64f81e3 100644
--- a/src/tools/rust-analyzer/crates/span/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/span/src/lib.rs
@@ -33,6 +33,16 @@ pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId =
 
 pub type Span = SpanData;
 
+impl Span {
+    pub fn cover(self, other: Span) -> Span {
+        if self.anchor != other.anchor {
+            return self;
+        }
+        let range = self.range.cover(other.range);
+        Span { range, ..self }
+    }
+}
+
 /// Spans represent a region of code, used by the IDE to be able link macro inputs and outputs
 /// together. Positions in spans are relative to some [`SpanAnchor`] to make them more incremental
 /// friendly.

From 5ac8b79ca8087fa86185ba2c472ee5e0ceae6e5c Mon Sep 17 00:00:00 2001
From: Lukas Wirth 
Date: Mon, 29 Jul 2024 16:05:21 +0200
Subject: [PATCH 229/489] Add missing doc string

---
 src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs
index 4e6349c31da59..252430e4e954a 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin.rs
@@ -1,3 +1,4 @@
+//! Builtin macros and attributes
 #[macro_use]
 mod quote;
 

From 97469cc4bf5d682ded196c60ee30d6a392b645aa Mon Sep 17 00:00:00 2001
From: bohan 
Date: Mon, 29 Jul 2024 22:29:12 +0800
Subject: [PATCH 230/489] only accept adt type during infer source visitor

---
 .../error_reporting/infer/need_type_info.rs   |  8 ++---
 tests/crashes/121613-2.rs                     | 28 ----------------
 tests/crashes/121613.rs                       | 24 --------------
 .../incompat-call-after-qualified-path-0.rs   | 24 ++++++++++++++
 ...ncompat-call-after-qualified-path-0.stderr | 32 +++++++++++++++++++
 .../incompat-call-after-qualified-path-1.rs   | 28 ++++++++++++++++
 ...ncompat-call-after-qualified-path-1.stderr | 32 +++++++++++++++++++
 7 files changed, 120 insertions(+), 56 deletions(-)
 delete mode 100644 tests/crashes/121613-2.rs
 delete mode 100644 tests/crashes/121613.rs
 create mode 100644 tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.rs
 create mode 100644 tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.stderr
 create mode 100644 tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.rs
 create mode 100644 tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.stderr

diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index f667e4c80fd49..f6dd7898fb28e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -934,13 +934,13 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
             // which makes this somewhat difficult and prevents us from just
             // using `self.path_inferred_arg_iter` here.
             hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _)
-            // FIXME(TaKO8Ki): Ideally we should support this. For that
-            // we have to map back from the self type to the
-            // type alias though. That's difficult.
+            // FIXME(TaKO8Ki): Ideally we should support other kinds,
+            // such as `TyAlias` or `AssocTy`. For that we have to map
+            // back from the self type to the type alias though. That's difficult.
             //
             // See the `need_type_info/issue-103053.rs` test for
             // a example.
-            if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => {
+            if matches!(path.res, Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) => {
                 if let Some(ty) = self.opt_node_type(expr.hir_id)
                     && let ty::Adt(_, args) = ty.kind()
                 {
diff --git a/tests/crashes/121613-2.rs b/tests/crashes/121613-2.rs
deleted file mode 100644
index ddc4f37c96a2f..0000000000000
--- a/tests/crashes/121613-2.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//@ known-bug: #121613
-fn main() {
-    // destructure through a qualified path
-    let ::Assoc { br } = StructStruct { br: 2 };
-    //~^ ERROR usage of qualified paths in this context is experimental
-    let _ = ::Assoc { br: 2 };
-    //~^ ERROR usage of qualified paths in this context is experimental
-    let ::V(..) = E::V(|a, b| a.cmp(b));
-    //~^ ERROR usage of qualified paths in this context is experimental
-}
-
-struct StructStruct {
-    br: i8,
-}
-
-struct Foo;
-
-trait A {
-    type Assoc;
-}
-
-impl A for Foo {
-    type Assoc = StructStruct;
-}
-
-enum E {
-    V(u8)
-}
diff --git a/tests/crashes/121613.rs b/tests/crashes/121613.rs
deleted file mode 100644
index ec9ba82a68c5f..0000000000000
--- a/tests/crashes/121613.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-//@ known-bug: #121613
-fn main() {
-    let _ = ::Assoc { br: 2 };
-
-    let ::V(..) = E::V(|a, b| a.cmp(b));
-}
-
-struct StructStruct {
-    br: i8,
-}
-
-struct Foo;
-
-trait A {
-    type Assoc;
-}
-
-impl A for Foo {
-    type Assoc = StructStruct;
-}
-
-enum E {
-    V(u8),
-}
diff --git a/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.rs b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.rs
new file mode 100644
index 0000000000000..830a6390fce6d
--- /dev/null
+++ b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.rs
@@ -0,0 +1,24 @@
+// issue#121613
+
+#![feature(more_qualified_paths)]
+
+struct S {}
+
+struct Foo;
+
+trait A {
+    type Assoc;
+}
+
+impl A for Foo {
+    type Assoc = S;
+}
+
+fn f() {}
+
+fn main() {
+  ::Assoc {};
+  f(|a, b| a.cmp(b));
+  //~^ ERROR: type annotations needed
+  //~| ERROR: this function takes 0 arguments but 1 argument was supplied
+}
diff --git a/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.stderr b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.stderr
new file mode 100644
index 0000000000000..10056bdf3d4f4
--- /dev/null
+++ b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-0.stderr
@@ -0,0 +1,32 @@
+error[E0282]: type annotations needed
+  --> $DIR/incompat-call-after-qualified-path-0.rs:21:6
+   |
+LL |   f(|a, b| a.cmp(b));
+   |      ^     - type must be known at this point
+   |
+help: consider giving this closure parameter an explicit type
+   |
+LL |   f(|a: /* Type */, b| a.cmp(b));
+   |       ++++++++++++
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/incompat-call-after-qualified-path-0.rs:21:3
+   |
+LL |   f(|a, b| a.cmp(b));
+   |   ^ --------------- unexpected argument
+   |
+note: function defined here
+  --> $DIR/incompat-call-after-qualified-path-0.rs:17:4
+   |
+LL | fn f() {}
+   |    ^
+help: remove the extra argument
+   |
+LL -   f(|a, b| a.cmp(b));
+LL +   f();
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0282.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.rs b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.rs
new file mode 100644
index 0000000000000..6b786332a8f43
--- /dev/null
+++ b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.rs
@@ -0,0 +1,28 @@
+// issue#121613
+
+#![feature(more_qualified_paths)]
+
+struct S {
+    a: T
+}
+
+struct Foo;
+
+trait A {
+    type Assoc;
+}
+
+impl A for Foo {
+    type Assoc = S;
+}
+
+fn f() {}
+
+fn main() {
+  ::Assoc:: {
+    a: 1
+  };
+  f(|a, b| a.cmp(b));
+  //~^ ERROR: type annotations needed
+  //~| ERROR: this function takes 0 arguments but 1 argument was supplied
+}
diff --git a/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.stderr b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.stderr
new file mode 100644
index 0000000000000..632a9b99f84ef
--- /dev/null
+++ b/tests/ui/inference/need_type_info/incompat-call-after-qualified-path-1.stderr
@@ -0,0 +1,32 @@
+error[E0282]: type annotations needed
+  --> $DIR/incompat-call-after-qualified-path-1.rs:25:6
+   |
+LL |   f(|a, b| a.cmp(b));
+   |      ^     - type must be known at this point
+   |
+help: consider giving this closure parameter an explicit type
+   |
+LL |   f(|a: /* Type */, b| a.cmp(b));
+   |       ++++++++++++
+
+error[E0061]: this function takes 0 arguments but 1 argument was supplied
+  --> $DIR/incompat-call-after-qualified-path-1.rs:25:3
+   |
+LL |   f(|a, b| a.cmp(b));
+   |   ^ --------------- unexpected argument
+   |
+note: function defined here
+  --> $DIR/incompat-call-after-qualified-path-1.rs:19:4
+   |
+LL | fn f() {}
+   |    ^
+help: remove the extra argument
+   |
+LL -   f(|a, b| a.cmp(b));
+LL +   f();
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0061, E0282.
+For more information about an error, try `rustc --explain E0061`.

From 794434ec639277273d2154607bdcbe033691cc29 Mon Sep 17 00:00:00 2001
From: EtomicBomb 
Date: Wed, 24 Jul 2024 21:52:32 +0000
Subject: [PATCH 231/489] initial implementation of rustdoc nested aux-build

---
 src/tools/compiletest/src/command-list.rs     |   2 +
 src/tools/compiletest/src/header.rs           |  13 +++
 src/tools/compiletest/src/runtest.rs          | 104 ++++++++++++------
 src/tools/compiletest/src/runtest/coverage.rs |   2 +-
 .../cargo-transitive-no-index/auxiliary/q.rs  |   4 +
 .../cargo-transitive-no-index/auxiliary/t.rs  |   6 +
 .../cargo-transitive-no-index/s.rs            |  17 +++
 .../cargo-transitive/auxiliary/q.rs           |   6 +
 .../cargo-transitive/auxiliary/t.rs           |   8 ++
 .../cross-crate-info/cargo-transitive/s.rs    |  24 ++++
 .../cargo-two-no-index/auxiliary/f.rs         |   4 +
 .../cross-crate-info/cargo-two-no-index/e.rs  |  15 +++
 .../cross-crate-info/cargo-two/auxiliary/f.rs |   6 +
 tests/rustdoc/cross-crate-info/cargo-two/e.rs |  21 ++++
 .../index-on-last/auxiliary/f.rs              |   4 +
 .../cross-crate-info/index-on-last/e.rs       |  21 ++++
 .../kitchen-sink/auxiliary/q.rs               |   6 +
 .../kitchen-sink/auxiliary/r.rs               |   8 ++
 .../kitchen-sink/auxiliary/s.rs               |   9 ++
 .../kitchen-sink/auxiliary/t.rs               |   8 ++
 .../cross-crate-info/kitchen-sink/i.rs        |  32 ++++++
 .../single-crate-baseline/q.rs                |  13 +++
 .../single-crate-no-index/q.rs                |   8 ++
 .../transitive/auxiliary/q.rs                 |   4 +
 .../transitive/auxiliary/t.rs                 |   6 +
 .../rustdoc/cross-crate-info/transitive/s.rs  |   9 ++
 .../cross-crate-info/two/auxiliary/f.rs       |   4 +
 tests/rustdoc/cross-crate-info/two/e.rs       |   9 ++
 .../working-dir-examples/q.rs                 |  10 ++
 .../write-docs-somewhere-else/auxiliary/f.rs  |   5 +
 .../write-docs-somewhere-else/e.rs            |  15 +++
 31 files changed, 369 insertions(+), 34 deletions(-)
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs
 create mode 100644 tests/rustdoc/cross-crate-info/cargo-two/e.rs
 create mode 100644 tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs
 create mode 100644 tests/rustdoc/cross-crate-info/index-on-last/e.rs
 create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs
 create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs
 create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs
 create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs
 create mode 100644 tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
 create mode 100644 tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
 create mode 100644 tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
 create mode 100644 tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs
 create mode 100644 tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs
 create mode 100644 tests/rustdoc/cross-crate-info/transitive/s.rs
 create mode 100644 tests/rustdoc/cross-crate-info/two/auxiliary/f.rs
 create mode 100644 tests/rustdoc/cross-crate-info/two/e.rs
 create mode 100644 tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
 create mode 100644 tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs
 create mode 100644 tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs

diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs
index c356f4266f016..305bf9c228c43 100644
--- a/src/tools/compiletest/src/command-list.rs
+++ b/src/tools/compiletest/src/command-list.rs
@@ -9,6 +9,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "aux-codegen-backend",
     "aux-crate",
     "build-aux-docs",
+    "unique-doc-out-dir",
     "build-fail",
     "build-pass",
     "check-fail",
@@ -18,6 +19,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "check-test-line-numbers-match",
     "compare-output-lines-by-subset",
     "compile-flags",
+    "doc-flags",
     "dont-check-compiler-stderr",
     "dont-check-compiler-stdout",
     "dont-check-failure-status",
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 0208ed34ac182..3a08a8e38950c 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -95,6 +95,8 @@ pub struct TestProps {
     pub compile_flags: Vec,
     // Extra flags to pass when the compiled code is run (such as --bench)
     pub run_flags: Vec,
+    /// Extra flags to pass to rustdoc but not the compiler.
+    pub doc_flags: Vec,
     // If present, the name of a file that this test should match when
     // pretty-printed
     pub pp_exact: Option,
@@ -122,6 +124,9 @@ pub struct TestProps {
     pub unset_exec_env: Vec,
     // Build documentation for all specified aux-builds as well
     pub build_aux_docs: bool,
+    /// Build the documentation for each crate in a unique output directory.
+    /// Uses /docs//doc
+    pub unique_doc_out_dir: bool,
     // Flag to force a crate to be built with the host architecture
     pub force_host: bool,
     // Check stdout for error-pattern output as well as stderr
@@ -220,8 +225,10 @@ mod directives {
     pub const REGEX_ERROR_PATTERN: &'static str = "regex-error-pattern";
     pub const COMPILE_FLAGS: &'static str = "compile-flags";
     pub const RUN_FLAGS: &'static str = "run-flags";
+    pub const DOC_FLAGS: &'static str = "doc-flags";
     pub const SHOULD_ICE: &'static str = "should-ice";
     pub const BUILD_AUX_DOCS: &'static str = "build-aux-docs";
+    pub const UNIQUE_DOC_OUT_DIR: &'static str = "unique-doc-out-dir";
     pub const FORCE_HOST: &'static str = "force-host";
     pub const CHECK_STDOUT: &'static str = "check-stdout";
     pub const CHECK_RUN_RESULTS: &'static str = "check-run-results";
@@ -267,6 +274,7 @@ impl TestProps {
             regex_error_patterns: vec![],
             compile_flags: vec![],
             run_flags: vec![],
+            doc_flags: vec![],
             pp_exact: None,
             aux_builds: vec![],
             aux_bins: vec![],
@@ -281,6 +289,7 @@ impl TestProps {
             exec_env: vec![],
             unset_exec_env: vec![],
             build_aux_docs: false,
+            unique_doc_out_dir: false,
             force_host: false,
             check_stdout: false,
             check_run_results: false,
@@ -377,6 +386,8 @@ impl TestProps {
                         |r| r,
                     );
 
+                    config.push_name_value_directive(ln, DOC_FLAGS, &mut self.doc_flags, |r| r);
+
                     fn split_flags(flags: &str) -> Vec {
                         // Individual flags can be single-quoted to preserve spaces; see
                         // .
@@ -414,6 +425,8 @@ impl TestProps {
 
                     config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice);
                     config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs);
+                    config.set_name_directive(ln, UNIQUE_DOC_OUT_DIR, &mut self.unique_doc_out_dir);
+
                     config.set_name_directive(ln, FORCE_HOST, &mut self.force_host);
                     config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout);
                     config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results);
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index f6e8fdd624434..2d298dfbc06f7 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,5 +1,17 @@
 // ignore-tidy-filelength
 
+use crate::compute_diff::{write_diff, write_filtered_diff};
+use crate::errors::{self, Error, ErrorKind};
+use crate::header::TestProps;
+use crate::json;
+use crate::read2::{read2_abbreviated, Truncated};
+use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt};
+use crate::ColorConfig;
+use colored::Colorize;
+use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
+use regex::{Captures, Regex};
+use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
+use std::borrow::Cow;
 use std::collections::{HashMap, HashSet};
 use std::ffi::{OsStr, OsString};
 use std::fs::{self, create_dir_all, File, OpenOptions};
@@ -723,7 +735,7 @@ impl<'test> TestCx<'test> {
         self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags);
         rustc.args(&self.props.compile_flags);
 
-        self.compose_and_run_compiler(rustc, Some(src))
+        self.compose_and_run_compiler(rustc, Some(src), self.testpaths)
     }
 
     fn run_debuginfo_test(&self) {
@@ -1579,13 +1591,15 @@ impl<'test> TestCx<'test> {
             passes,
         );
 
-        self.compose_and_run_compiler(rustc, None)
+        self.compose_and_run_compiler(rustc, None, self.testpaths)
     }
 
-    fn document(&self, out_dir: &Path) -> ProcRes {
+    /// `root_out_dir` and `root_testpaths` refer to the parameters of the actual test being run.
+    /// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths.
+    fn document(&self, root_out_dir: &Path, root_testpaths: &TestPaths) -> ProcRes {
         if self.props.build_aux_docs {
             for rel_ab in &self.props.aux_builds {
-                let aux_testpaths = self.compute_aux_test_paths(&self.testpaths, rel_ab);
+                let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab);
                 let aux_props =
                     self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
                 let aux_cx = TestCx {
@@ -1596,7 +1610,7 @@ impl<'test> TestCx<'test> {
                 };
                 // Create the directory for the stdout/stderr files.
                 create_dir_all(aux_cx.output_base_dir()).unwrap();
-                let auxres = aux_cx.document(out_dir);
+                let auxres = aux_cx.document(&root_out_dir, root_testpaths);
                 if !auxres.status.success() {
                     return auxres;
                 }
@@ -1606,21 +1620,47 @@ impl<'test> TestCx<'test> {
         let aux_dir = self.aux_output_dir_name();
 
         let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed");
-        let mut rustdoc = Command::new(rustdoc_path);
 
+        // actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire
+        // test
+        let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir {
+            let file_name = self
+                .testpaths
+                .file
+                .file_name()
+                .expect("file name should not be empty")
+                .to_str()
+                .expect("file name utf8")
+                .trim_end_matches(".rs");
+            let out_dir = PathBuf::from_iter([
+                root_out_dir,
+                Path::new("docs"),
+                Path::new(file_name),
+                Path::new("doc"),
+            ]);
+            create_dir_all(&out_dir).unwrap();
+            Cow::Owned(out_dir)
+        } else {
+            Cow::Borrowed(root_out_dir)
+        };
+
+        let mut rustdoc = Command::new(rustdoc_path);
+        let current_dir = output_base_dir(self.config, root_testpaths, self.safe_revision());
+        rustdoc.current_dir(current_dir);
         rustdoc
             .arg("-L")
             .arg(self.config.run_lib_path.to_str().unwrap())
             .arg("-L")
             .arg(aux_dir)
             .arg("-o")
-            .arg(out_dir)
+            .arg(out_dir.as_ref())
             .arg("--deny")
             .arg("warnings")
             .arg(&self.testpaths.file)
             .arg("-A")
             .arg("internal_features")
-            .args(&self.props.compile_flags);
+            .args(&self.props.compile_flags)
+            .args(&self.props.doc_flags);
 
         if self.config.mode == RustdocJson {
             rustdoc.arg("--output-format").arg("json").arg("-Zunstable-options");
@@ -1630,7 +1670,7 @@ impl<'test> TestCx<'test> {
             rustdoc.arg(format!("-Clinker={}", linker));
         }
 
-        self.compose_and_run_compiler(rustdoc, None)
+        self.compose_and_run_compiler(rustdoc, None, root_testpaths)
     }
 
     fn exec_compiled_test(&self) -> ProcRes {
@@ -1828,9 +1868,16 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes {
+    /// `root_testpaths` refers to the path of the original test.
+    /// the auxiliary and the test with an aux-build have the same `root_testpaths`.
+    fn compose_and_run_compiler(
+        &self,
+        mut rustc: Command,
+        input: Option,
+        root_testpaths: &TestPaths,
+    ) -> ProcRes {
         let aux_dir = self.aux_output_dir();
-        self.build_all_auxiliary(&self.testpaths, &aux_dir, &mut rustc);
+        self.build_all_auxiliary(root_testpaths, &aux_dir, &mut rustc);
 
         rustc.envs(self.props.rustc_env.clone());
         self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove);
@@ -2545,7 +2592,7 @@ impl<'test> TestCx<'test> {
             Vec::new(),
         );
 
-        let proc_res = self.compose_and_run_compiler(rustc, None);
+        let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
         let output_path = self.get_filecheck_file("ll");
         (proc_res, output_path)
     }
@@ -2581,7 +2628,7 @@ impl<'test> TestCx<'test> {
             Vec::new(),
         );
 
-        let proc_res = self.compose_and_run_compiler(rustc, None);
+        let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
         let output_path = self.get_filecheck_file("s");
         (proc_res, output_path)
     }
@@ -2664,7 +2711,7 @@ impl<'test> TestCx<'test> {
         let out_dir = self.output_base_dir();
         remove_and_create_dir_all(&out_dir);
 
-        let proc_res = self.document(&out_dir);
+        let proc_res = self.document(&out_dir, &self.testpaths);
         if !proc_res.status.success() {
             self.fatal_proc_rec("rustdoc failed!", &proc_res);
         }
@@ -2723,7 +2770,7 @@ impl<'test> TestCx<'test> {
         let aux_dir = new_rustdoc.aux_output_dir();
         new_rustdoc.build_all_auxiliary(&new_rustdoc.testpaths, &aux_dir, &mut rustc);
 
-        let proc_res = new_rustdoc.document(&compare_dir);
+        let proc_res = new_rustdoc.document(&compare_dir, &new_rustdoc.testpaths);
         if !proc_res.status.success() {
             eprintln!("failed to run nightly rustdoc");
             return;
@@ -2846,7 +2893,7 @@ impl<'test> TestCx<'test> {
         let out_dir = self.output_base_dir();
         remove_and_create_dir_all(&out_dir);
 
-        let proc_res = self.document(&out_dir);
+        let proc_res = self.document(&out_dir, &self.testpaths);
         if !proc_res.status.success() {
             self.fatal_proc_rec("rustdoc failed!", &proc_res);
         }
@@ -2922,24 +2969,15 @@ impl<'test> TestCx<'test> {
     fn check_rustdoc_test_option(&self, res: ProcRes) {
         let mut other_files = Vec::new();
         let mut files: HashMap> = HashMap::new();
-        let cwd = env::current_dir().unwrap();
-        files.insert(
-            self.testpaths
-                .file
-                .strip_prefix(&cwd)
-                .unwrap_or(&self.testpaths.file)
-                .to_str()
-                .unwrap()
-                .replace('\\', "/"),
-            self.get_lines(&self.testpaths.file, Some(&mut other_files)),
-        );
+        let normalized = fs::canonicalize(&self.testpaths.file).expect("failed to canonicalize");
+        let normalized = normalized.to_str().unwrap().replace('\\', "/");
+        files.insert(normalized, self.get_lines(&self.testpaths.file, Some(&mut other_files)));
         for other_file in other_files {
             let mut path = self.testpaths.file.clone();
             path.set_file_name(&format!("{}.rs", other_file));
-            files.insert(
-                path.strip_prefix(&cwd).unwrap_or(&path).to_str().unwrap().replace('\\', "/"),
-                self.get_lines(&path, None),
-            );
+            let path = fs::canonicalize(path).expect("failed to canonicalize");
+            let normalized = path.to_str().unwrap().replace('\\', "/");
+            files.insert(normalized, self.get_lines(&path, None));
         }
 
         let mut tested = 0;
@@ -3778,7 +3816,7 @@ impl<'test> TestCx<'test> {
         if let Some(nodejs) = &self.config.nodejs {
             let out_dir = self.output_base_dir();
 
-            self.document(&out_dir);
+            self.document(&out_dir, &self.testpaths);
 
             let root = self.config.find_rust_src_root().unwrap();
             let file_stem =
@@ -4094,7 +4132,7 @@ impl<'test> TestCx<'test> {
                 rustc.arg(crate_name);
             }
 
-            let res = self.compose_and_run_compiler(rustc, None);
+            let res = self.compose_and_run_compiler(rustc, None, self.testpaths);
             if !res.status.success() {
                 self.fatal_proc_rec("failed to compile fixed code", &res);
             }
diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs
index 6ee147da5a965..05191a159801c 100644
--- a/src/tools/compiletest/src/runtest/coverage.rs
+++ b/src/tools/compiletest/src/runtest/coverage.rs
@@ -191,7 +191,7 @@ impl<'test> TestCx<'test> {
 
         rustdoc_cmd.arg(&self.testpaths.file);
 
-        let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None);
+        let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None, self.testpaths);
         if !proc_res.status.success() {
             self.fatal_proc_rec("rustdoc --test failed!", &proc_res)
         }
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs
new file mode 100644
index 0000000000000..32ad96d3e8e36
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs
@@ -0,0 +1,4 @@
+//@ build-aux-docs
+
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs
new file mode 100644
index 0000000000000..e03c9a1c68c3b
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs
@@ -0,0 +1,6 @@
+//@ aux-build:q.rs
+//@ build-aux-docs
+
+
+extern crate q;
+pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
new file mode 100644
index 0000000000000..af0d31c733ee1
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
@@ -0,0 +1,17 @@
+//@ aux-build:t.rs
+//@ build-aux-docs
+
+//@ has t/trait.Tango.html
+//@ hasraw search-index.js 'Quebec'
+//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw s/struct.Sierra.html 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Tango'
+//@ has q/struct.Quebec.html
+//@ has s/struct.Sierra.html
+
+// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available.
+
+extern crate t;
+pub struct Sierra;
+impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs
new file mode 100644
index 0000000000000..e32fdbaabfe21
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs
@@ -0,0 +1,6 @@
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs
new file mode 100644
index 0000000000000..0a49072b68a67
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs
@@ -0,0 +1,8 @@
+//@ aux-build:q.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+
+extern crate q;
+pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
new file mode 100644
index 0000000000000..b050fbdf67d99
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
@@ -0,0 +1,24 @@
+//@ aux-build:t.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ has t/trait.Tango.html
+//@ hasraw search-index.js 'Quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
+//@ hasraw s/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
+//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't'
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Tango'
+//@ has index.html
+//@ has q/struct.Quebec.html
+//@ has s/struct.Sierra.html
+
+// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available.
+
+extern crate t;
+pub struct Sierra;
+impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs
new file mode 100644
index 0000000000000..1bfc785535b53
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs
@@ -0,0 +1,4 @@
+//@ build-aux-docs
+
+
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
new file mode 100644
index 0000000000000..d3e42989b7770
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
@@ -0,0 +1,15 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+
+//@ hasraw search-index.js 'Echo'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ has f/trait.Foxtrot.html
+//@ has e/enum.Echo.html
+//@ hasraw e/enum.Echo.html 'Foxtrot'
+
+// document two crates in the same way that cargo does. do not provide --enable-index-page
+
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs
new file mode 100644
index 0000000000000..e84835b3e3102
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs
@@ -0,0 +1,6 @@
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs
new file mode 100644
index 0000000000000..bb845877b52f0
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs
@@ -0,0 +1,21 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ hasraw search-index.js 'Echo'
+//@ hasraw search-index.js 'Foxtrot'
+//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e'
+//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ has f/trait.Foxtrot.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has e/enum.Echo.html
+//@ has index.html
+//@ hasraw e/enum.Echo.html 'Foxtrot'
+
+// document two crates in the same way that cargo does, writing them both into the same output directory
+
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs
new file mode 100644
index 0000000000000..1bfc785535b53
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs
@@ -0,0 +1,4 @@
+//@ build-aux-docs
+
+
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs
new file mode 100644
index 0000000000000..876b94464c372
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs
@@ -0,0 +1,21 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ hasraw search-index.js 'Echo'
+//@ hasraw search-index.js 'Foxtrot'
+//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e'
+//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ has f/trait.Foxtrot.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has e/enum.Echo.html
+//@ has index.html
+//@ hasraw e/enum.Echo.html 'Foxtrot'
+
+// only declare --enable-index-page to the last rustdoc invocation
+
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs
new file mode 100644
index 0000000000000..e32fdbaabfe21
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs
@@ -0,0 +1,6 @@
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs
new file mode 100644
index 0000000000000..c0ada1aea1a85
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs
@@ -0,0 +1,8 @@
+//@ aux-build:s.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+
+extern crate s;
+pub type Romeo = s::Sierra;
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs
new file mode 100644
index 0000000000000..6b414a289f5a8
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs
@@ -0,0 +1,9 @@
+//@ aux-build:t.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+
+extern crate t;
+pub struct Sierra;
+impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs
new file mode 100644
index 0000000000000..0a49072b68a67
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs
@@ -0,0 +1,8 @@
+//@ aux-build:q.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+
+extern crate q;
+pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
new file mode 100644
index 0000000000000..9df0e9779ffa7
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
@@ -0,0 +1,32 @@
+//@ aux-build:q.rs
+//@ aux-build:r.rs
+//@ aux-build:t.rs
+//@ aux-build:s.rs
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ hasraw search-index.js 'Quebec'
+//@ hasraw search-index.js 'Sierra'
+//@ has index.html
+//@ has s/struct.Sierra.html
+//@ hasraw s/struct.Sierra.html 'Tango'
+//@ has index.html '//ul[@class="all-items"]//a[@href="i/index.html"]' 'i'
+//@ has q/struct.Quebec.html
+//@ has type.impl/s/struct.Sierra.js
+//@ hasraw type.impl/s/struct.Sierra.js 'Romeo'
+//@ hasraw type.impl/s/struct.Sierra.js 'Tango'
+//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
+//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't'
+//@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's'
+//@ has r/type.Romeo.html
+//@ has t/trait.Tango.html
+//@ hasraw search-index.js 'Romeo'
+//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
+//@ has index.html '//h1' 'List of all crates'
+//@ hasraw search-index.js 'Tango'
+//@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r'
+
+// document everything in the default mode
+
+
diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
new file mode 100644
index 0000000000000..a9e03852f2297
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
@@ -0,0 +1,13 @@
+//@ build-aux-docs
+//@ doc-flags:--enable-index-page
+//@ doc-flags:-Zunstable-options
+
+//@ hasraw search-index.js 'Quebec'
+//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html
+//@ has q/struct.Quebec.html
+
+// there's nothing cross-crate going on here
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
new file mode 100644
index 0000000000000..38471e02a2820
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
@@ -0,0 +1,8 @@
+//@ build-aux-docs
+
+//@ hasraw search-index.js 'Quebec'
+//@ has q/struct.Quebec.html
+
+// there's nothing cross-crate going on here
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs
new file mode 100644
index 0000000000000..32ad96d3e8e36
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs
@@ -0,0 +1,4 @@
+//@ build-aux-docs
+
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs
new file mode 100644
index 0000000000000..e03c9a1c68c3b
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs
@@ -0,0 +1,6 @@
+//@ aux-build:q.rs
+//@ build-aux-docs
+
+
+extern crate q;
+pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/transitive/s.rs b/tests/rustdoc/cross-crate-info/transitive/s.rs
new file mode 100644
index 0000000000000..a758bd68be22f
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/transitive/s.rs
@@ -0,0 +1,9 @@
+//@ aux-build:t.rs
+//@ build-aux-docs
+
+
+// simple test to see if we support building transitive crates
+
+extern crate t;
+pub struct Sierra;
+impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs
new file mode 100644
index 0000000000000..1bfc785535b53
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs
@@ -0,0 +1,4 @@
+//@ build-aux-docs
+
+
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/two/e.rs b/tests/rustdoc/cross-crate-info/two/e.rs
new file mode 100644
index 0000000000000..431e73c390d4a
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/two/e.rs
@@ -0,0 +1,9 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+
+
+// simple test to assert that we can do a two-level aux-build
+
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
new file mode 100644
index 0000000000000..89d1349e520fa
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
@@ -0,0 +1,10 @@
+//@ build-aux-docs
+//@ doc-flags:--scrape-examples-output-path=examples
+//@ doc-flags:--scrape-examples-target-crate=q
+//@ doc-flags:-Zunstable-options
+
+//@ has examples
+
+// where will --scrape-examples-output-path resolve the path to be? should be the root output directory
+
+pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs
new file mode 100644
index 0000000000000..52e02e8b89715
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs
@@ -0,0 +1,5 @@
+//@ build-aux-docs
+//@ unique-doc-out-dir
+
+
+pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
new file mode 100644
index 0000000000000..0480a02bf22f7
--- /dev/null
+++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
@@ -0,0 +1,15 @@
+//@ aux-build:f.rs
+//@ build-aux-docs
+
+//@ hasraw search-index.js 'Echo'
+//@ !hasraw search-index.js 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ !has f/trait.Foxtrot.html
+//@ has e/enum.Echo.html
+//@ hasraw e/enum.Echo.html 'Foxtrot'
+
+// test the fact that our test runner will document this crate somewhere else
+
+extern crate f;
+pub enum Echo {}
+impl f::Foxtrot for Echo {}

From d8211def61d2b436d2a8335d745105e2de3ac172 Mon Sep 17 00:00:00 2001
From: EtomicBomb 
Date: Wed, 24 Jul 2024 22:16:01 +0000
Subject: [PATCH 232/489] ordering and wrapping cross-crate-info tests

---
 src/tools/compiletest/src/command-list.rs     |  2 +-
 .../cargo-transitive-no-index/s.rs            | 13 +++++-----
 .../cross-crate-info/cargo-transitive/s.rs    | 21 ++++++++-------
 .../cross-crate-info/cargo-two-no-index/e.rs  | 11 ++++----
 tests/rustdoc/cross-crate-info/cargo-two/e.rs | 17 ++++++------
 .../cross-crate-info/index-on-last/e.rs       | 14 +++++-----
 .../cross-crate-info/kitchen-sink/i.rs        | 26 +++++++++----------
 .../single-crate-baseline/q.rs                |  6 ++---
 .../single-crate-no-index/q.rs                |  2 +-
 .../working-dir-examples/q.rs                 |  3 ++-
 .../write-docs-somewhere-else/e.rs            | 11 ++++----
 11 files changed, 66 insertions(+), 60 deletions(-)

diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs
index 305bf9c228c43..68443c300fc5c 100644
--- a/src/tools/compiletest/src/command-list.rs
+++ b/src/tools/compiletest/src/command-list.rs
@@ -9,7 +9,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "aux-codegen-backend",
     "aux-crate",
     "build-aux-docs",
-    "unique-doc-out-dir",
     "build-fail",
     "build-pass",
     "check-fail",
@@ -227,6 +226,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "should-ice",
     "stderr-per-bitwidth",
     "test-mir-pass",
+    "unique-doc-out-dir",
     "unset-exec-env",
     "unset-rustc-env",
     // Used by the tidy check `unknown_revision`.
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
index af0d31c733ee1..639b772374fc8 100644
--- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
@@ -1,16 +1,17 @@
 //@ aux-build:t.rs
 //@ build-aux-docs
 
+//@ has q/struct.Quebec.html
+//@ has s/struct.Sierra.html
 //@ has t/trait.Tango.html
-//@ hasraw search-index.js 'Quebec'
-//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
 //@ hasraw s/struct.Sierra.html 'Tango'
-//@ hasraw search-index.js 'Sierra'
+//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
 //@ hasraw search-index.js 'Tango'
-//@ has q/struct.Quebec.html
-//@ has s/struct.Sierra.html
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
 
-// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available.
+// We document multiple crates into the same output directory, which
+// merges the cross-crate information. Everything is available.
 
 extern crate t;
 pub struct Sierra;
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
index b050fbdf67d99..4383d089c4c73 100644
--- a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
@@ -3,21 +3,22 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-//@ has t/trait.Tango.html
-//@ hasraw search-index.js 'Quebec'
-//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
-//@ hasraw s/struct.Sierra.html 'Tango'
-//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
-//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't'
+//@ has index.html
 //@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
 //@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's'
-//@ hasraw search-index.js 'Sierra'
-//@ hasraw search-index.js 'Tango'
-//@ has index.html
+//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't'
 //@ has q/struct.Quebec.html
 //@ has s/struct.Sierra.html
+//@ has t/trait.Tango.html
+//@ hasraw s/struct.Sierra.html 'Tango'
+//@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
+//@ hasraw search-index.js 'Tango'
+//@ hasraw search-index.js 'Sierra'
+//@ hasraw search-index.js 'Quebec'
 
-// We document multiple crates into the same output directory, which merges the cross-crate information. Everything is available.
+// We document multiple crates into the same output directory, which
+// merges the cross-crate information. Everything is available.
 
 extern crate t;
 pub struct Sierra;
diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
index d3e42989b7770..7d64f9481fb80 100644
--- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
@@ -1,14 +1,15 @@
 //@ aux-build:f.rs
 //@ build-aux-docs
 
-//@ hasraw search-index.js 'Echo'
-//@ hasraw search-index.js 'Foxtrot'
-//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
-//@ has f/trait.Foxtrot.html
 //@ has e/enum.Echo.html
+//@ has f/trait.Foxtrot.html
 //@ hasraw e/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
 
-// document two crates in the same way that cargo does. do not provide --enable-index-page
+// document two crates in the same way that cargo does. do not provide
+// --enable-index-page
 
 extern crate f;
 pub enum Echo {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs
index bb845877b52f0..29e3571e6c209 100644
--- a/tests/rustdoc/cross-crate-info/cargo-two/e.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs
@@ -3,18 +3,19 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-//@ hasraw search-index.js 'Echo'
-//@ hasraw search-index.js 'Foxtrot'
-//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e'
-//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f'
-//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
-//@ has f/trait.Foxtrot.html
+//@ has index.html
 //@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f'
+//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e'
 //@ has e/enum.Echo.html
-//@ has index.html
+//@ has f/trait.Foxtrot.html
 //@ hasraw e/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
 
-// document two crates in the same way that cargo does, writing them both into the same output directory
+// document two crates in the same way that cargo does, writing them both
+// into the same output directory
 
 extern crate f;
 pub enum Echo {}
diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs
index 876b94464c372..fee9f4bcddbe4 100644
--- a/tests/rustdoc/cross-crate-info/index-on-last/e.rs
+++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs
@@ -3,16 +3,16 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-//@ hasraw search-index.js 'Echo'
-//@ hasraw search-index.js 'Foxtrot'
-//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e'
-//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f'
-//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
-//@ has f/trait.Foxtrot.html
+//@ has index.html
 //@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="f/index.html"]' 'f'
+//@ has index.html '//ul[@class="all-items"]//a[@href="e/index.html"]' 'e'
 //@ has e/enum.Echo.html
-//@ has index.html
+//@ has f/trait.Foxtrot.html
 //@ hasraw e/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
 
 // only declare --enable-index-page to the last rustdoc invocation
 
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
index 9df0e9779ffa7..558f47ab7c4c9 100644
--- a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
@@ -1,31 +1,31 @@
 //@ aux-build:q.rs
 //@ aux-build:r.rs
-//@ aux-build:t.rs
 //@ aux-build:s.rs
+//@ aux-build:t.rs
 //@ build-aux-docs
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-//@ hasraw search-index.js 'Quebec'
-//@ hasraw search-index.js 'Sierra'
+//@ has index.html '//h1' 'List of all crates'
 //@ has index.html
-//@ has s/struct.Sierra.html
-//@ hasraw s/struct.Sierra.html 'Tango'
 //@ has index.html '//ul[@class="all-items"]//a[@href="i/index.html"]' 'i'
-//@ has q/struct.Quebec.html
-//@ has type.impl/s/struct.Sierra.js
-//@ hasraw type.impl/s/struct.Sierra.js 'Romeo'
-//@ hasraw type.impl/s/struct.Sierra.js 'Tango'
 //@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
-//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't'
+//@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r'
 //@ has index.html '//ul[@class="all-items"]//a[@href="s/index.html"]' 's'
+//@ has index.html '//ul[@class="all-items"]//a[@href="t/index.html"]' 't'
+//@ has q/struct.Quebec.html
 //@ has r/type.Romeo.html
+//@ has s/struct.Sierra.html
 //@ has t/trait.Tango.html
-//@ hasraw search-index.js 'Romeo'
+//@ hasraw s/struct.Sierra.html 'Tango'
 //@ hasraw trait.impl/t/trait.Tango.js 'struct.Sierra.html'
-//@ has index.html '//h1' 'List of all crates'
+//@ hasraw search-index.js 'Quebec'
+//@ hasraw search-index.js 'Romeo'
+//@ hasraw search-index.js 'Sierra'
 //@ hasraw search-index.js 'Tango'
-//@ has index.html '//ul[@class="all-items"]//a[@href="r/index.html"]' 'r'
+//@ has type.impl/s/struct.Sierra.js
+//@ hasraw type.impl/s/struct.Sierra.js 'Tango'
+//@ hasraw type.impl/s/struct.Sierra.js 'Romeo'
 
 // document everything in the default mode
 
diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
index a9e03852f2297..aa5cff73e7463 100644
--- a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
+++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
@@ -2,11 +2,11 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-//@ hasraw search-index.js 'Quebec'
-//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
-//@ has index.html '//h1' 'List of all crates'
 //@ has index.html
+//@ has index.html '//h1' 'List of all crates'
+//@ has index.html '//ul[@class="all-items"]//a[@href="q/index.html"]' 'q'
 //@ has q/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
 
 // there's nothing cross-crate going on here
 
diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
index 38471e02a2820..0cd126e8247d9 100644
--- a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
+++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
@@ -1,7 +1,7 @@
 //@ build-aux-docs
 
-//@ hasraw search-index.js 'Quebec'
 //@ has q/struct.Quebec.html
+//@ hasraw search-index.js 'Quebec'
 
 // there's nothing cross-crate going on here
 
diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
index 89d1349e520fa..ceced1fc46dcd 100644
--- a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
+++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
@@ -5,6 +5,7 @@
 
 //@ has examples
 
-// where will --scrape-examples-output-path resolve the path to be? should be the root output directory
+// where will --scrape-examples-output-path resolve the path to be?
+// should be the root output directory
 
 pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
index 0480a02bf22f7..6247ed5fd9660 100644
--- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
+++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
@@ -1,14 +1,15 @@
 //@ aux-build:f.rs
 //@ build-aux-docs
 
-//@ hasraw search-index.js 'Echo'
-//@ !hasraw search-index.js 'Foxtrot'
-//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
-//@ !has f/trait.Foxtrot.html
 //@ has e/enum.Echo.html
+//@ !has f/trait.Foxtrot.html
 //@ hasraw e/enum.Echo.html 'Foxtrot'
+//@ hasraw trait.impl/f/trait.Foxtrot.js 'enum.Echo.html'
+//@ !hasraw search-index.js 'Foxtrot'
+//@ hasraw search-index.js 'Echo'
 
-// test the fact that our test runner will document this crate somewhere else
+// test the fact that our test runner will document this crate somewhere
+// else
 
 extern crate f;
 pub enum Echo {}

From f6f0ef46f5a9f368183e8c59ee82d0319af7ec9c Mon Sep 17 00:00:00 2001
From: EtomicBomb 
Date: Wed, 24 Jul 2024 22:35:14 +0000
Subject: [PATCH 233/489] reformatted rustdoc/cross-crate-info, fixing trailing
 newline issue

---
 .../cargo-transitive-no-index/auxiliary/q.rs                | 2 --
 .../cargo-transitive-no-index/auxiliary/t.rs                | 2 --
 .../rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs | 2 --
 .../cross-crate-info/cargo-transitive/auxiliary/q.rs        | 1 -
 .../cross-crate-info/cargo-transitive/auxiliary/t.rs        | 1 -
 tests/rustdoc/cross-crate-info/cargo-transitive/s.rs        | 1 -
 .../cross-crate-info/cargo-two-no-index/auxiliary/f.rs      | 2 --
 tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs      | 2 --
 tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs     | 1 -
 tests/rustdoc/cross-crate-info/cargo-two/e.rs               | 1 -
 tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs | 2 --
 tests/rustdoc/cross-crate-info/index-on-last/e.rs           | 1 -
 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs  | 1 -
 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs  | 1 -
 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs  | 1 -
 tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs  | 1 -
 tests/rustdoc/cross-crate-info/kitchen-sink/i.rs            | 6 ++----
 tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs   | 1 -
 tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs   | 2 --
 tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs    | 2 --
 tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs    | 2 --
 tests/rustdoc/cross-crate-info/transitive/s.rs              | 3 ---
 tests/rustdoc/cross-crate-info/two/auxiliary/f.rs           | 2 --
 tests/rustdoc/cross-crate-info/two/e.rs                     | 3 ---
 tests/rustdoc/cross-crate-info/working-dir-examples/q.rs    | 1 -
 .../write-docs-somewhere-else/auxiliary/f.rs                | 2 --
 .../rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs | 2 --
 27 files changed, 2 insertions(+), 46 deletions(-)

diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs
index 32ad96d3e8e36..5d0881029cb2f 100644
--- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/q.rs
@@ -1,4 +1,2 @@
 //@ build-aux-docs
-
-
 pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs
index e03c9a1c68c3b..fab9ec4a92b96 100644
--- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/auxiliary/t.rs
@@ -1,6 +1,4 @@
 //@ aux-build:q.rs
 //@ build-aux-docs
-
-
 extern crate q;
 pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
index 639b772374fc8..85c460ace642f 100644
--- a/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive-no-index/s.rs
@@ -1,6 +1,5 @@
 //@ aux-build:t.rs
 //@ build-aux-docs
-
 //@ has q/struct.Quebec.html
 //@ has s/struct.Sierra.html
 //@ has t/trait.Tango.html
@@ -12,7 +11,6 @@
 
 // We document multiple crates into the same output directory, which
 // merges the cross-crate information. Everything is available.
-
 extern crate t;
 pub struct Sierra;
 impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs
index e32fdbaabfe21..932a0b17206d6 100644
--- a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/q.rs
@@ -2,5 +2,4 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-
 pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs
index 0a49072b68a67..c21a59c65188f 100644
--- a/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/auxiliary/t.rs
@@ -3,6 +3,5 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-
 extern crate q;
 pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
index 4383d089c4c73..68bfc34883bd8 100644
--- a/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-transitive/s.rs
@@ -19,7 +19,6 @@
 
 // We document multiple crates into the same output directory, which
 // merges the cross-crate information. Everything is available.
-
 extern crate t;
 pub struct Sierra;
 impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs
index 1bfc785535b53..abc580a388cd2 100644
--- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/auxiliary/f.rs
@@ -1,4 +1,2 @@
 //@ build-aux-docs
-
-
 pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
index 7d64f9481fb80..c93298f969eab 100644
--- a/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-two-no-index/e.rs
@@ -1,6 +1,5 @@
 //@ aux-build:f.rs
 //@ build-aux-docs
-
 //@ has e/enum.Echo.html
 //@ has f/trait.Foxtrot.html
 //@ hasraw e/enum.Echo.html 'Foxtrot'
@@ -10,7 +9,6 @@
 
 // document two crates in the same way that cargo does. do not provide
 // --enable-index-page
-
 extern crate f;
 pub enum Echo {}
 impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs
index e84835b3e3102..a2a7033b13112 100644
--- a/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-two/auxiliary/f.rs
@@ -2,5 +2,4 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-
 pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/cargo-two/e.rs b/tests/rustdoc/cross-crate-info/cargo-two/e.rs
index 29e3571e6c209..00f86cbc34889 100644
--- a/tests/rustdoc/cross-crate-info/cargo-two/e.rs
+++ b/tests/rustdoc/cross-crate-info/cargo-two/e.rs
@@ -16,7 +16,6 @@
 
 // document two crates in the same way that cargo does, writing them both
 // into the same output directory
-
 extern crate f;
 pub enum Echo {}
 impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs
index 1bfc785535b53..abc580a388cd2 100644
--- a/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs
+++ b/tests/rustdoc/cross-crate-info/index-on-last/auxiliary/f.rs
@@ -1,4 +1,2 @@
 //@ build-aux-docs
-
-
 pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/index-on-last/e.rs b/tests/rustdoc/cross-crate-info/index-on-last/e.rs
index fee9f4bcddbe4..ffee898cd966d 100644
--- a/tests/rustdoc/cross-crate-info/index-on-last/e.rs
+++ b/tests/rustdoc/cross-crate-info/index-on-last/e.rs
@@ -15,7 +15,6 @@
 //@ hasraw search-index.js 'Echo'
 
 // only declare --enable-index-page to the last rustdoc invocation
-
 extern crate f;
 pub enum Echo {}
 impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs
index e32fdbaabfe21..932a0b17206d6 100644
--- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/q.rs
@@ -2,5 +2,4 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-
 pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs
index c0ada1aea1a85..2c0db2abc53d9 100644
--- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/r.rs
@@ -3,6 +3,5 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-
 extern crate s;
 pub type Romeo = s::Sierra;
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs
index 6b414a289f5a8..355d3f1aaa883 100644
--- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/s.rs
@@ -3,7 +3,6 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-
 extern crate t;
 pub struct Sierra;
 impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs
index 0a49072b68a67..c21a59c65188f 100644
--- a/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/auxiliary/t.rs
@@ -3,6 +3,5 @@
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
 
-
 extern crate q;
 pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
index 558f47ab7c4c9..bcb9464795af2 100644
--- a/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
+++ b/tests/rustdoc/cross-crate-info/kitchen-sink/i.rs
@@ -1,7 +1,7 @@
-//@ aux-build:q.rs
 //@ aux-build:r.rs
-//@ aux-build:s.rs
+//@ aux-build:q.rs
 //@ aux-build:t.rs
+//@ aux-build:s.rs
 //@ build-aux-docs
 //@ doc-flags:--enable-index-page
 //@ doc-flags:-Zunstable-options
@@ -28,5 +28,3 @@
 //@ hasraw type.impl/s/struct.Sierra.js 'Romeo'
 
 // document everything in the default mode
-
-
diff --git a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
index aa5cff73e7463..c5e3dc0a0f4e5 100644
--- a/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
+++ b/tests/rustdoc/cross-crate-info/single-crate-baseline/q.rs
@@ -9,5 +9,4 @@
 //@ hasraw search-index.js 'Quebec'
 
 // there's nothing cross-crate going on here
-
 pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
index 0cd126e8247d9..d3e71fa0ce35f 100644
--- a/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
+++ b/tests/rustdoc/cross-crate-info/single-crate-no-index/q.rs
@@ -1,8 +1,6 @@
 //@ build-aux-docs
-
 //@ has q/struct.Quebec.html
 //@ hasraw search-index.js 'Quebec'
 
 // there's nothing cross-crate going on here
-
 pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs
index 32ad96d3e8e36..5d0881029cb2f 100644
--- a/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs
+++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/q.rs
@@ -1,4 +1,2 @@
 //@ build-aux-docs
-
-
 pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs
index e03c9a1c68c3b..fab9ec4a92b96 100644
--- a/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs
+++ b/tests/rustdoc/cross-crate-info/transitive/auxiliary/t.rs
@@ -1,6 +1,4 @@
 //@ aux-build:q.rs
 //@ build-aux-docs
-
-
 extern crate q;
 pub trait Tango {}
diff --git a/tests/rustdoc/cross-crate-info/transitive/s.rs b/tests/rustdoc/cross-crate-info/transitive/s.rs
index a758bd68be22f..0a4e5f646ddaa 100644
--- a/tests/rustdoc/cross-crate-info/transitive/s.rs
+++ b/tests/rustdoc/cross-crate-info/transitive/s.rs
@@ -1,9 +1,6 @@
 //@ aux-build:t.rs
 //@ build-aux-docs
-
-
 // simple test to see if we support building transitive crates
-
 extern crate t;
 pub struct Sierra;
 impl t::Tango for Sierra {}
diff --git a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs
index 1bfc785535b53..abc580a388cd2 100644
--- a/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs
+++ b/tests/rustdoc/cross-crate-info/two/auxiliary/f.rs
@@ -1,4 +1,2 @@
 //@ build-aux-docs
-
-
 pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/two/e.rs b/tests/rustdoc/cross-crate-info/two/e.rs
index 431e73c390d4a..9665af62706d1 100644
--- a/tests/rustdoc/cross-crate-info/two/e.rs
+++ b/tests/rustdoc/cross-crate-info/two/e.rs
@@ -1,9 +1,6 @@
 //@ aux-build:f.rs
 //@ build-aux-docs
-
-
 // simple test to assert that we can do a two-level aux-build
-
 extern crate f;
 pub enum Echo {}
 impl f::Foxtrot for Echo {}
diff --git a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
index ceced1fc46dcd..a7ab062fd9e28 100644
--- a/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
+++ b/tests/rustdoc/cross-crate-info/working-dir-examples/q.rs
@@ -7,5 +7,4 @@
 
 // where will --scrape-examples-output-path resolve the path to be?
 // should be the root output directory
-
 pub struct Quebec;
diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs
index 52e02e8b89715..f8c9adcaf9cad 100644
--- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs
+++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/auxiliary/f.rs
@@ -1,5 +1,3 @@
 //@ build-aux-docs
 //@ unique-doc-out-dir
-
-
 pub trait Foxtrot {}
diff --git a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
index 6247ed5fd9660..9dcec211e1787 100644
--- a/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
+++ b/tests/rustdoc/cross-crate-info/write-docs-somewhere-else/e.rs
@@ -1,6 +1,5 @@
 //@ aux-build:f.rs
 //@ build-aux-docs
-
 //@ has e/enum.Echo.html
 //@ !has f/trait.Foxtrot.html
 //@ hasraw e/enum.Echo.html 'Foxtrot'
@@ -10,7 +9,6 @@
 
 // test the fact that our test runner will document this crate somewhere
 // else
-
 extern crate f;
 pub enum Echo {}
 impl f::Foxtrot for Echo {}

From 12d87ee237a1f79c00ccd22424432f5ab869ed22 Mon Sep 17 00:00:00 2001
From: EtomicBomb 
Date: Thu, 25 Jul 2024 17:59:32 +0000
Subject: [PATCH 234/489] file_stem and comment per notriddle

---
 src/tools/compiletest/src/runtest.rs | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 2d298dfbc06f7..2beff593f08ad 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1610,6 +1610,8 @@ impl<'test> TestCx<'test> {
                 };
                 // Create the directory for the stdout/stderr files.
                 create_dir_all(aux_cx.output_base_dir()).unwrap();
+                // use root_testpaths here, because aux-builds should have the
+                // same --out-dir and auxiliary directory.
                 let auxres = aux_cx.document(&root_out_dir, root_testpaths);
                 if !auxres.status.success() {
                     return auxres;
@@ -1624,14 +1626,7 @@ impl<'test> TestCx<'test> {
         // actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire
         // test
         let out_dir: Cow<'_, Path> = if self.props.unique_doc_out_dir {
-            let file_name = self
-                .testpaths
-                .file
-                .file_name()
-                .expect("file name should not be empty")
-                .to_str()
-                .expect("file name utf8")
-                .trim_end_matches(".rs");
+            let file_name = self.testpaths.file.file_stem().expect("file name should not be empty");
             let out_dir = PathBuf::from_iter([
                 root_out_dir,
                 Path::new("docs"),

From f91da72cb75f03739985926c5e5561611f783b80 Mon Sep 17 00:00:00 2001
From: EtomicBomb 
Date: Mon, 29 Jul 2024 14:41:09 +0000
Subject: [PATCH 235/489] merge conflicts; fix rebase duplicating imports

---
 src/tools/compiletest/src/runtest.rs | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 2beff593f08ad..55f676e708670 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1,16 +1,5 @@
 // ignore-tidy-filelength
 
-use crate::compute_diff::{write_diff, write_filtered_diff};
-use crate::errors::{self, Error, ErrorKind};
-use crate::header::TestProps;
-use crate::json;
-use crate::read2::{read2_abbreviated, Truncated};
-use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt};
-use crate::ColorConfig;
-use colored::Colorize;
-use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
-use regex::{Captures, Regex};
-use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
 use std::borrow::Cow;
 use std::collections::{HashMap, HashSet};
 use std::ffi::{OsStr, OsString};

From 0c8f19473748487a8d3282dec694169e3f79da9f Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Tue, 23 Jul 2024 14:21:45 -0400
Subject: [PATCH 236/489] rewrite share-generics-dylib to rmake

---
 .../tidy/src/allowed_run_make_makefiles.txt   |  1 -
 tests/run-make/share-generics-dylib/Makefile  | 23 -------------
 tests/run-make/share-generics-dylib/rmake.rs  | 32 +++++++++++++++++++
 3 files changed, 32 insertions(+), 24 deletions(-)
 delete mode 100644 tests/run-make/share-generics-dylib/Makefile
 create mode 100644 tests/run-make/share-generics-dylib/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 7284feadf9cdd..3f416448f6d1e 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -50,7 +50,6 @@ run-make/reproducible-build-2/Makefile
 run-make/reproducible-build/Makefile
 run-make/rlib-format-packed-bundled-libs-2/Makefile
 run-make/rlib-format-packed-bundled-libs/Makefile
-run-make/share-generics-dylib/Makefile
 run-make/simd-ffi/Makefile
 run-make/split-debuginfo/Makefile
 run-make/stable-symbol-names/Makefile
diff --git a/tests/run-make/share-generics-dylib/Makefile b/tests/run-make/share-generics-dylib/Makefile
deleted file mode 100644
index 9d97eca80d3f5..0000000000000
--- a/tests/run-make/share-generics-dylib/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# ignore-cross-compile
-# This test makes sure all generic instances get re-exported from Rust dylibs for use by
-# `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`)
-# which both provide an instance of `Cell::set`. There is `instance_user_dylib` which is
-# supposed to re-export both these instances, and then there are `instance_user_a_rlib` and
-# `instance_user_b_rlib` which each rely on a specific instance to be available.
-#
-# In the end everything is linked together into `linked_leaf`. If `instance_user_dylib` does
-# not export both then we'll get an `undefined reference` error for one of the instances.
-#
-# This is regression test for https://github.com/rust-lang/rust/issues/67276.
-
-include ../tools.mk
-
-COMMON_ARGS=-Cprefer-dynamic -Zshare-generics=yes -Ccodegen-units=1 -Csymbol-mangling-version=v0
-
-all:
-	$(RUSTC) instance_provider_a.rs $(COMMON_ARGS) --crate-type=rlib
-	$(RUSTC) instance_provider_b.rs $(COMMON_ARGS) --crate-type=rlib
-	$(RUSTC) instance_user_dylib.rs $(COMMON_ARGS) --crate-type=dylib
-	$(RUSTC) instance_user_a_rlib.rs $(COMMON_ARGS) --crate-type=rlib
-	$(RUSTC) instance_user_b_rlib.rs $(COMMON_ARGS) --crate-type=rlib
-	$(RUSTC) linked_leaf.rs $(COMMON_ARGS) --crate-type=bin
diff --git a/tests/run-make/share-generics-dylib/rmake.rs b/tests/run-make/share-generics-dylib/rmake.rs
new file mode 100644
index 0000000000000..8dd402ea1b6eb
--- /dev/null
+++ b/tests/run-make/share-generics-dylib/rmake.rs
@@ -0,0 +1,32 @@
+// This test makes sure all generic instances get re-exported from Rust dylibs for use by
+// `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`)
+// which both provide an instance of `Cell::set`. There is `instance_user_dylib` which is
+// supposed to re-export both these instances, and then there are `instance_user_a_rlib` and
+// `instance_user_b_rlib` which each rely on a specific instance to be available.
+//
+// In the end everything is linked together into `linked_leaf`. If `instance_user_dylib` does
+// not export both then we'll get an `undefined reference` error for one of the instances.
+//
+// This is regression test for https://github.com/rust-lang/rust/issues/67276.
+
+//FIXME(Oneirical): ignore-cross-compile
+
+use run_make_support::rustc;
+
+fn main() {
+    compile("rlib", "instance_provider_a.rs");
+    compile("rlib", "instance_provider_b.rs");
+    compile("dylib", "instance_user_dylib.rs");
+    compile("rlib", "instance_user_a_rlib.rs");
+    compile("rlib", "instance_user_b_rlib.rs");
+    compile("bin", "linked_leaf.rs");
+}
+
+fn compile(crate_type: &str, input: &str) {
+    rustc()
+        .input(input)
+        .crate_type(crate_type)
+        .args(&["-Cprefer-dynamic", "-Zshare-generics=yes", "-Csymbol-mangling-version=v0"])
+        .codegen_units(1)
+        .run();
+}

From 8c09a7f11e1c5d3c595bb64beb1e493bc08cbd1a Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Tue, 23 Jul 2024 15:41:53 -0400
Subject: [PATCH 237/489] rewrite raw-dylib-import-name-type to rmake

---
 .../tidy/src/allowed_run_make_makefiles.txt   |  1 -
 .../raw-dylib-import-name-type/Makefile       | 17 ---------
 .../raw-dylib-import-name-type/rmake.rs       | 36 +++++++++++++++++++
 3 files changed, 36 insertions(+), 18 deletions(-)
 delete mode 100644 tests/run-make/raw-dylib-import-name-type/Makefile
 create mode 100644 tests/run-make/raw-dylib-import-name-type/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 3f416448f6d1e..fb72662405c97 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -41,7 +41,6 @@ run-make/print-calling-conventions/Makefile
 run-make/print-target-list/Makefile
 run-make/raw-dylib-alt-calling-convention/Makefile
 run-make/raw-dylib-c/Makefile
-run-make/raw-dylib-import-name-type/Makefile
 run-make/raw-dylib-link-ordinal/Makefile
 run-make/raw-dylib-stdcall-ordinal/Makefile
 run-make/redundant-libs/Makefile
diff --git a/tests/run-make/raw-dylib-import-name-type/Makefile b/tests/run-make/raw-dylib-import-name-type/Makefile
deleted file mode 100644
index 901d3e861c21a..0000000000000
--- a/tests/run-make/raw-dylib-import-name-type/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")] with alternative calling conventions.
-
-# only-x86
-# only-windows
-
-include ../tools.mk
-
-all:
-	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
-	$(call COMPILE_OBJ,"$(TMPDIR)"/extern.obj,extern.c)
-ifdef IS_MSVC
-	$(CC) "$(TMPDIR)"/extern.obj extern.msvc.def -link -dll -out:"$(TMPDIR)"/extern.dll -noimplib
-else
-	$(CC) "$(TMPDIR)"/extern.obj extern.gnu.def --no-leading-underscore -shared -o "$(TMPDIR)"/extern.dll
-endif
-	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
-	$(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt
diff --git a/tests/run-make/raw-dylib-import-name-type/rmake.rs b/tests/run-make/raw-dylib-import-name-type/rmake.rs
new file mode 100644
index 0000000000000..4dc916610e05c
--- /dev/null
+++ b/tests/run-make/raw-dylib-import-name-type/rmake.rs
@@ -0,0 +1,36 @@
+// `raw-dylib` is a Windows-specific attribute which emits idata sections for the items in the
+// attached extern block,
+// so they may be linked against without linking against an import library.
+// To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
+// This test uses this feature alongside `import_name_type`, which allows for customization
+// of how Windows symbols will be named. The correctness of this feature is checked by comparison
+// with expected output.
+// See https://github.com/rust-lang/rust/pull/100732
+
+//@ only-x86
+//@ only-windows
+
+use run_make_support::{cc, diff, is_msvc, run, rustc};
+
+// NOTE: build_native_dynamic lib is not used, as the special `def` files
+// must be passed to the CC compiler.
+
+fn main() {
+    rustc().crate_type("bin").input("driver.rs").run();
+    if is_msvc() {
+        cc().arg("-c").out_exe("extern").input("extern.c").run();
+        cc().input("extern.obj")
+            .arg("extern.msvc.def")
+            .args(&["-link", "-dll", "-noimplib", "-out:extern.dll"])
+            .run();
+    } else {
+        cc().arg("-v").arg("-c").out_exe("extern.obj").input("extern.c").run();
+        cc().input("extern.obj")
+            .arg("extern.gnu.def")
+            .args(&["--no-leading-underscore", "-shared"])
+            .output("extern.dll")
+            .run();
+    };
+    let out = run("driver").stdout_utf8();
+    diff().expected_file("output.txt").actual_text("actual", out).run();
+}

From 9ffe161ce8a016fa98b6a6d6b269691cb3a44c46 Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Tue, 23 Jul 2024 15:50:25 -0400
Subject: [PATCH 238/489] rewrite raw-dylib-link-ordinal to rmake

---
 .../tidy/src/allowed_run_make_makefiles.txt   |  1 -
 .../run-make/raw-dylib-link-ordinal/Makefile  | 17 ---------
 .../run-make/raw-dylib-link-ordinal/rmake.rs  | 38 +++++++++++++++++++
 3 files changed, 38 insertions(+), 18 deletions(-)
 delete mode 100644 tests/run-make/raw-dylib-link-ordinal/Makefile
 create mode 100644 tests/run-make/raw-dylib-link-ordinal/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index fb72662405c97..fa4e489f902d0 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -41,7 +41,6 @@ run-make/print-calling-conventions/Makefile
 run-make/print-target-list/Makefile
 run-make/raw-dylib-alt-calling-convention/Makefile
 run-make/raw-dylib-c/Makefile
-run-make/raw-dylib-link-ordinal/Makefile
 run-make/raw-dylib-stdcall-ordinal/Makefile
 run-make/redundant-libs/Makefile
 run-make/remap-path-prefix-dwarf/Makefile
diff --git a/tests/run-make/raw-dylib-link-ordinal/Makefile b/tests/run-make/raw-dylib-link-ordinal/Makefile
deleted file mode 100644
index 3cf1300c243a4..0000000000000
--- a/tests/run-make/raw-dylib-link-ordinal/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")] and #[link_ordinal] on windows-msvc
-
-# only-windows
-
-include ../tools.mk
-
-all:
-	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
-	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
-	$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
-ifdef IS_MSVC
-	$(CC) "$(TMPDIR)"/exporter.obj exporter.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
-else
-	$(CC) "$(TMPDIR)"/exporter.obj exporter.def -shared -o "$(TMPDIR)"/exporter.dll
-endif
-	"$(TMPDIR)"/driver | tr -d '\r' > "$(TMPDIR)"/output.txt
-	$(RUSTC_TEST_OP) "$(TMPDIR)"/output.txt output.txt
diff --git a/tests/run-make/raw-dylib-link-ordinal/rmake.rs b/tests/run-make/raw-dylib-link-ordinal/rmake.rs
new file mode 100644
index 0000000000000..c9bc9dea49e0f
--- /dev/null
+++ b/tests/run-make/raw-dylib-link-ordinal/rmake.rs
@@ -0,0 +1,38 @@
+// `raw-dylib` is a Windows-specific attribute which emits idata sections for the items in the
+// attached extern block,
+// so they may be linked against without linking against an import library.
+// To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
+// `#[link_ordinal(n)]` allows Rust to link against DLLs that export symbols by ordinal rather
+// than by name. As long as the ordinal matches, the name of the function in Rust is not
+// required to match the name of the corresponding function in the exporting DLL.
+// This test checks the correctness of this feature by comparing its output against expected
+// output.
+// See https://github.com/rust-lang/rust/pull/89025
+
+//@ only-windows
+
+use run_make_support::{cc, diff, is_msvc, run, rustc};
+
+// NOTE: build_native_dynamic lib is not used, as the special `def` files
+// must be passed to the CC compiler.
+
+fn main() {
+    rustc().crate_type("lib").crate_name("raw_dylib_test").input("lib.rs").run();
+    rustc().crate_type("bin").input("driver.rs").run();
+    if is_msvc() {
+        cc().arg("-c").out_exe("exporter").input("exporter.c").run();
+        cc().input("exporter.obj")
+            .arg("exporter.msvc.def")
+            .args(&["-link", "-dll", "-noimplib", "-out:exporter.dll"])
+            .run();
+    } else {
+        cc().arg("-v").arg("-c").out_exe("exporter.obj").input("exporter.c").run();
+        cc().input("exporter.obj")
+            .arg("exporter.gnu.def")
+            .args(&["--no-leading-underscore", "-shared"])
+            .output("exporter.dll")
+            .run();
+    };
+    let out = run("driver").stdout_utf8();
+    diff().expected_file("output.txt").actual_text("actual", out).normalize(r#"\r"#, "").run();
+}

From 23cccb3fc6f0039a12582e80fda42041405bd407 Mon Sep 17 00:00:00 2001
From: Oneirical 
Date: Tue, 23 Jul 2024 15:59:18 -0400
Subject: [PATCH 239/489] rewrite raw-dylib-stdcall-ordinal to rmake

---
 .../tidy/src/allowed_run_make_makefiles.txt   |  1 -
 .../raw-dylib-import-name-type/rmake.rs       |  5 ++-
 .../run-make/raw-dylib-link-ordinal/rmake.rs  | 10 ++---
 .../raw-dylib-stdcall-ordinal/Makefile        | 18 --------
 .../raw-dylib-stdcall-ordinal/rmake.rs        | 41 +++++++++++++++++++
 tests/run-make/share-generics-dylib/rmake.rs  |  2 -
 6 files changed, 47 insertions(+), 30 deletions(-)
 delete mode 100644 tests/run-make/raw-dylib-stdcall-ordinal/Makefile
 create mode 100644 tests/run-make/raw-dylib-stdcall-ordinal/rmake.rs

diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index fa4e489f902d0..a84b89ff4a113 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -41,7 +41,6 @@ run-make/print-calling-conventions/Makefile
 run-make/print-target-list/Makefile
 run-make/raw-dylib-alt-calling-convention/Makefile
 run-make/raw-dylib-c/Makefile
-run-make/raw-dylib-stdcall-ordinal/Makefile
 run-make/redundant-libs/Makefile
 run-make/remap-path-prefix-dwarf/Makefile
 run-make/reproducible-build-2/Makefile
diff --git a/tests/run-make/raw-dylib-import-name-type/rmake.rs b/tests/run-make/raw-dylib-import-name-type/rmake.rs
index 4dc916610e05c..13a2c99150e5b 100644
--- a/tests/run-make/raw-dylib-import-name-type/rmake.rs
+++ b/tests/run-make/raw-dylib-import-name-type/rmake.rs
@@ -3,12 +3,13 @@
 // so they may be linked against without linking against an import library.
 // To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
 // This test uses this feature alongside `import_name_type`, which allows for customization
-// of how Windows symbols will be named. The correctness of this feature is checked by comparison
+// of how Windows symbols will be named. A sanity check of this feature is done by comparison
 // with expected output.
 // See https://github.com/rust-lang/rust/pull/100732
 
 //@ only-x86
 //@ only-windows
+// Reason: this test specifically exercises a 32bit Windows calling convention.
 
 use run_make_support::{cc, diff, is_msvc, run, rustc};
 
@@ -32,5 +33,5 @@ fn main() {
             .run();
     };
     let out = run("driver").stdout_utf8();
-    diff().expected_file("output.txt").actual_text("actual", out).run();
+    diff().expected_file("output.txt").actual_text("actual", out).normalize(r#"\r"#, "").run();
 }
diff --git a/tests/run-make/raw-dylib-link-ordinal/rmake.rs b/tests/run-make/raw-dylib-link-ordinal/rmake.rs
index c9bc9dea49e0f..b52181ae3f9d6 100644
--- a/tests/run-make/raw-dylib-link-ordinal/rmake.rs
+++ b/tests/run-make/raw-dylib-link-ordinal/rmake.rs
@@ -5,7 +5,7 @@
 // `#[link_ordinal(n)]` allows Rust to link against DLLs that export symbols by ordinal rather
 // than by name. As long as the ordinal matches, the name of the function in Rust is not
 // required to match the name of the corresponding function in the exporting DLL.
-// This test checks the correctness of this feature by comparing its output against expected
+// This test is a sanity check for this feature, done by comparing its output against expected
 // output.
 // See https://github.com/rust-lang/rust/pull/89025
 
@@ -22,16 +22,12 @@ fn main() {
     if is_msvc() {
         cc().arg("-c").out_exe("exporter").input("exporter.c").run();
         cc().input("exporter.obj")
-            .arg("exporter.msvc.def")
+            .arg("exporter.def")
             .args(&["-link", "-dll", "-noimplib", "-out:exporter.dll"])
             .run();
     } else {
         cc().arg("-v").arg("-c").out_exe("exporter.obj").input("exporter.c").run();
-        cc().input("exporter.obj")
-            .arg("exporter.gnu.def")
-            .args(&["--no-leading-underscore", "-shared"])
-            .output("exporter.dll")
-            .run();
+        cc().input("exporter.obj").arg("exporter.def").arg("-shared").output("exporter.dll").run();
     };
     let out = run("driver").stdout_utf8();
     diff().expected_file("output.txt").actual_text("actual", out).normalize(r#"\r"#, "").run();
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/Makefile b/tests/run-make/raw-dylib-stdcall-ordinal/Makefile
deleted file mode 100644
index 70e4de62c1a9e..0000000000000
--- a/tests/run-make/raw-dylib-stdcall-ordinal/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# Test the behavior of #[link(.., kind = "raw-dylib")], #[link_ordinal], and alternative calling conventions on i686 windows.
-
-# only-x86
-# only-windows
-
-include ../tools.mk
-
-all:
-	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
-	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
-	$(call COMPILE_OBJ,"$(TMPDIR)"/exporter.obj,exporter.c)
-ifdef IS_MSVC
-	$(CC) "$(TMPDIR)"/exporter.obj exporter-msvc.def -link -dll -out:"$(TMPDIR)"/exporter.dll -noimplib
-else
-	$(CC) "$(TMPDIR)"/exporter.obj exporter-gnu.def -shared -o "$(TMPDIR)"/exporter.dll
-endif
-	"$(TMPDIR)"/driver > "$(TMPDIR)"/actual_output.txt
-	$(RUSTC_TEST_OP) "$(TMPDIR)"/actual_output.txt expected_output.txt
diff --git a/tests/run-make/raw-dylib-stdcall-ordinal/rmake.rs b/tests/run-make/raw-dylib-stdcall-ordinal/rmake.rs
new file mode 100644
index 0000000000000..320ea1520d85f
--- /dev/null
+++ b/tests/run-make/raw-dylib-stdcall-ordinal/rmake.rs
@@ -0,0 +1,41 @@
+// `raw-dylib` is a Windows-specific attribute which emits idata sections for the items in the
+// attached extern block,
+// so they may be linked against without linking against an import library.
+// To learn more, read https://github.com/rust-lang/rfcs/blob/master/text/2627-raw-dylib-kind.md
+// Almost identical to `raw-dylib-link-ordinal`, but with the addition of calling conventions,
+// such as stdcall.
+// See https://github.com/rust-lang/rust/pull/90782
+
+//@ only-x86
+//@ only-windows
+// Reason: this test specifically exercises a 32bit Windows calling convention.
+
+use run_make_support::{cc, diff, is_msvc, run, rustc};
+
+// NOTE: build_native_dynamic lib is not used, as the special `def` files
+// must be passed to the CC compiler.
+
+fn main() {
+    rustc().crate_type("lib").crate_name("raw_dylib_test").input("lib.rs").run();
+    rustc().crate_type("bin").input("driver.rs").run();
+    if is_msvc() {
+        cc().arg("-c").out_exe("exporter").input("exporter.c").run();
+        cc().input("exporter.obj")
+            .arg("exporter-msvc.def")
+            .args(&["-link", "-dll", "-noimplib", "-out:exporter.dll"])
+            .run();
+    } else {
+        cc().arg("-v").arg("-c").out_exe("exporter.obj").input("exporter.c").run();
+        cc().input("exporter.obj")
+            .arg("exporter-gnu.def")
+            .arg("-shared")
+            .output("exporter.dll")
+            .run();
+    };
+    let out = run("driver").stdout_utf8();
+    diff()
+        .expected_file("expected_output.txt")
+        .actual_text("actual", out)
+        .normalize(r#"\r"#, "")
+        .run();
+}
diff --git a/tests/run-make/share-generics-dylib/rmake.rs b/tests/run-make/share-generics-dylib/rmake.rs
index 8dd402ea1b6eb..e0e647fe19955 100644
--- a/tests/run-make/share-generics-dylib/rmake.rs
+++ b/tests/run-make/share-generics-dylib/rmake.rs
@@ -9,8 +9,6 @@
 //
 // This is regression test for https://github.com/rust-lang/rust/issues/67276.
 
-//FIXME(Oneirical): ignore-cross-compile
-
 use run_make_support::rustc;
 
 fn main() {

From dc471c16b2a2d6ae68cb7668228d95a17afa6cbd Mon Sep 17 00:00:00 2001
From: Ali Bektas 
Date: Mon, 29 Jul 2024 17:00:31 +0200
Subject: [PATCH 240/489] Remove clippy errors

---
 .../crates/rust-analyzer/src/config.rs              | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 996f48482aa13..8743c4faff691 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -758,6 +758,8 @@ pub enum RatomlFileKind {
 }
 
 #[derive(Debug, Clone)]
+// FIXME @alibektas : Seems like a clippy warning of this sort should tell that combining different ConfigInputs into one enum was not a good idea.
+#[allow(clippy::large_enum_variant)]
 enum RatomlFile {
     Workspace(GlobalLocalConfigInput),
     Crate(LocalConfigInput),
@@ -2598,14 +2600,9 @@ macro_rules! _impl_for_config_data {
                 $vis fn $field(&self, source_root : Option) -> &$ty {
                     let mut source_root = source_root.as_ref();
                     while let Some(sr) = source_root {
-                        if let Some((file, _)) = self.ratoml_file.get(&sr) {
-                            match file {
-                                RatomlFile::Workspace(config) => {
-                                    if let Some(v) = config.global.$field.as_ref() {
-                                        return &v;
-                                    }
-                                },
-                                _ => ()
+                        if let Some((RatomlFile::Workspace(config), _)) = self.ratoml_file.get(&sr) {
+                            if let Some(v) = config.global.$field.as_ref() {
+                                return &v;
                             }
                         }
 

From f3661dce09bc715a46c01f7ea57694e06b587f29 Mon Sep 17 00:00:00 2001
From: Michael Howell 
Date: Mon, 10 Jun 2024 15:01:31 -0700
Subject: [PATCH 241/489] rustdoc: word wrap CamelCase in the item list table

This is an alternative to ee6459d6521cf6a4c2e08b6e13ce3c6ce5d55ed0.
That is, it fixes the issue that affects the very long type names
in https://docs.rs/async-stripe/0.31.0/stripe/index.html#structs.

This is, necessarily, a pile of nasty heuristics.
We need to balance a few issues:

- Sometimes, there's no real word break.
  For example, `BTreeMap` should be `BTreeMap`,
  not `BTreeMap`.

- Sometimes, there's a legit word break,
  but the name is tiny and the HTML overhead isn't worth it.
  For example, if we're typesetting `TyCtx`,
  writing `TyCtx` would have an HTML overhead of 50%.
  Line breaking inside it makes no sense.
---
 Cargo.lock                                    |  1 +
 src/librustdoc/Cargo.toml                     |  1 +
 src/librustdoc/html/escape.rs                 | 44 ++++++++++++++
 src/librustdoc/html/escape/tests.rs           | 57 +++++++++++++++++++
 src/librustdoc/html/format.rs                 |  3 +-
 src/librustdoc/html/render/print_item.rs      |  6 +-
 ...long_typename.extremely_long_typename.html |  1 +
 tests/rustdoc/extremely_long_typename.rs      |  7 +++
 .../item-desc-list-at-start.item-table.html   |  2 +-
 9 files changed, 117 insertions(+), 5 deletions(-)
 create mode 100644 src/librustdoc/html/escape/tests.rs
 create mode 100644 tests/rustdoc/extremely_long_typename.extremely_long_typename.html
 create mode 100644 tests/rustdoc/extremely_long_typename.rs

diff --git a/Cargo.lock b/Cargo.lock
index 281599a21fc14..1a7d7e3f5d7d1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4826,6 +4826,7 @@ dependencies = [
  "tracing",
  "tracing-subscriber",
  "tracing-tree",
+ "unicode-segmentation",
 ]
 
 [[package]]
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index fe531f0ff5985..dfd7414652fa7 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -23,6 +23,7 @@ tempfile = "3"
 tracing = "0.1"
 tracing-tree = "0.3.0"
 threadpool = "1.8.1"
+unicode-segmentation = "1.9"
 
 [dependencies.tracing-subscriber]
 version = "0.3.3"
diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs
index ea4b573aeb955..9441491316345 100644
--- a/src/librustdoc/html/escape.rs
+++ b/src/librustdoc/html/escape.rs
@@ -5,6 +5,8 @@
 
 use std::fmt;
 
+use unicode_segmentation::UnicodeSegmentation;
+
 /// Wrapper struct which will emit the HTML-escaped version of the contained
 /// string when passed to a format string.
 pub(crate) struct Escape<'a>(pub &'a str);
@@ -74,3 +76,45 @@ impl<'a> fmt::Display for EscapeBodyText<'a> {
         Ok(())
     }
 }
+
+/// Wrapper struct which will emit the HTML-escaped version of the contained
+/// string when passed to a format string. This function also word-breaks
+/// CamelCase and snake_case word names.
+///
+/// This is only safe to use for text nodes. If you need your output to be
+/// safely contained in an attribute, use [`Escape`]. If you don't know the
+/// difference, use [`Escape`].
+pub(crate) struct EscapeBodyTextWithWbr<'a>(pub &'a str);
+
+impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let EscapeBodyTextWithWbr(text) = *self;
+        if text.len() < 8 {
+            return EscapeBodyText(text).fmt(fmt);
+        }
+        let mut last = 0;
+        let mut it = text.grapheme_indices(true).peekable();
+        let _ = it.next(); // don't insert wbr before first char
+        while let Some((i, s)) = it.next() {
+            let pk = it.peek();
+            let is_uppercase = || s.chars().any(|c| c.is_uppercase());
+            let next_is_uppercase =
+                || pk.map_or(true, |(_, t)| t.chars().any(|c| c.is_uppercase()));
+            let next_is_underscore = || pk.map_or(true, |(_, t)| t.contains('_'));
+            if (i - last > 3 && is_uppercase() && !next_is_uppercase())
+                || (s.contains('_') && !next_is_underscore())
+            {
+                EscapeBodyText(&text[last..i]).fmt(fmt)?;
+                fmt.write_str("")?;
+                last = i;
+            }
+        }
+        if last < text.len() {
+            EscapeBodyText(&text[last..]).fmt(fmt)?;
+        }
+        Ok(())
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustdoc/html/escape/tests.rs b/src/librustdoc/html/escape/tests.rs
new file mode 100644
index 0000000000000..f99a2a693a628
--- /dev/null
+++ b/src/librustdoc/html/escape/tests.rs
@@ -0,0 +1,57 @@
+// basic examples
+#[test]
+fn escape_body_text_with_wbr() {
+    use super::EscapeBodyTextWithWbr as E;
+    // extreme corner cases
+    assert_eq!(&E("").to_string(), "");
+    assert_eq!(&E("a").to_string(), "a");
+    assert_eq!(&E("A").to_string(), "A");
+    // real(istic) examples
+    assert_eq!(&E("FirstSecond").to_string(), "FirstSecond");
+    assert_eq!(&E("First_Second").to_string(), "First_Second");
+    assert_eq!(&E("First_Second").to_string(), "First<T>_Second");
+    assert_eq!(&E("first_second").to_string(), "first_second");
+    assert_eq!(&E("MY_CONSTANT").to_string(), "MY_CONSTANT");
+    assert_eq!(&E("___________").to_string(), "___________");
+    // a string won't get wrapped if it's less than 8 bytes
+    assert_eq!(&E("HashSet").to_string(), "HashSet");
+    // an individual word won't get wrapped if it's less than 4 bytes
+    assert_eq!(&E("VecDequeue").to_string(), "VecDequeue");
+    assert_eq!(&E("VecDequeueSet").to_string(), "VecDequeueSet");
+    // how to handle acronyms
+    assert_eq!(&E("BTreeMap").to_string(), "BTreeMap");
+    assert_eq!(&E("HTTPSProxy").to_string(), "HTTPSProxy");
+    // more corners
+    assert_eq!(&E("ṼẽçÑñéå").to_string(), "ṼẽçÑñéå");
+    assert_eq!(&E("V\u{0300}e\u{0300}c\u{0300}D\u{0300}e\u{0300}q\u{0300}u\u{0300}e\u{0300}u\u{0300}e\u{0300}").to_string(), "V\u{0300}e\u{0300}c\u{0300}D\u{0300}e\u{0300}q\u{0300}u\u{0300}e\u{0300}u\u{0300}e\u{0300}");
+    assert_eq!(&E("LPFNACCESSIBLEOBJECTFROMWINDOW").to_string(), "LPFNACCESSIBLEOBJECTFROMWINDOW");
+}
+// property test
+#[test]
+fn escape_body_text_with_wbr_makes_sense() {
+    use itertools::Itertools as _;
+
+    use super::EscapeBodyTextWithWbr as E;
+    const C: [u8; 3] = [b'a', b'A', b'_'];
+    for chars in [
+        C.into_iter(),
+        C.into_iter(),
+        C.into_iter(),
+        C.into_iter(),
+        C.into_iter(),
+        C.into_iter(),
+        C.into_iter(),
+        C.into_iter(),
+    ]
+    .into_iter()
+    .multi_cartesian_product()
+    {
+        let s = String::from_utf8(chars).unwrap();
+        assert_eq!(s.len(), 8);
+        let esc = E(&s).to_string();
+        assert!(!esc.contains(""));
+        assert!(!esc.ends_with(""));
+        assert!(!esc.starts_with(""));
+        assert_eq!(&esc.replace("", ""), &s);
+    }
+}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index d6aed75103dc4..bb5ac303ffd63 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -32,7 +32,7 @@ use crate::clean::utils::find_nearest_parent_module;
 use crate::clean::{self, ExternalCrate, PrimitiveType};
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
-use crate::html::escape::Escape;
+use crate::html::escape::{Escape, EscapeBodyText};
 use crate::html::render::Context;
 use crate::passes::collect_intra_doc_links::UrlFragment;
 
@@ -988,6 +988,7 @@ pub(crate) fn anchor<'a, 'cx: 'a>(
                 f,
                 r#"{text}"#,
                 path = join_with_double_colon(&fqp),
+                text = EscapeBodyText(text.as_str()),
             )
         } else {
             f.write_str(text.as_str())
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 24476e80778e1..3f01c082ba914 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -29,7 +29,7 @@ use crate::clean;
 use crate::config::ModuleSorting;
 use crate::formats::item_type::ItemType;
 use crate::formats::Impl;
-use crate::html::escape::Escape;
+use crate::html::escape::{Escape, EscapeBodyTextWithWbr};
 use crate::html::format::{
     display_fn, join_with_double_colon, print_abi_with_space, print_constness_with_space,
     print_where_clause, visibility_print_with_space, Buffer, Ending, PrintWithSpace,
@@ -423,7 +423,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
                         "
{}extern crate {} as {};", visibility_print_with_space(myitem, cx), anchor(myitem.item_id.expect_def_id(), src, cx), - myitem.name.unwrap(), + EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()), ), None => write!( w, @@ -520,7 +520,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: {stab_tags}\
\ {docs_before}{docs}{docs_after}", - name = myitem.name.unwrap(), + name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()), visibility_and_hidden = visibility_and_hidden, stab_tags = extra_info_tags(myitem, item, tcx), class = myitem.type_(), diff --git a/tests/rustdoc/extremely_long_typename.extremely_long_typename.html b/tests/rustdoc/extremely_long_typename.extremely_long_typename.html new file mode 100644 index 0000000000000..b20e59866dac6 --- /dev/null +++ b/tests/rustdoc/extremely_long_typename.extremely_long_typename.html @@ -0,0 +1 @@ +
  • \ No newline at end of file diff --git a/tests/rustdoc/extremely_long_typename.rs b/tests/rustdoc/extremely_long_typename.rs new file mode 100644 index 0000000000000..212afe2d11033 --- /dev/null +++ b/tests/rustdoc/extremely_long_typename.rs @@ -0,0 +1,7 @@ +// ignore-tidy-linelength +// Make sure that, if an extremely long type name is named, +// the item table has it line wrapped. +// There should be some reasonably-placed `` tags in the snapshot file. + +// @snapshot extremely_long_typename "extremely_long_typename/index.html" '//ul[@class="item-table"]/li' +pub struct CreateSubscriptionPaymentSettingsPaymentMethodOptionsCustomerBalanceBankTransferEuBankTransfer; diff --git a/tests/rustdoc/item-desc-list-at-start.item-table.html b/tests/rustdoc/item-desc-list-at-start.item-table.html index 72bde573cead3..ab8b1508b5519 100644 --- a/tests/rustdoc/item-desc-list-at-start.item-table.html +++ b/tests/rustdoc/item-desc-list-at-start.item-table.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 583bf1e5bf8ee78c60f5db5b3bb85f032545239c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 10 Jun 2024 16:28:51 -0700 Subject: [PATCH 242/489] Fix tidy call in runtest with custom HTML element --- src/tools/compiletest/src/runtest.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6e8fdd624434..1f15605d8beed 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2731,6 +2731,7 @@ impl<'test> TestCx<'test> { #[rustfmt::skip] let tidy_args = [ + "--new-blocklevel-tags", "rustdoc-search", "--indent", "yes", "--indent-spaces", "2", "--wrap", "0", From 0d0e18e7f6e5f3278d897123e78271cce95de863 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 6 Jul 2024 17:12:53 -0700 Subject: [PATCH 243/489] rustdoc: use ``-tolerant function to check text contents --- .../rustdoc-gui/duplicate-macro-reexport.goml | 4 ++-- tests/rustdoc-gui/font-weight.goml | 4 ++-- tests/rustdoc-gui/item-info.goml | 4 ++-- tests/rustdoc-gui/label-next-to-symbol.goml | 18 +++++++++--------- tests/rustdoc-gui/notable-trait.goml | 8 ++++---- tests/rustdoc-gui/search-result-color.goml | 12 ++++++------ tests/rustdoc-gui/sidebar-macro-reexport.goml | 2 +- tests/rustdoc-gui/sidebar-mobile.goml | 7 +++++-- tests/rustdoc-gui/sidebar-source-code.goml | 8 ++++---- tests/rustdoc-gui/source-anchor-scroll.goml | 2 +- 10 files changed, 36 insertions(+), 33 deletions(-) diff --git a/tests/rustdoc-gui/duplicate-macro-reexport.goml b/tests/rustdoc-gui/duplicate-macro-reexport.goml index 7d01c88f31ba5..a838d99c4bffc 100644 --- a/tests/rustdoc-gui/duplicate-macro-reexport.goml +++ b/tests/rustdoc-gui/duplicate-macro-reexport.goml @@ -4,11 +4,11 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/macro.a.html" wait-for: ".sidebar-elems .macro" // Check there is only one macro named "a" listed in the sidebar. assert-count: ( - "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[text()='a']", + "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[normalize-space()='a']", 1, ) // Check there is only one macro named "b" listed in the sidebar. assert-count: ( - "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[text()='b']", + "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[normalize-space()='b']", 1, ) diff --git a/tests/rustdoc-gui/font-weight.goml b/tests/rustdoc-gui/font-weight.goml index 602b8d6f5b34c..26e9bf515a3ff 100644 --- a/tests/rustdoc-gui/font-weight.goml +++ b/tests/rustdoc-gui/font-weight.goml @@ -1,8 +1,8 @@ // This test checks that the font weight is correctly applied. go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html" -assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"}) +assert-css: ("//*[@class='rust item-decl']//a[normalize-space()='Alias']", {"font-weight": "400"}) assert-css: ( - "//*[@class='structfield section-header']//a[text()='Alias']", + "//*[@class='structfield section-header']//a[normalize-space()='Alias']", {"font-weight": "400"}, ) assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"}) diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index 1eb46e832b70b..7a0194c6cc1f6 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -12,11 +12,11 @@ assert-position: (".item-info .stab", {"x": 245}) // test for . set-window-size: (850, 800) store-position: ( - "//*[@class='stab portability']//code[text()='Win32_System']", + "//*[@class='stab portability']//code[normalize-space()='Win32_System']", {"x": first_line_x, "y": first_line_y}, ) store-position: ( - "//*[@class='stab portability']//code[text()='Win32_System_Diagnostics']", + "//*[@class='stab portability']//code[normalize-space()='Win32_System_Diagnostics']", {"x": second_line_x, "y": second_line_y}, ) assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272 diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml index 0582bd2cad36e..1fa0a120adaec 100644 --- a/tests/rustdoc-gui/label-next-to-symbol.goml +++ b/tests/rustdoc-gui/label-next-to-symbol.goml @@ -23,7 +23,7 @@ assert-css: ( // table like view assert-css: (".desc.docblock-short", { "padding-left": "0px" }) compare-elements-position-near: ( - "//*[@class='item-name']//a[text()='replaced_function']", + "//*[@class='item-name']//a[normalize-space()='replaced_function']", ".item-name .stab.deprecated", {"y": 2}, ) @@ -35,8 +35,8 @@ compare-elements-position: ( // Ensure no wrap compare-elements-position: ( - "//*[@class='item-name']//a[text()='replaced_function']/..", - "//*[@class='desc docblock-short'][text()='a thing with a label']", + "//*[@class='item-name']//a[normalize-space()='replaced_function']/..", + "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']", ["y"], ) @@ -45,7 +45,7 @@ set-window-size: (600, 600) // staggered layout with 2em spacing assert-css: (".desc.docblock-short", { "padding-left": "32px" }) compare-elements-position-near: ( - "//*[@class='item-name']//a[text()='replaced_function']", + "//*[@class='item-name']//a[normalize-space()='replaced_function']", ".item-name .stab.deprecated", {"y": 2}, ) @@ -57,13 +57,13 @@ compare-elements-position: ( // Ensure wrap compare-elements-position-false: ( - "//*[@class='item-name']//a[text()='replaced_function']/..", - "//*[@class='desc docblock-short'][text()='a thing with a label']", + "//*[@class='item-name']//a[normalize-space()='replaced_function']/..", + "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']", ["y"], ) compare-elements-position-false: ( ".item-name .stab.deprecated", - "//*[@class='desc docblock-short'][text()='a thing with a label']", + "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']", ["y"], ) @@ -73,7 +73,7 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/cfgs/index.html" // This part of the tags should not be on the same line as the beginning since the width // is too small for that. compare-elements-position-false: ( - "//*[@class='stab portability']/code[text()='appservice-api-c']", - "//*[@class='stab portability']/code[text()='server']", + "//*[@class='stab portability']/code[normalize-space()='appservice-api-c']", + "//*[@class='stab portability']/code[normalize-space()='server']", ["y"], ) diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index 6ee810c5768c2..e2a8a43007eb0 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -9,19 +9,19 @@ define-function: ( block { // Checking they have the same y position. compare-elements-position: ( - "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", + "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", ["y"], ) // Checking they don't have the same x position. compare-elements-position-false: ( - "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", + "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", ["x"], ) // The `i` should be *after* the type. assert-position: ( - "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", + "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", {"x": |x|}, ) assert-position: ( @@ -70,7 +70,7 @@ call-function: ("check-notable-tooltip-position-complete", { // Now only the `i` should be on the next line. set-window-size: (1055, 600) compare-elements-position-false: ( - "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", + "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", ["y", "x"], ) diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 9825f92b45351..e8da43eb896bc 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -20,11 +20,11 @@ define-function: ( ALL, ) assert-css: ( - "//*[@class='desc'][text()='Just a normal struct.']", + "//*[@class='desc'][normalize-space()='Just a normal struct.']", {"color": |desc_color|}, ) assert-css: ( - "//*[@class='result-name']//*[text()='test_docs::']", + "//*[@class='result-name']//*[normalize-space()='test_docs::']", {"color": |path_color|}, ) @@ -85,19 +85,19 @@ define-function: ( move-cursor-to: ".search-input" focus: ".search-input" // To ensure the `` container isn't focused or hovered. assert-css: ( - "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a", + "//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a", {"color": |path_color|, "background-color": "transparent"}, ALL, ) // Checking color and background on hover. - move-cursor-to: "//*[@class='desc'][text()='Just a normal struct.']" + move-cursor-to: "//*[@class='desc'][normalize-space()='Just a normal struct.']" assert-css: ( - "//*[@class='result-name']//*[text()='test_docs::']", + "//*[@class='result-name']//*[normalize-space()='test_docs::']", {"color": |hover_path_color|}, ) assert-css: ( - "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a", + "//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a", {"color": |hover_path_color|, "background-color": |hover_background|}, ) } diff --git a/tests/rustdoc-gui/sidebar-macro-reexport.goml b/tests/rustdoc-gui/sidebar-macro-reexport.goml index 0f7ef6c355828..cad25507fbbd6 100644 --- a/tests/rustdoc-gui/sidebar-macro-reexport.goml +++ b/tests/rustdoc-gui/sidebar-macro-reexport.goml @@ -2,4 +2,4 @@ // displayed twice in the sidebar. go-to: "file://" + |DOC_PATH| + "/test_docs/macro.repro.html" wait-for: ".sidebar-elems .block.macro a" -assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[text()='repro']", 1) +assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[normalize-space()='repro']", 1) diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml index b4ff483c18097..4ada4837a5774 100644 --- a/tests/rustdoc-gui/sidebar-mobile.goml +++ b/tests/rustdoc-gui/sidebar-mobile.goml @@ -25,9 +25,12 @@ click: ".sidebar-menu-toggle" assert-css: (".sidebar", {"left": "0px"}) // Make sure the "struct Foo" header is hidden, since the mobile topbar already does it. -assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='Foo']/parent::h2", {"display": "none"}) +assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[normalize-space()='Foo']/parent::h2", {"display": "none"}) // Make sure the global navigation is still here. -assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='In crate test_docs']/parent::h2", {"display": "block"}) +assert-css: ( + "//nav[contains(@class, 'sidebar')]//h2/a[normalize-space()='In crate test_docs']/parent::h2", + {"display": "block"} +) // Click elsewhere. click: "body" diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml index ef0b5ab38b138..6afccf6a95fe2 100644 --- a/tests/rustdoc-gui/sidebar-source-code.goml +++ b/tests/rustdoc-gui/sidebar-source-code.goml @@ -66,12 +66,12 @@ click: "#sidebar-button" // We wait for the sidebar to be expanded. wait-for-css: (".src-sidebar-expanded nav.sidebar", {"width": "300px"}) assert: "//*[@class='dir-entry' and @open]/*[text()='lib2']" -assert: "//*[@class='dir-entry' and @open]/*[text()='another_folder']" -assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']" +assert: "//*[@class='dir-entry' and @open]/*[normalize-space()='another_folder']" +assert: "//*[@class='dir-entry' and @open]/*[normalize-space()='sub_mod']" // Only "another_folder" should be "open" in "lib2". -assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']" +assert: "//*[@class='dir-entry' and not(@open)]/*[normalize-space()='another_mod']" // All other trees should be collapsed. -assert-count: ("//*[@id='src-sidebar']/details[not(text()='lib2') and not(@open)]", 11) +assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 11) // We now switch to mobile mode. set-window-size: (600, 600) diff --git a/tests/rustdoc-gui/source-anchor-scroll.goml b/tests/rustdoc-gui/source-anchor-scroll.goml index 940851ea14632..3508b26a0bf24 100644 --- a/tests/rustdoc-gui/source-anchor-scroll.goml +++ b/tests/rustdoc-gui/source-anchor-scroll.goml @@ -11,7 +11,7 @@ click: '//a[text() = "barbar" and @href="#5-7"]' assert-property: ("html", {"scrollTop": "123"}) click: '//a[text() = "bar" and @href="#28-36"]' assert-property: ("html", {"scrollTop": "154"}) -click: '//a[text() = "sub_fn" and @href="#2-4"]' +click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]' assert-property: ("html", {"scrollTop": "51"}) // We now check that clicking on lines doesn't change the scroll From 9186001f3491c0eb996de6f61a457cecfb089333 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 6 Jul 2024 19:05:28 -0700 Subject: [PATCH 244/489] rustdoc: avoid redundant HTML when there's already line breaks --- src/librustdoc/html/escape.rs | 6 ++++++ src/librustdoc/html/escape/tests.rs | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index 9441491316345..3e20c5b322b4a 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -97,6 +97,12 @@ impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> { let _ = it.next(); // don't insert wbr before first char while let Some((i, s)) = it.next() { let pk = it.peek(); + if s.chars().all(|c| c.is_whitespace()) { + // don't need "First Second"; the space is enough + EscapeBodyText(&text[last..i]).fmt(fmt)?; + last = i; + continue; + } let is_uppercase = || s.chars().any(|c| c.is_uppercase()); let next_is_uppercase = || pk.map_or(true, |(_, t)| t.chars().any(|c| c.is_uppercase())); diff --git a/src/librustdoc/html/escape/tests.rs b/src/librustdoc/html/escape/tests.rs index f99a2a693a628..7933f23eb7474 100644 --- a/src/librustdoc/html/escape/tests.rs +++ b/src/librustdoc/html/escape/tests.rs @@ -9,6 +9,10 @@ fn escape_body_text_with_wbr() { // real(istic) examples assert_eq!(&E("FirstSecond").to_string(), "FirstSecond"); assert_eq!(&E("First_Second").to_string(), "First_Second"); + assert_eq!(&E("First Second").to_string(), "First Second"); + assert_eq!(&E("First HSecond").to_string(), "First HSecond"); + assert_eq!(&E("First HTTPSecond").to_string(), "First HTTPSecond"); + assert_eq!(&E("First SecondThird").to_string(), "First SecondThird"); assert_eq!(&E("First_Second").to_string(), "First<T>_Second"); assert_eq!(&E("first_second").to_string(), "first_second"); assert_eq!(&E("MY_CONSTANT").to_string(), "MY_CONSTANT"); From f990239b34d4cc81999d62e3f2271c7c53c72fb7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 24 Jul 2024 15:58:34 -0400 Subject: [PATCH 245/489] Stop using MoveDataParamEnv for places that don't need a param-env --- compiler/rustc_borrowck/src/lib.rs | 16 +++-- .../src/drop_flag_effects.rs | 7 +-- .../src/impls/initialized.rs | 60 ++++++++----------- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 9 ++- .../src/elaborate_drops.rs | 16 +++-- .../src/remove_uninit_drops.rs | 9 ++- 6 files changed, 53 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 74d9f9d8f81b8..9c2a0036befa8 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -45,7 +45,7 @@ use rustc_mir_dataflow::impls::{ use rustc_mir_dataflow::move_paths::{ InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex, }; -use rustc_mir_dataflow::{Analysis, MoveDataParamEnv}; +use rustc_mir_dataflow::Analysis; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use rustc_target::abi::FieldIdx; @@ -194,9 +194,7 @@ fn do_mir_borrowck<'tcx>( .iter_enumerated() .map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, param_env, |_| true))); - let mdpe = MoveDataParamEnv { move_data, param_env }; - - let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) + let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint() @@ -204,7 +202,7 @@ fn do_mir_borrowck<'tcx>( let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure(); let borrow_set = - Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); + Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &move_data)); // Compute non-lexical lifetimes. let nll::NllOutput { @@ -222,7 +220,7 @@ fn do_mir_borrowck<'tcx>( &location_table, param_env, &mut flow_inits, - &mdpe.move_data, + &move_data, &borrow_set, tcx.closure_captures(def), consumer_options, @@ -254,11 +252,11 @@ fn do_mir_borrowck<'tcx>( .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint(); - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe) + let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint(); - let flow_ever_inits = EverInitializedPlaces::new(body, &mdpe) + let flow_ever_inits = EverInitializedPlaces::new(body, &move_data) .into_engine(tcx, body) .pass_name("borrowck") .iterate_to_fixpoint(); @@ -324,7 +322,7 @@ fn do_mir_borrowck<'tcx>( infcx: &infcx, param_env, body, - move_data: &mdpe.move_data, + move_data: &move_data, location_table: &location_table, movable_coroutine, locals_are_invalidated_at_exit, diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs index 4f67a0fa09541..bb53eaf6cbd1c 100644 --- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs +++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs @@ -3,7 +3,6 @@ use rustc_target::abi::VariantIdx; use tracing::debug; use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex}; -use super::MoveDataParamEnv; use crate::elaborate_drops::DropFlagState; pub fn move_path_children_matching<'tcx, F>( @@ -70,12 +69,11 @@ pub fn on_all_children_bits<'tcx, F>( pub fn drop_flag_effects_for_function_entry<'tcx, F>( body: &Body<'tcx>, - ctxt: &MoveDataParamEnv<'tcx>, + move_data: &MoveData<'tcx>, mut callback: F, ) where F: FnMut(MovePathIndex, DropFlagState), { - let move_data = &ctxt.move_data; for arg in body.args_iter() { let place = mir::Place::from(arg); let lookup_result = move_data.rev_lookup.find(place.as_ref()); @@ -87,13 +85,12 @@ pub fn drop_flag_effects_for_function_entry<'tcx, F>( pub fn drop_flag_effects_for_location<'tcx, F>( body: &Body<'tcx>, - ctxt: &MoveDataParamEnv<'tcx>, + move_data: &MoveData<'tcx>, loc: Location, mut callback: F, ) where F: FnMut(MovePathIndex, DropFlagState), { - let move_data = &ctxt.move_data; debug!("drop_flag_effects_for_location({:?})", loc); // first, move out of the RHS diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs index 77f4dcf892a39..e9e8ddefa020b 100644 --- a/compiler/rustc_mir_dataflow/src/impls/initialized.rs +++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs @@ -11,7 +11,7 @@ use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData use crate::{ drop_flag_effects, drop_flag_effects_for_function_entry, drop_flag_effects_for_location, lattice, on_all_children_bits, on_lookup_result_bits, AnalysisDomain, GenKill, GenKillAnalysis, - MaybeReachable, MoveDataParamEnv, + MaybeReachable, }; /// `MaybeInitializedPlaces` tracks all places that might be @@ -52,17 +52,13 @@ use crate::{ pub struct MaybeInitializedPlaces<'a, 'mir, 'tcx> { tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, - mdpe: &'a MoveDataParamEnv<'tcx>, + move_data: &'a MoveData<'tcx>, skip_unreachable_unwind: bool, } impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, - mdpe: &'a MoveDataParamEnv<'tcx>, - ) -> Self { - MaybeInitializedPlaces { tcx, body, mdpe, skip_unreachable_unwind: false } + pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { + MaybeInitializedPlaces { tcx, body, move_data, skip_unreachable_unwind: false } } pub fn skipping_unreachable_unwind(mut self) -> Self { @@ -89,7 +85,7 @@ impl<'a, 'mir, 'tcx> MaybeInitializedPlaces<'a, 'mir, 'tcx> { impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { - &self.mdpe.move_data + self.move_data } } @@ -131,22 +127,18 @@ impl<'a, 'mir, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'mir, 'tcx pub struct MaybeUninitializedPlaces<'a, 'mir, 'tcx> { tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, - mdpe: &'a MoveDataParamEnv<'tcx>, + move_data: &'a MoveData<'tcx>, mark_inactive_variants_as_uninit: bool, skip_unreachable_unwind: BitSet, } impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - body: &'mir Body<'tcx>, - mdpe: &'a MoveDataParamEnv<'tcx>, - ) -> Self { + pub fn new(tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { MaybeUninitializedPlaces { tcx, body, - mdpe, + move_data, mark_inactive_variants_as_uninit: false, skip_unreachable_unwind: BitSet::new_empty(body.basic_blocks.len()), } @@ -173,7 +165,7 @@ impl<'a, 'mir, 'tcx> MaybeUninitializedPlaces<'a, 'mir, 'tcx> { impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, '_, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { - &self.mdpe.move_data + self.move_data } } @@ -213,18 +205,18 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, '_, 'tcx> { /// that would require a dynamic drop-flag at that statement. pub struct DefinitelyInitializedPlaces<'a, 'tcx> { body: &'a Body<'tcx>, - mdpe: &'a MoveDataParamEnv<'tcx>, + move_data: &'a MoveData<'tcx>, } impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - DefinitelyInitializedPlaces { body, mdpe } + pub fn new(body: &'a Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { + DefinitelyInitializedPlaces { body, move_data } } } impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { - &self.mdpe.move_data + self.move_data } } @@ -259,18 +251,18 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { /// ``` pub struct EverInitializedPlaces<'a, 'mir, 'tcx> { body: &'mir Body<'tcx>, - mdpe: &'a MoveDataParamEnv<'tcx>, + move_data: &'a MoveData<'tcx>, } impl<'a, 'mir, 'tcx> EverInitializedPlaces<'a, 'mir, 'tcx> { - pub fn new(body: &'mir Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { - EverInitializedPlaces { body, mdpe } + pub fn new(body: &'mir Body<'tcx>, move_data: &'a MoveData<'tcx>) -> Self { + EverInitializedPlaces { body, move_data } } } impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, '_, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { - &self.mdpe.move_data + self.move_data } } @@ -328,7 +320,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { *state = MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len())); - drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.move_data, |path, s| { assert!(s == DropFlagState::Present); state.gen_(path); }); @@ -348,7 +340,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { Self::update_bits(trans, path, s) }); @@ -380,7 +372,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, '_, 'tcx> { { edges = TerminatorEdges::Single(target); } - drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { Self::update_bits(state, path, s) }); edges @@ -465,7 +457,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { // set all bits to 1 (uninit) before gathering counter-evidence state.insert_all(); - drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.move_data, |path, s| { assert!(s == DropFlagState::Present); state.remove(path); }); @@ -485,7 +477,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { _statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { Self::update_bits(trans, path, s) }); @@ -499,7 +491,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, '_, 'tcx> { terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { Self::update_bits(trans, path, s) }); if self.skip_unreachable_unwind.contains(location.block) { @@ -592,7 +584,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) { state.0.clear(); - drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| { + drop_flag_effects_for_function_entry(self.body, self.move_data, |path, s| { assert!(s == DropFlagState::Present); state.0.insert(path); }); @@ -612,7 +604,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { _statement: &mir::Statement<'tcx>, location: Location, ) { - drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { Self::update_bits(trans, path, s) }) } @@ -623,7 +615,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { terminator: &'mir mir::Terminator<'tcx>, location: Location, ) -> TerminatorEdges<'mir, 'tcx> { - drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| { + drop_flag_effects_for_location(self.body, self.move_data, location, |path, s| { Self::update_bits(trans, path, s) }); terminator.edges() diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 23bf35b30cae0..0171cc8591809 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -16,7 +16,7 @@ use crate::impls::{ DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces, }; use crate::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; -use crate::{Analysis, JoinSemiLattice, MoveDataParamEnv, ResultsCursor}; +use crate::{Analysis, JoinSemiLattice, ResultsCursor}; pub struct SanityCheck; @@ -46,10 +46,9 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { let param_env = tcx.param_env(def_id); let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); - let mdpe = MoveDataParamEnv { move_data, param_env }; if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { - let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) + let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) .into_engine(tcx, body) .iterate_to_fixpoint(); @@ -57,7 +56,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &mdpe) + let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) .into_engine(tcx, body) .iterate_to_fixpoint(); @@ -65,7 +64,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { } if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { - let flow_def_inits = DefinitelyInitializedPlaces::new(body, &mdpe) + let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data) .into_engine(tcx, body) .iterate_to_fixpoint(); diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 026812852dd31..5a22ef7790349 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -62,7 +62,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { let elaborate_patch = { let env = MoveDataParamEnv { move_data, param_env }; - let mut inits = MaybeInitializedPlaces::new(tcx, body, &env) + let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data) .skipping_unreachable_unwind() .into_engine(tcx, body) .pass_name("elaborate_drops") @@ -70,7 +70,7 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { .into_results_cursor(body); let dead_unwinds = compute_dead_unwinds(body, &mut inits); - let uninits = MaybeUninitializedPlaces::new(tcx, body, &env) + let uninits = MaybeUninitializedPlaces::new(tcx, body, &env.move_data) .mark_inactive_variants_as_uninit() .skipping_unreachable_unwind(dead_unwinds) .into_engine(tcx, body) @@ -443,9 +443,13 @@ impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> { fn drop_flags_for_args(&mut self) { let loc = Location::START; - rustc_mir_dataflow::drop_flag_effects_for_function_entry(self.body, self.env, |path, ds| { - self.set_drop_flag(loc, path, ds); - }) + rustc_mir_dataflow::drop_flag_effects_for_function_entry( + self.body, + &self.env.move_data, + |path, ds| { + self.set_drop_flag(loc, path, ds); + }, + ) } fn drop_flags_for_locs(&mut self) { @@ -478,7 +482,7 @@ impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> { let loc = Location { block: bb, statement_index: i }; rustc_mir_dataflow::drop_flag_effects_for_location( self.body, - self.env, + &self.env.move_data, loc, |path, ds| self.set_drop_flag(loc, path, ds), ) diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index d642c307a3f37..fae1cb5f7d8a5 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -3,7 +3,7 @@ use rustc_middle::mir::{Body, TerminatorKind}; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; -use rustc_mir_dataflow::{move_path_children_matching, Analysis, MaybeReachable, MoveDataParamEnv}; +use rustc_mir_dataflow::{move_path_children_matching, Analysis, MaybeReachable}; use rustc_target::abi::FieldIdx; use crate::MirPass; @@ -24,8 +24,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { let move_data = MoveData::gather_moves(body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env)); - let mdpe = MoveDataParamEnv { move_data, param_env }; - let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) + let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) .into_engine(tcx, body) .pass_name("remove_uninit_drops") .iterate_to_fixpoint() @@ -40,7 +39,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { let MaybeReachable::Reachable(maybe_inits) = maybe_inits.get() else { continue }; // If there's no move path for the dropped place, it's probably a `Deref`. Let it alone. - let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else { + let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) else { continue; }; @@ -48,7 +47,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { tcx, param_env, maybe_inits, - &mdpe.move_data, + &move_data, place.ty(body, tcx).ty, mpi, ); From 23f46e5b9944f35d2726d583f18d8e387f1556f4 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Mon, 29 Jul 2024 17:50:12 +0100 Subject: [PATCH 246/489] Stabilize offset_of_nested --- .../src/error_codes/E0795.md | 4 +- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_hir_typeck/src/expr.rs | 12 -- library/core/src/lib.rs | 2 +- library/core/src/mem/mod.rs | 3 +- library/core/tests/lib.rs | 110 +++++++++--------- tests/mir-opt/const_prop/offset_of.rs | 2 +- .../mir-opt/dataflow-const-prop/offset_of.rs | 2 - .../feature-gate-offset-of-enum.rs | 2 - .../feature-gate-offset-of-enum.stderr | 8 +- .../feature-gate-offset-of-nested.rs | 28 ----- .../feature-gate-offset-of-nested.stderr | 60 ---------- .../dead-code/offset-of-correct-param-env.rs | 1 - tests/ui/lint/dead-code/offset-of.rs | 1 - tests/ui/lint/dead-code/offset-of.stderr | 12 +- tests/ui/offset-of/offset-of-enum.rs | 2 +- tests/ui/offset-of/offset-of-private.rs | 2 +- tests/ui/offset-of/offset-of-self.rs | 2 - tests/ui/offset-of/offset-of-self.stderr | 14 +-- tests/ui/offset-of/offset-of-slice.rs | 2 +- tests/ui/offset-of/offset-of-tuple-nested.rs | 2 - tests/ui/offset-of/offset-of-tuple.rs | 1 - tests/ui/offset-of/offset-of-tuple.stderr | 66 +++++------ .../offset-of-unstable-with-feature.rs | 2 +- tests/ui/offset-of/offset-of-unstable.rs | 2 - tests/ui/offset-of/offset-of-unstable.stderr | 16 +-- 27 files changed, 126 insertions(+), 236 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-offset-of-nested.rs delete mode 100644 tests/ui/feature-gates/feature-gate-offset-of-nested.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md index ad77d72c913a8..69e61f7738f79 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0795.md +++ b/compiler/rustc_error_codes/src/error_codes/E0795.md @@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro. Erroneous code example: ```compile_fail,E0795 -#![feature(offset_of_enum, offset_of_nested)] +#![feature(offset_of_enum)] let x = std::mem::offset_of!(Option, Some); ``` @@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option` can be found by specifying the field name `0`: ``` -#![feature(offset_of_enum, offset_of_nested)] +#![feature(offset_of_enum)] let x: usize = std::mem::offset_of!(Option, Some.0); ``` diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 46992347f839d..99fcc66a4adc1 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -292,6 +292,8 @@ declare_features! ( (accepted, non_exhaustive, "1.40.0", Some(44109)), /// Allows `foo.rs` as an alternative to `foo/mod.rs`. (accepted, non_modrs_mods, "1.30.0", Some(44660)), + /// Allows using multiple nested field accesses in offset_of! + (accepted, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)), /// Allows the use of or-patterns (e.g., `0 | 1`). (accepted, or_patterns, "1.53.0", Some(54883)), /// Allows using `+bundle,+whole-archive` link modifiers with native libs. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 7d0ca3a1d0faf..a57ff3f7b006f 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -560,8 +560,6 @@ declare_features! ( (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)), /// Allows using enums in offset_of! (unstable, offset_of_enum, "1.75.0", Some(120141)), - /// Allows using multiple nested field accesses in offset_of! - (unstable, offset_of_nested, "1.77.0", Some(120140)), /// Allows using fields with slice type in offset_of! (unstable, offset_of_slice, "CURRENT_RUSTC_VERSION", Some(126151)), /// Allows using `#[optimize(X)]`. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f3266e04f8194..d75a5f8806bc9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3338,18 +3338,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let container = self.lower_ty(container).normalized; - if let Some(ident_2) = fields.get(1) - && !self.tcx.features().offset_of_nested - { - rustc_session::parse::feature_err( - &self.tcx.sess, - sym::offset_of_nested, - ident_2.span, - "only a single ident or integer is stable as the field in offset_of", - ) - .emit(); - } - let mut field_indices = Vec::with_capacity(fields.len()); let mut current_container = container; let mut fields = fields.into_iter(); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a3eca34a35cfc..d9c7a0877399b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -107,6 +107,7 @@ // // Library features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(offset_of_nested))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(char_indices_offset)] @@ -172,7 +173,6 @@ #![feature(isqrt)] #![feature(link_cfg)] #![feature(offset_of_enum)] -#![feature(offset_of_nested)] #![feature(panic_internals)] #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index b8e9f606a9ad6..ea2dcdce6e89e 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1321,7 +1321,8 @@ impl SizedTypeProperties for T {} /// # Examples /// /// ``` -/// #![feature(offset_of_enum, offset_of_nested)] +/// # #![cfg_attr(bootstrap, feature(offset_of_nested))] +/// #![feature(offset_of_enum)] /// /// use std::mem; /// #[repr(C)] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 5dad5937a603d..1e336bf96b8fa 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -1,6 +1,11 @@ +// tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(offset_of_nested))] +#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] +#![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] #![feature(array_chunks)] #![feature(array_ptr_get)] +#![feature(array_try_from_fn)] #![feature(array_windows)] #![feature(ascii_char)] #![feature(ascii_char_variants)] @@ -9,112 +14,109 @@ #![feature(bigint_helper_methods)] #![feature(cell_update)] #![feature(clone_to_uninit)] -#![feature(const_align_offset)] #![feature(const_align_of_val_raw)] +#![feature(const_align_offset)] +#![feature(const_array_from_ref)] #![feature(const_black_box)] #![feature(const_cell_into_inner)] #![feature(const_hash)] #![feature(const_heap)] #![feature(const_intrinsic_copy)] +#![feature(const_ip)] +#![feature(const_ipv4)] +#![feature(const_ipv6)] +#![feature(const_likely)] #![feature(const_maybe_uninit_as_mut_ptr)] +#![feature(const_mut_refs)] #![feature(const_nonnull_new)] +#![feature(const_option)] +#![feature(const_option_ext)] +#![feature(const_pin)] #![feature(const_pointer_is_aligned)] #![feature(const_ptr_as_ref)] #![feature(const_ptr_write)] +#![feature(const_result)] +#![feature(const_slice_from_ref)] #![feature(const_three_way_compare)] #![feature(const_trait_impl)] -#![feature(const_likely)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] #![feature(dec2flt)] -#![feature(duration_consts_float)] #![feature(duration_constants)] #![feature(duration_constructors)] +#![feature(duration_consts_float)] +#![feature(error_generic_member_access)] #![feature(exact_size_is_empty)] #![feature(extern_types)] -#![feature(freeze)] +#![feature(float_minimum_maximum)] #![feature(flt2dec)] #![feature(fmt_internals)] -#![feature(float_minimum_maximum)] +#![feature(freeze)] #![feature(future_join)] #![feature(generic_assert_internals)] -#![feature(array_try_from_fn)] +#![feature(get_many_mut)] #![feature(hasher_prefixfree_extras)] #![feature(hashmap_internals)] -#![feature(try_find)] -#![feature(layout_for_ptr)] -#![feature(pattern)] -#![feature(slice_take)] -#![feature(slice_from_ptr_range)] -#![feature(slice_split_once)] -#![feature(split_as_slice)] -#![feature(maybe_uninit_fill)] -#![feature(maybe_uninit_write_slice)] -#![feature(maybe_uninit_uninit_array_transpose)] -#![feature(min_specialization)] -#![feature(noop_waker)] -#![feature(numfmt)] -#![feature(num_midpoint)] -#![feature(offset_of_nested)] -#![feature(isqrt)] -#![feature(unsigned_is_multiple_of)] -#![feature(step_trait)] -#![feature(str_internals)] -#![feature(std_internals)] -#![feature(test)] -#![feature(trusted_len)] -#![feature(try_blocks)] -#![feature(try_trait_v2)] -#![feature(slice_internals)] -#![feature(slice_partition_dedup)] +#![feature(int_roundings)] #![feature(ip)] +#![feature(is_ascii_octdigit)] +#![feature(isqrt)] #![feature(iter_advance_by)] #![feature(iter_array_chunks)] #![feature(iter_chain)] #![feature(iter_collect_into)] -#![feature(iter_partition_in_place)] #![feature(iter_intersperse)] #![feature(iter_is_partitioned)] +#![feature(iter_map_windows)] #![feature(iter_next_chunk)] #![feature(iter_order_by)] +#![feature(iter_partition_in_place)] #![feature(iter_repeat_n)] #![feature(iterator_try_collect)] #![feature(iterator_try_reduce)] -#![feature(const_ip)] -#![feature(const_ipv4)] -#![feature(const_ipv6)] -#![feature(const_mut_refs)] -#![feature(const_pin)] +#![feature(layout_for_ptr)] +#![feature(maybe_uninit_fill)] +#![feature(maybe_uninit_uninit_array_transpose)] +#![feature(maybe_uninit_write_slice)] +#![feature(min_specialization)] #![feature(never_type)] -#![feature(unwrap_infallible)] +#![feature(noop_waker)] +#![feature(num_midpoint)] +#![feature(numfmt)] +#![feature(pattern)] #![feature(pointer_is_aligned_to)] #![feature(portable_simd)] #![feature(ptr_metadata)] -#![feature(unsized_tuple_coercion)] -#![feature(const_option)] -#![feature(const_option_ext)] -#![feature(const_result)] -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] -#![cfg_attr(test, feature(cfg_match))] -#![feature(int_roundings)] +#![feature(slice_from_ptr_range)] +#![feature(slice_internals)] +#![feature(slice_partition_dedup)] +#![feature(slice_split_once)] +#![feature(slice_take)] #![feature(split_array)] +#![feature(split_as_slice)] +#![feature(std_internals)] +#![feature(step_trait)] +#![feature(str_internals)] #![feature(strict_provenance)] #![feature(strict_provenance_atomic_ptr)] +#![feature(test)] +#![feature(trait_upcasting)] +#![feature(trusted_len)] #![feature(trusted_random_access)] +#![feature(try_blocks)] +#![feature(try_find)] +#![feature(try_trait_v2)] +#![feature(unsigned_is_multiple_of)] #![feature(unsize)] -#![feature(const_array_from_ref)] -#![feature(const_slice_from_ref)] +#![feature(unsized_tuple_coercion)] +#![feature(unwrap_infallible)] #![feature(waker_getters)] -#![feature(error_generic_member_access)] -#![feature(trait_upcasting)] -#![feature(is_ascii_octdigit)] -#![feature(get_many_mut)] -#![feature(iter_map_windows)] +// tidy-alphabetical-end #![allow(internal_features)] -#![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] +#![deny(unsafe_op_in_unsafe_fn)] mod alloc; mod any; diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs index 264c8a3d21cdc..c2f5e83d6868f 100644 --- a/tests/mir-opt/const_prop/offset_of.rs +++ b/tests/mir-opt/const_prop/offset_of.rs @@ -2,7 +2,7 @@ //@ test-mir-pass: GVN // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of_enum, offset_of_nested)] +#![feature(offset_of_enum)] use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index 12396b31ed0e9..bb4a74d3712a0 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -1,8 +1,6 @@ //@ test-mir-pass: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(offset_of_nested)] - use std::marker::PhantomData; use std::mem::offset_of; diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs index 1f2f7ee1e1919..cc9efeb67f31d 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs @@ -1,5 +1,3 @@ -#![feature(offset_of_nested)] - use std::mem::offset_of; enum Alpha { diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr index fc7dd7923f7a8..8a73abc8cadbe 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr +++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr @@ -1,5 +1,5 @@ error[E0573]: expected type, found variant `Alpha::One` - --> $DIR/feature-gate-offset-of-enum.rs:11:16 + --> $DIR/feature-gate-offset-of-enum.rs:9:16 | LL | offset_of!(Alpha::One, 0); | ^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | offset_of!(Alpha::One, 0); | help: try using the variant's enum: `Alpha` error[E0658]: using enums in offset_of is experimental - --> $DIR/feature-gate-offset-of-enum.rs:12:23 + --> $DIR/feature-gate-offset-of-enum.rs:10:23 | LL | offset_of!(Alpha, One); | ^^^ @@ -18,13 +18,13 @@ LL | offset_of!(Alpha, One); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0795]: `One` is an enum variant; expected field at end of `offset_of` - --> $DIR/feature-gate-offset-of-enum.rs:12:23 + --> $DIR/feature-gate-offset-of-enum.rs:10:23 | LL | offset_of!(Alpha, One); | ^^^ enum variant error[E0658]: using enums in offset_of is experimental - --> $DIR/feature-gate-offset-of-enum.rs:14:23 + --> $DIR/feature-gate-offset-of-enum.rs:12:23 | LL | offset_of!(Alpha, Two.0); | ^^^ diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.rs b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs deleted file mode 100644 index c4eb4720fde5e..0000000000000 --- a/tests/ui/feature-gates/feature-gate-offset-of-nested.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![feature(offset_of_enum)] - -use std::mem::offset_of; - -struct S { - a: u8, - b: (u8, u8), - c: T, -} - -struct T { - t: &'static str, -} - -enum Alpha { - One(u8), - Two(u8), -} - -fn main() { - offset_of!(Alpha, Two.0); //~ ERROR only a single ident or integer is stable as the field in offset_of - offset_of!(S, a); - offset_of!((u8, S), 1); - offset_of!((u32, (S, T)), 1.1); //~ ERROR only a single ident or integer is stable as the field in offset_of - offset_of!(S, b.0); //~ ERROR only a single ident or integer is stable as the field in offset_of - offset_of!((S, ()), 0.c); //~ ERROR only a single ident or integer is stable as the field in offset_of - offset_of!(S, c.t); //~ ERROR only a single ident or integer is stable as the field in offset_of -} diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr deleted file mode 100644 index f367fc9fa0dd4..0000000000000 --- a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr +++ /dev/null @@ -1,60 +0,0 @@ -error[E0658]: only a single ident or integer is stable as the field in offset_of - --> $DIR/feature-gate-offset-of-nested.rs:21:27 - | -LL | offset_of!(Alpha, Two.0); - | ^ - | - = note: see issue #120140 for more information - = help: add `#![feature(offset_of_nested)]` 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]: only a single ident or integer is stable as the field in offset_of - --> $DIR/feature-gate-offset-of-nested.rs:24:33 - | -LL | offset_of!((u32, (S, T)), 1.1); - | _____----------------------------^- - | | | - | | in this macro invocation -LL | | offset_of!(S, b.0); -LL | | offset_of!((S, ()), 0.c); -LL | | offset_of!(S, c.t); -... | - | - = note: see issue #120140 for more information - = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0658]: only a single ident or integer is stable as the field in offset_of - --> $DIR/feature-gate-offset-of-nested.rs:25:21 - | -LL | offset_of!(S, b.0); - | ^ - | - = note: see issue #120140 for more information - = help: add `#![feature(offset_of_nested)]` 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]: only a single ident or integer is stable as the field in offset_of - --> $DIR/feature-gate-offset-of-nested.rs:26:27 - | -LL | offset_of!((S, ()), 0.c); - | ^ - | - = note: see issue #120140 for more information - = help: add `#![feature(offset_of_nested)]` 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]: only a single ident or integer is stable as the field in offset_of - --> $DIR/feature-gate-offset-of-nested.rs:27:21 - | -LL | offset_of!(S, c.t); - | ^ - | - = note: see issue #120140 for more information - = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs index 61babdeb28b5b..8cb242f82822a 100644 --- a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs +++ b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(offset_of_nested)] #![deny(dead_code)] // This struct contains a projection that can only be normalized after getting the field type. diff --git a/tests/ui/lint/dead-code/offset-of.rs b/tests/ui/lint/dead-code/offset-of.rs index 5269426d2ff3a..89e9fd910cb64 100644 --- a/tests/ui/lint/dead-code/offset-of.rs +++ b/tests/ui/lint/dead-code/offset-of.rs @@ -1,4 +1,3 @@ -#![feature(offset_of_nested)] #![deny(dead_code)] use std::mem::offset_of; diff --git a/tests/ui/lint/dead-code/offset-of.stderr b/tests/ui/lint/dead-code/offset-of.stderr index ed2916461cde8..4a903a9d6e899 100644 --- a/tests/ui/lint/dead-code/offset-of.stderr +++ b/tests/ui/lint/dead-code/offset-of.stderr @@ -1,5 +1,5 @@ error: field `b` is never read - --> $DIR/offset-of.rs:8:5 + --> $DIR/offset-of.rs:7:5 | LL | struct Alpha { | ----- field in this struct @@ -8,13 +8,13 @@ LL | b: (), | ^ | note: the lint level is defined here - --> $DIR/offset-of.rs:2:9 + --> $DIR/offset-of.rs:1:9 | LL | #![deny(dead_code)] | ^^^^^^^^^ error: field `a` is never read - --> $DIR/offset-of.rs:13:5 + --> $DIR/offset-of.rs:12:5 | LL | struct Beta { | ---- field in this struct @@ -22,7 +22,7 @@ LL | a: (), | ^ error: field `a` is never read - --> $DIR/offset-of.rs:18:5 + --> $DIR/offset-of.rs:17:5 | LL | struct Gamma { | ----- field in this struct @@ -30,7 +30,7 @@ LL | a: (), | ^ error: field `b` is never read - --> $DIR/offset-of.rs:24:5 + --> $DIR/offset-of.rs:23:5 | LL | struct Delta { | ----- field in this struct @@ -39,7 +39,7 @@ LL | b: (), | ^ error: field `a` is never read - --> $DIR/offset-of.rs:35:5 + --> $DIR/offset-of.rs:34:5 | LL | struct Project { | ------- field in this struct diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs index cb2f04786ac5c..64850e4782335 100644 --- a/tests/ui/offset-of/offset-of-enum.rs +++ b/tests/ui/offset-of/offset-of-enum.rs @@ -1,4 +1,4 @@ -#![feature(offset_of_enum, offset_of_nested)] +#![feature(offset_of_enum)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs index 1c326b5c79a5e..8b8ffb5e08e90 100644 --- a/tests/ui/offset-of/offset-of-private.rs +++ b/tests/ui/offset-of/offset-of-private.rs @@ -1,4 +1,4 @@ -#![feature(offset_of_enum, offset_of_nested)] +#![feature(offset_of_enum)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs index 1558e13b53095..e5730b8cf6cdb 100644 --- a/tests/ui/offset-of/offset-of-self.rs +++ b/tests/ui/offset-of/offset-of-self.rs @@ -1,5 +1,3 @@ -#![feature(offset_of_nested)] - use std::mem::offset_of; struct C { diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr index 7c7576e066b6f..5bbb4ecf091a7 100644 --- a/tests/ui/offset-of/offset-of-self.stderr +++ b/tests/ui/offset-of/offset-of-self.stderr @@ -1,11 +1,11 @@ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-self.rs:20:26 + --> $DIR/offset-of-self.rs:18:26 | LL | offset_of!(Self, Self::v); | ^^^^^^^ error[E0412]: cannot find type `S` in module `self` - --> $DIR/offset-of-self.rs:34:26 + --> $DIR/offset-of-self.rs:32:26 | LL | offset_of!(self::S, v); | ^ not found in `self` @@ -21,7 +21,7 @@ LL + offset_of!(S, v); | error[E0411]: cannot find type `Self` in this scope - --> $DIR/offset-of-self.rs:51:16 + --> $DIR/offset-of-self.rs:49:16 | LL | fn main() { | ---- `Self` not allowed in a function @@ -30,7 +30,7 @@ LL | offset_of!(Self, v); | ^^^^ `Self` is only available in impls, traits, and type definitions error[E0609]: no field `Self` on type `S` - --> $DIR/offset-of-self.rs:21:23 + --> $DIR/offset-of-self.rs:19:23 | LL | offset_of!(S, Self); | ^^^^ @@ -38,13 +38,13 @@ LL | offset_of!(S, Self); = note: available fields are: `v`, `w` error[E0616]: field `v` of struct `T` is private - --> $DIR/offset-of-self.rs:40:30 + --> $DIR/offset-of-self.rs:38:30 | LL | offset_of!(Self, v) | ^ private field error[E0609]: no field `self` on type `S` - --> $DIR/offset-of-self.rs:53:19 + --> $DIR/offset-of-self.rs:51:19 | LL | offset_of!(S, self); | ^^^^ @@ -52,7 +52,7 @@ LL | offset_of!(S, self); = note: available fields are: `v`, `w` error[E0609]: no field `self` on type `u8` - --> $DIR/offset-of-self.rs:54:21 + --> $DIR/offset-of-self.rs:52:21 | LL | offset_of!(S, v.self); | ^^^^ diff --git a/tests/ui/offset-of/offset-of-slice.rs b/tests/ui/offset-of/offset-of-slice.rs index a0fe3198f6869..e6eb12abd7bbc 100644 --- a/tests/ui/offset-of/offset-of-slice.rs +++ b/tests/ui/offset-of/offset-of-slice.rs @@ -1,5 +1,5 @@ //@run-pass -#![feature(offset_of_slice, offset_of_nested)] +#![feature(offset_of_slice)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-tuple-nested.rs b/tests/ui/offset-of/offset-of-tuple-nested.rs index 4a58b7167cb7c..210a8b6e897b3 100644 --- a/tests/ui/offset-of/offset-of-tuple-nested.rs +++ b/tests/ui/offset-of/offset-of-tuple-nested.rs @@ -2,8 +2,6 @@ // Test for issue #112204 -- make sure this goes through the entire compilation pipeline, // similar to why `offset-of-unsized.rs` is also build-pass -#![feature(offset_of_nested)] - use std::mem::offset_of; type ComplexTup = ((u8, (u8, (u8, u16), u8)), (u8, u32, u16)); diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index 75ba8d77f2fbd..b0822352c9dc6 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -1,4 +1,3 @@ -#![feature(offset_of_nested)] #![feature(builtin_syntax)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index 1e2d9240267da..e6b45c0b6b846 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -1,11 +1,11 @@ error: suffixes on a tuple index are invalid - --> $DIR/offset-of-tuple.rs:19:35 + --> $DIR/offset-of-tuple.rs:18:35 | LL | builtin # offset_of((u8, u8), 1_u8); | ^^^^ invalid suffix `u8` error: leading `+` is not supported - --> $DIR/offset-of-tuple.rs:23:37 + --> $DIR/offset-of-tuple.rs:22:37 | LL | { builtin # offset_of((u8, u8), +1) }; | ^ unexpected `+` @@ -17,67 +17,67 @@ LL + { builtin # offset_of((u8, u8), 1) }; | error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:24:38 + --> $DIR/offset-of-tuple.rs:23:38 | LL | { builtin # offset_of((u8, u8), 1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:25:40 + --> $DIR/offset-of-tuple.rs:24:40 | LL | { builtin # offset_of((u8, u8), 1 .) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:47:45 + --> $DIR/offset-of-tuple.rs:46:45 | LL | { builtin # offset_of(ComplexTup, 0.0.1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:48:46 + --> $DIR/offset-of-tuple.rs:47:46 | LL | { builtin # offset_of(ComplexTup, 0 .0.1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:49:47 + --> $DIR/offset-of-tuple.rs:48:47 | LL | { builtin # offset_of(ComplexTup, 0 . 0.1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:50:46 + --> $DIR/offset-of-tuple.rs:49:46 | LL | { builtin # offset_of(ComplexTup, 0. 0.1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:51:46 + --> $DIR/offset-of-tuple.rs:50:46 | LL | { builtin # offset_of(ComplexTup, 0.0 .1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:52:47 + --> $DIR/offset-of-tuple.rs:51:47 | LL | { builtin # offset_of(ComplexTup, 0.0 . 1.) }; | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:53:46 + --> $DIR/offset-of-tuple.rs:52:46 | LL | { builtin # offset_of(ComplexTup, 0.0. 1.) }; | ^ error: suffixes on a tuple index are invalid - --> $DIR/offset-of-tuple.rs:10:26 + --> $DIR/offset-of-tuple.rs:9:26 | LL | offset_of!((u8, u8), 1_u8); | ^^^^ invalid suffix `u8` error: no rules expected the token `+` - --> $DIR/offset-of-tuple.rs:12:26 + --> $DIR/offset-of-tuple.rs:11:26 | LL | offset_of!((u8, u8), +1); | ^ no rules expected this token in macro call @@ -86,115 +86,115 @@ note: while trying to match meta-variable `$fields:expr` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:13:26 + --> $DIR/offset-of-tuple.rs:12:26 | LL | offset_of!((u8, u8), -1); | ^^ error: offset_of expects dot-separated field and variant names - --> $DIR/offset-of-tuple.rs:14:27 + --> $DIR/offset-of-tuple.rs:13:27 | LL | offset_of!((u8, u8), 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:15:29 + --> $DIR/offset-of-tuple.rs:14:29 | LL | offset_of!((u8, u8), 1 .); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:36:34 + --> $DIR/offset-of-tuple.rs:35:34 | LL | offset_of!(ComplexTup, 0.0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:37:35 + --> $DIR/offset-of-tuple.rs:36:35 | LL | offset_of!(ComplexTup, 0 .0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:38:36 + --> $DIR/offset-of-tuple.rs:37:36 | LL | offset_of!(ComplexTup, 0 . 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:39:35 + --> $DIR/offset-of-tuple.rs:38:35 | LL | offset_of!(ComplexTup, 0. 0.1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:40:35 + --> $DIR/offset-of-tuple.rs:39:35 | LL | offset_of!(ComplexTup, 0.0 .1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:41:36 + --> $DIR/offset-of-tuple.rs:40:36 | LL | offset_of!(ComplexTup, 0.0 . 1.); | ^ error: unexpected token: `)` - --> $DIR/offset-of-tuple.rs:42:35 + --> $DIR/offset-of-tuple.rs:41:35 | LL | offset_of!(ComplexTup, 0.0. 1.); | ^ error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:7:26 + --> $DIR/offset-of-tuple.rs:6:26 | LL | offset_of!((u8, u8), _0); | ^^ error[E0609]: no field `01` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:8:26 + --> $DIR/offset-of-tuple.rs:7:26 | LL | offset_of!((u8, u8), 01); | ^^ error[E0609]: no field `1e2` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:9:26 + --> $DIR/offset-of-tuple.rs:8:26 | LL | offset_of!((u8, u8), 1e2); | ^^^ error[E0609]: no field `1_` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:10:26 + --> $DIR/offset-of-tuple.rs:9:26 | LL | offset_of!((u8, u8), 1_u8); | ^^^^ error[E0609]: no field `1e2` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:16:35 + --> $DIR/offset-of-tuple.rs:15:35 | LL | builtin # offset_of((u8, u8), 1e2); | ^^^ error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:17:35 + --> $DIR/offset-of-tuple.rs:16:35 | LL | builtin # offset_of((u8, u8), _0); | ^^ error[E0609]: no field `01` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:18:35 + --> $DIR/offset-of-tuple.rs:17:35 | LL | builtin # offset_of((u8, u8), 01); | ^^ error[E0609]: no field `1_` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:19:35 + --> $DIR/offset-of-tuple.rs:18:35 | LL | builtin # offset_of((u8, u8), 1_u8); | ^^^^ error[E0609]: no field `2` on type `(u8, u16)` - --> $DIR/offset-of-tuple.rs:31:47 + --> $DIR/offset-of-tuple.rs:30:47 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); | _____------------------------------------------^- @@ -207,7 +207,7 @@ LL | | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `0` on type `u8` - --> $DIR/offset-of-tuple.rs:33:49 + --> $DIR/offset-of-tuple.rs:32:49 | LL | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); | ^ diff --git a/tests/ui/offset-of/offset-of-unstable-with-feature.rs b/tests/ui/offset-of/offset-of-unstable-with-feature.rs index c9d4f30e99a20..c2614ba3d8af8 100644 --- a/tests/ui/offset-of/offset-of-unstable-with-feature.rs +++ b/tests/ui/offset-of/offset-of-unstable-with-feature.rs @@ -1,7 +1,7 @@ //@ check-pass //@ aux-build:offset-of-staged-api.rs -#![feature(offset_of_nested, unstable_test_feature)] +#![feature(unstable_test_feature)] use std::mem::offset_of; diff --git a/tests/ui/offset-of/offset-of-unstable.rs b/tests/ui/offset-of/offset-of-unstable.rs index ab6f89ce52a53..d249e8871c326 100644 --- a/tests/ui/offset-of/offset-of-unstable.rs +++ b/tests/ui/offset-of/offset-of-unstable.rs @@ -1,7 +1,5 @@ //@ aux-build:offset-of-staged-api.rs -#![feature(offset_of_nested)] - use std::mem::offset_of; extern crate offset_of_staged_api; diff --git a/tests/ui/offset-of/offset-of-unstable.stderr b/tests/ui/offset-of/offset-of-unstable.stderr index 4882dee404226..44ccad3ff39fd 100644 --- a/tests/ui/offset-of/offset-of-unstable.stderr +++ b/tests/ui/offset-of/offset-of-unstable.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/offset-of-unstable.rs:14:9 + --> $DIR/offset-of-unstable.rs:12:9 | LL | Unstable, | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | Unstable, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/offset-of-unstable.rs:23:9 + --> $DIR/offset-of-unstable.rs:21:9 | LL | UnstableWithStableFieldType, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | UnstableWithStableFieldType, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/offset-of-unstable.rs:28:9 + --> $DIR/offset-of-unstable.rs:26:9 | LL | UnstableWithStableFieldType, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | UnstableWithStableFieldType, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/offset-of-unstable.rs:12:5 + --> $DIR/offset-of-unstable.rs:10:5 | LL | / offset_of!( LL | | @@ -40,7 +40,7 @@ LL | | ); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/offset-of-unstable.rs:18:5 + --> $DIR/offset-of-unstable.rs:16:5 | LL | offset_of!(StableWithUnstableField, unstable); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +50,7 @@ LL | offset_of!(StableWithUnstableField, unstable); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/offset-of-unstable.rs:20:5 + --> $DIR/offset-of-unstable.rs:18:5 | LL | offset_of!(StableWithUnstableFieldType, stable.unstable); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | offset_of!(StableWithUnstableFieldType, stable.unstable); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/offset-of-unstable.rs:21:5 + --> $DIR/offset-of-unstable.rs:19:5 | LL | / offset_of!( LL | | @@ -74,7 +74,7 @@ LL | | ); = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: use of unstable library feature 'unstable_test_feature' - --> $DIR/offset-of-unstable.rs:26:5 + --> $DIR/offset-of-unstable.rs:24:5 | LL | / offset_of!( LL | | From f4fa80ff5a10e468360f1a5a7090fae8519488a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Mon, 29 Jul 2024 17:01:39 +0000 Subject: [PATCH 247/489] triagebot: make sure Nora is called Nora --- triagebot.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 5c5aa47538518..2795f93728470 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -852,7 +852,7 @@ cc = ["@Urgau"] cc = ["@Urgau"] [mentions."src/doc/rustc/src/platform-support"] -cc = ["@Nilstrieb"] +cc = ["@Noratrieb"] [mentions."tests/codegen/sanitizer"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] @@ -938,7 +938,7 @@ libs = [ "@cuviper", "@Mark-Simulacrum", "@Amanieu", - "@Nilstrieb", + "@Noratrieb", "@workingjubilee", "@joboet", "@jhpratt", From f2f9aab3806916105518ce8e4ccb143028ab81ff Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Thu, 30 May 2024 22:00:44 +0300 Subject: [PATCH 248/489] Delegation: support generics for delegation from free functions --- compiler/rustc_ast_lowering/src/delegation.rs | 2 +- compiler/rustc_hir_analysis/messages.ftl | 3 +- .../src/collect/generics_of.rs | 8 + .../src/collect/predicates_of.rs | 8 + compiler/rustc_hir_analysis/src/delegation.rs | 259 ++++++++++++++++++ compiler/rustc_hir_analysis/src/errors.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 94 +------ compiler/rustc_hir_analysis/src/lib.rs | 5 + compiler/rustc_middle/src/hir/map/mod.rs | 15 + compiler/rustc_middle/src/query/mod.rs | 4 + tests/ui/delegation/explicit-paths.rs | 2 - tests/ui/delegation/explicit-paths.stderr | 46 +--- .../generics/free-fn-to-free-fn-pass.rs | 28 ++ .../delegation/generics/free-fn-to-free-fn.rs | 27 ++ .../generics/free-fn-to-free-fn.stderr | 54 ++++ .../generics/free-fn-to-trait-method-pass.rs | 30 ++ .../generics/free-fn-to-trait-method.rs | 56 ++++ .../generics/free-fn-to-trait-method.stderr | 88 ++++++ tests/ui/delegation/ice-issue-124347.rs | 3 +- tests/ui/delegation/ice-issue-124347.stderr | 15 +- tests/ui/delegation/not-supported.rs | 35 ++- tests/ui/delegation/not-supported.stderr | 103 +++---- tests/ui/delegation/target-expr.rs | 5 +- tests/ui/delegation/target-expr.stderr | 43 +-- 24 files changed, 702 insertions(+), 233 deletions(-) create mode 100644 compiler/rustc_hir_analysis/src/delegation.rs create mode 100644 tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs create mode 100644 tests/ui/delegation/generics/free-fn-to-free-fn.rs create mode 100644 tests/ui/delegation/generics/free-fn-to-free-fn.stderr create mode 100644 tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs create mode 100644 tests/ui/delegation/generics/free-fn-to-trait-method.rs create mode 100644 tests/ui/delegation/generics/free-fn-to-trait-method.stderr diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 378d98e5c34e1..6e8ff72cf8759 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -33,7 +33,7 @@ //! HIR ty lowering. //! //! Similarly generics, predicates and header are set to the "default" values. -//! In case of discrepancy with callee function the `NotSupportedDelegation` error will +//! In case of discrepancy with callee function the `UnsupportedDelegation` error will //! also be emitted during HIR ty lowering. use std::iter; diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 367f6e17e7fe6..bde94be6f514e 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -341,8 +341,7 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args -hir_analysis_not_supported_delegation = - {$descr} is not supported yet +hir_analysis_not_supported_delegation = {$descr} .label = callee defined here hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 41ffb03834141..80a65aa298851 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -10,6 +10,7 @@ use rustc_session::lint; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; +use crate::delegation::inherit_generics_for_delegation_item; use crate::middle::resolve_bound_vars as rbv; #[instrument(level = "debug", skip(tcx), ret)] @@ -53,6 +54,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { }; } + // For a delegation item inherit generics from callee. + if let Some(sig_id) = tcx.hir().opt_delegation_sig_id(def_id) + && let Some(generics) = inherit_generics_for_delegation_item(tcx, def_id, sig_id) + { + return generics; + } + let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 783365bdacc49..ae52dbd56f9b7 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -12,6 +12,7 @@ use rustc_span::{Span, DUMMY_SP}; use crate::bounds::Bounds; use crate::collect::ItemCtxt; use crate::constrained_generic_params as cgp; +use crate::delegation::inherit_predicates_for_delegation_item; use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason}; /// Returns a list of all type predicates (explicit and implicit) for the definition with @@ -114,6 +115,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen None => {} } + // For a delegation item inherit predicates from callee. + if let Some(sig_id) = tcx.hir().opt_delegation_sig_id(def_id) + && let Some(predicates) = inherit_predicates_for_delegation_item(tcx, def_id, sig_id) + { + return predicates; + } + let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs new file mode 100644 index 0000000000000..e21ed55bce3fc --- /dev/null +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -0,0 +1,259 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::ErrorGuaranteed; +use rustc_type_ir::visit::TypeVisitableExt; + +type RemapTable = FxHashMap; + +struct ParamIndexRemapper<'tcx> { + tcx: TyCtxt<'tcx>, + remap_table: RemapTable, +} + +impl<'tcx> TypeFolder> for ParamIndexRemapper<'tcx> { + fn cx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + if !ty.has_param() { + return ty; + } + + if let ty::Param(param) = ty.kind() + && let Some(index) = self.remap_table.get(¶m.index) + { + return Ty::new_param(self.tcx, *index, param.name); + } + ty.super_fold_with(self) + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + if let ty::ReEarlyParam(param) = r.kind() + && let Some(index) = self.remap_table.get(¶m.index).copied() + { + return ty::Region::new_early_param( + self.tcx, + ty::EarlyParamRegion { index, name: param.name }, + ); + } + r + } + + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + if let ty::ConstKind::Param(param) = ct.kind() + && let Some(idx) = self.remap_table.get(¶m.index) + { + let param = ty::ParamConst::new(*idx, param.name); + return ty::Const::new_param(self.tcx, param); + } + ct.super_fold_with(self) + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +enum FnKind { + Free, + AssocInherentImpl, + AssocTrait, + AssocTraitImpl, +} + +fn fn_kind<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> FnKind { + debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn)); + + let parent = tcx.parent(def_id); + match tcx.def_kind(parent) { + DefKind::Trait => FnKind::AssocTrait, + DefKind::Impl { of_trait: true } => FnKind::AssocTraitImpl, + DefKind::Impl { of_trait: false } => FnKind::AssocInherentImpl, + _ => FnKind::Free, + } +} + +fn create_generic_args<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sig_id: DefId, +) -> ty::GenericArgsRef<'tcx> { + let caller_generics = tcx.generics_of(def_id); + let callee_generics = tcx.generics_of(sig_id); + + let caller_kind = fn_kind(tcx, def_id.into()); + let callee_kind = fn_kind(tcx, sig_id); + // FIXME(fn_delegation): Support generics on associated delegation items. + // Error will be reported in `check_constraints`. + match (caller_kind, callee_kind) { + (FnKind::Free, _) => { + // Lifetime parameters must be declared before type and const parameters. + // Therefore, When delegating from a free function to a associated function, + // generic parameters need to be reordered: + // + // trait Trait<'a, A> { + // fn foo<'b, B>(...) {...} + // } + // + // reuse Trait::foo; + // desugaring: + // fn foo<'a, 'b, This: Trait<'a, A>, A, B>(...) { + // Trait::foo(...) + // } + let mut remap_table = RemapTable::default(); + for caller_param in &caller_generics.own_params { + let callee_index = + callee_generics.param_def_id_to_index(tcx, caller_param.def_id).unwrap(); + remap_table.insert(callee_index, caller_param.index); + } + let mut folder = ParamIndexRemapper { tcx, remap_table }; + ty::GenericArgs::identity_for_item(tcx, sig_id).fold_with(&mut folder) + } + // FIXME(fn_delegation): Only `Self` param supported here. + (FnKind::AssocTraitImpl, FnKind::AssocTrait) + | (FnKind::AssocInherentImpl, FnKind::AssocTrait) => { + let parent = tcx.parent(def_id.into()); + let self_ty = tcx.type_of(parent).instantiate_identity(); + let generic_self_ty = ty::GenericArg::from(self_ty); + tcx.mk_args_from_iter(std::iter::once(generic_self_ty)) + } + _ => ty::GenericArgs::identity_for_item(tcx, sig_id), + } +} + +pub(crate) fn inherit_generics_for_delegation_item<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sig_id: DefId, +) -> Option { + // FIXME(fn_delegation): Support generics on associated delegation items. + // Error will be reported in `check_constraints`. + if fn_kind(tcx, def_id.into()) != FnKind::Free { + return None; + } + + let mut own_params = vec![]; + + let callee_generics = tcx.generics_of(sig_id); + if let Some(parent_sig_id) = callee_generics.parent { + let parent_sig_generics = tcx.generics_of(parent_sig_id); + own_params.append(&mut parent_sig_generics.own_params.clone()); + } + own_params.append(&mut callee_generics.own_params.clone()); + + // Lifetimes go first. + own_params.sort_by_key(|key| key.kind.is_ty_or_const()); + + for (idx, param) in own_params.iter_mut().enumerate() { + param.index = idx as u32; + // Default parameters are not inherited: they are not allowed + // in fn's. + if let ty::GenericParamDefKind::Type { has_default, .. } + | ty::GenericParamDefKind::Const { has_default, .. } = &mut param.kind + { + *has_default = false; + } + } + + let param_def_id_to_index = + own_params.iter().map(|param| (param.def_id, param.index)).collect(); + + Some(ty::Generics { + parent: None, + parent_count: 0, + own_params, + param_def_id_to_index, + has_self: false, + has_late_bound_regions: callee_generics.has_late_bound_regions, + host_effect_index: callee_generics.host_effect_index, + }) +} + +pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sig_id: DefId, +) -> Option> { + // FIXME(fn_delegation): Support generics on associated delegation items. + // Error will be reported in `check_constraints`. + if fn_kind(tcx, def_id.into()) != FnKind::Free { + return None; + } + + let callee_predicates = tcx.predicates_of(sig_id); + let args = create_generic_args(tcx, def_id, sig_id); + + let mut preds = vec![]; + if let Some(parent_id) = callee_predicates.parent { + preds.extend(tcx.predicates_of(parent_id).instantiate_own(tcx, args)); + } + preds.extend(callee_predicates.instantiate_own(tcx, args)); + + Some(ty::GenericPredicates { + parent: None, + predicates: tcx.arena.alloc_from_iter(preds), + effects_min_tys: ty::List::empty(), + }) +} + +fn check_constraints<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + sig_id: DefId, +) -> Result<(), ErrorGuaranteed> { + let mut ret = Ok(()); + + let mut emit = |descr| { + ret = Err(tcx.dcx().emit_err(crate::errors::UnsupportedDelegation { + span: tcx.def_span(def_id), + descr, + callee_span: tcx.def_span(sig_id), + })); + }; + + if tcx.has_host_param(sig_id) { + emit("delegation to a function with effect parameter is not supported yet"); + } + + if let Some(local_sig_id) = sig_id.as_local() + && tcx.hir().opt_delegation_sig_id(local_sig_id).is_some() + { + emit("recursive delegation is not supported yet"); + } + + if fn_kind(tcx, def_id.into()) != FnKind::Free { + let sig_generics = tcx.generics_of(sig_id); + let parent = tcx.parent(def_id.into()); + let parent_generics = tcx.generics_of(parent); + + let parent_has_self = parent_generics.has_self as usize; + let sig_has_self = sig_generics.has_self as usize; + + if sig_generics.count() > sig_has_self || parent_generics.count() > parent_has_self { + emit("early bound generics are not supported for associated delegation items"); + } + } + + ret +} + +pub(crate) fn inherit_sig_for_delegation_item<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> &'tcx [Ty<'tcx>] { + let sig_id = tcx.hir().delegation_sig_id(def_id); + let caller_sig = tcx.fn_sig(sig_id); + if let Err(err) = check_constraints(tcx, def_id, sig_id) { + let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1; + let err_type = Ty::new_error(tcx, err); + return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type)); + } + let args = create_generic_args(tcx, def_id, sig_id); + + // Bound vars are also inherited from `sig_id`. + // They will be rebound later in `lower_fn_ty`. + let sig = caller_sig.instantiate(tcx, args).skip_binder(); + let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output())); + tcx.arena.alloc_from_iter(sig_iter) +} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index b1ac973ef2e00..7034735aec038 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1575,7 +1575,7 @@ pub struct RefOfMutStatic<'a> { #[derive(Diagnostic)] #[diag(hir_analysis_not_supported_delegation)] -pub struct NotSupportedDelegation<'a> { +pub struct UnsupportedDelegation<'a> { #[primary_span] pub span: Span, pub descr: &'a str, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 52b2411cd3717..d865357b82900 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2007,93 +2007,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_ty_common(hir_ty, false, true) } - fn check_delegation_constraints(&self, sig_id: DefId, span: Span, emit: bool) -> bool { - let mut error_occured = false; - let sig_span = self.tcx().def_span(sig_id); - let mut try_emit = |descr| { - if emit { - self.dcx().emit_err(crate::errors::NotSupportedDelegation { - span, - descr, - callee_span: sig_span, - }); - } - error_occured = true; - }; - - if let Some(node) = self.tcx().hir().get_if_local(sig_id) - && let Some(decl) = node.fn_decl() - && let hir::FnRetTy::Return(ty) = decl.output - && let hir::TyKind::InferDelegation(_, _) = ty.kind - { - try_emit("recursive delegation"); - } - - let sig_generics = self.tcx().generics_of(sig_id); - let parent = self.tcx().local_parent(self.item_def_id()); - let parent_generics = self.tcx().generics_of(parent); - - let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize; - let sig_has_self = sig_generics.has_self as usize; - - if sig_generics.count() > sig_has_self || parent_generics.count() > parent_is_trait { - try_emit("delegation with early bound generics"); - } - - // There is no way to instantiate `Self` param for caller if - // 1. callee is a trait method - // 2. delegation item isn't an associative item - if let DefKind::AssocFn = self.tcx().def_kind(sig_id) - && let DefKind::Fn = self.tcx().def_kind(self.item_def_id()) - && self.tcx().associated_item(sig_id).container - == ty::AssocItemContainer::TraitContainer - { - try_emit("delegation to a trait method from a free function"); - } - - error_occured - } - - fn lower_delegation_ty( - &self, - sig_id: DefId, - idx: hir::InferDelegationKind, - span: Span, - ) -> Ty<'tcx> { - if self.check_delegation_constraints(sig_id, span, idx == hir::InferDelegationKind::Output) - { - let e = self.dcx().span_delayed_bug(span, "not supported delegation case"); - return Ty::new_error(self.tcx(), e); - }; - let sig = self.tcx().fn_sig(sig_id); - let sig_generics = self.tcx().generics_of(sig_id); - - let parent = self.tcx().local_parent(self.item_def_id()); - let parent_def_kind = self.tcx().def_kind(parent); - - let sig = if let DefKind::Impl { .. } = parent_def_kind - && sig_generics.has_self - { - // Generic params can't be here except the trait self type. - // They are not supported yet. - assert_eq!(sig_generics.count(), 1); - assert_eq!(self.tcx().generics_of(parent).count(), 0); - - let self_ty = self.tcx().type_of(parent).instantiate_identity(); - let generic_self_ty = ty::GenericArg::from(self_ty); - let args = self.tcx().mk_args_from_iter(std::iter::once(generic_self_ty)); - sig.instantiate(self.tcx(), args) - } else { - sig.instantiate_identity() - }; - - // Bound vars are also inherited from `sig_id`. - // They will be rebound later in `lower_fn_ty`. - let sig = sig.skip_binder(); - + fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> { + let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id()); match idx { - hir::InferDelegationKind::Input(id) => sig.inputs()[id], - hir::InferDelegationKind::Output => sig.output(), + hir::InferDelegationKind::Input(idx) => delegation_sig[idx], + hir::InferDelegationKind::Output => *delegation_sig.last().unwrap(), } } @@ -2110,9 +2028,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); let result_ty = match &hir_ty.kind { - hir::TyKind::InferDelegation(sig_id, idx) => { - self.lower_delegation_ty(*sig_id, *idx, hir_ty.span) - } + hir::TyKind::InferDelegation(_, idx) => self.lower_delegation_ty(*idx), hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)), hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl), hir::TyKind::Ref(region, mt) => { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 8154e7cfd368d..061db14ad0a61 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -83,6 +83,7 @@ pub mod autoderef; mod bounds; mod check_unused; mod coherence; +mod delegation; pub mod hir_ty_lowering; // FIXME: This module shouldn't be public. pub mod collect; @@ -146,6 +147,10 @@ pub fn provide(providers: &mut Providers) { variance::provide(providers); outlives::provide(providers); hir_wf_check::provide(providers); + *providers = Providers { + inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item, + ..*providers + }; } pub fn check_crate(tcx: TyCtxt<'_>) { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 1c223481a0769..1705c016437cc 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -746,6 +746,21 @@ impl<'hir> Map<'hir> { } } + pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option { + if let Some(ret) = self.get_fn_output(def_id) + && let FnRetTy::Return(ty) = ret + && let TyKind::InferDelegation(sig_id, _) = ty.kind + { + return Some(sig_id); + } + None + } + + #[inline] + pub fn delegation_sig_id(self, def_id: LocalDefId) -> DefId { + self.opt_delegation_sig_id(def_id).unwrap() + } + #[inline] fn opt_ident(self, id: HirId) -> Option { match self.tcx.hir_node(id) { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ff8ee9f64566d..c22c2e985abba 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1722,6 +1722,10 @@ rustc_queries! { desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) } } + query inherit_sig_for_delegation_item(def_id: LocalDefId) -> &'tcx [Ty<'tcx>] { + desc { "inheriting delegation signature" } + } + /// Does lifetime resolution on items. Importantly, we can't resolve /// lifetimes directly on things like trait methods, because of trait params. /// See `rustc_resolve::late::lifetimes` for details. diff --git a/tests/ui/delegation/explicit-paths.rs b/tests/ui/delegation/explicit-paths.rs index d42e305b252f0..3b0454eb52400 100644 --- a/tests/ui/delegation/explicit-paths.rs +++ b/tests/ui/delegation/explicit-paths.rs @@ -22,9 +22,7 @@ mod fn_to_other { use super::*; reuse Trait::foo1; - //~^ ERROR delegation to a trait method from a free function is not supported yet reuse ::foo2; - //~^ ERROR delegation to a trait method from a free function is not supported yet reuse to_reuse::foo3; reuse S::foo4; //~^ ERROR cannot find function `foo4` in `S` diff --git a/tests/ui/delegation/explicit-paths.stderr b/tests/ui/delegation/explicit-paths.stderr index b5afe19f87897..8098ea8c54f6c 100644 --- a/tests/ui/delegation/explicit-paths.stderr +++ b/tests/ui/delegation/explicit-paths.stderr @@ -1,5 +1,5 @@ error[E0407]: method `foo3` is not a member of trait `Trait` - --> $DIR/explicit-paths.rs:51:9 + --> $DIR/explicit-paths.rs:49:9 | LL | reuse to_reuse::foo3; | ^^^^^^^^^^^^^^^^----^ @@ -8,7 +8,7 @@ LL | reuse to_reuse::foo3; | not a member of trait `Trait` error[E0407]: method `foo4` is not a member of trait `Trait` - --> $DIR/explicit-paths.rs:53:9 + --> $DIR/explicit-paths.rs:51:9 | LL | reuse F::foo4 { &self.0 } | ^^^^^^^^^----^^^^^^^^^^^^ @@ -17,49 +17,49 @@ LL | reuse F::foo4 { &self.0 } | not a member of trait `Trait` error[E0425]: cannot find function `foo4` in `S` - --> $DIR/explicit-paths.rs:29:14 + --> $DIR/explicit-paths.rs:27:14 | LL | reuse S::foo4; | ^^^^ not found in `S` error[E0425]: cannot find function `foo4` in `F` - --> $DIR/explicit-paths.rs:40:18 + --> $DIR/explicit-paths.rs:38:18 | LL | reuse F::foo4 { &self.0 } | ^^^^ not found in `F` | note: function `fn_to_other::foo4` exists but is inaccessible - --> $DIR/explicit-paths.rs:29:5 + --> $DIR/explicit-paths.rs:27:5 | LL | reuse S::foo4; | ^^^^^^^^^^^^^^ not accessible error[E0425]: cannot find function `foo4` in `F` - --> $DIR/explicit-paths.rs:53:18 + --> $DIR/explicit-paths.rs:51:18 | LL | reuse F::foo4 { &self.0 } | ^^^^ not found in `F` | note: function `fn_to_other::foo4` exists but is inaccessible - --> $DIR/explicit-paths.rs:29:5 + --> $DIR/explicit-paths.rs:27:5 | LL | reuse S::foo4; | ^^^^^^^^^^^^^^ not accessible error[E0425]: cannot find function `foo4` in `F` - --> $DIR/explicit-paths.rs:67:18 + --> $DIR/explicit-paths.rs:65:18 | LL | reuse F::foo4 { &F } | ^^^^ not found in `F` | note: function `fn_to_other::foo4` exists but is inaccessible - --> $DIR/explicit-paths.rs:29:5 + --> $DIR/explicit-paths.rs:27:5 | LL | reuse S::foo4; | ^^^^^^^^^^^^^^ not accessible error[E0119]: conflicting implementations of trait `Trait` for type `S` - --> $DIR/explicit-paths.rs:76:5 + --> $DIR/explicit-paths.rs:74:5 | LL | impl Trait for S { | ---------------- first implementation here @@ -67,26 +67,8 @@ LL | impl Trait for S { LL | impl Trait for S { | ^^^^^^^^^^^^^^^^ conflicting implementation for `S` -error: delegation to a trait method from a free function is not supported yet - --> $DIR/explicit-paths.rs:24:18 - | -LL | fn foo1(&self, x: i32) -> i32 { x } - | ----------------------------- callee defined here -... -LL | reuse Trait::foo1; - | ^^^^ - -error: delegation to a trait method from a free function is not supported yet - --> $DIR/explicit-paths.rs:26:25 - | -LL | fn foo2(x: i32) -> i32 { x } - | ---------------------- callee defined here -... -LL | reuse ::foo2; - | ^^^^ - error[E0308]: mismatched types - --> $DIR/explicit-paths.rs:63:36 + --> $DIR/explicit-paths.rs:61:36 | LL | trait Trait2 : Trait { | -------------------- found this type parameter @@ -104,7 +86,7 @@ LL | fn foo1(&self, x: i32) -> i32 { x } | ^^^^ ----- error[E0277]: the trait bound `S2: Trait` is not satisfied - --> $DIR/explicit-paths.rs:78:16 + --> $DIR/explicit-paths.rs:76:16 | LL | reuse ::foo1; | ^^ the trait `Trait` is not implemented for `S2` @@ -114,7 +96,7 @@ LL | reuse ::foo1; S error[E0308]: mismatched types - --> $DIR/explicit-paths.rs:78:30 + --> $DIR/explicit-paths.rs:76:30 | LL | reuse ::foo1; | ^^^^ @@ -130,7 +112,7 @@ note: method defined here LL | fn foo1(&self, x: i32) -> i32 { x } | ^^^^ ----- -error: aborting due to 12 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0119, E0277, E0308, E0407, E0425. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs b/tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs new file mode 100644 index 0000000000000..625bbdd758c1b --- /dev/null +++ b/tests/ui/delegation/generics/free-fn-to-free-fn-pass.rs @@ -0,0 +1,28 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod to_reuse { + pub fn types(x: U, y: T) -> (T, U) { + (y, x) + } + pub fn late<'a, 'b>(x: &'a u8, y: &'b u8) -> u8 { + *x + *y + } + pub fn early<'a: 'a>(x: &'a str) -> &'a str { + x + } +} + +reuse to_reuse::types; +reuse to_reuse::late; +reuse to_reuse::early; + +fn main() { + assert_eq!(types(0, "str"), ("str", 0)); + assert_eq!(late(&1u8, &2u8), 3); + { + let s: &'static str = "hello world"; + assert_eq!(early::<'static>(s), "hello world"); + } +} diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn.rs b/tests/ui/delegation/generics/free-fn-to-free-fn.rs new file mode 100644 index 0000000000000..3741ad664852a --- /dev/null +++ b/tests/ui/delegation/generics/free-fn-to-free-fn.rs @@ -0,0 +1,27 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod to_reuse { + pub fn consts() -> i32 { + N + } + pub fn late<'a>(x: &'a u8) -> u8 { + *x + } + pub fn bounds(_: T) {} +} + +// FIXME(fn_delegation): this is supposed to work eventually +reuse to_reuse::consts; +//~^ ERROR type annotations needed +reuse to_reuse::late; +reuse to_reuse::bounds; + +fn main() { + late::<'static>(&0u8); + //~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + + struct S; + bounds(S); + //~^ ERROR the trait bound `S: Clone` is not satisfied +} diff --git a/tests/ui/delegation/generics/free-fn-to-free-fn.stderr b/tests/ui/delegation/generics/free-fn-to-free-fn.stderr new file mode 100644 index 0000000000000..5ba56ce1718f0 --- /dev/null +++ b/tests/ui/delegation/generics/free-fn-to-free-fn.stderr @@ -0,0 +1,54 @@ +error[E0284]: type annotations needed + --> $DIR/free-fn-to-free-fn.rs:15:17 + | +LL | reuse to_reuse::consts; + | ^^^^^^ cannot infer the value of the const parameter `N` declared on the function `consts` + | +note: required by a const generic parameter in `to_reuse::consts` + --> $DIR/free-fn-to-free-fn.rs:5:19 + | +LL | pub fn consts() -> i32 { + | ^^^^^^^^^^^^ required by this const generic parameter in `consts` +help: consider specifying the generic argument + | +LL | reuse to_reuse::consts::; + | +++++ + +error[E0794]: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/free-fn-to-free-fn.rs:21:12 + | +LL | late::<'static>(&0u8); + | ^^^^^^^ + | +note: the late bound lifetime parameter is introduced here + --> $DIR/free-fn-to-free-fn.rs:8:17 + | +LL | pub fn late<'a>(x: &'a u8) -> u8 { + | ^^ + +error[E0277]: the trait bound `S: Clone` is not satisfied + --> $DIR/free-fn-to-free-fn.rs:25:12 + | +LL | bounds(S); + | ------ ^ the trait `Clone` is not implemented for `S` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bounds` + --> $DIR/free-fn-to-free-fn.rs:11:22 + | +LL | pub fn bounds(_: T) {} + | ^^^^^ required by this bound in `bounds` +... +LL | reuse to_reuse::bounds; + | ------ required by a bound in this function +help: consider annotating `S` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct S; + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0284, E0794. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs b/tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs new file mode 100644 index 0000000000000..f7b7c09e2ca42 --- /dev/null +++ b/tests/ui/delegation/generics/free-fn-to-trait-method-pass.rs @@ -0,0 +1,30 @@ +//@ run-pass +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod types { + pub trait Trait { + fn foo(&self, x: U, y: T) -> (T, U) {(y, x)} + } + impl Trait for u8 {} +} + +mod types_and_lifetimes { + pub trait Trait<'a, T> { + fn foo<'b, U>(&self, _: &'b U, _: &'a T) -> bool { + true + } + } + impl<'a, T> Trait<'a, T> for u8 {} +} + +reuse types::Trait::foo as types; +reuse types_and_lifetimes::Trait::foo as types_and_lifetimes; + +fn main() { + assert_eq!(types(&2, "str", 1), (1, "str")); + + struct T; + struct U; + assert_eq!(types_and_lifetimes::(&1, &U, &T), true); +} diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method.rs b/tests/ui/delegation/generics/free-fn-to-trait-method.rs new file mode 100644 index 0000000000000..70be1a4ace7c0 --- /dev/null +++ b/tests/ui/delegation/generics/free-fn-to-trait-method.rs @@ -0,0 +1,56 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod default_param { + pub trait Trait { + fn foo(&self, _: T) {} + } + + impl Trait for u8 {} +} + +mod types_and_lifetimes { + pub trait Trait<'a, T> { + fn foo<'b: 'b>(&'a self, x: &'b T) { + loop {} + } + } + impl<'a, T> Trait<'a, T> for u8 {} +} + +mod bounds { + pub trait Trait { + fn foo(&self, t: T, u: U) where T: Copy {} + } + + impl Trait for u8 {} +} + +mod generic_arguments { + trait Trait { + fn foo(&self, _: U, _: T) {} + } + + impl Trait for u8 {} + + reuse Trait::<_>::foo:: as generic_arguments1; + //~^ ERROR mismatched types + reuse >::foo as generic_arguments2; + //~^ ERROR mismatched types + reuse <_ as Trait<_>>::foo as generic_arguments3; // OK +} + +reuse default_param::Trait::foo as default_param; +reuse types_and_lifetimes::Trait::foo as types_and_lifetimes; +reuse bounds::Trait::foo as bounds; + +fn main() { + default_param(&0u8, "hello world"); // OK, default params are not substituted + types_and_lifetimes::<'static, 'static, _, _>(&0u8, &0u16); // OK, lifetimes go first + + struct S; + struct U; + bounds(&0u8, S, U); + //~^ ERROR the trait bound `S: Copy` is not satisfied + //~| ERROR the trait bound `U: Clone` is not satisfied +} diff --git a/tests/ui/delegation/generics/free-fn-to-trait-method.stderr b/tests/ui/delegation/generics/free-fn-to-trait-method.stderr new file mode 100644 index 0000000000000..d8299d00c7e94 --- /dev/null +++ b/tests/ui/delegation/generics/free-fn-to-trait-method.stderr @@ -0,0 +1,88 @@ +error[E0308]: mismatched types + --> $DIR/free-fn-to-trait-method.rs:36:23 + | +LL | fn foo(&self, _: U, _: T) {} + | - found this type parameter +... +LL | reuse Trait::<_>::foo:: as generic_arguments1; + | ^^^ + | | + | expected `i32`, found type parameter `U` + | arguments to this function are incorrect + | + = note: expected type `i32` + found type parameter `U` +note: method defined here + --> $DIR/free-fn-to-trait-method.rs:31:12 + | +LL | fn foo(&self, _: U, _: T) {} + | ^^^ ---- + +error[E0308]: mismatched types + --> $DIR/free-fn-to-trait-method.rs:38:29 + | +LL | trait Trait { + | -------------- found this type parameter +... +LL | reuse >::foo as generic_arguments2; + | ^^^ + | | + | expected `&u8`, found `&Self` + | arguments to this function are incorrect + | + = note: expected reference `&u8` + found reference `&Self` +note: method defined here + --> $DIR/free-fn-to-trait-method.rs:31:12 + | +LL | fn foo(&self, _: U, _: T) {} + | ^^^ ----- + +error[E0277]: the trait bound `S: Copy` is not satisfied + --> $DIR/free-fn-to-trait-method.rs:53:18 + | +LL | bounds(&0u8, S, U); + | ------ ^ the trait `Copy` is not implemented for `S` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bounds` + --> $DIR/free-fn-to-trait-method.rs:23:54 + | +LL | fn foo(&self, t: T, u: U) where T: Copy {} + | ^^^^ required by this bound in `bounds` +... +LL | reuse bounds::Trait::foo as bounds; + | ------ required by a bound in this function +help: consider annotating `S` with `#[derive(Copy)]` + | +LL + #[derive(Copy)] +LL | struct S; + | + +error[E0277]: the trait bound `U: Clone` is not satisfied + --> $DIR/free-fn-to-trait-method.rs:53:21 + | +LL | bounds(&0u8, S, U); + | ------ ^ the trait `Clone` is not implemented for `U` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bounds` + --> $DIR/free-fn-to-trait-method.rs:23:19 + | +LL | fn foo(&self, t: T, u: U) where T: Copy {} + | ^^^^^ required by this bound in `bounds` +... +LL | reuse bounds::Trait::foo as bounds; + | ------ required by a bound in this function +help: consider annotating `U` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct U; + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/ice-issue-124347.rs b/tests/ui/delegation/ice-issue-124347.rs index 82a96055099c7..3bfae8face597 100644 --- a/tests/ui/delegation/ice-issue-124347.rs +++ b/tests/ui/delegation/ice-issue-124347.rs @@ -6,7 +6,8 @@ trait Trait { //~^ ERROR recursive delegation is not supported yet } +// FIXME(fn_delegation): `recursive delegation` error should be emitted here reuse foo; -//~^ ERROR recursive delegation is not supported yet +//~^ ERROR cycle detected when computing generics of `foo` fn main() {} diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr index 5a3f4525d29e5..87dd75ffec82c 100644 --- a/tests/ui/delegation/ice-issue-124347.stderr +++ b/tests/ui/delegation/ice-issue-124347.stderr @@ -4,11 +4,20 @@ error: recursive delegation is not supported yet LL | reuse Trait::foo { &self.0 } | ^^^ callee defined here -error: recursive delegation is not supported yet - --> $DIR/ice-issue-124347.rs:9:7 +error[E0391]: cycle detected when computing generics of `foo` + --> $DIR/ice-issue-124347.rs:10:7 + | +LL | reuse foo; + | ^^^ + | + = note: ...which immediately requires computing generics of `foo` again +note: cycle used when checking that `foo` is well-formed + --> $DIR/ice-issue-124347.rs:10:7 | LL | reuse foo; - | ^^^ callee defined here + | ^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs index 25d7a4cb89557..5701cc6055db7 100644 --- a/tests/ui/delegation/not-supported.rs +++ b/tests/ui/delegation/not-supported.rs @@ -1,4 +1,6 @@ +#![feature(const_trait_impl)] #![feature(c_variadic)] +#![feature(effects)] #![feature(fn_delegation)] #![allow(incomplete_features)] @@ -14,9 +16,9 @@ mod generics { fn foo3<'a: 'a>(_: &'a u32) {} reuse GenericTrait::bar; - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items reuse GenericTrait::bar1; - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items } struct F; @@ -27,37 +29,37 @@ mod generics { impl GenericTrait for S { reuse >::bar { &self.0 } - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items reuse GenericTrait::::bar1; - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items } impl GenericTrait<()> for () { reuse GenericTrait::bar { &F } - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items reuse GenericTrait::bar1; - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items } impl Trait for &S { reuse Trait::foo; - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items } impl Trait for S { reuse Trait::foo1 { &self.0 } reuse Trait::foo2 { &self.0 } - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items //~| ERROR method `foo2` has 0 type parameters but its trait declaration has 1 type parameter reuse ::foo3; - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items //~| ERROR lifetime parameters or bounds on method `foo3` do not match the trait declaration } struct GenericS(T); impl Trait for GenericS { reuse Trait::foo { &self.0 } - //~^ ERROR delegation with early bound generics is not supported yet + //~^ ERROR early bound generics are not supported for associated delegation items } } @@ -68,13 +70,10 @@ mod opaque { mod to_reuse { use super::Trait; - pub fn opaque_arg(_: impl Trait) -> i32 { 0 } pub fn opaque_ret() -> impl Trait { unimplemented!() } //~^ warn: this function depends on never type fallback being `()` //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } - reuse to_reuse::opaque_arg; - //~^ ERROR delegation with early bound generics is not supported yet trait ToReuse { fn opaque_ret() -> impl Trait { unimplemented!() } @@ -104,4 +103,14 @@ mod recursive { //~^ ERROR recursive delegation is not supported yet } +mod effects { + #[const_trait] + trait Trait { + fn foo(); + } + + reuse Trait::foo; + //~^ ERROR delegation to a function with effect parameter is not supported yet +} + fn main() {} diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr index 4ce01fd5d8827..e7ba9fc6719a0 100644 --- a/tests/ui/delegation/not-supported.stderr +++ b/tests/ui/delegation/not-supported.stderr @@ -1,5 +1,10 @@ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:16:29 +error: using `#![feature(effects)]` without enabling next trait solver globally + | + = note: the next trait solver must be enabled globally for the effects feature to work correctly + = help: use `-Znext-solver` to enable + +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:18:29 | LL | fn bar(&self, x: T) -> T { x } | ------------------------ callee defined here @@ -7,8 +12,8 @@ LL | fn bar(&self, x: T) -> T { x } LL | reuse GenericTrait::bar; | ^^^ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:18:29 +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:20:29 | LL | fn bar1() {} | --------- callee defined here @@ -16,8 +21,8 @@ LL | fn bar1() {} LL | reuse GenericTrait::bar1; | ^^^^ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:29:39 +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:31:39 | LL | fn bar(&self, x: T) -> T { x } | ------------------------ callee defined here @@ -25,8 +30,8 @@ LL | fn bar(&self, x: T) -> T { x } LL | reuse >::bar { &self.0 } | ^^^ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:31:34 +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:33:34 | LL | fn bar1() {} | --------- callee defined here @@ -34,8 +39,8 @@ LL | fn bar1() {} LL | reuse GenericTrait::::bar1; | ^^^^ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:36:29 +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:38:29 | LL | fn bar(&self, x: T) -> T { x } | ------------------------ callee defined here @@ -43,8 +48,8 @@ LL | fn bar(&self, x: T) -> T { x } LL | reuse GenericTrait::bar { &F } | ^^^ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:38:29 +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:40:29 | LL | fn bar1() {} | --------- callee defined here @@ -52,8 +57,8 @@ LL | fn bar1() {} LL | reuse GenericTrait::bar1; | ^^^^ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:43:22 +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:45:22 | LL | fn foo(&self, x: i32) -> i32 { x } | ---------------------------- callee defined here @@ -62,7 +67,7 @@ LL | reuse Trait::foo; | ^^^ error[E0049]: method `foo2` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/not-supported.rs:49:22 + --> $DIR/not-supported.rs:51:22 | LL | fn foo2(&self, x: T) -> T { x } | - expected 1 type parameter @@ -70,8 +75,8 @@ LL | fn foo2(&self, x: T) -> T { x } LL | reuse Trait::foo2 { &self.0 } | ^^^^ found 0 type parameters -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:52:29 +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:54:29 | LL | fn foo3<'a: 'a>(_: &'a u32) {} | --------------------------- callee defined here @@ -80,7 +85,7 @@ LL | reuse ::foo3; | ^^^^ error[E0195]: lifetime parameters or bounds on method `foo3` do not match the trait declaration - --> $DIR/not-supported.rs:52:29 + --> $DIR/not-supported.rs:54:29 | LL | fn foo3<'a: 'a>(_: &'a u32) {} | -------- lifetimes in impl do not match this method in trait @@ -88,8 +93,17 @@ LL | fn foo3<'a: 'a>(_: &'a u32) {} LL | reuse ::foo3; | ^^^^ lifetimes do not match method in trait -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:59:22 +error: delegation to a function with effect parameter is not supported yet + --> $DIR/not-supported.rs:112:18 + | +LL | fn foo(); + | --------- callee defined here +... +LL | reuse Trait::foo; + | ^^^ + +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:61:22 | LL | fn foo(&self, x: i32) -> i32 { x } | ---------------------------- callee defined here @@ -97,8 +111,8 @@ LL | fn foo(&self, x: i32) -> i32 { x } LL | reuse Trait::foo { &self.0 } | ^^^ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:49:22 +error: early bound generics are not supported for associated delegation items + --> $DIR/not-supported.rs:51:22 | LL | fn foo2(&self, x: T) -> T { x } | ---------------------------- callee defined here @@ -106,17 +120,8 @@ LL | fn foo2(&self, x: T) -> T { x } LL | reuse Trait::foo2 { &self.0 } | ^^^^ -error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:76:21 - | -LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 } - | --------------------------------------- callee defined here -... -LL | reuse to_reuse::opaque_arg; - | ^^^^^^^^^^ - warning: this function depends on never type fallback being `()` - --> $DIR/not-supported.rs:80:9 + --> $DIR/not-supported.rs:79:9 | LL | fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -125,33 +130,33 @@ LL | fn opaque_ret() -> impl Trait { unimplemented!() } = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/not-supported.rs:80:28 + --> $DIR/not-supported.rs:79:28 | LL | fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/not-supported.rs:87:25 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/not-supported.rs:86:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/not-supported.rs:87:25 + --> $DIR/not-supported.rs:86:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/not-supported.rs:86:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/not-supported.rs:85:5 | LL | impl ToReuse for u8 { | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information warning: this function depends on never type fallback being `()` - --> $DIR/not-supported.rs:72:9 + --> $DIR/not-supported.rs:73:9 | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,32 +165,32 @@ LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/not-supported.rs:72:32 + --> $DIR/not-supported.rs:73:32 | LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } | ^^^^^^^^^^ -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/not-supported.rs:90:24 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/not-supported.rs:89:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/not-supported.rs:90:24 + --> $DIR/not-supported.rs:89:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/not-supported.rs:89:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/not-supported.rs:88:5 | LL | impl ToReuse for u16 { | ^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: recursive delegation is not supported yet - --> $DIR/not-supported.rs:103:22 + --> $DIR/not-supported.rs:102:22 | LL | pub reuse to_reuse2::foo; | --- callee defined here @@ -193,7 +198,7 @@ LL | pub reuse to_reuse2::foo; LL | reuse to_reuse1::foo; | ^^^ -error: aborting due to 16 previous errors; 2 warnings emitted +error: aborting due to 17 previous errors; 2 warnings emitted Some errors have detailed explanations: E0049, E0195, E0391. For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/delegation/target-expr.rs b/tests/ui/delegation/target-expr.rs index fd7ea943b9d5e..f766ca7356a4c 100644 --- a/tests/ui/delegation/target-expr.rs +++ b/tests/ui/delegation/target-expr.rs @@ -14,9 +14,7 @@ fn foo(x: i32) -> i32 { x } fn bar(_: T) { reuse Trait::static_method { - //~^ ERROR delegation to a trait method from a free function is not supported yet - //~| ERROR delegation with early bound generics is not supported yet - //~| ERROR mismatched types + //~^ ERROR mismatched types let _ = T::Default(); //~^ ERROR can't use generic parameters from outer item } @@ -25,7 +23,6 @@ fn bar(_: T) { fn main() { let y = 0; reuse ::static_method { - //~^ ERROR delegation to a trait method from a free function is not supported yet let x = y; //~^ ERROR can't capture dynamic environment in a fn item foo(self); diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr index b30f0c474c68b..f5556bf9f4514 100644 --- a/tests/ui/delegation/target-expr.stderr +++ b/tests/ui/delegation/target-expr.stderr @@ -1,16 +1,16 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/target-expr.rs:20:17 + --> $DIR/target-expr.rs:18:17 | LL | fn bar(_: T) { | - type parameter from outer item LL | reuse Trait::static_method { | - help: try introducing a local generic parameter here: `T,` -... +LL | LL | let _ = T::Default(); | ^^^^^^^^^^ use of generic parameter from outer item error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/target-expr.rs:29:17 + --> $DIR/target-expr.rs:26:17 | LL | let x = y; | ^ @@ -18,7 +18,7 @@ LL | let x = y; = help: use the `|| { ... }` closure form instead error[E0424]: expected value, found module `self` - --> $DIR/target-expr.rs:36:5 + --> $DIR/target-expr.rs:33:5 | LL | fn main() { | ---- this function can't have a `self` parameter @@ -27,58 +27,29 @@ LL | self.0; | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0425]: cannot find value `x` in this scope - --> $DIR/target-expr.rs:38:13 + --> $DIR/target-expr.rs:35:13 | LL | let z = x; | ^ | help: the binding `x` is available in a different scope in the same function - --> $DIR/target-expr.rs:29:13 + --> $DIR/target-expr.rs:26:13 | LL | let x = y; | ^ -error: delegation with early bound generics is not supported yet - --> $DIR/target-expr.rs:16:18 - | -LL | fn static_method(x: i32) -> i32 { x } - | ------------------------------- callee defined here -... -LL | reuse Trait::static_method { - | ^^^^^^^^^^^^^ - -error: delegation to a trait method from a free function is not supported yet - --> $DIR/target-expr.rs:16:18 - | -LL | fn static_method(x: i32) -> i32 { x } - | ------------------------------- callee defined here -... -LL | reuse Trait::static_method { - | ^^^^^^^^^^^^^ - -error: delegation to a trait method from a free function is not supported yet - --> $DIR/target-expr.rs:27:25 - | -LL | fn static_method(x: i32) -> i32 { x } - | ------------------------------- callee defined here -... -LL | reuse ::static_method { - | ^^^^^^^^^^^^^ - error[E0308]: mismatched types --> $DIR/target-expr.rs:16:32 | LL | reuse Trait::static_method { | ________________________________^ LL | | -LL | | -LL | | LL | | let _ = T::Default(); LL | | LL | | } | |_____^ expected `i32`, found `()` -error: aborting due to 8 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434. For more information about an error, try `rustc --explain E0308`. From 1d339b07ca84743710dc87dc0bc4c0597006ed59 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 6 Jul 2024 19:07:22 -0700 Subject: [PATCH 249/489] rustdoc: use `` in sidebar headers This also improves sidebar layout, so instead of BTreeM ap you get this BTree Map --- src/librustdoc/html/layout.rs | 2 ++ src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/render/sidebar.rs | 16 ++++++++++++++++ src/librustdoc/html/templates/page.html | 2 +- src/librustdoc/html/templates/sidebar.html | 6 ++++-- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 7dfcc88398faf..780cda9b1cdf4 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -69,6 +69,8 @@ struct PageLayout<'a> { display_krate_version_extra: &'a str, } +pub(crate) use crate::html::render::sidebar::filters; + pub(crate) fn render( layout: &Layout, page: &Page<'_>, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index aaac8678264aa..b5cc495ce41ef 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -30,7 +30,7 @@ mod tests; mod context; mod print_item; -mod sidebar; +pub(crate) mod sidebar; mod span_map; mod type_layout; mod write_shared; diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 6e826446c0e0e..101cc839f0988 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -77,6 +77,22 @@ impl<'a> Link<'a> { } } +pub(crate) mod filters { + use std::fmt::Display; + + use rinja::filters::Safe; + + use crate::html::escape::EscapeBodyTextWithWbr; + use crate::html::render::display_fn; + pub(crate) fn wrapped(v: T) -> rinja::Result> + where + T: Display, + { + let string = v.to_string(); + Ok(Safe(display_fn(move |f| EscapeBodyTextWithWbr(&string).fmt(f)))) + } +} + pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { let blocks: Vec> = match *it.kind { clean::StructItem(ref s) => sidebar_struct(cx, it, s), diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index cdf01fa7a97e8..65c4304e20207 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -98,7 +98,7 @@ {# #} {% endif %}

    {# #} - {{display_krate}} {# #} + {{display_krate|wrapped|safe}} {# #} {% if !display_krate_version_number.is_empty() %} {{+ display_krate_version_number}} {% endif %} diff --git a/src/librustdoc/html/templates/sidebar.html b/src/librustdoc/html/templates/sidebar.html index 3251b4c14c95a..025220ab4159c 100644 --- a/src/librustdoc/html/templates/sidebar.html +++ b/src/librustdoc/html/templates/sidebar.html @@ -1,6 +1,6 @@ {% if !title.is_empty() %}

    {# #} - {{title_prefix}}{{title}} {# #} + {{title_prefix}}{{title|wrapped|safe}} {# #}

    {% endif %} diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml index 1fa0a120adaec..a8363f29dd5de 100644 --- a/tests/rustdoc-gui/label-next-to-symbol.goml +++ b/tests/rustdoc-gui/label-next-to-symbol.goml @@ -27,7 +27,8 @@ compare-elements-position-near: ( ".item-name .stab.deprecated", {"y": 2}, ) -compare-elements-position: ( +// "Unix" part is on second line +compare-elements-position-false: ( ".item-name .stab.deprecated", ".item-name .stab.portability", ["y"], From ac303df4e21eabfbf692f2d1959f7403f4887a31 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 22 Jul 2024 09:49:49 -0700 Subject: [PATCH 251/489] rustdoc: move the wbr after the underscore, instead of before --- src/librustdoc/html/escape.rs | 8 ++++---- src/librustdoc/html/escape/tests.rs | 8 ++++---- tests/rustdoc/item-desc-list-at-start.item-table.html | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index f8199cd6e0e7f..691f86847b56d 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -108,13 +108,13 @@ impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> { || pk.map_or(true, |(_, t)| t.chars().any(|c| c.is_uppercase())); let next_is_underscore = || pk.map_or(true, |(_, t)| t.contains('_')); let next_is_colon = || pk.map_or(true, |(_, t)| t.contains(':')); - if (i - last > 3 && is_uppercase() && !next_is_uppercase()) - || (s.contains('_') && !next_is_underscore()) - { + if i - last > 3 && is_uppercase() && !next_is_uppercase() { EscapeBodyText(&text[last..i]).fmt(fmt)?; fmt.write_str("")?; last = i; - } else if s.contains(':') && !next_is_colon() { + } else if (s.contains(':') && !next_is_colon()) + || (s.contains('_') && !next_is_underscore()) + { EscapeBodyText(&text[last..i + 1]).fmt(fmt)?; fmt.write_str("")?; last = i + 1; diff --git a/src/librustdoc/html/escape/tests.rs b/src/librustdoc/html/escape/tests.rs index e2d81cf5c27aa..a09649e9e18dc 100644 --- a/src/librustdoc/html/escape/tests.rs +++ b/src/librustdoc/html/escape/tests.rs @@ -14,16 +14,16 @@ fn escape_body_text_with_wbr() { assert_eq!(&E(" ").to_string(), " "); // real(istic) examples assert_eq!(&E("FirstSecond").to_string(), "FirstSecond"); - assert_eq!(&E("First_Second").to_string(), "First_Second"); + assert_eq!(&E("First_Second").to_string(), "First_Second"); assert_eq!(&E("First Second").to_string(), "First Second"); assert_eq!(&E("First HSecond").to_string(), "First HSecond"); assert_eq!(&E("First HTTPSecond").to_string(), "First HTTPSecond"); assert_eq!(&E("First SecondThird").to_string(), "First SecondThird"); - assert_eq!(&E("First_Second").to_string(), "First<T>_Second"); - assert_eq!(&E("first_second").to_string(), "first_second"); + assert_eq!(&E("First_Second").to_string(), "First<T>_Second"); + assert_eq!(&E("first_second").to_string(), "first_second"); assert_eq!(&E("first:second").to_string(), "first:second"); assert_eq!(&E("first::second").to_string(), "first::second"); - assert_eq!(&E("MY_CONSTANT").to_string(), "MY_CONSTANT"); + assert_eq!(&E("MY_CONSTANT").to_string(), "MY_CONSTANT"); // a string won't get wrapped if it's less than 8 bytes assert_eq!(&E("HashSet").to_string(), "HashSet"); // an individual word won't get wrapped if it's less than 4 bytes diff --git a/tests/rustdoc/item-desc-list-at-start.item-table.html b/tests/rustdoc/item-desc-list-at-start.item-table.html index ab8b1508b5519..cff4f816529c3 100644 --- a/tests/rustdoc/item-desc-list-at-start.item-table.html +++ b/tests/rustdoc/item-desc-list-at-start.item-table.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file From 454c600004035776e87e80312ffcfa0b5645b44a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 29 Jul 2024 14:26:16 -0400 Subject: [PATCH 252/489] Detect non-lifetime binder params shadowing item params --- compiler/rustc_resolve/src/late.rs | 20 ++++----- tests/crashes/119716-2.rs | 2 +- ...icates-of-no-entry-found-for-key-119275.rs | 7 +-- ...es-of-no-entry-found-for-key-119275.stderr | 15 +++++-- .../traits/non_lifetime_binders/shadowed.rs | 18 ++++++++ .../non_lifetime_binders/shadowed.stderr | 44 +++++++++++++++++++ 6 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 tests/ui/traits/non_lifetime_binders/shadowed.rs create mode 100644 tests/ui/traits/non_lifetime_binders/shadowed.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 7e5fd82b80cee..f844930ad265e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2671,17 +2671,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Store all seen lifetimes names from outer scopes. let mut seen_lifetimes = FxHashSet::default(); - // We also can't shadow bindings from the parent item - if let RibKind::AssocItem = kind { - let mut add_bindings_for_ns = |ns| { - let parent_rib = self.ribs[ns] - .iter() - .rfind(|r| matches!(r.kind, RibKind::Item(..))) - .expect("associated item outside of an item"); + // We also can't shadow bindings from associated parent items. + for ns in [ValueNS, TypeNS] { + for parent_rib in self.ribs[ns].iter().rev() { seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); - }; - add_bindings_for_ns(ValueNS); - add_bindings_for_ns(TypeNS); + + // Break at mod level, to account for nested items which are + // allowed to shadow generic param names. + if matches!(parent_rib.kind, RibKind::Module(..)) { + break; + } + } } // Forbid shadowing lifetime bindings diff --git a/tests/crashes/119716-2.rs b/tests/crashes/119716-2.rs index 9cdc4417f5ba9..47bffb5c1de0d 100644 --- a/tests/crashes/119716-2.rs +++ b/tests/crashes/119716-2.rs @@ -1,4 +1,4 @@ //@ known-bug: #119716 #![feature(non_lifetime_binders)] trait Trait {} -fn f() -> impl for Trait> {} +fn f() -> impl for Trait> {} diff --git a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs index 4ba696f4ae080..9f20cf0857947 100644 --- a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs +++ b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.rs @@ -9,9 +9,10 @@ fn bug(&self) where for [(); COT::BYTES]:, //~^ ERROR only lifetime parameters can be used in this context - //~^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders - //~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders - //~^^^^ ERROR failed to resolve: use of undeclared type `COT` + //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders + //~| ERROR defaults for generic parameters are not allowed in `for<...>` binders + //~| ERROR failed to resolve: use of undeclared type `COT` + //~| ERROR the name `N` is already used for a generic parameter in this item's generic parameters { } diff --git a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr index ee0ec38ab0631..6037e685e44d7 100644 --- a/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr +++ b/tests/ui/const-generics/generic_const_exprs/ice-predicates-of-no-entry-found-for-key-119275.stderr @@ -6,6 +6,15 @@ LL | fn bug(&self) | = note: associated functions are those in `impl` or `trait` definitions +error[E0403]: the name `N` is already used for a generic parameter in this item's generic parameters + --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:10:15 + | +LL | fn bug(&self) + | - first use of `N` +... +LL | for [(); COT::BYTES]:, + | ^ already used + error[E0412]: cannot find type `Nat` in this scope --> $DIR/ice-predicates-of-no-entry-found-for-key-119275.rs:6:17 | @@ -40,7 +49,7 @@ error[E0433]: failed to resolve: use of undeclared type `COT` LL | for [(); COT::BYTES]:, | ^^^ use of undeclared type `COT` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0412, E0433, E0658. -For more information about an error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0403, E0412, E0433, E0658. +For more information about an error, try `rustc --explain E0403`. diff --git a/tests/ui/traits/non_lifetime_binders/shadowed.rs b/tests/ui/traits/non_lifetime_binders/shadowed.rs new file mode 100644 index 0000000000000..1c480e3940b89 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/shadowed.rs @@ -0,0 +1,18 @@ +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +fn function() where for (): Sized {} +//~^ ERROR the name `T` is already used for a generic parameter + +struct Struct(T) where for (): Sized; +//~^ ERROR the name `T` is already used for a generic parameter + +impl Struct { + fn method() where for (): Sized {} + //~^ ERROR the name `T` is already used for a generic parameter +} + +fn repeated() where for (): Sized {} +//~^ ERROR the name `T` is already used for a generic parameter + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/shadowed.stderr b/tests/ui/traits/non_lifetime_binders/shadowed.stderr new file mode 100644 index 0000000000000..59a073aefc961 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/shadowed.stderr @@ -0,0 +1,44 @@ +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed.rs:4:28 + | +LL | fn function() where for (): Sized {} + | - ^ already used + | | + | first use of `T` + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed.rs:7:31 + | +LL | struct Struct(T) where for (): Sized; + | - ^ already used + | | + | first use of `T` + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed.rs:11:27 + | +LL | impl Struct { + | - first use of `T` +LL | fn method() where for (): Sized {} + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed.rs:15:28 + | +LL | fn repeated() where for (): Sized {} + | - ^ already used + | | + | first use of `T` + +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/shadowed.rs:1:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #108185 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 4 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0403`. From e9f45e1eb2e6ef09034453f4a7a0998c65ce5736 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 14:33:54 -0400 Subject: [PATCH 253/489] rewrite link-cfg to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/link-cfg/Makefile | 23 ---------- tests/run-make/link-cfg/rmake.rs | 43 +++++++++++++++++++ 3 files changed, 43 insertions(+), 24 deletions(-) delete mode 100644 tests/run-make/link-cfg/Makefile create mode 100644 tests/run-make/link-cfg/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 7284feadf9cdd..dc4db13902da9 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -25,7 +25,6 @@ run-make/libs-through-symlinks/Makefile run-make/libtest-json/Makefile run-make/libtest-junit/Makefile run-make/libtest-thread-limit/Makefile -run-make/link-cfg/Makefile run-make/long-linker-command-lines-cmd-exe/Makefile run-make/long-linker-command-lines/Makefile run-make/macos-deployment-target/Makefile diff --git a/tests/run-make/link-cfg/Makefile b/tests/run-make/link-cfg/Makefile deleted file mode 100644 index a40997011443c..0000000000000 --- a/tests/run-make/link-cfg/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: $(call DYLIB,return1) $(call DYLIB,return2) $(call NATIVE_STATICLIB,return3) - ls $(TMPDIR) - $(BARE_RUSTC) --print cfg --target x86_64-unknown-linux-musl | $(CGREP) crt-static - - $(RUSTC) no-deps.rs --cfg foo - $(call RUN,no-deps) - $(RUSTC) no-deps.rs --cfg bar - $(call RUN,no-deps) - - $(RUSTC) dep.rs - $(RUSTC) with-deps.rs --cfg foo - $(call RUN,with-deps) - $(RUSTC) with-deps.rs --cfg bar - $(call RUN,with-deps) - - $(RUSTC) dep-with-staticlib.rs - $(RUSTC) with-staticlib-deps.rs --cfg foo - $(call RUN,with-staticlib-deps) - $(RUSTC) with-staticlib-deps.rs --cfg bar - $(call RUN,with-staticlib-deps) diff --git a/tests/run-make/link-cfg/rmake.rs b/tests/run-make/link-cfg/rmake.rs new file mode 100644 index 0000000000000..732de5dbd0b80 --- /dev/null +++ b/tests/run-make/link-cfg/rmake.rs @@ -0,0 +1,43 @@ +// The `#[link(cfg(..))]` annotation means that the `#[link]` +// directive is only active in a compilation unit if that `cfg` value is satisfied. +// For example, when compiling an rlib, these directives are just encoded and +// ignored for dylibs, and all staticlibs are continued to be put into the rlib as +// usual. When placing that rlib into a staticlib, executable, or dylib, however, +// the `cfg` is evaluated *as if it were defined in the final artifact* and the +// library is decided to be linked or not. +// This test exercises this new feature by testing it with no dependencies, then +// with only dynamic libraries, then with both a staticlib and dylibs. Compilation +// and execution should be successful. +// See https://github.com/rust-lang/rust/pull/37545 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{bare_rustc, build_native_dynamic_lib, build_native_static_lib, run, rustc}; + +fn main() { + build_native_dynamic_lib("return1"); + build_native_dynamic_lib("return2"); + build_native_static_lib("return3"); + bare_rustc() + .print("cfg") + .target("x86_64-unknown-linux-musl") + .run() + .assert_stdout_contains("crt-static"); + rustc().input("no-deps.rs").cfg("foo").run(); + run("no-deps"); + rustc().input("no-deps.rs").cfg("bar").run(); + run("no-deps"); + + rustc().input("dep.rs").run(); + rustc().input("with-deps.rs").cfg("foo").run(); + run("with-deps"); + rustc().input("with-deps.rs").cfg("bar").run(); + run("with-deps"); + + rustc().input("dep-with-staticlib.rs").run(); + rustc().input("with-staticlib-deps.rs").cfg("foo").run(); + run("with-staticlib-deps"); + rustc().input("with-staticlib-deps.rs").cfg("bar").run(); + run("with-staticlib-deps"); +} From 6d9ee6ee26c296d9361d5f0fb479b2462687fe4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 25 Jul 2024 18:38:28 +0000 Subject: [PATCH 254/489] Change output normalization logic to be linear against size of output Scan strings to be normalized for printing in a linear scan and collect the resulting `String` only once. Use a binary search when looking for chars to be replaced, instead of a `HashMap::get`. --- Cargo.lock | 1 + compiler/rustc_errors/Cargo.toml | 1 + compiler/rustc_errors/src/emitter.rs | 98 +++++++++++++++------------- 3 files changed, 54 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 281599a21fc14..43fbaf966b79f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3867,6 +3867,7 @@ version = "0.0.0" dependencies = [ "annotate-snippets 0.10.2", "derive_setters", + "either", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 2fff9f2de50fb..ddf72a2d5fdb2 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" # tidy-alphabetical-start annotate-snippets = "0.10" derive_setters = "0.1.6" +either = "1.5.0" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 73908e5808569..d186996040bd2 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -16,6 +16,7 @@ use std::iter; use std::path::Path; use derive_setters::Setters; +use either::Either; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc}; use rustc_error_messages::{FluentArgs, SpanLabel}; @@ -2559,60 +2560,65 @@ fn num_decimal_digits(num: usize) -> usize { // We replace some characters so the CLI output is always consistent and underlines aligned. // Keep the following list in sync with `rustc_span::char_width`. +// ATTENTION: keep lexicografically sorted so that the binary search will work const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ - ('\t', " "), // We do our own tab replacement - ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. - ('\u{202A}', "�"), // The following unicode text flow control characters are inconsistently - ('\u{202B}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk - ('\u{202D}', "�"), // not corresponding to the visible source code, so we replace them always. - ('\u{202E}', "�"), + // In terminals without Unicode support the following will be garbled, but in *all* terminals + // the underlying codepoint will be as well. We could gate this replacement behind a "unicode + // support" gate. + ('\0', "␀"), + ('\u{1}', "␁"), + ('\u{2}', "␂"), + ('\u{3}', "␃"), + ('\u{4}', "␄"), + ('\u{5}', "␅"), + ('\u{6}', "␆"), + ('\u{7}', "␇"), + ('\u{8}', "␈"), + ('\t', " "), // We do our own tab replacement + ('\u{b}', "␋"), + ('\u{c}', "␌"), + ('\r', "␍"), + ('\u{e}', "␎"), + ('\u{f}', "␏"), + ('\u{10}', "␐"), + ('\u{11}', "␑"), + ('\u{12}', "␒"), + ('\u{13}', "␓"), + ('\u{14}', "␔"), + ('\u{15}', "␕"), + ('\u{16}', "␖"), + ('\u{17}', "␗"), + ('\u{18}', "␘"), + ('\u{19}', "␙"), + ('\u{1a}', "␚"), + ('\u{1b}', "␛"), + ('\u{1c}', "␜"), + ('\u{1d}', "␝"), + ('\u{1e}', "␞"), + ('\u{1f}', "␟"), + ('\u{7f}', "␡"), + ('\u{200d}', ""), // Replace ZWJ for consistent terminal output of grapheme clusters. + ('\u{202a}', "�"), // The following unicode text flow control characters are inconsistently + ('\u{202b}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk + ('\u{202c}', "�"), // not corresponding to the visible source code, so we replace them always. + ('\u{202d}', "�"), + ('\u{202e}', "�"), ('\u{2066}', "�"), ('\u{2067}', "�"), ('\u{2068}', "�"), - ('\u{202C}', "�"), ('\u{2069}', "�"), - // In terminals without Unicode support the following will be garbled, but in *all* terminals - // the underlying codepoint will be as well. We could gate this replacement behind a "unicode - // support" gate. - ('\u{0000}', "␀"), - ('\u{0001}', "␁"), - ('\u{0002}', "␂"), - ('\u{0003}', "␃"), - ('\u{0004}', "␄"), - ('\u{0005}', "␅"), - ('\u{0006}', "␆"), - ('\u{0007}', "␇"), - ('\u{0008}', "␈"), - ('\u{000B}', "␋"), - ('\u{000C}', "␌"), - ('\u{000D}', "␍"), - ('\u{000E}', "␎"), - ('\u{000F}', "␏"), - ('\u{0010}', "␐"), - ('\u{0011}', "␑"), - ('\u{0012}', "␒"), - ('\u{0013}', "␓"), - ('\u{0014}', "␔"), - ('\u{0015}', "␕"), - ('\u{0016}', "␖"), - ('\u{0017}', "␗"), - ('\u{0018}', "␘"), - ('\u{0019}', "␙"), - ('\u{001A}', "␚"), - ('\u{001B}', "␛"), - ('\u{001C}', "␜"), - ('\u{001D}', "␝"), - ('\u{001E}', "␞"), - ('\u{001F}', "␟"), - ('\u{007F}', "␡"), ]; fn normalize_whitespace(str: &str) -> String { - let mut s = str.to_string(); - for (c, replacement) in OUTPUT_REPLACEMENTS { - s = s.replace(*c, replacement); - } - s + // Scan the input string for a character in the ordered table above. If it's present, replace + // it with it's alternative string (it can be more than 1 char!). Otherwise, retain the input + // char. At the end, allocate all chars into a string in one operation. + str.chars() + .flat_map(|c| match OUTPUT_REPLACEMENTS.binary_search_by_key(&c, |(k, _)| *k) { + Ok(i) => Either::Left(OUTPUT_REPLACEMENTS[i].1.chars()), + _ => Either::Right([c].into_iter()), + }) + .collect() } fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { From 3945480ce7b93eefc2fec90bb87bc53a19e30f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 29 Jul 2024 18:35:11 +0000 Subject: [PATCH 255/489] Use `fold` instead of `flat_map` --- Cargo.lock | 1 - compiler/rustc_errors/Cargo.toml | 1 - compiler/rustc_errors/src/emitter.rs | 16 ++++++++-------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43fbaf966b79f..281599a21fc14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3867,7 +3867,6 @@ version = "0.0.0" dependencies = [ "annotate-snippets 0.10.2", "derive_setters", - "either", "rustc_ast", "rustc_ast_pretty", "rustc_data_structures", diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index ddf72a2d5fdb2..2fff9f2de50fb 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" # tidy-alphabetical-start annotate-snippets = "0.10" derive_setters = "0.1.6" -either = "1.5.0" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index d186996040bd2..18e077ed8a22a 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -16,7 +16,6 @@ use std::iter; use std::path::Path; use derive_setters::Setters; -use either::Either; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::sync::{DynSend, IntoDynSyncSend, Lrc}; use rustc_error_messages::{FluentArgs, SpanLabel}; @@ -2609,16 +2608,17 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\u{2069}', "�"), ]; -fn normalize_whitespace(str: &str) -> String { +fn normalize_whitespace(s: &str) -> String { // Scan the input string for a character in the ordered table above. If it's present, replace // it with it's alternative string (it can be more than 1 char!). Otherwise, retain the input // char. At the end, allocate all chars into a string in one operation. - str.chars() - .flat_map(|c| match OUTPUT_REPLACEMENTS.binary_search_by_key(&c, |(k, _)| *k) { - Ok(i) => Either::Left(OUTPUT_REPLACEMENTS[i].1.chars()), - _ => Either::Right([c].into_iter()), - }) - .collect() + s.chars().fold(String::with_capacity(s.len()), |mut s, c| { + match OUTPUT_REPLACEMENTS.binary_search_by_key(&c, |(k, _)| *k) { + Ok(i) => s.push_str(OUTPUT_REPLACEMENTS[i].1), + _ => s.push(c), + } + s + }) } fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { From a7cb1a5352e648bcf5ffb1403b6535275a6c511d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Jul 2024 13:58:15 +0200 Subject: [PATCH 256/489] Make the buttons remain when code example is clicked --- src/librustdoc/html/static/css/rustdoc.css | 15 ++++++++++++- src/librustdoc/html/static/js/main.js | 25 ++++++++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index e936e1ca07ecd..1b9dfdf3fdd67 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1474,7 +1474,20 @@ a.test-arrow:hover { .example-wrap:hover > .test-arrow { padding: 2px 7px; } -.example-wrap:hover > .test-arrow, .example-wrap:hover > .button-holder { +/* +On iPad, the ":hover" state sticks around, making things work not greatly. Do work around +it, we move it into this media query. More information can be found at: +https://css-tricks.com/solving-sticky-hover-states-with-media-hover-hover/ + +However, using `@media (hover: hover)` makes this rule never to be applied in GUI tests, so +instead, we check that it's not a "finger" cursor. +*/ +@media not (pointer: coarse) { + .example-wrap:hover > .test-arrow, .example-wrap:hover > .button-holder { + visibility: visible; + } +} +.example-wrap .button-holder.keep-visible { visibility: visible; } .example-wrap .button-holder .copy-button { diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 40d65ae7910e2..e0ea234f9e710 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1829,14 +1829,22 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm copyContentToClipboard(codeElem.textContent); } - function addCopyButton(event) { + function getExampleWrap(event) { let elem = event.target; while (!hasClass(elem, "example-wrap")) { elem = elem.parentElement; if (elem.tagName === "body" || hasClass(elem, "docblock")) { - return; + return null; } } + return elem; + } + + function addCopyButton(event) { + const elem = getExampleWrap(event); + if (elem === null) { + return; + } // Since the button will be added, no need to keep this listener around. elem.removeEventListener("mouseover", addCopyButton); @@ -1858,7 +1866,20 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm parent.appendChild(copyButton); } + function showHideCodeExampleButtons(event) { + const elem = getExampleWrap(event); + if (elem === null) { + return; + } + const buttons = elem.querySelector(".button-holder"); + if (buttons === null) { + return; + } + buttons.classList.toggle("keep-visible"); + } + onEachLazy(document.querySelectorAll(".docblock .example-wrap"), elem => { elem.addEventListener("mouseover", addCopyButton); + elem.addEventListener("click", showHideCodeExampleButtons); }); }()); From 99906dc89c241d29c6e63d10f719d36d81a9a049 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Jul 2024 13:58:33 +0200 Subject: [PATCH 257/489] Add rustdoc GUI test to check click on code examples --- tests/rustdoc-gui/code-example-buttons.goml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/rustdoc-gui/code-example-buttons.goml diff --git a/tests/rustdoc-gui/code-example-buttons.goml b/tests/rustdoc-gui/code-example-buttons.goml new file mode 100644 index 0000000000000..57ea2970072e6 --- /dev/null +++ b/tests/rustdoc-gui/code-example-buttons.goml @@ -0,0 +1,21 @@ +// This test ensures that code blocks buttons are displayed on hover and when you click on them. +go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html" + +// First we check we "hover". +move-cursor-to: ".example-wrap" +assert-css: (".example-wrap .copy-button", { "visibility": "visible" }) +move-cursor-to: ".search-input" +assert-css: (".example-wrap .copy-button", { "visibility": "hidden" }) + +// Now we check the click. +assert-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 0) +click: ".example-wrap" +move-cursor-to: ".search-input" +// It should have a new class and be visible. +wait-for-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 1) +wait-for-css: (".example-wrap:not(:hover) .button-holder.keep-visible", { "visibility": "visible" }) +// Clicking again will remove the class. +click: ".example-wrap" +move-cursor-to: ".search-input" +assert-count: (".example-wrap:not(:hover) .button-holder.keep-visible", 0) +assert-css: (".example-wrap .copy-button", { "visibility": "hidden" }) From d280b8ca14edea616af39f0f0642f1aeb6714243 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 29 Jul 2024 00:51:33 +0200 Subject: [PATCH 258/489] CI: rfl: build the generated doctests We were already generating the doctests, which should already catch most issues with our hack around `--test-builder` and `--no-run`. However, we were not building the result of that transformation, thus build it for completeness and to ensure the hack may not have produced something completely broken. In the worst case, we can revert it. Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 3acc09e0b9b1a..4e3079b35cac6 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -65,4 +65,5 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ samples/rust/rust_minimal.o \ samples/rust/rust_print.o \ - drivers/net/phy/ax88796b_rust.o + drivers/net/phy/ax88796b_rust.o \ + rust/doctests_kernel_generated.o From 77cc18fd79073beada6dcd1e392be7996683503d Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Mon, 29 Jul 2024 23:03:26 +0200 Subject: [PATCH 259/489] CI: rfl: build the documentation Since the `rfl` CI job has not had almost any issue for some weeks, it is a good time to try to increase a bit the scope of what it tests. The kernel does not use any particular `rustdoc` unstable issue (apart from the doctests ones) so far, so in principle it should not introduce extra issues here, and may be a good extra test case for Rust. In addition, it may help to test new unstable features in the future. In the worst case, we can revert it. Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 4e3079b35cac6..d690aac27fae6 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -67,3 +67,6 @@ make -C linux LLVM=1 -j$(($(nproc) + 1)) \ samples/rust/rust_print.o \ drivers/net/phy/ax88796b_rust.o \ rust/doctests_kernel_generated.o + +make -C linux LLVM=1 -j$(($(nproc) + 1)) \ + rustdoc From bd24763aaf32fe92e79491aba05346b570301647 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jul 2024 07:20:17 +1000 Subject: [PATCH 260/489] Move a comment. In #125443 this comment ended up in the wrong spot. I'm not sure why; after careful checking this was the only case I could find like this. --- library/std/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ee6f5a6f3c0d5..5a33a243743e5 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -671,7 +671,6 @@ mod panicking; #[allow(dead_code, unused_attributes, fuzzy_provenance_casts, unsafe_op_in_unsafe_fn)] mod backtrace_rs; -// Re-export macros defined in core. #[unstable(feature = "cfg_match", issue = "115585")] pub use core::cfg_match; #[unstable( @@ -690,6 +689,7 @@ pub use core::{ env, file, format_args, format_args_nl, include, include_bytes, include_str, line, log_syntax, module_path, option_env, stringify, trace_macros, }; +// Re-export macros defined in core. #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::{ From 70fcf9e7908cfa3da975a322b4aa533ad67d52ec Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 30 Jul 2024 07:21:13 +1000 Subject: [PATCH 261/489] Insert some blank lines. After things that are immediately followed by a `use` declaration and look like they might apply to that `use` item but actually don't. --- .../src/macro_expr_fragment_specifier_2024_migration.rs | 4 ++-- library/std/src/sys/pal/sgx/thread.rs | 1 + library/std/src/sys/pal/windows/net.rs | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs index c39c86f6fe8f1..e3b1967da09c7 100644 --- a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs +++ b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs @@ -1,5 +1,5 @@ -//! Migration code for the `expr_fragment_specifier_2024` -//! rule. +//! Migration code for the `expr_fragment_specifier_2024` rule. + use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_session::lint::FutureIncompatibilityReason; diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index df65d1cc8fc48..cecd53c352c5a 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -1,4 +1,5 @@ #![cfg_attr(test, allow(dead_code))] // why is this necessary? + use super::abi::usercalls; use super::unsupported; use crate::ffi::CStr; diff --git a/library/std/src/sys/pal/windows/net.rs b/library/std/src/sys/pal/windows/net.rs index e27fdb72256f4..ce995f5ed5af7 100644 --- a/library/std/src/sys/pal/windows/net.rs +++ b/library/std/src/sys/pal/windows/net.rs @@ -21,6 +21,7 @@ pub mod netc { //! //! Some Windows API types are not quite what's expected by our cross-platform //! net code. E.g. naming differences or different pointer types. + use core::ffi::{c_char, c_int, c_uint, c_ulong, c_ushort, c_void}; use crate::sys::c::{self, ADDRESS_FAMILY, ADDRINFOA, SOCKADDR, SOCKET}; From b61570ac11650579252a9350505a7064e85b48c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 24 Jul 2024 19:31:02 +0000 Subject: [PATCH 262/489] Structured suggestion for `extern crate foo` when `foo` isn't resolved in import When encountering a name in an import that could have come from a crate that wasn't imported, use a structured suggestion to suggest `extern crate foo;` pointing at the right place in the crate. When encountering `_` in an import, do not suggest `extern crate _;`. ``` error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-3.rs:2:9 | LL | use spam::*; | ^^^^ maybe a missing crate `spam`? | help: consider importing the `spam` crate | LL + extern crate spam; | ``` --- compiler/rustc_interface/src/passes.rs | 8 +++++++- compiler/rustc_resolve/src/diagnostics.rs | 11 ++++++---- compiler/rustc_resolve/src/lib.rs | 6 ++++++ .../ice-unresolved-import-100241.stderr | 5 ++++- .../unresolved-import-recovery.stderr | 5 ++++- tests/rustdoc-ui/issues/issue-61732.stderr | 5 ++++- .../field-attributes-vis-unresolved.stderr | 10 ++++++++-- tests/ui/error-codes/E0432.stderr | 5 ++++- .../imports/import-from-missing-star-2.stderr | 5 ++++- .../imports/import-from-missing-star-3.stderr | 10 ++++++++-- .../imports/import-from-missing-star.stderr | 5 ++++- tests/ui/imports/import3.stderr | 5 ++++- tests/ui/imports/issue-109343.stderr | 5 ++++- tests/ui/imports/issue-1697.rs | 2 +- tests/ui/imports/issue-1697.stderr | 5 ++++- tests/ui/imports/issue-33464.stderr | 15 +++++++++++--- tests/ui/imports/issue-36881.stderr | 5 ++++- tests/ui/imports/issue-37887.stderr | 5 ++++- tests/ui/imports/issue-53269.stderr | 5 ++++- tests/ui/imports/issue-55457.stderr | 5 ++++- tests/ui/imports/issue-81413.stderr | 5 ++++- tests/ui/imports/tool-mod-child.stderr | 20 +++++++++++++++---- .../ui/imports/unresolved-imports-used.stderr | 20 +++++++++++++++---- .../keyword-extern-as-identifier-use.stderr | 5 ++++- tests/ui/privacy/restricted/test.stderr | 5 ++++- .../resolve/editions-crate-root-2015.stderr | 10 ++++++++-- tests/ui/resolve/extern-prelude-fail.stderr | 10 ++++++++-- tests/ui/resolve/issue-82865.stderr | 5 ++++- .../ui/resolve/resolve-bad-visibility.stderr | 10 ++++++++-- .../ui/underscore-imports/issue-110164.stderr | 16 ++++----------- .../unresolved-asterisk-imports.stderr | 5 ++++- tests/ui/unresolved/unresolved-import.rs | 3 ++- tests/ui/unresolved/unresolved-import.stderr | 15 ++++++++------ 33 files changed, 192 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a5e25b917dc5b..8c99b1f444766 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -544,7 +544,13 @@ fn resolver_for_lowering_raw<'tcx>( let arenas = Resolver::arenas(); let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`. let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal(); - let mut resolver = Resolver::new(tcx, &pre_configured_attrs, krate.spans.inner_span, &arenas); + let mut resolver = Resolver::new( + tcx, + &pre_configured_attrs, + krate.spans.inner_span, + krate.spans.inject_use_span, + &arenas, + ); let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver); // Make sure we don't mutate the cstore from here on. diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index ccb7223b62128..8080bb60e415e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2026,14 +2026,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Applicability::MaybeIncorrect, )), ) + } else if ident.name == kw::Underscore { + (format!("`_` is not a valid crate or module name"), None) } else if self.tcx.sess.is_rust_2015() { ( format!("you might be missing crate `{ident}`"), Some(( - vec![], - format!( - "consider adding `extern crate {ident}` to use the `{ident}` crate" - ), + vec![( + self.current_crate_outer_attr_insert_span, + format!("extern crate {ident};\n"), + )], + format!("consider importing the `{ident}` crate"), Applicability::MaybeIncorrect, )), ) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6aca0545e64de..6405cb82493b5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1180,6 +1180,10 @@ pub struct Resolver<'a, 'tcx> { /// Simplified analogue of module `resolutions` but in trait impls, excluding glob delegations. /// Needed because glob delegations exclude explicitly defined names. impl_binding_keys: FxHashMap>, + + /// This is the `Span` where an `extern crate foo;` suggestion would be inserted, if `foo` + /// could be a crate that wasn't imported. For diagnostics use only. + current_crate_outer_attr_insert_span: Span, } /// Nothing really interesting here; it just provides memory for the rest of the crate. @@ -1342,6 +1346,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { tcx: TyCtxt<'tcx>, attrs: &[ast::Attribute], crate_span: Span, + current_crate_outer_attr_insert_span: Span, arenas: &'a ResolverArenas<'a>, ) -> Resolver<'a, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); @@ -1525,6 +1530,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { glob_delegation_invoc_ids: Default::default(), impl_unexpanded_invocations: Default::default(), impl_binding_keys: Default::default(), + current_crate_outer_attr_insert_span, }; let root_parent_scope = ParentScope::module(graph_root, &resolver); diff --git a/tests/rustdoc-ui/ice-unresolved-import-100241.stderr b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr index e23e0f01fabe3..2eebedba9a5ee 100644 --- a/tests/rustdoc-ui/ice-unresolved-import-100241.stderr +++ b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `inner` LL | pub use inner::S; | ^^^^^ you might be missing crate `inner` | - = help: consider adding `extern crate inner` to use the `inner` crate +help: consider importing the `inner` crate + | +LL + extern crate inner; + | error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr index a74e6b7393891..e68943192130d 100644 --- a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr +++ b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr @@ -4,7 +4,10 @@ error[E0433]: failed to resolve: you might be missing crate `unresolved_crate` LL | use unresolved_crate::module::Name; | ^^^^^^^^^^^^^^^^ you might be missing crate `unresolved_crate` | - = help: consider adding `extern crate unresolved_crate` to use the `unresolved_crate` crate +help: consider importing the `unresolved_crate` crate + | +LL + extern crate unresolved_crate; + | error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/issues/issue-61732.stderr b/tests/rustdoc-ui/issues/issue-61732.stderr index f49d53b0d9ad0..0aa7d558c307d 100644 --- a/tests/rustdoc-ui/issues/issue-61732.stderr +++ b/tests/rustdoc-ui/issues/issue-61732.stderr @@ -4,7 +4,10 @@ error[E0433]: failed to resolve: you might be missing crate `r#mod` LL | pub(in crate::r#mod) fn main() {} | ^^^^^ you might be missing crate `r#mod` | - = help: consider adding `extern crate r#mod` to use the `r#mod` crate +help: consider importing the `r#mod` crate + | +LL + extern crate r#mod; + | error: aborting due to 1 previous error diff --git a/tests/ui/attributes/field-attributes-vis-unresolved.stderr b/tests/ui/attributes/field-attributes-vis-unresolved.stderr index 819cd859ae909..f8610c08b0220 100644 --- a/tests/ui/attributes/field-attributes-vis-unresolved.stderr +++ b/tests/ui/attributes/field-attributes-vis-unresolved.stderr @@ -4,7 +4,10 @@ error[E0433]: failed to resolve: you might be missing crate `nonexistent` LL | pub(in nonexistent) field: u8 | ^^^^^^^^^^^ you might be missing crate `nonexistent` | - = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate +help: consider importing the `nonexistent` crate + | +LL + extern crate nonexistent; + | error[E0433]: failed to resolve: you might be missing crate `nonexistent` --> $DIR/field-attributes-vis-unresolved.rs:22:12 @@ -12,7 +15,10 @@ error[E0433]: failed to resolve: you might be missing crate `nonexistent` LL | pub(in nonexistent) u8 | ^^^^^^^^^^^ you might be missing crate `nonexistent` | - = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate +help: consider importing the `nonexistent` crate + | +LL + extern crate nonexistent; + | error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0432.stderr b/tests/ui/error-codes/E0432.stderr index a0b17e35c94a8..36fefc95897d6 100644 --- a/tests/ui/error-codes/E0432.stderr +++ b/tests/ui/error-codes/E0432.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `something` LL | use something::Foo; | ^^^^^^^^^ you might be missing crate `something` | - = help: consider adding `extern crate something` to use the `something` crate +help: consider importing the `something` crate + | +LL + extern crate something; + | error: aborting due to 1 previous error diff --git a/tests/ui/imports/import-from-missing-star-2.stderr b/tests/ui/imports/import-from-missing-star-2.stderr index 59b000a43822b..dd35627c68465 100644 --- a/tests/ui/imports/import-from-missing-star-2.stderr +++ b/tests/ui/imports/import-from-missing-star-2.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `spam` LL | use spam::*; | ^^^^ you might be missing crate `spam` | - = help: consider adding `extern crate spam` to use the `spam` crate +help: consider importing the `spam` crate + | +LL + extern crate spam; + | error: aborting due to 1 previous error diff --git a/tests/ui/imports/import-from-missing-star-3.stderr b/tests/ui/imports/import-from-missing-star-3.stderr index 23df6b354450b..1e2412b095975 100644 --- a/tests/ui/imports/import-from-missing-star-3.stderr +++ b/tests/ui/imports/import-from-missing-star-3.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `spam` LL | use spam::*; | ^^^^ you might be missing crate `spam` | - = help: consider adding `extern crate spam` to use the `spam` crate +help: consider importing the `spam` crate + | +LL + extern crate spam; + | error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-3.rs:27:13 @@ -12,7 +15,10 @@ error[E0432]: unresolved import `spam` LL | use spam::*; | ^^^^ you might be missing crate `spam` | - = help: consider adding `extern crate spam` to use the `spam` crate +help: consider importing the `spam` crate + | +LL + extern crate spam; + | error: aborting due to 2 previous errors diff --git a/tests/ui/imports/import-from-missing-star.stderr b/tests/ui/imports/import-from-missing-star.stderr index b311527bc28e4..c9bb9baeb4dde 100644 --- a/tests/ui/imports/import-from-missing-star.stderr +++ b/tests/ui/imports/import-from-missing-star.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `spam` LL | use spam::*; | ^^^^ you might be missing crate `spam` | - = help: consider adding `extern crate spam` to use the `spam` crate +help: consider importing the `spam` crate + | +LL + extern crate spam; + | error: aborting due to 1 previous error diff --git a/tests/ui/imports/import3.stderr b/tests/ui/imports/import3.stderr index 06260ef9ebc75..157b5b6356687 100644 --- a/tests/ui/imports/import3.stderr +++ b/tests/ui/imports/import3.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `main` LL | use main::bar; | ^^^^ you might be missing crate `main` | - = help: consider adding `extern crate main` to use the `main` crate +help: consider importing the `main` crate + | +LL + extern crate main; + | error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr index fe06eddeada69..e66528e8df528 100644 --- a/tests/ui/imports/issue-109343.stderr +++ b/tests/ui/imports/issue-109343.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `unresolved` LL | pub use unresolved::f; | ^^^^^^^^^^ you might be missing crate `unresolved` | - = help: consider adding `extern crate unresolved` to use the `unresolved` crate +help: consider importing the `unresolved` crate + | +LL + extern crate unresolved; + | error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-1697.rs b/tests/ui/imports/issue-1697.rs index 8ec48d4d28628..019237611df0d 100644 --- a/tests/ui/imports/issue-1697.rs +++ b/tests/ui/imports/issue-1697.rs @@ -3,6 +3,6 @@ use unresolved::*; //~^ ERROR unresolved import `unresolved` [E0432] //~| NOTE you might be missing crate `unresolved` -//~| HELP consider adding `extern crate unresolved` to use the `unresolved` crate +//~| HELP consider importing the `unresolved` crate fn main() {} diff --git a/tests/ui/imports/issue-1697.stderr b/tests/ui/imports/issue-1697.stderr index df2957b8f2b13..ec0d94bd672f9 100644 --- a/tests/ui/imports/issue-1697.stderr +++ b/tests/ui/imports/issue-1697.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `unresolved` LL | use unresolved::*; | ^^^^^^^^^^ you might be missing crate `unresolved` | - = help: consider adding `extern crate unresolved` to use the `unresolved` crate +help: consider importing the `unresolved` crate + | +LL + extern crate unresolved; + | error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-33464.stderr b/tests/ui/imports/issue-33464.stderr index 17cc0e4469e43..28fbcee401f91 100644 --- a/tests/ui/imports/issue-33464.stderr +++ b/tests/ui/imports/issue-33464.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `abc` LL | use abc::one_el; | ^^^ you might be missing crate `abc` | - = help: consider adding `extern crate abc` to use the `abc` crate +help: consider importing the `abc` crate + | +LL + extern crate abc; + | error[E0432]: unresolved import `abc` --> $DIR/issue-33464.rs:5:5 @@ -12,7 +15,10 @@ error[E0432]: unresolved import `abc` LL | use abc::{a, bbb, cccccc}; | ^^^ you might be missing crate `abc` | - = help: consider adding `extern crate abc` to use the `abc` crate +help: consider importing the `abc` crate + | +LL + extern crate abc; + | error[E0432]: unresolved import `a_very_long_name` --> $DIR/issue-33464.rs:7:5 @@ -20,7 +26,10 @@ error[E0432]: unresolved import `a_very_long_name` LL | use a_very_long_name::{el, el2}; | ^^^^^^^^^^^^^^^^ you might be missing crate `a_very_long_name` | - = help: consider adding `extern crate a_very_long_name` to use the `a_very_long_name` crate +help: consider importing the `a_very_long_name` crate + | +LL + extern crate a_very_long_name; + | error: aborting due to 3 previous errors diff --git a/tests/ui/imports/issue-36881.stderr b/tests/ui/imports/issue-36881.stderr index 3c136df83fe4c..004836e072c5e 100644 --- a/tests/ui/imports/issue-36881.stderr +++ b/tests/ui/imports/issue-36881.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `issue_36881_aux` LL | use issue_36881_aux::Foo; | ^^^^^^^^^^^^^^^ you might be missing crate `issue_36881_aux` | - = help: consider adding `extern crate issue_36881_aux` to use the `issue_36881_aux` crate +help: consider importing the `issue_36881_aux` crate + | +LL + extern crate issue_36881_aux; + | error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-37887.stderr b/tests/ui/imports/issue-37887.stderr index 36020707405f1..02c2c80326217 100644 --- a/tests/ui/imports/issue-37887.stderr +++ b/tests/ui/imports/issue-37887.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `test` LL | use test::*; | ^^^^ you might be missing crate `test` | - = help: consider adding `extern crate test` to use the `test` crate +help: consider importing the `test` crate + | +LL + extern crate test; + | error[E0658]: use of unstable library feature 'test' --> $DIR/issue-37887.rs:2:5 diff --git a/tests/ui/imports/issue-53269.stderr b/tests/ui/imports/issue-53269.stderr index 317b3c633a65f..d25d85bf46f02 100644 --- a/tests/ui/imports/issue-53269.stderr +++ b/tests/ui/imports/issue-53269.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `nonexistent_module` LL | use nonexistent_module::mac; | ^^^^^^^^^^^^^^^^^^ you might be missing crate `nonexistent_module` | - = help: consider adding `extern crate nonexistent_module` to use the `nonexistent_module` crate +help: consider importing the `nonexistent_module` crate + | +LL + extern crate nonexistent_module; + | error[E0659]: `mac` is ambiguous --> $DIR/issue-53269.rs:8:5 diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr index e9126e6575c0d..9c99b6a20de7c 100644 --- a/tests/ui/imports/issue-55457.stderr +++ b/tests/ui/imports/issue-55457.stderr @@ -13,7 +13,10 @@ error[E0432]: unresolved import `non_existent` LL | use non_existent::non_existent; | ^^^^^^^^^^^^ you might be missing crate `non_existent` | - = help: consider adding `extern crate non_existent` to use the `non_existent` crate +help: consider importing the `non_existent` crate + | +LL + extern crate non_existent; + | error: aborting due to 2 previous errors diff --git a/tests/ui/imports/issue-81413.stderr b/tests/ui/imports/issue-81413.stderr index 321b3695d2cc0..aa1246c1d2f50 100644 --- a/tests/ui/imports/issue-81413.stderr +++ b/tests/ui/imports/issue-81413.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `doesnt_exist` LL | pub use doesnt_exist::*; | ^^^^^^^^^^^^ you might be missing crate `doesnt_exist` | - = help: consider adding `extern crate doesnt_exist` to use the `doesnt_exist` crate +help: consider importing the `doesnt_exist` crate + | +LL + extern crate doesnt_exist; + | error: aborting due to 1 previous error diff --git a/tests/ui/imports/tool-mod-child.stderr b/tests/ui/imports/tool-mod-child.stderr index 764256e76f045..ec110ccd75dbc 100644 --- a/tests/ui/imports/tool-mod-child.stderr +++ b/tests/ui/imports/tool-mod-child.stderr @@ -4,7 +4,10 @@ error[E0433]: failed to resolve: you might be missing crate `clippy` LL | use clippy::a::b; | ^^^^^^ you might be missing crate `clippy` | - = help: consider adding `extern crate clippy` to use the `clippy` crate +help: consider importing the `clippy` crate + | +LL + extern crate clippy; + | error[E0432]: unresolved import `clippy` --> $DIR/tool-mod-child.rs:1:5 @@ -12,7 +15,10 @@ error[E0432]: unresolved import `clippy` LL | use clippy::a; | ^^^^^^ you might be missing crate `clippy` | - = help: consider adding `extern crate clippy` to use the `clippy` crate +help: consider importing the `clippy` crate + | +LL + extern crate clippy; + | error[E0433]: failed to resolve: you might be missing crate `rustdoc` --> $DIR/tool-mod-child.rs:5:5 @@ -20,7 +26,10 @@ error[E0433]: failed to resolve: you might be missing crate `rustdoc` LL | use rustdoc::a::b; | ^^^^^^^ you might be missing crate `rustdoc` | - = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate +help: consider importing the `rustdoc` crate + | +LL + extern crate rustdoc; + | error[E0432]: unresolved import `rustdoc` --> $DIR/tool-mod-child.rs:4:5 @@ -28,7 +37,10 @@ error[E0432]: unresolved import `rustdoc` LL | use rustdoc::a; | ^^^^^^^ you might be missing crate `rustdoc` | - = help: consider adding `extern crate rustdoc` to use the `rustdoc` crate +help: consider importing the `rustdoc` crate + | +LL + extern crate rustdoc; + | error: aborting due to 4 previous errors diff --git a/tests/ui/imports/unresolved-imports-used.stderr b/tests/ui/imports/unresolved-imports-used.stderr index 1cbc2356320f7..4bf02ff6e3a9f 100644 --- a/tests/ui/imports/unresolved-imports-used.stderr +++ b/tests/ui/imports/unresolved-imports-used.stderr @@ -16,7 +16,10 @@ error[E0432]: unresolved import `foo` LL | use foo::bar; | ^^^ you might be missing crate `foo` | - = help: consider adding `extern crate foo` to use the `foo` crate +help: consider importing the `foo` crate + | +LL + extern crate foo; + | error[E0432]: unresolved import `baz` --> $DIR/unresolved-imports-used.rs:12:5 @@ -24,7 +27,10 @@ error[E0432]: unresolved import `baz` LL | use baz::*; | ^^^ you might be missing crate `baz` | - = help: consider adding `extern crate baz` to use the `baz` crate +help: consider importing the `baz` crate + | +LL + extern crate baz; + | error[E0432]: unresolved import `foo2` --> $DIR/unresolved-imports-used.rs:14:5 @@ -32,7 +38,10 @@ error[E0432]: unresolved import `foo2` LL | use foo2::bar2; | ^^^^ you might be missing crate `foo2` | - = help: consider adding `extern crate foo2` to use the `foo2` crate +help: consider importing the `foo2` crate + | +LL + extern crate foo2; + | error[E0432]: unresolved import `baz2` --> $DIR/unresolved-imports-used.rs:15:5 @@ -40,7 +49,10 @@ error[E0432]: unresolved import `baz2` LL | use baz2::*; | ^^^^ you might be missing crate `baz2` | - = help: consider adding `extern crate baz2` to use the `baz2` crate +help: consider importing the `baz2` crate + | +LL + extern crate baz2; + | error[E0603]: function `quz` is private --> $DIR/unresolved-imports-used.rs:9:10 diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr index a647ca27f1c26..f23f855c9e8e8 100644 --- a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr @@ -15,7 +15,10 @@ error[E0432]: unresolved import `r#extern` LL | use extern::foo; | ^^^^^^ you might be missing crate `r#extern` | - = help: consider adding `extern crate r#extern` to use the `r#extern` crate +help: consider importing the `r#extern` crate + | +LL + extern crate r#extern; + | error: aborting due to 2 previous errors diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr index a48bb671d9f88..5deaffbdbf3f8 100644 --- a/tests/ui/privacy/restricted/test.stderr +++ b/tests/ui/privacy/restricted/test.stderr @@ -4,7 +4,10 @@ error[E0433]: failed to resolve: you might be missing crate `bad` LL | pub(in bad::path) mod m1 {} | ^^^ you might be missing crate `bad` | - = help: consider adding `extern crate bad` to use the `bad` crate +help: consider importing the `bad` crate + | +LL + extern crate bad; + | error[E0742]: visibilities can only be restricted to ancestor modules --> $DIR/test.rs:51:12 diff --git a/tests/ui/resolve/editions-crate-root-2015.stderr b/tests/ui/resolve/editions-crate-root-2015.stderr index 74fb7e6019ff5..7a842aca0fd27 100644 --- a/tests/ui/resolve/editions-crate-root-2015.stderr +++ b/tests/ui/resolve/editions-crate-root-2015.stderr @@ -4,7 +4,10 @@ error[E0433]: failed to resolve: you might be missing crate `nonexistant` LL | fn global_inner(_: ::nonexistant::Foo) { | ^^^^^^^^^^^ you might be missing crate `nonexistant` | - = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate +help: consider importing the `nonexistant` crate + | +LL + extern crate nonexistant; + | error[E0433]: failed to resolve: you might be missing crate `nonexistant` --> $DIR/editions-crate-root-2015.rs:7:30 @@ -12,7 +15,10 @@ error[E0433]: failed to resolve: you might be missing crate `nonexistant` LL | fn crate_inner(_: crate::nonexistant::Foo) { | ^^^^^^^^^^^ you might be missing crate `nonexistant` | - = help: consider adding `extern crate nonexistant` to use the `nonexistant` crate +help: consider importing the `nonexistant` crate + | +LL + extern crate nonexistant; + | error[E0412]: cannot find type `nonexistant` in the crate root --> $DIR/editions-crate-root-2015.rs:11:25 diff --git a/tests/ui/resolve/extern-prelude-fail.stderr b/tests/ui/resolve/extern-prelude-fail.stderr index 4c2d5abb78247..77c10f5f995bc 100644 --- a/tests/ui/resolve/extern-prelude-fail.stderr +++ b/tests/ui/resolve/extern-prelude-fail.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `extern_prelude` LL | use extern_prelude::S; | ^^^^^^^^^^^^^^ you might be missing crate `extern_prelude` | - = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate +help: consider importing the `extern_prelude` crate + | +LL + extern crate extern_prelude; + | error[E0433]: failed to resolve: you might be missing crate `extern_prelude` --> $DIR/extern-prelude-fail.rs:8:15 @@ -12,7 +15,10 @@ error[E0433]: failed to resolve: you might be missing crate `extern_prelude` LL | let s = ::extern_prelude::S; | ^^^^^^^^^^^^^^ you might be missing crate `extern_prelude` | - = help: consider adding `extern crate extern_prelude` to use the `extern_prelude` crate +help: consider importing the `extern_prelude` crate + | +LL + extern crate extern_prelude; + | error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr index ce0061a2b665e..bc7e0f0798177 100644 --- a/tests/ui/resolve/issue-82865.stderr +++ b/tests/ui/resolve/issue-82865.stderr @@ -4,7 +4,10 @@ error[E0433]: failed to resolve: you might be missing crate `x` LL | use x::y::z; | ^ you might be missing crate `x` | - = help: consider adding `extern crate x` to use the `x` crate +help: consider importing the `x` crate + | +LL + extern crate x; + | error[E0599]: no function or associated item named `z` found for struct `Box<_, _>` in the current scope --> $DIR/issue-82865.rs:8:10 diff --git a/tests/ui/resolve/resolve-bad-visibility.stderr b/tests/ui/resolve/resolve-bad-visibility.stderr index 8e4757354030e..281e5afb22302 100644 --- a/tests/ui/resolve/resolve-bad-visibility.stderr +++ b/tests/ui/resolve/resolve-bad-visibility.stderr @@ -22,7 +22,10 @@ error[E0433]: failed to resolve: you might be missing crate `nonexistent` LL | pub(in nonexistent) struct G; | ^^^^^^^^^^^ you might be missing crate `nonexistent` | - = help: consider adding `extern crate nonexistent` to use the `nonexistent` crate +help: consider importing the `nonexistent` crate + | +LL + extern crate nonexistent; + | error[E0433]: failed to resolve: you might be missing crate `too_soon` --> $DIR/resolve-bad-visibility.rs:8:8 @@ -30,7 +33,10 @@ error[E0433]: failed to resolve: you might be missing crate `too_soon` LL | pub(in too_soon) struct H; | ^^^^^^^^ you might be missing crate `too_soon` | - = help: consider adding `extern crate too_soon` to use the `too_soon` crate +help: consider importing the `too_soon` crate + | +LL + extern crate too_soon; + | error: aborting due to 5 previous errors diff --git a/tests/ui/underscore-imports/issue-110164.stderr b/tests/ui/underscore-imports/issue-110164.stderr index 240742996e12a..d8a4b6bbb7549 100644 --- a/tests/ui/underscore-imports/issue-110164.stderr +++ b/tests/ui/underscore-imports/issue-110164.stderr @@ -38,33 +38,25 @@ error[E0432]: unresolved import `_` --> $DIR/issue-110164.rs:8:5 | LL | use _::*; - | ^ you might be missing crate `_` - | - = help: consider adding `extern crate _` to use the `_` crate + | ^ `_` is not a valid crate or module name error[E0432]: unresolved import `_` --> $DIR/issue-110164.rs:5:5 | LL | use _::a; - | ^ you might be missing crate `_` - | - = help: consider adding `extern crate _` to use the `_` crate + | ^ `_` is not a valid crate or module name error[E0432]: unresolved import `_` --> $DIR/issue-110164.rs:13:9 | LL | use _::a; - | ^ you might be missing crate `_` - | - = help: consider adding `extern crate _` to use the `_` crate + | ^ `_` is not a valid crate or module name error[E0432]: unresolved import `_` --> $DIR/issue-110164.rs:16:9 | LL | use _::*; - | ^ you might be missing crate `_` - | - = help: consider adding `extern crate _` to use the `_` crate + | ^ `_` is not a valid crate or module name error: aborting due to 10 previous errors diff --git a/tests/ui/unresolved/unresolved-asterisk-imports.stderr b/tests/ui/unresolved/unresolved-asterisk-imports.stderr index 299ec699775e9..ed01f3fdbea41 100644 --- a/tests/ui/unresolved/unresolved-asterisk-imports.stderr +++ b/tests/ui/unresolved/unresolved-asterisk-imports.stderr @@ -4,7 +4,10 @@ error[E0432]: unresolved import `not_existing_crate` LL | use not_existing_crate::*; | ^^^^^^^^^^^^^^^^^^ you might be missing crate `not_existing_crate` | - = help: consider adding `extern crate not_existing_crate` to use the `not_existing_crate` crate +help: consider importing the `not_existing_crate` crate + | +LL + extern crate not_existing_crate; + | error: aborting due to 1 previous error diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs index e8f3b323e3375..ee520d65e6f4a 100644 --- a/tests/ui/unresolved/unresolved-import.rs +++ b/tests/ui/unresolved/unresolved-import.rs @@ -1,7 +1,8 @@ use foo::bar; //~^ ERROR unresolved import `foo` [E0432] //~| NOTE you might be missing crate `foo` -//~| HELP consider adding `extern crate foo` to use the `foo` crate +//~| HELP consider importing the `foo` crate +//~| SUGGESTION extern crate foo; use bar::Baz as x; //~^ ERROR unresolved import `bar::Baz` [E0432] diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr index 7b03717c827ce..a1ff2f19eb640 100644 --- a/tests/ui/unresolved/unresolved-import.stderr +++ b/tests/ui/unresolved/unresolved-import.stderr @@ -4,10 +4,13 @@ error[E0432]: unresolved import `foo` LL | use foo::bar; | ^^^ you might be missing crate `foo` | - = help: consider adding `extern crate foo` to use the `foo` crate +help: consider importing the `foo` crate + | +LL + extern crate foo; + | error[E0432]: unresolved import `bar::Baz` - --> $DIR/unresolved-import.rs:6:5 + --> $DIR/unresolved-import.rs:7:5 | LL | use bar::Baz as x; | ^^^^^---^^^^^ @@ -16,7 +19,7 @@ LL | use bar::Baz as x; | no `Baz` in `bar` error[E0432]: unresolved import `food::baz` - --> $DIR/unresolved-import.rs:12:5 + --> $DIR/unresolved-import.rs:13:5 | LL | use food::baz; | ^^^^^^--- @@ -25,7 +28,7 @@ LL | use food::baz; | no `baz` in `food` error[E0432]: unresolved import `food::beens` - --> $DIR/unresolved-import.rs:18:12 + --> $DIR/unresolved-import.rs:19:12 | LL | use food::{beens as Foo}; | -----^^^^^^^ @@ -34,13 +37,13 @@ LL | use food::{beens as Foo}; | help: a similar name exists in the module: `beans` error[E0432]: unresolved import `MyEnum` - --> $DIR/unresolved-import.rs:43:9 + --> $DIR/unresolved-import.rs:44:9 | LL | use MyEnum::*; | ^^^^^^ help: a similar path exists: `self::MyEnum` error[E0432]: unresolved import `Enum` - --> $DIR/unresolved-import.rs:54:9 + --> $DIR/unresolved-import.rs:55:9 | LL | use Enum::*; | ^^^^ help: a similar path exists: `self::Enum` From 51b5bb179884d71d4758e05c7913c26f3d03385c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 30 Jul 2024 00:18:38 +0000 Subject: [PATCH 263/489] Enforce sort order --- compiler/rustc_errors/src/emitter.rs | 64 ++++++++++++++-------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 18e077ed8a22a..8b0a3888eb78f 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2561,41 +2561,42 @@ fn num_decimal_digits(num: usize) -> usize { // Keep the following list in sync with `rustc_span::char_width`. // ATTENTION: keep lexicografically sorted so that the binary search will work const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ + // tidy-alphabetical-start // In terminals without Unicode support the following will be garbled, but in *all* terminals // the underlying codepoint will be as well. We could gate this replacement behind a "unicode // support" gate. ('\0', "␀"), - ('\u{1}', "␁"), - ('\u{2}', "␂"), - ('\u{3}', "␃"), - ('\u{4}', "␄"), - ('\u{5}', "␅"), - ('\u{6}', "␆"), - ('\u{7}', "␇"), - ('\u{8}', "␈"), - ('\t', " "), // We do our own tab replacement - ('\u{b}', "␋"), - ('\u{c}', "␌"), - ('\r', "␍"), - ('\u{e}', "␎"), - ('\u{f}', "␏"), - ('\u{10}', "␐"), - ('\u{11}', "␑"), - ('\u{12}', "␒"), - ('\u{13}', "␓"), - ('\u{14}', "␔"), - ('\u{15}', "␕"), - ('\u{16}', "␖"), - ('\u{17}', "␗"), - ('\u{18}', "␘"), - ('\u{19}', "␙"), - ('\u{1a}', "␚"), - ('\u{1b}', "␛"), - ('\u{1c}', "␜"), - ('\u{1d}', "␝"), - ('\u{1e}', "␞"), - ('\u{1f}', "␟"), - ('\u{7f}', "␡"), + ('\u{0001}', "␁"), + ('\u{0002}', "␂"), + ('\u{0003}', "␃"), + ('\u{0004}', "␄"), + ('\u{0005}', "␅"), + ('\u{0006}', "␆"), + ('\u{0007}', "␇"), + ('\u{0008}', "␈"), + ('\u{0009}', " "), // We do our own tab replacement + ('\u{000b}', "␋"), + ('\u{000c}', "␌"), + ('\u{000d}', "␍"), + ('\u{000e}', "␎"), + ('\u{000f}', "␏"), + ('\u{0010}', "␐"), + ('\u{0011}', "␑"), + ('\u{0012}', "␒"), + ('\u{0013}', "␓"), + ('\u{0014}', "␔"), + ('\u{0015}', "␕"), + ('\u{0016}', "␖"), + ('\u{0017}', "␗"), + ('\u{0018}', "␘"), + ('\u{0019}', "␙"), + ('\u{001a}', "␚"), + ('\u{001b}', "␛"), + ('\u{001c}', "␜"), + ('\u{001d}', "␝"), + ('\u{001e}', "␞"), + ('\u{001f}', "␟"), + ('\u{007f}', "␡"), ('\u{200d}', ""), // Replace ZWJ for consistent terminal output of grapheme clusters. ('\u{202a}', "�"), // The following unicode text flow control characters are inconsistently ('\u{202b}', "�"), // supported across CLIs and can cause confusion due to the bytes on disk @@ -2606,6 +2607,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\u{2067}', "�"), ('\u{2068}', "�"), ('\u{2069}', "�"), + // tidy-alphabetical-end ]; fn normalize_whitespace(s: &str) -> String { From e4076e34f8215cff65c4deaff4ba7fbda20d2a7f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 29 Jul 2024 21:21:15 -0400 Subject: [PATCH 264/489] Mark Parser::eat/check methods as must_use --- .../rustc_builtin_macros/src/pattern_type.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 5 +++-- compiler/rustc_parse/src/parser/generics.rs | 3 ++- compiler/rustc_parse/src/parser/item.rs | 7 ++++--- compiler/rustc_parse/src/parser/mod.rs | 19 +++++++++++++++---- compiler/rustc_parse/src/parser/path.rs | 3 ++- tests/crashes/123809.rs | 2 +- tests/ui/type/pattern_types/missing-is.rs | 8 ++++++++ tests/ui/type/pattern_types/missing-is.stderr | 8 ++++++++ 9 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 tests/ui/type/pattern_types/missing-is.rs create mode 100644 tests/ui/type/pattern_types/missing-is.stderr diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index 87187125541b2..869d203f68eba 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -24,7 +24,7 @@ fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P let mut parser = cx.new_parser_from_tts(stream); let ty = parser.parse_ty()?; - parser.eat_keyword(sym::is); + parser.expect_keyword(sym::is)?; let pat = parser.parse_pat_no_top_alt(None, None)?; Ok((ty, pat)) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a242dc5cd582d..a4d9d97045d2a 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3153,7 +3153,8 @@ impl<'a> Parser<'a> { if !require_comma { arm_body = Some(expr); - this.eat(&token::Comma); + // Eat a comma if it exists, though. + let _ = this.eat(&token::Comma); Ok(Recovered::No) } else if let Some((span, guar)) = this.parse_arm_body_missing_braces(&expr, arrow_span) @@ -3654,7 +3655,7 @@ impl<'a> Parser<'a> { fields.push(f); } self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore); - self.eat(&token::Comma); + let _ = self.eat(&token::Comma); } } } diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index a67e3d05551db..9124c15707de5 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -178,7 +178,8 @@ impl<'a> Parser<'a> { span: this.prev_token.span, }); - this.eat(&token::Comma); + // Eat a trailing comma, if it exists. + let _ = this.eat(&token::Comma); } let param = if this.check_lifetime() { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 68da055494528..baa5eb2df635d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1192,13 +1192,14 @@ impl<'a> Parser<'a> { mut safety: Safety, ) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? + // FIXME: This recovery should be tested better. if safety == Safety::Default && self.token.is_keyword(kw::Unsafe) && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace)) { self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err().emit(); safety = Safety::Unsafe(self.token.span); - self.eat_keyword(kw::Unsafe); + let _ = self.eat_keyword(kw::Unsafe); } let module = ast::ForeignMod { safety, @@ -1759,7 +1760,7 @@ impl<'a> Parser<'a> { } } } - self.eat(&token::CloseDelim(Delimiter::Brace)); + self.expect(&token::CloseDelim(Delimiter::Brace))?; } else { let token_str = super::token_descr(&self.token); let where_str = if parsed_where { "" } else { "`where`, or " }; @@ -1902,7 +1903,7 @@ impl<'a> Parser<'a> { if let Some(_guar) = guar { // Handle a case like `Vec>,` where we can continue parsing fields // after the comma - self.eat(&token::Comma); + let _ = self.eat(&token::Comma); // `check_trailing_angle_brackets` already emitted a nicer error, as // proven by the presence of `_guar`. We can continue parsing. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 26ee5bfdee42c..e01f605722b72 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -547,6 +547,7 @@ impl<'a> Parser<'a> { } #[inline] + #[must_use] fn check_noexpect(&self, tok: &TokenKind) -> bool { self.token == *tok } @@ -556,6 +557,7 @@ impl<'a> Parser<'a> { /// the main purpose of this function is to reduce the cluttering of the suggestions list /// which using the normal eat method could introduce in some cases. #[inline] + #[must_use] fn eat_noexpect(&mut self, tok: &TokenKind) -> bool { let is_present = self.check_noexpect(tok); if is_present { @@ -566,6 +568,7 @@ impl<'a> Parser<'a> { /// Consumes a token 'tok' if it exists. Returns whether the given token was present. #[inline] + #[must_use] pub fn eat(&mut self, tok: &TokenKind) -> bool { let is_present = self.check(tok); if is_present { @@ -577,12 +580,14 @@ impl<'a> Parser<'a> { /// If the next token is the given keyword, returns `true` without eating it. /// An expectation is also added for diagnostics purposes. #[inline] + #[must_use] fn check_keyword(&mut self, kw: Symbol) -> bool { self.expected_tokens.push(TokenType::Keyword(kw)); self.token.is_keyword(kw) } #[inline] + #[must_use] fn check_keyword_case(&mut self, kw: Symbol, case: Case) -> bool { if self.check_keyword(kw) { return true; @@ -602,6 +607,7 @@ impl<'a> Parser<'a> { /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes. // Public for rustc_builtin_macros and rustfmt usage. #[inline] + #[must_use] pub fn eat_keyword(&mut self, kw: Symbol) -> bool { if self.check_keyword(kw) { self.bump(); @@ -615,6 +621,7 @@ impl<'a> Parser<'a> { /// If the case differs (and is ignored) an error is issued. /// This is useful for recovery. #[inline] + #[must_use] fn eat_keyword_case(&mut self, kw: Symbol, case: Case) -> bool { if self.eat_keyword(kw) { return true; @@ -636,6 +643,7 @@ impl<'a> Parser<'a> { /// Otherwise, returns `false`. No expectation is added. // Public for rustc_builtin_macros usage. #[inline] + #[must_use] pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool { if self.token.is_keyword(kw) { self.bump(); @@ -648,7 +656,7 @@ impl<'a> Parser<'a> { /// If the given word is not a keyword, signals an error. /// If the next token is not the given word, signals an error. /// Otherwise, eats it. - fn expect_keyword(&mut self, kw: Symbol) -> PResult<'a, ()> { + pub fn expect_keyword(&mut self, kw: Symbol) -> PResult<'a, ()> { if !self.eat_keyword(kw) { self.unexpected() } else { Ok(()) } } @@ -1025,8 +1033,11 @@ impl<'a> Parser<'a> { f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, (ThinVec, Trailing)> { let (val, trailing, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; - if matches!(recovered, Recovered::No) { - self.eat(ket); + if matches!(recovered, Recovered::No) && !self.eat(ket) { + self.dcx().span_delayed_bug( + self.token.span, + "recovered but `parse_seq_to_before_end` did not give us the ket token", + ); } Ok((val, trailing)) } @@ -1250,7 +1261,7 @@ impl<'a> Parser<'a> { if pat { self.psess.gated_spans.gate(sym::inline_const_pat, span); } - self.eat_keyword(kw::Const); + self.expect_keyword(kw::Const)?; let (attrs, blk) = self.parse_inner_attrs_and_block()?; let anon_const = AnonConst { id: DUMMY_NODE_ID, diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index c5111226d3783..70d2c98d4f1bd 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -313,7 +313,8 @@ impl<'a> Parser<'a> { } // Generic arguments are found - `<`, `(`, `::<` or `::(`. - self.eat(&token::PathSep); + // First, eat `::` if it exists. + let _ = self.eat(&token::PathSep); let lo = self.token.span; let args = if self.eat_lt() { // `<'a, T, A = U>` diff --git a/tests/crashes/123809.rs b/tests/crashes/123809.rs index c7a633aed018c..75abe6dc0cd83 100644 --- a/tests/crashes/123809.rs +++ b/tests/crashes/123809.rs @@ -1,4 +1,4 @@ //@ known-bug: #123809 -type Positive = std::pat::pattern_type!(std::pat:: is 0..); +type Positive = std::pat::pattern_type!(std::pat is 0..); pub fn main() {} diff --git a/tests/ui/type/pattern_types/missing-is.rs b/tests/ui/type/pattern_types/missing-is.rs new file mode 100644 index 0000000000000..2fbcc1908efcb --- /dev/null +++ b/tests/ui/type/pattern_types/missing-is.rs @@ -0,0 +1,8 @@ +#![feature(core_pattern_type, core_pattern_types)] + +use std::pat::pattern_type; + +fn main() { + let x: pattern_type!(i32 0..1); + //~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `is`, found `0` +} diff --git a/tests/ui/type/pattern_types/missing-is.stderr b/tests/ui/type/pattern_types/missing-is.stderr new file mode 100644 index 0000000000000..8ed654fe9071a --- /dev/null +++ b/tests/ui/type/pattern_types/missing-is.stderr @@ -0,0 +1,8 @@ +error: expected one of `!`, `(`, `+`, `::`, `<`, or `is`, found `0` + --> $DIR/missing-is.rs:6:30 + | +LL | let x: pattern_type!(i32 0..1); + | ^ expected one of `!`, `(`, `+`, `::`, `<`, or `is` + +error: aborting due to 1 previous error + From d8bc8761a5bb8456c0b7940434b3b3b4f0ed035c Mon Sep 17 00:00:00 2001 From: carbotaniuman <41451839+carbotaniuman@users.noreply.github.com> Date: Tue, 2 Jul 2024 23:52:16 -0500 Subject: [PATCH 265/489] Deny unsafe on more builtin attributes --- .../src/cfg_accessible.rs | 2 + compiler/rustc_builtin_macros/src/derive.rs | 2 + compiler/rustc_builtin_macros/src/util.rs | 2 + compiler/rustc_expand/src/config.rs | 16 +- compiler/rustc_parse/src/validate_attr.rs | 148 +++++++++++------- .../unsafe/derive-unsafe-attributes.rs | 3 + .../unsafe/derive-unsafe-attributes.stderr | 10 +- .../unsafe/extraneous-unsafe-attributes.rs | 31 ++++ .../extraneous-unsafe-attributes.stderr | 66 ++++++++ .../unsafe/proc-unsafe-attributes.rs | 27 ++++ .../unsafe/proc-unsafe-attributes.stderr | 58 +++++++ 11 files changed, 307 insertions(+), 58 deletions(-) create mode 100644 tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs create mode 100644 tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr create mode 100644 tests/ui/attributes/unsafe/proc-unsafe-attributes.rs create mode 100644 tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index 2d4a93776bb66..006b6aa823fbf 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -47,11 +47,13 @@ impl MultiItemModifier for Expander { ) -> ExpandResult, Annotatable> { let template = AttributeTemplate { list: Some("path"), ..Default::default() }; validate_attr::check_builtin_meta_item( + &ecx.ecfg.features, &ecx.sess.psess, meta_item, ast::AttrStyle::Outer, sym::cfg_accessible, template, + true, ); let Some(path) = validate_input(ecx, meta_item) else { diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 03970a48638a0..c540ff4e1de82 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -38,11 +38,13 @@ impl MultiItemModifier for Expander { let template = AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; validate_attr::check_builtin_meta_item( + features, &sess.psess, meta_item, ast::AttrStyle::Outer, sym::derive, template, + true, ); let mut resolutions = match &meta_item.kind { diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 65b50736c5555..73cc8ff547d51 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -17,11 +17,13 @@ pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaI // All the built-in macro attributes are "words" at the moment. let template = AttributeTemplate { word: true, ..Default::default() }; validate_attr::check_builtin_meta_item( + &ecx.ecfg.features, &ecx.sess.psess, meta_item, AttrStyle::Outer, name, template, + true, ); } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 756290be0a813..d46ec7a9ac0fe 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -8,7 +8,7 @@ use rustc_ast::tokenstream::{ use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, NodeId}; use rustc_attr as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; -use rustc_feature::{Features, ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES}; +use rustc_feature::{AttributeSafety, Features, ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES}; use rustc_lint_defs::BuiltinLintDiag; use rustc_parse::validate_attr; use rustc_session::parse::feature_err; @@ -263,6 +263,13 @@ impl<'a> StripUnconfigured<'a> { /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect. pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec { + validate_attr::check_attribute_safety( + self.features.unwrap_or(&Features::default()), + &self.sess.psess, + AttributeSafety::Normal, + &cfg_attr, + ); + let Some((cfg_predicate, expanded_attrs)) = rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess) else { @@ -385,6 +392,13 @@ impl<'a> StripUnconfigured<'a> { return (true, None); } }; + + validate_attr::deny_builtin_meta_unsafety( + self.features.unwrap_or(&Features::default()), + &self.sess.psess, + &meta_item, + ); + ( parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| { attr::cfg_matches(meta_item, &self.sess, self.lint_node_id, self.features) diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 356bc9a410d6b..af2db17184086 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -26,76 +26,35 @@ pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) { let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); let attr_item = attr.get_normal_item(); - let is_unsafe_attr = attr_info.is_some_and(|attr| attr.safety == AttributeSafety::Unsafe); - - if features.unsafe_attributes { - if is_unsafe_attr { - if let ast::Safety::Default = attr_item.unsafety { - let path_span = attr_item.path.span; - - // If the `attr_item`'s span is not from a macro, then just suggest - // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the - // `unsafe(`, `)` right after and right before the opening and closing - // square bracket respectively. - let diag_span = if attr_item.span().can_be_used_for_suggestions() { - attr_item.span() - } else { - attr.span - .with_lo(attr.span.lo() + BytePos(2)) - .with_hi(attr.span.hi() - BytePos(1)) - }; - - if attr.span.at_least_rust_2024() { - psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe { - span: path_span, - suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { - left: diag_span.shrink_to_lo(), - right: diag_span.shrink_to_hi(), - }, - }); - } else { - psess.buffer_lint( - UNSAFE_ATTR_OUTSIDE_UNSAFE, - path_span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::UnsafeAttrOutsideUnsafe { - attribute_name_span: path_span, - sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), - }, - ); - } - } - } else { - if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { - psess.dcx().emit_err(errors::InvalidAttrUnsafe { - span: unsafe_span, - name: attr_item.path.clone(), - }); - } - } - } + // All non-builtin attributes are considered safe + let safety = attr_info.map(|x| x.safety).unwrap_or(AttributeSafety::Normal); + check_attribute_safety(features, psess, safety, attr); // Check input tokens for built-in and key-value attributes. match attr_info { // `rustc_dummy` doesn't have any restrictions specific to built-in attributes. Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => { match parse_meta(psess, attr) { - Ok(meta) => check_builtin_meta_item(psess, &meta, attr.style, *name, *template), + // Don't check safety again, we just did that + Ok(meta) => check_builtin_meta_item( + features, psess, &meta, attr.style, *name, *template, false, + ), Err(err) => { err.emit(); } } } - _ if let AttrArgs::Eq(..) = attr_item.args => { - // All key-value attributes are restricted to meta-item syntax. - match parse_meta(psess, attr) { - Ok(_) => {} - Err(err) => { - err.emit(); + _ => { + if let AttrArgs::Eq(..) = attr_item.args { + // All key-value attributes are restricted to meta-item syntax. + match parse_meta(psess, attr) { + Ok(_) => {} + Err(err) => { + err.emit(); + } } } } - _ => {} } } @@ -198,12 +157,85 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte } } +pub fn check_attribute_safety( + features: &Features, + psess: &ParseSess, + safety: AttributeSafety, + attr: &Attribute, +) { + if features.unsafe_attributes { + let attr_item = attr.get_normal_item(); + + if safety == AttributeSafety::Unsafe { + if let ast::Safety::Default = attr_item.unsafety { + let path_span = attr_item.path.span; + + // If the `attr_item`'s span is not from a macro, then just suggest + // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the + // `unsafe(`, `)` right after and right before the opening and closing + // square bracket respectively. + let diag_span = if attr_item.span().can_be_used_for_suggestions() { + attr_item.span() + } else { + attr.span + .with_lo(attr.span.lo() + BytePos(2)) + .with_hi(attr.span.hi() - BytePos(1)) + }; + + if attr.span.at_least_rust_2024() { + psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe { + span: path_span, + suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { + left: diag_span.shrink_to_lo(), + right: diag_span.shrink_to_hi(), + }, + }); + } else { + psess.buffer_lint( + UNSAFE_ATTR_OUTSIDE_UNSAFE, + path_span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::UnsafeAttrOutsideUnsafe { + attribute_name_span: path_span, + sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), + }, + ); + } + } + } else { + if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { + psess.dcx().emit_err(errors::InvalidAttrUnsafe { + span: unsafe_span, + name: attr_item.path.clone(), + }); + } + } + } +} + +// Called by `check_builtin_meta_item` and code that manually denies +// `unsafe(...)` in `cfg` +pub fn deny_builtin_meta_unsafety(features: &Features, psess: &ParseSess, meta: &MetaItem) { + // This only supports denying unsafety right now - making builtin attributes + // support unsafety will requite us to thread the actual `Attribute` through + // for the nice diagnostics. + if features.unsafe_attributes { + if let Safety::Unsafe(unsafe_span) = meta.unsafety { + psess + .dcx() + .emit_err(errors::InvalidAttrUnsafe { span: unsafe_span, name: meta.path.clone() }); + } + } +} + pub fn check_builtin_meta_item( + features: &Features, psess: &ParseSess, meta: &MetaItem, style: ast::AttrStyle, name: Symbol, template: AttributeTemplate, + deny_unsafety: bool, ) { // Some special attributes like `cfg` must be checked // before the generic check, so we skip them here. @@ -212,6 +244,10 @@ pub fn check_builtin_meta_item( if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) { emit_malformed_attribute(psess, style, meta.span, name, template); } + + if deny_unsafety { + deny_builtin_meta_unsafety(features, psess, meta); + } } fn emit_malformed_attribute( diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs index 774ce86c0960c..7f0d6a0cf8b91 100644 --- a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs @@ -3,4 +3,7 @@ #[derive(unsafe(Debug))] //~ ERROR: traits in `#[derive(...)]` don't accept `unsafe(...)` struct Foo; +#[unsafe(derive(Debug))] //~ ERROR: is not an unsafe attribute +struct Bar; + fn main() {} diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr index fc0daf16790a8..22010c61b5f52 100644 --- a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr @@ -4,5 +4,13 @@ error: traits in `#[derive(...)]` don't accept `unsafe(...)` LL | #[derive(unsafe(Debug))] | ^^^^^^ -error: aborting due to 1 previous error +error: `derive` is not an unsafe attribute + --> $DIR/derive-unsafe-attributes.rs:6:3 + | +LL | #[unsafe(derive(Debug))] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: aborting due to 2 previous errors diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs new file mode 100644 index 0000000000000..0181add843bcd --- /dev/null +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.rs @@ -0,0 +1,31 @@ +//@ edition: 2024 +//@ compile-flags: -Zunstable-options +#![feature(unsafe_attributes)] + +#[unsafe(cfg(any()))] //~ ERROR: is not an unsafe attribute +fn a() {} + +#[unsafe(cfg_attr(any(), allow(dead_code)))] //~ ERROR: is not an unsafe attribute +fn b() {} + +#[unsafe(test)] //~ ERROR: is not an unsafe attribute +fn aa() {} + +#[unsafe(ignore = "test")] //~ ERROR: is not an unsafe attribute +fn bb() {} + +#[unsafe(should_panic(expected = "test"))] //~ ERROR: is not an unsafe attribute +fn cc() {} + +#[unsafe(macro_use)] //~ ERROR: is not an unsafe attribute +mod inner { + #[unsafe(macro_export)] //~ ERROR: is not an unsafe attribute + macro_rules! m { + () => {}; + } +} + +#[unsafe(used)] //~ ERROR: is not an unsafe attribute +static FOO: usize = 0; + +fn main() {} diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr new file mode 100644 index 0000000000000..a2e56087d1615 --- /dev/null +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr @@ -0,0 +1,66 @@ +error: `cfg` is not an unsafe attribute + --> $DIR/extraneous-unsafe-attributes.rs:5:3 + | +LL | #[unsafe(cfg(any()))] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `cfg_attr` is not an unsafe attribute + --> $DIR/extraneous-unsafe-attributes.rs:8:3 + | +LL | #[unsafe(cfg_attr(any(), allow(dead_code)))] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `test` is not an unsafe attribute + --> $DIR/extraneous-unsafe-attributes.rs:11:3 + | +LL | #[unsafe(test)] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `ignore` is not an unsafe attribute + --> $DIR/extraneous-unsafe-attributes.rs:14:3 + | +LL | #[unsafe(ignore = "test")] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `should_panic` is not an unsafe attribute + --> $DIR/extraneous-unsafe-attributes.rs:17:3 + | +LL | #[unsafe(should_panic(expected = "test"))] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `macro_use` is not an unsafe attribute + --> $DIR/extraneous-unsafe-attributes.rs:20:3 + | +LL | #[unsafe(macro_use)] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `macro_export` is not an unsafe attribute + --> $DIR/extraneous-unsafe-attributes.rs:22:7 + | +LL | #[unsafe(macro_export)] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `used` is not an unsafe attribute + --> $DIR/extraneous-unsafe-attributes.rs:28:3 + | +LL | #[unsafe(used)] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: aborting due to 8 previous errors + diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs new file mode 100644 index 0000000000000..caf6c6dc8ffde --- /dev/null +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs @@ -0,0 +1,27 @@ +#![feature(unsafe_attributes)] + +#[unsafe(proc_macro)] +//~^ ERROR: is not an unsafe attribute +//~| ERROR attribute is only usable with crates of the `proc-macro` crate type +pub fn a() {} + + +#[unsafe(proc_macro_derive(Foo))] +//~^ ERROR: is not an unsafe attribute +//~| ERROR attribute is only usable with crates of the `proc-macro` crate type +pub fn b() {} + +#[proc_macro_derive(unsafe(Foo))] +//~^ ERROR attribute is only usable with crates of the `proc-macro` crate type +pub fn c() {} + +#[unsafe(proc_macro_attribute)] +//~^ ERROR: is not an unsafe attribute +//~| ERROR attribute is only usable with crates of the `proc-macro` crate type +pub fn d() {} + +#[unsafe(allow(dead_code))] +//~^ ERROR: is not an unsafe attribute +pub fn e() {} + +fn main() {} diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr new file mode 100644 index 0000000000000..346d2c2e9ae69 --- /dev/null +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -0,0 +1,58 @@ +error: `proc_macro` is not an unsafe attribute + --> $DIR/proc-unsafe-attributes.rs:3:3 + | +LL | #[unsafe(proc_macro)] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `proc_macro_derive` is not an unsafe attribute + --> $DIR/proc-unsafe-attributes.rs:9:3 + | +LL | #[unsafe(proc_macro_derive(Foo))] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `proc_macro_attribute` is not an unsafe attribute + --> $DIR/proc-unsafe-attributes.rs:18:3 + | +LL | #[unsafe(proc_macro_attribute)] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: `allow` is not an unsafe attribute + --> $DIR/proc-unsafe-attributes.rs:23:3 + | +LL | #[unsafe(allow(dead_code))] + | ^^^^^^ + | + = note: extraneous unsafe is not allowed in attributes + +error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/proc-unsafe-attributes.rs:3:1 + | +LL | #[unsafe(proc_macro)] + | ^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/proc-unsafe-attributes.rs:9:1 + | +LL | #[unsafe(proc_macro_derive(Foo))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/proc-unsafe-attributes.rs:14:1 + | +LL | #[proc_macro_derive(unsafe(Foo))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/proc-unsafe-attributes.rs:18:1 + | +LL | #[unsafe(proc_macro_attribute)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors + From fc584d7da3ab1fa7ae7cb0a7ed954e7bbec48e11 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 30 Jul 2024 05:03:59 +0000 Subject: [PATCH 266/489] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 58ec4e10856df..105457c3cd3b4 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -a526d7ce45fd2284e0e7c7556ccba2425b9d25e5 +dba8e2d2c2890a8b9e88cbf4855ac5711337946c From dadf3d2a970999ee0d7a0f97045acc70919d751e Mon Sep 17 00:00:00 2001 From: aissata Date: Tue, 30 Jul 2024 08:16:47 +0200 Subject: [PATCH 267/489] the output in stderr expects panic-unwind --- tests/ui/backtrace/synchronized-panic-handler.rs | 1 + tests/ui/backtrace/synchronized-panic-handler.run.stderr | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/ui/backtrace/synchronized-panic-handler.rs b/tests/ui/backtrace/synchronized-panic-handler.rs index 00eb249da1dd5..29431ae3c458a 100644 --- a/tests/ui/backtrace/synchronized-panic-handler.rs +++ b/tests/ui/backtrace/synchronized-panic-handler.rs @@ -3,6 +3,7 @@ //@ edition:2021 //@ exec-env:RUST_BACKTRACE=0 //@ needs-threads +//@ needs-unwind use std::thread; const PANIC_MESSAGE: &str = "oops oh no woe is me"; diff --git a/tests/ui/backtrace/synchronized-panic-handler.run.stderr b/tests/ui/backtrace/synchronized-panic-handler.run.stderr index b7c815a94c868..8a06d00ea5998 100644 --- a/tests/ui/backtrace/synchronized-panic-handler.run.stderr +++ b/tests/ui/backtrace/synchronized-panic-handler.run.stderr @@ -1,5 +1,5 @@ -thread '' panicked at $DIR/synchronized-panic-handler.rs:10:5: +thread '' panicked at $DIR/synchronized-panic-handler.rs:11:5: oops oh no woe is me note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread '' panicked at $DIR/synchronized-panic-handler.rs:10:5: +thread '' panicked at $DIR/synchronized-panic-handler.rs:11:5: oops oh no woe is me From 90e1a58cc6ead86b3caab59e3a46761c89374e50 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 30 Jul 2024 08:19:32 +0200 Subject: [PATCH 268/489] fix: Fix builtin includes rejecting raw string literals --- .../src/macro_expansion_tests/builtin_fn_macro.rs | 4 ++-- .../crates/hir-expand/src/builtin/fn_macro.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index 487ab537cdac3..b6dbba12cd6d6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -439,7 +439,7 @@ macro_rules! include_bytes { ($file:expr,) => {{ /* compiler built-in */ }}; } -fn main() { include_bytes("foo"); } +fn main() { include_bytes("foo");include_bytes(r"foo"); } "#, expect![[r##" #[rustc_builtin_macro] @@ -448,7 +448,7 @@ macro_rules! include_bytes { ($file:expr,) => {{ /* compiler built-in */ }}; } -fn main() { include_bytes("foo"); } +fn main() { include_bytes("foo");include_bytes(r"foo"); } "##]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index 391b891ad6cdb..7903ac075be4e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -714,6 +714,12 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> { kind: tt::LitKind::Str, suffix: _, })) => Ok((unescape_str(text), *span)), + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + symbol: text, + span, + kind: tt::LitKind::StrRaw(_), + suffix: _, + })) => Ok((text.clone(), *span)), // FIXME: We wrap expression fragments in parentheses which can break this expectation // here // Remove this once we handle none delims correctly @@ -725,6 +731,12 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> { kind: tt::LitKind::Str, suffix: _, })) => Some((unescape_str(text), *span)), + tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { + symbol: text, + span, + kind: tt::LitKind::StrRaw(_), + suffix: _, + })) => Some((text.clone(), *span)), _ => None, }) } From 13c095aaf1b6008d8e4a032008b9fcd6e79a0df5 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 30 Jul 2024 08:23:17 +0200 Subject: [PATCH 269/489] fix: Fix incorrect retrying of inlay hint requests --- .../rust-analyzer/crates/rust-analyzer/src/main_loop.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 58d73611c63e3..9c820749ece6d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -1053,11 +1053,10 @@ impl GlobalState { .on::(handlers::handle_goto_declaration) .on::(handlers::handle_goto_implementation) .on::(handlers::handle_goto_type_definition) - // FIXME: This should not be tried as it contains offsets that can get outdated! - .on::(handlers::handle_inlay_hints) - .on::(handlers::handle_inlay_hints_resolve) + .on::(handlers::handle_inlay_hints) + .on::(handlers::handle_inlay_hints_resolve) .on::(handlers::handle_code_lens) - .on::(handlers::handle_code_lens_resolve) + .on::(handlers::handle_code_lens_resolve) .on::(handlers::handle_prepare_rename) .on::(handlers::handle_rename) .on::(handlers::handle_references) From 579ab05e76f1434f3074195c7291895f1257bc97 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 9 Jul 2024 09:34:59 +0200 Subject: [PATCH 270/489] Update to LLVM 19 --- .gitmodules | 2 +- src/llvm-project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 9ad207a0d5226..b5250d493864e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -33,7 +33,7 @@ [submodule "src/llvm-project"] path = src/llvm-project url = https://github.com/rust-lang/llvm-project.git - branch = rustc/18.1-2024-05-19 + branch = rustc/19.1-2024-07-30 shallow = true [submodule "src/doc/embedded-book"] path = src/doc/embedded-book diff --git a/src/llvm-project b/src/llvm-project index c54cff0e6e4d1..57ae1a3474057 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit c54cff0e6e4d1a0d0a2df7c1ce3d96cdd554763e +Subproject commit 57ae1a3474057fead2c438928ed368b3740bf0ec From 00bfd702dc8c3b760b4f965fd059a5f1db8bb2b1 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Mon, 17 Jun 2024 09:35:38 +0000 Subject: [PATCH 271/489] Disable MC/DC tests on LLVM 19 Disable the tests and generate an error if MC/DC is used on LLVM 19. The support will be ported separately, as it is substantially different on LLVM 19, and there are no plans to support both versions. --- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 2 +- tests/coverage/mcdc/condition-limit.rs | 1 + tests/coverage/mcdc/if.rs | 1 + tests/coverage/mcdc/inlined_expressions.rs | 1 + tests/coverage/mcdc/nested_if.rs | 1 + tests/coverage/mcdc/non_control_flow.rs | 1 + 6 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 4cdd8af1008c0..2ff7335a0fc81 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1555,7 +1555,7 @@ LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) { extern "C" LLVMValueRef LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRef M) { -#if LLVM_VERSION_GE(18, 0) +#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0) return wrap(llvm::Intrinsic::getDeclaration( unwrap(M), llvm::Intrinsic::instrprof_mcdc_condbitmap_update)); #else diff --git a/tests/coverage/mcdc/condition-limit.rs b/tests/coverage/mcdc/condition-limit.rs index 571c600ebd096..2ff46b11a1681 100644 --- a/tests/coverage/mcdc/condition-limit.rs +++ b/tests/coverage/mcdc/condition-limit.rs @@ -1,6 +1,7 @@ #![feature(coverage_attribute)] //@ edition: 2021 //@ min-llvm-version: 18 +//@ ignore-llvm-version: 19 - 99 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/if.rs b/tests/coverage/mcdc/if.rs index d8e6b61a9d59d..6f589659a3d7b 100644 --- a/tests/coverage/mcdc/if.rs +++ b/tests/coverage/mcdc/if.rs @@ -1,6 +1,7 @@ #![feature(coverage_attribute)] //@ edition: 2021 //@ min-llvm-version: 18 +//@ ignore-llvm-version: 19 - 99 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/inlined_expressions.rs b/tests/coverage/mcdc/inlined_expressions.rs index 65f7ee66f3994..fc1e4dae37c7b 100644 --- a/tests/coverage/mcdc/inlined_expressions.rs +++ b/tests/coverage/mcdc/inlined_expressions.rs @@ -1,6 +1,7 @@ #![feature(coverage_attribute)] //@ edition: 2021 //@ min-llvm-version: 18 +//@ ignore-llvm-version: 19 - 99 //@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0 //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/nested_if.rs b/tests/coverage/mcdc/nested_if.rs index f5068b5dcc23f..f9ce7a0bc254f 100644 --- a/tests/coverage/mcdc/nested_if.rs +++ b/tests/coverage/mcdc/nested_if.rs @@ -1,6 +1,7 @@ #![feature(coverage_attribute)] //@ edition: 2021 //@ min-llvm-version: 18 +//@ ignore-llvm-version: 19 - 99 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc diff --git a/tests/coverage/mcdc/non_control_flow.rs b/tests/coverage/mcdc/non_control_flow.rs index 77e64e6625b2c..633d381a1aafc 100644 --- a/tests/coverage/mcdc/non_control_flow.rs +++ b/tests/coverage/mcdc/non_control_flow.rs @@ -1,6 +1,7 @@ #![feature(coverage_attribute)] //@ edition: 2021 //@ min-llvm-version: 18 +//@ ignore-llvm-version: 19 - 99 //@ compile-flags: -Zcoverage-options=mcdc //@ llvm-cov-flags: --show-branches=count --show-mcdc From b960390548b373bd80b5d9fe590ae3b577e8e8f2 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 24 Jul 2024 16:03:36 +0200 Subject: [PATCH 272/489] Crash test for issue 121444 has been fixed --- tests/{crashes/121444.rs => ui/abi/large-byval-align.rs} | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) rename tests/{crashes/121444.rs => ui/abi/large-byval-align.rs} (68%) diff --git a/tests/crashes/121444.rs b/tests/ui/abi/large-byval-align.rs similarity index 68% rename from tests/crashes/121444.rs rename to tests/ui/abi/large-byval-align.rs index a6373a58c426e..e39170df72b49 100644 --- a/tests/crashes/121444.rs +++ b/tests/ui/abi/large-byval-align.rs @@ -1,11 +1,13 @@ -//@ known-bug: #121444 //@ compile-flags: -Copt-level=0 -//@ edition:2021 //@ only-x86_64 //@ ignore-windows +//@ min-llvm-version: 19 +//@ build-pass + #[repr(align(536870912))] pub struct A(i64); +#[allow(improper_ctypes_definitions)] pub extern "C" fn foo(x: A) {} fn main() { From cc7e7bc0964ed29963bb3c455f2b89c9e06c5a87 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 30 Jul 2024 12:12:41 +0200 Subject: [PATCH 273/489] cargo-miri: better error when we seem to run inside bootstrap but something is wrong --- src/tools/miri/cargo-miri/src/setup.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index fe67aad465cdd..0cf6f1a375cdf 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -100,7 +100,10 @@ pub fn setup( // for target crates. let cargo_miri_path = std::env::current_exe().expect("current executable path invalid"); if env::var_os("RUSTC_STAGE").is_some() { - assert!(env::var_os("RUSTC").is_some()); + assert!( + env::var_os("RUSTC").is_some() && env::var_os("RUSTC_WRAPPER").is_some(), + "cargo-miri setup is running inside rustc bootstrap but RUSTC or RUST_WRAPPER is not set" + ); command.env("RUSTC_REAL", &cargo_miri_path); } else { command.env("RUSTC", &cargo_miri_path); From 58bfd98bafef799b032d5facaeec888f990c071b Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 30 Jul 2024 09:55:36 +0200 Subject: [PATCH 274/489] make `///` doc comments compatible with naked functions --- compiler/rustc_passes/src/check_attr.rs | 6 ++++++ tests/ui/asm/naked-functions.rs | 3 +++ 2 files changed, 9 insertions(+) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e0cf65d3f9830..c845cd36ff1e6 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -460,6 +460,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { for other_attr in attrs { + // this covers "sugared doc comments" of the form `/// ...` + // it does not cover `#[doc = "..."]`, which is handled below + if other_attr.is_doc_comment() { + continue; + } + if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) { self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { span: other_attr.span, diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 6d335ac2def1e..cb1e5c325c239 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -239,6 +239,9 @@ pub unsafe extern "C" fn compatible_target_feature() { } #[doc = "foo bar baz"] +/// a doc comment +// a normal comment +#[doc(alias = "ADocAlias")] #[naked] pub unsafe extern "C" fn compatible_doc_attributes() { asm!("", options(noreturn, raw)); From 2169fc7f0fb64d9e24e0bf262fc3746257d8a8ef Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 30 Jul 2024 12:57:21 +0200 Subject: [PATCH 275/489] Set tracing level to debug when `cargo config get env` fails --- src/tools/rust-analyzer/crates/project-model/src/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs index 3df46e1e37d9c..049acc290bbfe 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/env.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs @@ -81,7 +81,7 @@ pub(crate) fn cargo_config_env( tracing::debug!("Discovered cargo config env: {:?}", env); }) .inspect_err(|err| { - tracing::error!("Failed to discover cargo config env: {:?}", err); + tracing::debug!("Failed to discover cargo config env: {:?}", err); }) .unwrap_or_default() } From 918cdcc9c542eea0d7d3d4517dead7ae9a704e3e Mon Sep 17 00:00:00 2001 From: Liigo Zhuang Date: Tue, 30 Jul 2024 19:36:28 +0800 Subject: [PATCH 276/489] More detailed note to deprecate ONCE_INIT --- library/std/src/sync/once.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 9d969af8c6d84..5e0694e8de2db 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -70,7 +70,7 @@ pub(crate) enum ExclusiveState { #[stable(feature = "rust1", since = "1.0.0")] #[deprecated( since = "1.38.0", - note = "the `new` function is now preferred", + note = "the `Once::new()` function is now preferred", suggestion = "Once::new()" )] pub const ONCE_INIT: Once = Once::new(); From 6fc1b699937b2be59635efa2d4f77a3c5ce20c5b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 30 Jul 2024 13:18:16 +0000 Subject: [PATCH 277/489] Use Scalar consistently in foreign item emulation --- src/tools/miri/src/shims/time.rs | 16 +- src/tools/miri/src/shims/unix/env.rs | 40 +++-- src/tools/miri/src/shims/unix/fd.rs | 47 +++--- .../miri/src/shims/unix/foreign_items.rs | 146 +++++++++--------- src/tools/miri/src/shims/unix/fs.rs | 101 ++++++------ .../src/shims/unix/linux/foreign_items.rs | 8 +- src/tools/miri/src/shims/unix/sync.rs | 94 ++++++----- src/tools/miri/src/shims/unix/thread.rs | 20 +-- src/tools/miri/src/shims/windows/env.rs | 4 +- .../miri/src/shims/windows/foreign_items.rs | 8 +- 10 files changed, 239 insertions(+), 245 deletions(-) diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index e8f906d37e842..ebec1a70c5cd0 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -93,7 +93,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Scalar::from_i32(0)) } - fn gettimeofday(&mut self, tv_op: &OpTy<'tcx>, tz_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn gettimeofday( + &mut self, + tv_op: &OpTy<'tcx>, + tz_op: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("gettimeofday"); @@ -106,7 +110,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if !this.ptr_is_null(tz)? { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let duration = system_time_to_duration(&SystemTime::now())?; @@ -115,7 +119,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_int_fields(&[tv_sec.into(), tv_usec.into()], &tv)?; - Ok(0) + Ok(Scalar::from_i32(0)) } // The localtime() function shall convert the time in seconds since the Epoch pointed to by @@ -308,7 +312,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, req_op: &OpTy<'tcx>, _rem: &OpTy<'tcx>, // Signal handlers are not supported, so rem will never be written to. - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("nanosleep"); @@ -320,7 +324,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { None => { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } }; @@ -333,7 +337,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { @timeout = |_this| { Ok(()) } ), ); - Ok(0) + Ok(Scalar::from_i32(0)) } #[allow(non_snake_case)] diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs index 3b8ad65195b8a..ac9933ea705b9 100644 --- a/src/tools/miri/src/shims/unix/env.rs +++ b/src/tools/miri/src/shims/unix/env.rs @@ -148,7 +148,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(var_ptr.unwrap_or_else(Pointer::null)) } - fn setenv(&mut self, name_op: &OpTy<'tcx>, value_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn setenv( + &mut self, + name_op: &OpTy<'tcx>, + value_op: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("setenv"); @@ -169,16 +173,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; } this.update_environ()?; - Ok(0) // return zero on success + Ok(Scalar::from_i32(0)) // return zero on success } else { // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character. let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - Ok(-1) + Ok(Scalar::from_i32(-1)) } } - fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("unsetenv"); @@ -195,12 +199,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; } this.update_environ()?; - Ok(0) + Ok(Scalar::from_i32(0)) } else { // name argument is a null pointer, points to an empty string, or points to a string containing an '=' character. let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - Ok(-1) + Ok(Scalar::from_i32(-1)) } } @@ -232,7 +236,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Pointer::null()) } - fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("chdir"); @@ -242,16 +246,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.reject_in_isolation("`chdir`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } - match env::set_current_dir(path) { - Ok(()) => Ok(0), - Err(e) => { - this.set_last_error_from_io_error(e)?; - Ok(-1) - } - } + let result = env::set_current_dir(path).map(|()| 0); + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } /// Updates the `environ` static. @@ -270,18 +269,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn getpid(&mut self) -> InterpResult<'tcx, i32> { + fn getpid(&mut self) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("getpid"); // The reason we need to do this wacky of a conversion is because // `libc::getpid` returns an i32, however, `std::process::id()` return an u32. // So we un-do the conversion that stdlib does and turn it back into an i32. - #[allow(clippy::cast_possible_wrap)] - Ok(this.get_pid() as i32) + // In `Scalar` representation, these are the same, so we don't need to anything else. + Ok(Scalar::from_u32(this.get_pid())) } - fn linux_gettid(&mut self) -> InterpResult<'tcx, i32> { + fn linux_gettid(&mut self) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_ref(); this.assert_target_os("linux", "gettid"); @@ -290,7 +289,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Compute a TID for this thread, ensuring that the main thread has PID == TID. let tid = this.get_pid().strict_add(index); - #[allow(clippy::cast_possible_wrap)] - Ok(tid as i32) + Ok(Scalar::from_u32(tid)) } } diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index ada5592f61fe0..74e690a5f1433 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -310,20 +310,20 @@ impl FdTable { impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, i32> { + fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let Some(dup_fd) = this.machine.fds.dup(old_fd) else { - return this.fd_not_found(); + return Ok(Scalar::from_i32(this.fd_not_found()?)); }; - Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, 0)) + Ok(Scalar::from_i32(this.machine.fds.insert_fd_with_min_fd(dup_fd, 0))) } - fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, i32> { + fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let Some(dup_fd) = this.machine.fds.dup(old_fd) else { - return this.fd_not_found(); + return Ok(Scalar::from_i32(this.fd_not_found()?)); }; if new_fd != old_fd { // Close new_fd if it is previously opened. @@ -333,7 +333,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { file_description.close(this.machine.communicate())?.ok(); } } - Ok(new_fd) + Ok(Scalar::from_i32(new_fd)) } fn flock(&mut self, fd: i32, op: i32) -> InterpResult<'tcx, Scalar> { @@ -370,7 +370,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> { + fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); if args.len() < 2 { @@ -388,11 +388,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `FD_CLOEXEC` value without checking if the flag is set for the file because `std` // always sets this flag when opening a file. However we still need to check that the // file itself is open. - if this.machine.fds.is_fd(fd) { - Ok(this.eval_libc_i32("FD_CLOEXEC")) + Ok(Scalar::from_i32(if this.machine.fds.is_fd(fd) { + this.eval_libc_i32("FD_CLOEXEC") } else { - this.fd_not_found() - } + this.fd_not_found()? + })) } else if cmd == this.eval_libc_i32("F_DUPFD") || cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC") { @@ -409,15 +409,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let start = this.read_scalar(&args[2])?.to_i32()?; match this.machine.fds.dup(fd) { - Some(dup_fd) => Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, start)), - None => this.fd_not_found(), + Some(dup_fd) => + Ok(Scalar::from_i32(this.machine.fds.insert_fd_with_min_fd(dup_fd, start))), + None => Ok(Scalar::from_i32(this.fd_not_found()?)), } } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") { // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`fcntl`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } this.ffullsync_fd(fd) @@ -462,7 +463,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { buf: Pointer, count: u64, offset: Option, - ) -> InterpResult<'tcx, i64> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescriptor` trait. @@ -482,7 +483,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We temporarily dup the FD to be able to retain mutable access to `this`. let Some(fd) = this.machine.fds.dup(fd) else { trace!("read: FD not found"); - return this.fd_not_found(); + return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; trace!("read: FD mapped to {fd:?}"); @@ -496,7 +497,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_target_isize(-1, this)); }; fd.borrow_mut().pread(communicate, &mut bytes, offset, this) } @@ -513,11 +514,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { buf, bytes[..usize::try_from(read_bytes).unwrap()].iter().copied(), )?; - Ok(read_bytes) + Ok(Scalar::from_target_isize(read_bytes, this)) } Err(e) => { this.set_last_error_from_io_error(e)?; - Ok(-1) + Ok(Scalar::from_target_isize(-1, this)) } } } @@ -528,7 +529,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { buf: Pointer, count: u64, offset: Option, - ) -> InterpResult<'tcx, i64> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); // Isolation check is done via `FileDescriptor` trait. @@ -546,7 +547,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned(); // We temporarily dup the FD to be able to retain mutable access to `this`. let Some(fd) = this.machine.fds.dup(fd) else { - return this.fd_not_found(); + return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; let result = match offset { @@ -555,7 +556,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_target_isize(-1, this)); }; fd.borrow_mut().pwrite(communicate, &bytes, offset, this) } @@ -563,7 +564,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { drop(fd); let result = result?.map(|c| i64::try_from(c).unwrap()); - this.try_unwrap_io_result(result) + Ok(Scalar::from_target_isize(this.try_unwrap_io_result(result)?, this)) } } diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 17851e1aec01b..57930f9807d62 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -62,13 +62,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "unsetenv" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.unsetenv(name)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "setenv" => { let [name, value, overwrite] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_scalar(overwrite)?.to_i32()?; let result = this.setenv(name, value)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "getcwd" => { let [buf, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -78,12 +78,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "chdir" => { let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.chdir(path)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "getpid" => { let [] = this.check_shim(abi, Abi::C { unwind: false}, link_name, args)?; let result = this.getpid()?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } // File descriptors @@ -93,7 +93,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; let result = this.read(fd, buf, count, None)?; - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "write" => { let [fd, buf, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -103,7 +103,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { trace!("Called write({:?}, {:?}, {:?})", fd, buf, count); let result = this.write(fd, buf, count, None)?; // Now, `result` is the value we return back to the program. - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "pread" => { let [fd, buf, count, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -112,7 +112,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let count = this.read_target_usize(count)?; let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; let result = this.read(fd, buf, count, Some(offset))?; - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "pwrite" => { let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -123,7 +123,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { trace!("Called pwrite({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); let result = this.write(fd, buf, count, Some(offset))?; // Now, `result` is the value we return back to the program. - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "pread64" => { let [fd, buf, count, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -132,7 +132,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let count = this.read_target_usize(count)?; let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?; let result = this.read(fd, buf, count, Some(offset))?; - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "pwrite64" => { let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -143,7 +143,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset); let result = this.write(fd, buf, count, Some(offset))?; // Now, `result` is the value we return back to the program. - this.write_scalar(Scalar::from_target_isize(result, this), dest)?; + this.write_scalar(result, dest)?; } "close" => { let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -155,20 +155,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // in `this.fcntl()`, so we do not use `check_shim` here. this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?; let result = this.fcntl(args)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "dup" => { let [old_fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let old_fd = this.read_scalar(old_fd)?.to_i32()?; let new_fd = this.dup(old_fd)?; - this.write_scalar(Scalar::from_i32(new_fd), dest)?; + this.write_scalar(new_fd, dest)?; } "dup2" => { let [old_fd, new_fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let old_fd = this.read_scalar(old_fd)?.to_i32()?; let new_fd = this.read_scalar(new_fd)?.to_i32()?; let result = this.dup2(old_fd, new_fd)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "flock" => { let [fd, op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -183,32 +183,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `open` is variadic, the third argument is only present when the second argument has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?; let result = this.open(args)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "unlink" => { let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.unlink(path)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "symlink" => { let [target, linkpath] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.symlink(target, linkpath)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "rename" => { let [oldpath, newpath] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.rename(oldpath, newpath)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "mkdir" => { let [path, mode] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.mkdir(path, mode)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "rmdir" => { let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.rmdir(path)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "opendir" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -218,7 +218,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "closedir" => { let [dirp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.closedir(dirp)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "lseek64" => { let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -255,12 +255,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "fsync" => { let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.fsync(fd)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "fdatasync" => { let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.fdatasync(fd)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "readlink" => { let [pathname, buf, bufsize] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -285,7 +285,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "mkstemp" => { let [template] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.mkstemp(template)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } // Sockets @@ -301,7 +301,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "gettimeofday" => { let [tv, tz] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.gettimeofday(tv, tz)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "localtime_r" => { let [timep, result_op] = this.check_shim(abi, Abi::C {unwind: false}, link_name, args)?; @@ -473,23 +473,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Synchronization primitives "pthread_mutexattr_init" => { let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_mutexattr_init(attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_mutexattr_init(attr)?; + this.write_null(dest)?; } "pthread_mutexattr_settype" => { let [attr, kind] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_mutexattr_settype(attr, kind)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_mutexattr_destroy" => { let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_mutexattr_destroy(attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_mutexattr_destroy(attr)?; + this.write_null(dest)?; } "pthread_mutex_init" => { let [mutex, attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_mutex_init(mutex, attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_mutex_init(mutex, attr)?; + this.write_null(dest)?; } "pthread_mutex_lock" => { let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -498,17 +498,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_mutex_trylock" => { let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_mutex_trylock(mutex)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_mutex_unlock" => { let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_mutex_unlock(mutex)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_mutex_destroy" => { let [mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_mutex_destroy(mutex)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_mutex_destroy(mutex)?; + this.write_int(0, dest)?; } "pthread_rwlock_rdlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -517,7 +517,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_rwlock_tryrdlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_rwlock_tryrdlock(rwlock)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_rwlock_wrlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -526,22 +526,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_rwlock_trywrlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.pthread_rwlock_trywrlock(rwlock)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "pthread_rwlock_unlock" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_rwlock_unlock(rwlock)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_rwlock_unlock(rwlock)?; + this.write_null(dest)?; } "pthread_rwlock_destroy" => { let [rwlock] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_rwlock_destroy(rwlock)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_rwlock_destroy(rwlock)?; + this.write_null(dest)?; } "pthread_condattr_init" => { let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_condattr_init(attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_condattr_init(attr)?; + this.write_null(dest)?; } "pthread_condattr_setclock" => { let [attr, clock_id] = @@ -552,28 +552,28 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "pthread_condattr_getclock" => { let [attr, clock_id] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_condattr_getclock(attr, clock_id)?; - this.write_scalar(result, dest)?; + this.pthread_condattr_getclock(attr, clock_id)?; + this.write_null(dest)?; } "pthread_condattr_destroy" => { let [attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_condattr_destroy(attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_condattr_destroy(attr)?; + this.write_null(dest)?; } "pthread_cond_init" => { let [cond, attr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_cond_init(cond, attr)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_cond_init(cond, attr)?; + this.write_null(dest)?; } "pthread_cond_signal" => { let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_cond_signal(cond)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_cond_signal(cond)?; + this.write_null(dest)?; } "pthread_cond_broadcast" => { let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_cond_broadcast(cond)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_cond_broadcast(cond)?; + this.write_null(dest)?; } "pthread_cond_wait" => { let [cond, mutex] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -585,25 +585,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "pthread_cond_destroy" => { let [cond] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_cond_destroy(cond)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_cond_destroy(cond)?; + this.write_null(dest)?; } // Threading "pthread_create" => { let [thread, attr, start, arg] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_create(thread, attr, start, arg)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_create(thread, attr, start, arg)?; + this.write_null(dest)?; } "pthread_join" => { let [thread, retval] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_join(thread, retval)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_join(thread, retval)?; + this.write_null(dest)?; } "pthread_detach" => { let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.pthread_detach(thread)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.pthread_detach(thread)?; + this.write_null(dest)?; } "pthread_self" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -612,13 +612,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "sched_yield" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.sched_yield()?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.sched_yield()?; + this.write_null(dest)?; } "nanosleep" => { let [req, rem] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.nanosleep(req, rem)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } "sched_getaffinity" => { // Currently this function does not exist on all Unixes, e.g. on macOS. @@ -647,23 +647,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.ptr_is_null(mask)? { let einval = this.eval_libc("EFAULT"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } else if cpusetsize == 0 || cpusetsize.checked_rem(chunk_size).unwrap() != 0 { // we only copy whole chunks of size_of::() let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } else if let Some(cpuset) = this.machine.thread_cpu_affinity.get(&thread_id) { let cpuset = cpuset.clone(); // we only copy whole chunks of size_of::() let byte_count = Ord::min(cpuset.as_slice().len(), cpusetsize.try_into().unwrap()); this.write_bytes_ptr(mask, cpuset.as_slice()[..byte_count].iter().copied())?; - this.write_scalar(Scalar::from_i32(0), dest)?; + this.write_null(dest)?; } else { // The thread whose ID is pid could not be found let einval = this.eval_libc("ESRCH"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } } "sched_setaffinity" => { @@ -690,7 +690,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.ptr_is_null(mask)? { let einval = this.eval_libc("EFAULT"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } else { // NOTE: cpusetsize might be smaller than `CpuAffinityMask::CPU_MASK_BYTES`. // Any unspecified bytes are treated as zero here (none of the CPUs are configured). @@ -702,13 +702,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match CpuAffinityMask::from_array(this, this.machine.num_cpus, bits_array) { Some(cpuset) => { this.machine.thread_cpu_affinity.insert(thread_id, cpuset); - this.write_scalar(Scalar::from_i32(0), dest)?; + this.write_null(dest)?; } None => { // The intersection between the mask and the available CPUs was empty. let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } } } @@ -766,10 +766,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if bufsize > 256 { let err = this.eval_libc("EIO"); this.set_last_error(err)?; - this.write_scalar(Scalar::from_i32(-1), dest)?; + this.write_int(-1, dest)?; } else { this.gen_random(buf, bufsize)?; - this.write_scalar(Scalar::from_i32(0), dest)?; + this.write_null(dest)?; } } "getrandom" => { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 38ef3f13b4458..7891b65a9d4fb 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -395,7 +395,7 @@ fn maybe_sync_file( impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> { + fn open(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { if args.len() < 2 { throw_ub_format!( "incorrect number of arguments for `open`: got {}, expected at least 2", @@ -503,7 +503,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // if the flag contains `O_TMPFILE` then we return a graceful error let eopnotsupp = this.eval_libc("EOPNOTSUPP"); this.set_last_error(eopnotsupp)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } } @@ -524,7 +524,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if path.is_symlink() { let eloop = this.eval_libc("ELOOP"); this.set_last_error(eloop)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } } mirror |= o_nofollow; @@ -540,14 +540,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`open`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let fd = options .open(path) .map(|file| this.machine.fds.insert_fd(FileHandle { file, writable })); - this.try_unwrap_io_result(fd) + Ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?)) } fn lseek64(&mut self, fd: i32, offset: i128, whence: i32) -> InterpResult<'tcx, Scalar> { @@ -588,7 +588,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Scalar::from_i64(result)) } - fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn unlink(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?; @@ -597,18 +597,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`unlink`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let result = remove_file(path).map(|_| 0); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } fn symlink( &mut self, target_op: &OpTy<'tcx>, linkpath_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { #[cfg(unix)] fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> { std::os::unix::fs::symlink(src, dst) @@ -628,11 +628,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`symlink`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let result = create_link(&target, &linkpath).map(|_| 0); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } fn macos_fbsd_stat( @@ -731,7 +731,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { flags_op: &OpTy<'tcx>, // Should be an `int` mask_op: &OpTy<'tcx>, // Should be an `unsigned int` statxbuf_op: &OpTy<'tcx>, // Should be a `struct statx *` - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os("linux", "statx"); @@ -746,7 +746,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.ptr_is_null(statxbuf_ptr)? || this.ptr_is_null(pathname_ptr)? { let efault = this.eval_libc("EFAULT"); this.set_last_error(efault)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let statxbuf = this.deref_pointer_as(statxbuf_op, this.libc_ty_layout("statx"))?; @@ -788,7 +788,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.eval_libc("EBADF") }; this.set_last_error(ecode)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } // the `_mask_op` parameter specifies the file information that the caller requested. @@ -810,7 +810,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; let metadata = match metadata { Some(metadata) => metadata, - None => return Ok(-1), + None => return Ok(Scalar::from_i32(-1)), }; // The `mode` field specifies the type of the file and the permissions over the file for @@ -903,14 +903,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &this.project_field_named(&statxbuf, "stx_mtime")?, )?; - Ok(0) + Ok(Scalar::from_i32(0)) } fn rename( &mut self, oldpath_op: &OpTy<'tcx>, newpath_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let oldpath_ptr = this.read_pointer(oldpath_op)?; @@ -919,7 +919,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.ptr_is_null(oldpath_ptr)? || this.ptr_is_null(newpath_ptr)? { let efault = this.eval_libc("EFAULT"); this.set_last_error(efault)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let oldpath = this.read_path_from_c_str(oldpath_ptr)?; @@ -929,15 +929,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`rename`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let result = rename(oldpath, newpath).map(|_| 0); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn mkdir(&mut self, path_op: &OpTy<'tcx>, mode_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); #[cfg_attr(not(unix), allow(unused_variables))] @@ -953,7 +953,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`mkdir`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } #[cfg_attr(not(unix), allow(unused_mut))] @@ -969,10 +969,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let result = builder.create(path).map(|_| 0i32); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } - fn rmdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn rmdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?; @@ -981,12 +981,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`rmdir`", reject_with)?; this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } let result = remove_dir(path).map(|_| 0i32); - this.try_unwrap_io_result(result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) } fn opendir(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { @@ -1236,27 +1236,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { })) } - fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let dirp = this.read_target_usize(dirp_op)?; // Reject if isolation is enabled. - if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { + Ok(Scalar::from_i32(if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`closedir`", reject_with)?; - // Set error code as "EBADF" (bad fd) - return this.fd_not_found(); - } - - if let Some(open_dir) = this.machine.dirs.streams.remove(&dirp) { + this.fd_not_found()? + } else if let Some(open_dir) = this.machine.dirs.streams.remove(&dirp) { if let Some(entry) = open_dir.entry { this.deallocate_ptr(entry, None, MiriMemoryKind::Runtime.into())?; } drop(open_dir); - Ok(0) + 0 } else { - this.fd_not_found() - } + this.fd_not_found()? + })) } fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar> { @@ -1300,7 +1297,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn fsync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { // On macOS, `fsync` (unlike `fcntl(F_FULLFSYNC)`) does not wait for the // underlying disk to finish writing. In the interest of host compatibility, // we conservatively implement this with `sync_all`, which @@ -1314,16 +1311,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`fsync`", reject_with)?; // Set error code as "EBADF" (bad fd) - return this.fd_not_found(); + return Ok(Scalar::from_i32(this.fd_not_found()?)); } - return self.ffullsync_fd(fd); + self.ffullsync_fd(fd) } - fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, i32> { + fn ffullsync_fd(&mut self, fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let Some(file_description) = this.machine.fds.get(fd) else { - return Ok(this.fd_not_found()?); + return Ok(Scalar::from_i32(this.fd_not_found()?)); }; // Only regular files support synchronization. let FileHandle { file, writable } = @@ -1332,10 +1329,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { })?; let io_result = maybe_sync_file(file, *writable, File::sync_all); drop(file_description); - this.try_unwrap_io_result(io_result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) } - fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn fdatasync(&mut self, fd_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let fd = this.read_scalar(fd_op)?.to_i32()?; @@ -1344,11 +1341,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`fdatasync`", reject_with)?; // Set error code as "EBADF" (bad fd) - return this.fd_not_found(); + return Ok(Scalar::from_i32(this.fd_not_found()?)); } let Some(file_description) = this.machine.fds.get(fd) else { - return Ok(this.fd_not_found()?); + return Ok(Scalar::from_i32(this.fd_not_found()?)); }; // Only regular files support synchronization. let FileHandle { file, writable } = @@ -1357,7 +1354,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { })?; let io_result = maybe_sync_file(file, *writable, File::sync_data); drop(file_description); - this.try_unwrap_io_result(io_result) + Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?)) } fn sync_file_range( @@ -1534,7 +1531,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } } - fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn mkstemp(&mut self, template_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { use rand::seq::SliceRandom; // POSIX defines the template string. @@ -1565,7 +1562,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.reject_in_isolation("`mkstemp`", reject_with)?; let eacc = this.eval_libc("EACCES"); this.set_last_error(eacc)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } // Get the bytes of the suffix we expect in _target_ encoding. @@ -1583,7 +1580,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if last_six_char_bytes != suffix_bytes { let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } // At this point we know we have 6 ASCII 'X' characters as a suffix. @@ -1638,7 +1635,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match file { Ok(f) => { let fd = this.machine.fds.insert_fd(FileHandle { file: f, writable: true }); - return Ok(fd); + return Ok(Scalar::from_i32(fd)); } Err(e) => match e.kind() { @@ -1649,7 +1646,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // "On error, -1 is returned, and errno is set to // indicate the error" this.set_last_error_from_io_error(e)?; - return Ok(-1); + return Ok(Scalar::from_i32(-1)); } }, } @@ -1658,7 +1655,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We ran out of attempts to create the file, return an error. let eexist = this.eval_libc("EEXIST"); this.set_last_error(eexist)?; - Ok(-1) + Ok(Scalar::from_i32(-1)) } } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 20c6a23479421..581f0db42e1dc 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -44,7 +44,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [dirfd, pathname, flags, mask, statxbuf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } // epoll, eventfd @@ -97,7 +97,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "gettid" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let result = this.linux_gettid()?; - this.write_scalar(Scalar::from_i32(result), dest)?; + this.write_scalar(result, dest)?; } // Dynamically invoked syscalls @@ -176,12 +176,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "__libc_current_sigrtmin" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.write_scalar(Scalar::from_i32(SIGRTMIN), dest)?; + this.write_int(SIGRTMIN, dest)?; } "__libc_current_sigrtmax" => { let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - this.write_scalar(Scalar::from_i32(SIGRTMAX), dest)?; + this.write_int(SIGRTMAX, dest)?; } // Incomplete shims that we "stub out" just to get pre-main initialization code to work. diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs index e8653117ae94b..0b889b1182248 100644 --- a/src/tools/miri/src/shims/unix/sync.rs +++ b/src/tools/miri/src/shims/unix/sync.rs @@ -363,20 +363,20 @@ fn cond_set_clock_id<'tcx>( impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { - fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let default_kind = this.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"); mutexattr_set_kind(this, attr_op, default_kind)?; - Ok(0) + Ok(()) } fn pthread_mutexattr_settype( &mut self, attr_op: &OpTy<'tcx>, kind_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let kind = this.read_scalar(kind_op)?.to_i32()?; @@ -407,13 +407,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { mutexattr_set_kind(this, attr_op, kind)?; } else { let einval = this.eval_libc_i32("EINVAL"); - return Ok(einval); + return Ok(Scalar::from_i32(einval)); } - Ok(0) + Ok(Scalar::from_i32(0)) } - fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); // Destroying an uninit pthread_mutexattr is UB, so check to make sure it's not uninit. @@ -435,14 +435,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_mutexattr_t"))?, )?; - Ok(0) + Ok(()) } fn pthread_mutex_init( &mut self, mutex_op: &OpTy<'tcx>, attr_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let attr = this.read_pointer(attr_op)?; @@ -457,7 +457,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { mutex_set_kind(this, mutex_op, kind)?; - Ok(0) + Ok(()) } fn pthread_mutex_lock( @@ -501,25 +501,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let kind = mutex_get_kind(this, mutex_op)?; let id = mutex_get_id(this, mutex_op)?; - if this.mutex_is_locked(id) { + Ok(Scalar::from_i32(if this.mutex_is_locked(id) { let owner_thread = this.mutex_get_owner(id); if owner_thread != this.active_thread() { - Ok(this.eval_libc_i32("EBUSY")) + this.eval_libc_i32("EBUSY") } else { if is_mutex_kind_default(this, kind)? || is_mutex_kind_normal(this, kind)? || kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") { - Ok(this.eval_libc_i32("EBUSY")) + this.eval_libc_i32("EBUSY") } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { this.mutex_lock(id); - Ok(0) + 0 } else { throw_unsup_format!( "called pthread_mutex_trylock on an unsupported type of mutex" @@ -529,11 +529,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else { // The mutex is unlocked. Let's lock it. this.mutex_lock(id); - Ok(0) - } + 0 + })) } - fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let kind = mutex_get_kind(this, mutex_op)?; @@ -541,7 +541,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if let Some(_old_locked_count) = this.mutex_unlock(id)? { // The mutex was locked by the current thread. - Ok(0) + Ok(Scalar::from_i32(0)) } else { // The mutex was locked by another thread or not locked at all. See // the “Unlock When Not Owner” column in @@ -557,14 +557,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") || kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") { - Ok(this.eval_libc_i32("EPERM")) + Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))) } else { throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex"); } } } - fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = mutex_get_id(this, mutex_op)?; @@ -583,7 +583,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; // FIXME: delete interpreter state associated with this mutex. - Ok(0) + Ok(()) } fn pthread_rwlock_rdlock( @@ -605,16 +605,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let id = rwlock_get_id(this, rwlock_op)?; if this.rwlock_is_write_locked(id) { - Ok(this.eval_libc_i32("EBUSY")) + Ok(Scalar::from_i32(this.eval_libc_i32("EBUSY"))) } else { this.rwlock_reader_lock(id); - Ok(0) + Ok(Scalar::from_i32(0)) } } @@ -649,35 +649,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); let id = rwlock_get_id(this, rwlock_op)?; if this.rwlock_is_locked(id) { - Ok(this.eval_libc_i32("EBUSY")) + Ok(Scalar::from_i32(this.eval_libc_i32("EBUSY"))) } else { this.rwlock_writer_lock(id); - Ok(0) + Ok(Scalar::from_i32(0)) } } - fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = rwlock_get_id(this, rwlock_op)?; #[allow(clippy::if_same_then_else)] - if this.rwlock_reader_unlock(id)? { - Ok(0) - } else if this.rwlock_writer_unlock(id)? { - Ok(0) + if this.rwlock_reader_unlock(id)? || this.rwlock_writer_unlock(id)? { + Ok(()) } else { throw_ub_format!("unlocked an rwlock that was not locked by the active thread"); } } - fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = rwlock_get_id(this, rwlock_op)?; @@ -695,10 +693,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; // FIXME: delete interpreter state associated with this rwlock. - Ok(0) + Ok(()) } - fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); // no clock attribute on macOS @@ -710,7 +708,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { condattr_set_clock_id(this, attr_op, default_clock_id)?; } - Ok(0) + Ok(()) } fn pthread_condattr_setclock( @@ -737,16 +735,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &mut self, attr_op: &OpTy<'tcx>, clk_id_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, Scalar> { + ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let clock_id = condattr_get_clock_id(this, attr_op)?; this.write_scalar(Scalar::from_i32(clock_id), &this.deref_pointer(clk_id_op)?)?; - Ok(Scalar::from_i32(0)) + Ok(()) } - fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); // Destroying an uninit pthread_condattr is UB, so check to make sure it's not uninit. @@ -761,14 +759,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &this.deref_pointer_as(attr_op, this.libc_ty_layout("pthread_condattr_t"))?, )?; - Ok(0) + Ok(()) } fn pthread_cond_init( &mut self, cond_op: &OpTy<'tcx>, attr_op: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let attr = this.read_pointer(attr_op)?; @@ -784,21 +782,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { cond_set_clock_id(this, cond_op, clock_id)?; - Ok(0) + Ok(()) } - fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = cond_get_id(this, cond_op)?; this.condvar_signal(id)?; - Ok(0) + Ok(()) } - fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = cond_get_id(this, cond_op)?; while this.condvar_signal(id)? {} - Ok(0) + Ok(()) } fn pthread_cond_wait( @@ -869,7 +867,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(()) } - fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let id = cond_get_id(this, cond_op)?; @@ -885,6 +883,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_uninit(&this.deref_pointer_as(cond_op, this.libc_ty_layout("pthread_cond_t"))?)?; // FIXME: delete interpreter state associated with this condvar. - Ok(0) + Ok(()) } } diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 6fe331ba623a1..83bb95c797d97 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -10,7 +10,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { _attr: &OpTy<'tcx>, start_routine: &OpTy<'tcx>, arg: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let thread_info_place = this.deref_pointer_as(thread, this.libc_ty_layout("pthread_t"))?; @@ -27,14 +27,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.layout_of(this.tcx.types.usize)?, )?; - Ok(0) + Ok(()) } - fn pthread_join( - &mut self, - thread: &OpTy<'tcx>, - retval: &OpTy<'tcx>, - ) -> InterpResult<'tcx, i32> { + fn pthread_join(&mut self, thread: &OpTy<'tcx>, retval: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); if !this.ptr_is_null(this.read_pointer(retval)?)? { @@ -45,10 +41,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?; this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?; - Ok(0) + Ok(()) } - fn pthread_detach(&mut self, thread: &OpTy<'tcx>) -> InterpResult<'tcx, i32> { + fn pthread_detach(&mut self, thread: &OpTy<'tcx>) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); let thread_id = this.read_scalar(thread)?.to_int(this.libc_ty_layout("pthread_t").size)?; @@ -57,7 +53,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /*allow_terminated_joined*/ false, )?; - Ok(0) + Ok(()) } fn pthread_self(&mut self) -> InterpResult<'tcx, Scalar> { @@ -113,11 +109,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(if success { Scalar::from_u32(0) } else { this.eval_libc("ERANGE") }) } - fn sched_yield(&mut self) -> InterpResult<'tcx, i32> { + fn sched_yield(&mut self) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); this.yield_active_thread(); - Ok(0) + Ok(()) } } diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs index 77ae06bd5c2d8..495df18a6eaa2 100644 --- a/src/tools/miri/src/shims/windows/env.rs +++ b/src/tools/miri/src/shims/windows/env.rs @@ -197,11 +197,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } #[allow(non_snake_case)] - fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, u32> { + fn GetCurrentProcessId(&mut self) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); this.assert_target_os("windows", "GetCurrentProcessId"); - Ok(this.get_pid()) + Ok(Scalar::from_u32(this.get_pid())) } #[allow(non_snake_case)] diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 71f6a2bc03333..f840ba161650e 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -141,7 +141,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "GetCurrentProcessId" => { let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; let result = this.GetCurrentProcessId()?; - this.write_int(result, dest)?; + this.write_scalar(result, dest)?; } // File related shims @@ -372,7 +372,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.machine.tls.store_tls(key, active_thread, new_data, &*this.tcx)?; // Return success (`1`). - this.write_scalar(Scalar::from_i32(1), dest)?; + this.write_int(1, dest)?; } // Access to command-line arguments @@ -563,7 +563,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; this.gen_random(ptr, len)?; - this.write_scalar(Scalar::from_i32(1), dest)?; + this.write_int(1, dest)?; } "BCryptGenRandom" => { // used by getrandom 0.2 @@ -627,7 +627,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.CloseHandle(handle)?; - this.write_scalar(Scalar::from_u32(1), dest)?; + this.write_int(1, dest)?; } "GetModuleFileNameW" => { let [handle, filename, size] = From bbeff8c7862ad70fada412502324ecd41d1dea14 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 30 Jul 2024 16:55:45 +0300 Subject: [PATCH 278/489] set `force_recompile: true` if library is modified This allows the standard library to be compiled even with `download-rustc` enabled. Which means it's no longer a requirement to compile `rustc` in order to compile `std`. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/compile.rs | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 268e89c7f6011..c09180e542ff6 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -26,7 +26,8 @@ use crate::core::builder::{ use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; use crate::utils::exec::command; use crate::utils::helpers::{ - exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, + self, exe, get_clang_cl_resource_dir, get_closest_merge_base_commit, is_debug_info, is_dylib, + symlink_dir, t, up_to_date, }; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode, LLVM_TOOLS}; @@ -114,21 +115,43 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - // When downloading stage1, the standard library has already been copied to the sysroot, so - // there's no need to rebuild it. - let builder = run.builder; - run.crate_or_deps("sysroot") - .path("library") - .lazy_default_condition(Box::new(|| !builder.download_rustc())) + run.crate_or_deps("sysroot").path("library") } fn make_run(run: RunConfig<'_>) { let crates = std_crates_for_run_make(&run); + let builder = run.builder; + + // Force compilation of the standard library from source if the `library` is modified. This allows + // library team to compile the standard library without needing to compile the compiler with + // the `rust.download-rustc=true` option. + let force_recompile = + if builder.rust_info().is_managed_git_subrepository() && builder.download_rustc() { + let closest_merge_commit = get_closest_merge_base_commit( + Some(&builder.src), + &builder.config.git_config(), + &builder.config.stage0_metadata.config.git_merge_commit_email, + &[], + ) + .unwrap(); + + // Check if `library` has changes (returns false otherwise) + !t!(helpers::git(Some(&builder.src)) + .args(["diff-index", "--quiet", &closest_merge_commit]) + .arg("--") + .arg(builder.src.join("library")) + .as_command_mut() + .status()) + .success() + } else { + false + }; + run.builder.ensure(Std { compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), target: run.target, crates, - force_recompile: false, + force_recompile, extra_rust_args: &[], is_for_mir_opt_tests: false, }); From 6fcc630e56263d7d17a37a77202717f1c83c5b2a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 30 Jul 2024 16:56:47 +0300 Subject: [PATCH 279/489] update download-rustc documentation Signed-off-by: onur-ozkan --- config.example.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.example.toml b/config.example.toml index 45faa66ec114f..1a7bdc4737fbf 100644 --- a/config.example.toml +++ b/config.example.toml @@ -472,7 +472,8 @@ # This is mostly useful for tools; if you have changes to `compiler/` or `library/` they will be ignored. # # Set this to "if-unchanged" to only download if the compiler and standard library have not been modified. -# Set this to `true` to download unconditionally (useful if e.g. you are only changing doc-comments). +# Set this to `true` to download unconditionally. This is useful if you are working on tools, doc-comments, +# or library (you will be able to build the standard library without needing to build the compiler). #download-rustc = false # Number of codegen units to use for each compiler invocation. A value of 0 From cbab16feafcd828c813a1c4926eade67f464cff9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Apr 2024 08:55:39 +0000 Subject: [PATCH 280/489] Test RUSTC_OVERRIDE_VERSION_STRING --- src/tools/compiletest/src/header.rs | 1 + tests/ui/feature-gates/version_check.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/ui/feature-gates/version_check.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 0208ed34ac182..cde3e3295c631 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -330,6 +330,7 @@ impl TestProps { pub fn from_file(testfile: &Path, revision: Option<&str>, config: &Config) -> Self { let mut props = TestProps::new(); props.load_from(testfile, revision, config); + props.exec_env.push(("RUSTC".to_string(), config.rustc_path.display().to_string())); match (props.pass_mode, props.fail_mode) { (None, None) if config.mode == Mode::Ui => props.fail_mode = Some(FailMode::Check), diff --git a/tests/ui/feature-gates/version_check.rs b/tests/ui/feature-gates/version_check.rs new file mode 100644 index 0000000000000..093fda3fbe570 --- /dev/null +++ b/tests/ui/feature-gates/version_check.rs @@ -0,0 +1,17 @@ +//@ run-pass +//@ only-linux +//@ only-x86 +// FIXME: this should be more like //@ needs-subprocesses +use std::process::Command; + +fn main() { + let signalled_version = "Ceci n'est pas une rustc"; + let version = Command::new(std::env::var_os("RUSTC").unwrap()) + .env("RUSTC_OVERRIDE_VERSION_STRING", signalled_version) + .arg("--version") + .output() + .unwrap() + .stdout; + let version = std::str::from_utf8(&version).unwrap().strip_prefix("rustc ").unwrap().trim_end(); + assert_ne!(version, signalled_version); +} From 92f263b7926537d086bcb6bfac33fe2b93e44aa1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Apr 2024 15:29:51 +0000 Subject: [PATCH 281/489] Make RUSTC_OVERRIDE_VERSION_STRING overwrite the rendered version output, too --- compiler/rustc_driver_impl/src/lib.rs | 9 +++++++++ tests/ui/feature-gates/version_check.rs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index d9633d69f1d45..627a0ebb4e5e3 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -909,6 +909,15 @@ pub fn version_at_macro_invocation( ) { let verbose = matches.opt_present("verbose"); + let mut version = version; + let mut release = release; + let tmp; + if let Ok(force_version) = std::env::var("RUSTC_OVERRIDE_VERSION_STRING") { + tmp = force_version; + version = &tmp; + release = &tmp; + } + safe_println!("{binary} {version}"); if verbose { diff --git a/tests/ui/feature-gates/version_check.rs b/tests/ui/feature-gates/version_check.rs index 093fda3fbe570..e212dc74fd123 100644 --- a/tests/ui/feature-gates/version_check.rs +++ b/tests/ui/feature-gates/version_check.rs @@ -13,5 +13,5 @@ fn main() { .unwrap() .stdout; let version = std::str::from_utf8(&version).unwrap().strip_prefix("rustc ").unwrap().trim_end(); - assert_ne!(version, signalled_version); + assert_eq!(version, signalled_version); } From 4776ac0f885044685c6f6127632f42522a88c05d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 10:10:36 -0400 Subject: [PATCH 282/489] Suppress must_use on eat calls in rustfmt --- src/tools/rustfmt/src/parse/macros/lazy_static.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tools/rustfmt/src/parse/macros/lazy_static.rs b/src/tools/rustfmt/src/parse/macros/lazy_static.rs index 7baac247e2229..b6de5f8691c25 100644 --- a/src/tools/rustfmt/src/parse/macros/lazy_static.rs +++ b/src/tools/rustfmt/src/parse/macros/lazy_static.rs @@ -33,15 +33,17 @@ pub(crate) fn parse_lazy_static( } while parser.token.kind != TokenKind::Eof { // Parse a `lazy_static!` item. + // FIXME: These `eat_*` calls should be converted to `parse_or` to avoid + // silently formatting malformed lazy-statics. let vis = parse_or!(parse_visibility, rustc_parse::parser::FollowedByType::No); - parser.eat_keyword(kw::Static); - parser.eat_keyword(kw::Ref); + let _ = parser.eat_keyword(kw::Static); + let _ = parser.eat_keyword(kw::Ref); let id = parse_or!(parse_ident); - parser.eat(&TokenKind::Colon); + let _ = parser.eat(&TokenKind::Colon); let ty = parse_or!(parse_ty); - parser.eat(&TokenKind::Eq); + let _ = parser.eat(&TokenKind::Eq); let expr = parse_or!(parse_expr); - parser.eat(&TokenKind::Semi); + let _ = parser.eat(&TokenKind::Semi); result.push((vis, id, ty, expr)); } From b1b48dc58480cc6c36ba88f842144a8190aa589c Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Tue, 30 Jul 2024 09:35:12 -0500 Subject: [PATCH 283/489] tidy: Fix quote in error message --- src/tools/tidy/src/error_codes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 8ddacc07c6fd9..e2d1b85797ffe 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -319,7 +319,7 @@ fn check_error_codes_tests( if !found_code { verbose_print!( verbose, - "warning: Error code {code}`` has a UI test file, but doesn't contain its own error code!" + "warning: Error code `{code}` has a UI test file, but doesn't contain its own error code!" ); } } From 67a08b5deba5a6fdf5fd4acfc095851f79172e59 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 30 Jul 2024 15:02:40 +0000 Subject: [PATCH 284/489] Attribute checking simplifications remove an unused boolean and then merge two big matches into one --- compiler/rustc_passes/src/check_attr.rs | 546 ++++++++---------------- 1 file changed, 179 insertions(+), 367 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a58c57041f830..07c0a116bfeaf 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -207,37 +207,34 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::rustc_safe_intrinsic] => { self.check_rustc_safe_intrinsic(hir_id, attr, span, target) } - _ => true, - }; - - // lint-only checks - match attr.name_or_empty() { - sym::cold => self.check_cold(hir_id, attr, span, target), - sym::link => self.check_link(hir_id, attr, span, target), - sym::link_name => self.check_link_name(hir_id, attr, span, target), - sym::link_section => self.check_link_section(hir_id, attr, span, target), - sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target), - sym::deprecated => self.check_deprecated(hir_id, attr, span, target), - sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target), - sym::path => self.check_generic_attr(hir_id, attr, target, Target::Mod), - sym::macro_export => self.check_macro_export(hir_id, attr, target), - sym::ignore | sym::should_panic => { + [sym::cold] => self.check_cold(hir_id, attr, span, target), + [sym::link] => self.check_link(hir_id, attr, span, target), + [sym::link_name] => self.check_link_name(hir_id, attr, span, target), + [sym::link_section] => self.check_link_section(hir_id, attr, span, target), + [sym::no_mangle] => self.check_no_mangle(hir_id, attr, span, target), + [sym::deprecated] => self.check_deprecated(hir_id, attr, span, target), + [sym::macro_use] | [sym::macro_escape] => { + self.check_macro_use(hir_id, attr, target) + } + [sym::path] => self.check_generic_attr(hir_id, attr, target, Target::Mod), + [sym::macro_export] => self.check_macro_export(hir_id, attr, target), + [sym::ignore] | [sym::should_panic] => { self.check_generic_attr(hir_id, attr, target, Target::Fn) } - sym::automatically_derived => { + [sym::automatically_derived] => { self.check_generic_attr(hir_id, attr, target, Target::Impl) } - sym::no_implicit_prelude => { + [sym::no_implicit_prelude] => { self.check_generic_attr(hir_id, attr, target, Target::Mod) } - sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id), - sym::proc_macro => { + [sym::rustc_object_lifetime_default] => self.check_object_lifetime_default(hir_id), + [sym::proc_macro] => { self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike) } - sym::proc_macro_attribute => { + [sym::proc_macro_attribute] => { self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute); } - sym::proc_macro_derive => { + [sym::proc_macro_derive] => { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } @@ -297,7 +294,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl. - fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) -> bool { + fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) { if !matches!(target, Target::Impl) { self.tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, @@ -306,16 +303,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { errors::IncorrectDoNotRecommendLocation, ); } - true } /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition - fn check_diagnostic_on_unimplemented( - &self, - attr_span: Span, - hir_id: HirId, - target: Target, - ) -> bool { + fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) { if !matches!(target, Target::Trait) { self.tcx.emit_node_span_lint( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, @@ -324,68 +315,60 @@ impl<'tcx> CheckAttrVisitor<'tcx> { DiagnosticOnUnimplementedOnlyForTraits, ); } - true } - /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid. - fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { + /// Checks if an `#[inline]` is applied to a function or a closure. + fn check_inline(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { Target::Fn | Target::Closure - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, + | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {} Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => { self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, attr.span, errors::IgnoredInlineAttrFnProto, - ); - true + ) } // FIXME(#65833): We permit associated consts to have an `#[inline]` attribute with // just a lint, because we previously erroneously allowed it and some crates used it // accidentally, to be compatible with crates depending on them, we can't throw an // error here. - Target::AssocConst => { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span, - errors::IgnoredInlineAttrConstants, - ); - true - } + Target::AssocConst => self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::IgnoredInlineAttrConstants, + ), // FIXME(#80564): Same for fields, arms, and macro defs Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr, "inline"); - true + self.inline_attr_str_error_with_macro_def(hir_id, attr, "inline") } _ => { self.dcx().emit_err(errors::InlineNotFnOrClosure { attr_span: attr.span, defn_span: span, }); - false } } } /// Checks that `#[coverage(..)]` is applied to a function/closure/method, /// or to an impl block or module. - fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) { match target { Target::Fn | Target::Closure | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) | Target::Impl - | Target::Mod => true, + | Target::Mod => {} _ => { self.dcx().emit_err(errors::CoverageNotFnOrClosure { attr_span: attr.span, defn_span: span, }); - false } } } @@ -418,7 +401,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: Span, target: Target, attrs: &[Attribute], - ) -> bool { + ) { // many attributes don't make sense in combination with #[naked]. // Notable attributes that are incompatible with `#[naked]` are: // @@ -468,19 +451,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr: other_attr.name_or_empty(), }); - return false; + return; } } - - true } // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[naked]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr, "naked"); - true + self.inline_attr_str_error_with_macro_def(hir_id, attr, "naked") } _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { @@ -488,7 +468,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { defn_span: span, on_crate: hir_id == CRATE_HIR_ID, }); - false } } } @@ -500,17 +479,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr: &Attribute, span: Span, target: Target, - ) -> bool { + ) { match target { Target::Fn - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, + | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {} _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { attr_span: attr.span, defn_span: span, on_crate: hir_id == CRATE_HIR_ID, }); - false } } } @@ -536,19 +514,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[collapse_debuginfo]` is applied to a macro. - fn check_collapse_debuginfo(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_collapse_debuginfo(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::MacroDef => true, + Target::MacroDef => {} _ => { self.tcx .dcx() .emit_err(errors::CollapseDebuginfo { attr_span: attr.span, defn_span: span }); - false } } } - /// Checks if a `#[track_caller]` is applied to a function. Returns `true` if valid. + /// Checks if a `#[track_caller]` is applied to a function. fn check_track_caller( &self, hir_id: HirId, @@ -556,7 +533,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attrs: &[Attribute], span: Span, target: Target, - ) -> bool { + ) { match target { Target::Fn => { // `#[track_caller]` is not valid on weak lang items because they are called via @@ -572,12 +549,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { name: lang_item, sig_span: sig.span, }); - false - } else { - true } } - Target::Method(..) | Target::ForeignFn | Target::Closure => true, + Target::Method(..) | Target::ForeignFn | Target::Closure => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[track_caller]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible @@ -586,7 +560,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for attr in attrs { self.inline_attr_str_error_with_macro_def(hir_id, attr, "track_caller"); } - true } _ => { self.dcx().emit_err(errors::TrackedCallerWrongLocation { @@ -594,62 +567,51 @@ impl<'tcx> CheckAttrVisitor<'tcx> { defn_span: span, on_crate: hir_id == CRATE_HIR_ID, }); - false } } } - /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid. - fn check_non_exhaustive( - &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, - ) -> bool { + /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. + fn check_non_exhaustive(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { - Target::Struct | Target::Enum | Target::Variant => true, + Target::Struct | Target::Enum | Target::Variant => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[non_exhaustive]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "non_exhaustive"); - true } _ => { self.dcx().emit_err(errors::NonExhaustiveWrongLocation { attr_span: attr.span, defn_span: span, }); - false } } } - /// Checks if the `#[marker]` attribute on an `item` is valid. Returns `true` if valid. - fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { + /// Checks if the `#[marker]` attribute on an `item` is valid. + fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { - Target::Trait => true, + Target::Trait => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[marker]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "marker"); - true } _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait { attr_span: attr.span, defn_span: span, }); - false } } } - /// Checks if the `#[target_feature]` attribute on `item` is valid. Returns `true` if valid. + /// Checks if the `#[target_feature]` attribute on `item` is valid. fn check_target_feature( &self, hir_id: HirId, @@ -657,7 +619,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: Span, target: Target, attrs: &[Attribute], - ) -> bool { + ) { match target { Target::Fn => { // `#[target_feature]` is not allowed in lang items. @@ -674,12 +636,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { name: lang_item, sig_span: sig.span, }); - false - } else { - true } } - Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, + Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {} // FIXME: #[target_feature] was previously erroneously allowed on statements and some // crates used this, so only emit a warning. Target::Statement => { @@ -689,7 +648,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr.span, errors::TargetFeatureOnStatement, ); - true } // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[target_feature]` attribute with just a lint, because we previously @@ -697,7 +655,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature"); - true } _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { @@ -705,21 +662,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> { defn_span: span, on_crate: hir_id == CRATE_HIR_ID, }); - false } } } - /// Checks if the `#[thread_local]` attribute on `item` is valid. Returns `true` if valid. - fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) -> bool { + /// Checks if the `#[thread_local]` attribute on `item` is valid. + fn check_thread_local(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::ForeignStatic | Target::Static => true, + Target::ForeignStatic | Target::Static => {} _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToStatic { attr_span: attr.span, defn_span: span, }); - false } } } @@ -736,14 +691,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { target: Target, is_list: bool, aliases: &mut FxHashMap, - ) -> bool { + ) { let tcx = self.tcx; let span = meta.name_value_literal_span().unwrap_or_else(|| meta.span()); let attr_str = &format!("`#[doc(alias{})]`", if is_list { "(\"...\")" } else { " = \"...\"" }); if doc_alias == kw::Empty { tcx.dcx().emit_err(errors::DocAliasEmpty { span, attr_str }); - return false; + return; } let doc_alias_str = doc_alias.as_str(); @@ -752,11 +707,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { .find(|&c| c == '"' || c == '\'' || (c.is_whitespace() && c != ' ')) { tcx.dcx().emit_err(errors::DocAliasBadChar { span, attr_str, char_: c }); - return false; + return; } if doc_alias_str.starts_with(' ') || doc_alias_str.ends_with(' ') { tcx.dcx().emit_err(errors::DocAliasStartEnd { span, attr_str }); - return false; + return; } let span = meta.span(); @@ -781,7 +736,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } // we check the validity of params elsewhere - Target::Param => return false, + Target::Param => return, Target::Expression | Target::Statement | Target::Arm @@ -814,12 +769,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | Target::ExprField => None, } { tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location }); - return false; + return; } let item_name = self.tcx.hir().name(hir_id); if item_name == doc_alias { tcx.dcx().emit_err(errors::DocAliasNotAnAlias { span, attr_str }); - return false; + return; } if let Err(entry) = aliases.try_insert(doc_alias_str.to_owned(), span) { self.tcx.emit_node_span_lint( @@ -829,7 +784,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { errors::DocAliasDuplicated { first_defn: *entry.entry.get() }, ); } - true } fn check_doc_alias( @@ -838,46 +792,39 @@ impl<'tcx> CheckAttrVisitor<'tcx> { hir_id: HirId, target: Target, aliases: &mut FxHashMap, - ) -> bool { + ) { if let Some(values) = meta.meta_item_list() { - let mut errors = 0; for v in values { match v.lit() { Some(l) => match l.kind { LitKind::Str(s, _) => { - if !self.check_doc_alias_value(v, s, hir_id, target, true, aliases) { - errors += 1; - } + self.check_doc_alias_value(v, s, hir_id, target, true, aliases); } _ => { self.tcx .dcx() .emit_err(errors::DocAliasNotStringLiteral { span: v.span() }); - errors += 1; } }, None => { self.tcx .dcx() .emit_err(errors::DocAliasNotStringLiteral { span: v.span() }); - errors += 1; } } } - errors == 0 } else if let Some(doc_alias) = meta.value_str() { self.check_doc_alias_value(meta, doc_alias, hir_id, target, false, aliases) } else { self.dcx().emit_err(errors::DocAliasMalformed { span: meta.span() }); - false } } - fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { + fn check_doc_keyword(&self, meta: &NestedMetaItem, hir_id: HirId) { let doc_keyword = meta.value_str().unwrap_or(kw::Empty); if doc_keyword == kw::Empty { self.doc_attr_str_error(meta, "keyword"); - return false; + return; } let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), @@ -887,12 +834,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Some(ItemKind::Mod(module)) => { if !module.item_ids.is_empty() { self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() }); - return false; + return; } } _ => { self.dcx().emit_err(errors::DocKeywordNotMod { span: meta.span() }); - return false; + return; } } if !rustc_lexer::is_ident(doc_keyword.as_str()) { @@ -900,12 +847,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: meta.name_value_literal_span().unwrap_or_else(|| meta.span()), doc_keyword, }); - return false; } - true } - fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { + fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) { let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, @@ -920,18 +865,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }; if !is_valid { self.dcx().emit_err(errors::DocFakeVariadicNotValid { span: meta.span() }); - return false; } } _ => { self.dcx().emit_err(errors::DocKeywordOnlyImpl { span: meta.span() }); - return false; } } - true } - /// Checks `#[doc(inline)]`/`#[doc(no_inline)]` attributes. Returns `true` if valid. + /// Checks `#[doc(inline)]`/`#[doc(no_inline)]` attributes. /// /// A doc inlining attribute is invalid if it is applied to a non-`use` item, or /// if there are conflicting attributes for one item. @@ -947,7 +889,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { hir_id: HirId, target: Target, specified_inline: &mut Option<(bool, Span)>, - ) -> bool { + ) { match target { Target::Use | Target::ExternCrate => { let do_inline = meta.name_or_empty() == sym::inline; @@ -960,12 +902,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fluent::passes_doc_inline_conflict_second, ); self.dcx().emit_err(errors::DocKeywordConflict { spans }); - return false; } - true } else { *specified_inline = Some((do_inline, meta.span())); - true } } _ => { @@ -979,7 +918,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { .then(|| self.tcx.hir().span(hir_id)), }, ); - false } } } @@ -990,7 +928,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { meta: &NestedMetaItem, hir_id: HirId, target: Target, - ) -> bool { + ) { if target != Target::ExternCrate { self.tcx.emit_node_span_lint( INVALID_DOC_ATTRIBUTES, @@ -1002,7 +940,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { .then(|| self.tcx.hir().span(hir_id)), }, ); - return false; + return; } if self.tcx.extern_mod_stmt_cnum(hir_id.owner).is_none() { @@ -1016,10 +954,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { .then(|| self.tcx.hir().span(hir_id)), }, ); - return false; } - - true } /// Checks that an attribute is *not* used at the crate level. Returns `true` if valid. @@ -1064,8 +999,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that `doc(test(...))` attribute contains only valid attributes. Returns `true` if /// valid. - fn check_test_attr(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { - let mut is_valid = true; + fn check_test_attr(&self, meta: &NestedMetaItem, hir_id: HirId) { if let Some(metas) = meta.meta_item_list() { for i_meta in metas { match (i_meta.name_or_empty(), i_meta.meta_item()) { @@ -1079,7 +1013,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { path: rustc_ast_pretty::pprust::path_to_string(&m.path), }, ); - is_valid = false; } (_, None) => { self.tcx.emit_node_span_lint( @@ -1088,7 +1021,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { i_meta.span(), errors::DocTestLiteral, ); - is_valid = false; } } } @@ -1099,28 +1031,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> { meta.span(), errors::DocTestTakesList, ); - is_valid = false; } - is_valid } /// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes. - /// Returns `true` if valid. - fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { - if meta.meta_item_list().is_some() { - true - } else { + /// + fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) { + if meta.meta_item_list().is_none() { self.tcx.emit_node_span_lint( INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), errors::DocCfgHideTakesList, ); - false } } - /// Runs various checks on `#[doc]` attributes. Returns `true` if valid. + /// Runs various checks on `#[doc]` attributes. /// /// `specified_inline` should be initialized to `None` and kept for the scope /// of one item. Read the documentation of [`check_doc_inline`] for more information. @@ -1134,34 +1061,35 @@ impl<'tcx> CheckAttrVisitor<'tcx> { target: Target, specified_inline: &mut Option<(bool, Span)>, aliases: &mut FxHashMap, - ) -> bool { - let mut is_valid = true; - + ) { if let Some(mi) = attr.meta() && let Some(list) = mi.meta_item_list() { for meta in list { if let Some(i_meta) = meta.meta_item() { match i_meta.name_or_empty() { - sym::alias - if !self.check_attr_not_crate_level(meta, hir_id, "alias") - || !self.check_doc_alias(meta, hir_id, target, aliases) => - { - is_valid = false + sym::alias => { + if self.check_attr_not_crate_level(meta, hir_id, "alias") { + self.check_doc_alias(meta, hir_id, target, aliases); + } + } + + sym::keyword => { + if self.check_attr_not_crate_level(meta, hir_id, "keyword") { + self.check_doc_keyword(meta, hir_id); + } } - sym::keyword - if !self.check_attr_not_crate_level(meta, hir_id, "keyword") - || !self.check_doc_keyword(meta, hir_id) => - { - is_valid = false + sym::fake_variadic => { + if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") { + self.check_doc_fake_variadic(meta, hir_id); + } } - sym::fake_variadic - if !self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") - || !self.check_doc_fake_variadic(meta, hir_id) => - { - is_valid = false + sym::test => { + if self.check_attr_crate_level(attr, meta, hir_id) { + self.check_test_attr(meta, hir_id); + } } sym::html_favicon_url @@ -1169,62 +1097,36 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::html_playground_url | sym::issue_tracker_base_url | sym::html_root_url - | sym::html_no_source - | sym::test - | sym::rust_logo - if !self.check_attr_crate_level(attr, meta, hir_id) => - { - is_valid = false; + | sym::html_no_source => { + self.check_attr_crate_level(attr, meta, hir_id); } - sym::cfg_hide - if !self.check_attr_crate_level(attr, meta, hir_id) - || !self.check_doc_cfg_hide(meta, hir_id) => - { - is_valid = false; + sym::cfg_hide => { + if self.check_attr_crate_level(attr, meta, hir_id) { + self.check_doc_cfg_hide(meta, hir_id); + } } - sym::inline | sym::no_inline - if !self.check_doc_inline( - attr, - meta, - hir_id, - target, - specified_inline, - ) => - { - is_valid = false; + sym::inline | sym::no_inline => { + self.check_doc_inline(attr, meta, hir_id, target, specified_inline) } - sym::masked if !self.check_doc_masked(attr, meta, hir_id, target) => { - is_valid = false; - } + sym::masked => self.check_doc_masked(attr, meta, hir_id, target), // no_default_passes: deprecated // passes: deprecated // plugins: removed, but rustdoc warns about it itself - sym::alias - | sym::cfg - | sym::cfg_hide + sym::cfg | sym::hidden - | sym::html_favicon_url - | sym::html_logo_url - | sym::html_no_source - | sym::html_playground_url - | sym::html_root_url - | sym::inline - | sym::issue_tracker_base_url - | sym::keyword - | sym::masked | sym::no_default_passes - | sym::no_inline | sym::notable_trait | sym::passes - | sym::plugins - | sym::fake_variadic => {} + | sym::plugins => {} sym::rust_logo => { - if !self.tcx.features().rustdoc_internals { + if self.check_attr_crate_level(attr, meta, hir_id) + && !self.tcx.features().rustdoc_internals + { feature_err( &self.tcx.sess, sym::rustdoc_internals, @@ -1235,12 +1137,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - sym::test => { - if !self.check_test_attr(meta, hir_id) { - is_valid = false; - } - } - _ => { let path = rustc_ast_pretty::pprust::path_to_string(&i_meta.path); if i_meta.has_name(sym::spotlight) { @@ -1282,7 +1178,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { errors::DocTestUnknownAny { path }, ); } - is_valid = false; } } } else { @@ -1292,79 +1187,60 @@ impl<'tcx> CheckAttrVisitor<'tcx> { meta.span(), errors::DocInvalid, ); - is_valid = false; } } } - - is_valid } /// Warns against some misuses of `#[pass_by_value]` - fn check_pass_by_value(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_pass_by_value(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Struct | Target::Enum | Target::TyAlias => true, + Target::Struct | Target::Enum | Target::TyAlias => {} _ => { self.dcx().emit_err(errors::PassByValue { attr_span: attr.span, span }); - false } } } - fn check_allow_incoherent_impl(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_allow_incoherent_impl(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Method(MethodKind::Inherent) => true, + Target::Method(MethodKind::Inherent) => {} _ => { self.dcx().emit_err(errors::AllowIncoherentImpl { attr_span: attr.span, span }); - false } } } - fn check_has_incoherent_inherent_impls( - &self, - attr: &Attribute, - span: Span, - target: Target, - ) -> bool { + fn check_has_incoherent_inherent_impls(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Trait | Target::Struct | Target::Enum | Target::Union | Target::ForeignTy => { - true - } + Target::Trait | Target::Struct | Target::Enum | Target::Union | Target::ForeignTy => {} _ => { self.tcx .dcx() .emit_err(errors::HasIncoherentInherentImpl { attr_span: attr.span, span }); - false } } } - fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) -> bool { + fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) { if target != Target::ForeignFn { self.dcx().emit_err(errors::FfiPureInvalidTarget { attr_span }); - return false; + return; } if attrs.iter().any(|a| a.has_name(sym::ffi_const)) { // `#[ffi_const]` functions cannot be `#[ffi_pure]` self.dcx().emit_err(errors::BothFfiConstAndPure { attr_span }); - false - } else { - true } } - fn check_ffi_const(&self, attr_span: Span, target: Target) -> bool { - if target == Target::ForeignFn { - true - } else { + fn check_ffi_const(&self, attr_span: Span, target: Target) { + if target != Target::ForeignFn { self.dcx().emit_err(errors::FfiConstInvalidTarget { attr_span }); - false } } /// Warns against some misuses of `#[must_use]` - fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool { + fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) { if !matches!( target, Target::Fn @@ -1397,23 +1273,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> { errors::MustUseNoEffect { article, target }, ); } - - // For now, its always valid - true } - /// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid. - fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) -> bool { + /// Checks if `#[must_not_suspend]` is applied to a function. + fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Struct | Target::Enum | Target::Union | Target::Trait => true, + Target::Struct | Target::Enum | Target::Union | Target::Trait => {} _ => { self.dcx().emit_err(errors::MustNotSuspend { attr_span: attr.span, span }); - false } } } - /// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid. + /// Checks if `#[cold]` is applied to a non-function. fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => {} @@ -1489,21 +1361,19 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[no_link]` is applied to an `extern crate`. Returns `true` if valid. - fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool { + /// Checks if `#[no_link]` is applied to an `extern crate`. + fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { - Target::ExternCrate => true, + Target::ExternCrate => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[no_link]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_link"); - true } _ => { self.dcx().emit_err(errors::NoLink { attr_span: attr.span, span }); - false } } } @@ -1512,57 +1382,42 @@ impl<'tcx> CheckAttrVisitor<'tcx> { matches!(self.tcx.hir_node(hir_id), hir::Node::ImplItem(..)) } - /// Checks if `#[export_name]` is applied to a function or static. Returns `true` if valid. - fn check_export_name( - &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, - ) -> bool { + /// Checks if `#[export_name]` is applied to a function or static. + fn check_export_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { - Target::Static | Target::Fn => true, - Target::Method(..) if self.is_impl_item(hir_id) => true, + Target::Static | Target::Fn => {} + Target::Method(..) if self.is_impl_item(hir_id) => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[export_name]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "export_name"); - true } _ => { self.dcx().emit_err(errors::ExportName { attr_span: attr.span, span }); - false } } } - fn check_rustc_layout_scalar_valid_range( - &self, - attr: &Attribute, - span: Span, - target: Target, - ) -> bool { + fn check_rustc_layout_scalar_valid_range(&self, attr: &Attribute, span: Span, target: Target) { if target != Target::Struct { self.dcx().emit_err(errors::RustcLayoutScalarValidRangeNotStruct { attr_span: attr.span, span, }); - return false; + return; } let Some(list) = attr.meta_item_list() else { - return false; + return; }; - if matches!(&list[..], &[NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Int(..), .. })]) { - true - } else { + if !matches!(&list[..], &[NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Int(..), .. })]) + { self.tcx .dcx() .emit_err(errors::RustcLayoutScalarValidRangeArg { attr_span: attr.span }); - false } } @@ -1574,7 +1429,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: Span, target: Target, item: Option>, - ) -> bool { + ) { let is_function = matches!(target, Target::Fn); if !is_function { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { @@ -1582,12 +1437,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { defn_span: span, on_crate: hir_id == CRATE_HIR_ID, }); - return false; + return; } let Some(list) = attr.meta_item_list() else { // The attribute form is validated on AST. - return false; + return; }; let Some(ItemLike::Item(Item { @@ -1605,7 +1460,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr_span: attr.span, param_span: param.span, }); - return false; + return; } } } @@ -1615,7 +1470,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr_span: attr.span, generics_span: generics.span, }); - return false; + return; } let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128; @@ -1628,7 +1483,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span, arg_count: arg_count as usize, }); - return false; + return; } } else { invalid_args.push(meta.span()); @@ -1637,9 +1492,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if !invalid_args.is_empty() { self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexNegative { invalid_args }); - false - } else { - true } } @@ -1651,7 +1503,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr: &Attribute, span: Span, target: Target, - ) -> bool { + ) { let is_function = matches!(target, Target::Fn | Target::Method(..)); if !is_function { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { @@ -1659,9 +1511,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { defn_span: span, on_crate: hir_id == CRATE_HIR_ID, }); - false - } else { - true } } @@ -1673,7 +1522,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr: &Attribute, span: Span, target: Target, - ) -> bool { + ) { self.check_applied_to_fn_or_method(hir_id, attr, span, target) } @@ -1685,60 +1534,49 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr: &Attribute, span: Span, target: Target, - ) -> bool { + ) { self.check_applied_to_fn_or_method(hir_id, attr, span, target) } /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct. - fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_rustc_lint_opt_ty(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Struct => true, + Target::Struct => {} _ => { self.dcx().emit_err(errors::RustcLintOptTy { attr_span: attr.span, span }); - false } } } /// Checks that the `#[rustc_lint_opt_deny_field_access]` attribute is only applied to a field. - fn check_rustc_lint_opt_deny_field_access( - &self, - attr: &Attribute, - span: Span, - target: Target, - ) -> bool { + fn check_rustc_lint_opt_deny_field_access(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Field => true, + Target::Field => {} _ => { self.tcx .dcx() .emit_err(errors::RustcLintOptDenyFieldAccess { attr_span: attr.span, span }); - false } } } /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph /// option is passed to the compiler. - fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool { - if self.tcx.sess.opts.unstable_opts.query_dep_graph { - true - } else { + fn check_rustc_dirty_clean(&self, attr: &Attribute) { + if !self.tcx.sess.opts.unstable_opts.query_dep_graph { self.dcx().emit_err(errors::RustcDirtyClean { span: attr.span }); - false } } /// Checks if the attribute is applied to a trait. - fn check_must_be_applied_to_trait(&self, attr: &Attribute, span: Span, target: Target) -> bool { + fn check_must_be_applied_to_trait(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Trait => true, + Target::Trait => {} _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait { attr_span: attr.span, defn_span: span, }); - false } } } @@ -2036,43 +1874,38 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: Span, target: Target, attrs: &[Attribute], - ) -> bool { + ) { debug!("Checking target: {:?}", target); match target { Target::Fn => { for attr in attrs { if attr.is_proc_macro_attr() { debug!("Is proc macro attr"); - return true; + return; } } debug!("Is not proc macro attr"); - false } - Target::MacroDef => true, + Target::MacroDef => {} // FIXME(#80564): We permit struct fields and match arms to have an // `#[allow_internal_unstable]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm => { - self.inline_attr_str_error_without_macro_def( - hir_id, - attr, - "allow_internal_unstable", - ); - true - } + Target::Field | Target::Arm => self.inline_attr_str_error_without_macro_def( + hir_id, + attr, + "allow_internal_unstable", + ), _ => { self.tcx .dcx() .emit_err(errors::AllowInternalUnstable { attr_span: attr.span, span }); - false } } } /// Checks if the items on the `#[debugger_visualizer]` attribute are valid. - fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool { + fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) { // Here we only check that the #[debugger_visualizer] attribute is attached // to nothing other than a module. All other checks are done in the // `debugger_visualizer` query where they need to be done for decoding @@ -2081,11 +1914,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Mod => {} _ => { self.dcx().emit_err(errors::DebugVisualizerPlacement { span: attr.span }); - return false; } } - - true } /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. @@ -2096,26 +1926,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr: &Attribute, span: Span, target: Target, - ) -> bool { + ) { match target { Target::Fn | Target::Method(_) - if self.tcx.is_const_fn_raw(hir_id.expect_owner().to_def_id()) => - { - true - } + if self.tcx.is_const_fn_raw(hir_id.expect_owner().to_def_id()) => {} // FIXME(#80564): We permit struct fields and match arms to have an // `#[allow_internal_unstable]` attribute with just a lint, because we previously // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr, "allow_internal_unstable"); - true + self.inline_attr_str_error_with_macro_def(hir_id, attr, "allow_internal_unstable") } _ => { self.tcx .dcx() .emit_err(errors::RustcAllowConstFnUnstable { attr_span: attr.span, span }); - false } } } @@ -2126,65 +1951,56 @@ impl<'tcx> CheckAttrVisitor<'tcx> { attr: &Attribute, span: Span, target: Target, - ) -> bool { + ) { if let Target::ForeignFn = target && let hir::Node::Item(Item { kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic, .. }, .. }) = self.tcx.parent_hir_node(hir_id) { - return true; + return; } self.dcx().emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span }); - false } - fn check_rustc_std_internal_symbol( - &self, - attr: &Attribute, - span: Span, - target: Target, - ) -> bool { + fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Fn | Target::Static => true, + Target::Fn | Target::Static => {} _ => { self.tcx .dcx() .emit_err(errors::RustcStdInternalSymbol { attr_span: attr.span, span }); - false } } } - fn check_stability_promotable(&self, attr: &Attribute, target: Target) -> bool { + fn check_stability_promotable(&self, attr: &Attribute, target: Target) { match target { Target::Expression => { self.dcx().emit_err(errors::StabilityPromotable { attr_span: attr.span }); - false } - _ => true, + _ => {} } } - fn check_link_ordinal(&self, attr: &Attribute, _span: Span, target: Target) -> bool { + fn check_link_ordinal(&self, attr: &Attribute, _span: Span, target: Target) { match target { - Target::ForeignFn | Target::ForeignStatic => true, + Target::ForeignFn | Target::ForeignStatic => {} _ => { self.dcx().emit_err(errors::LinkOrdinal { attr_span: attr.span }); - false } } } - fn check_confusables(&self, attr: &Attribute, target: Target) -> bool { + fn check_confusables(&self, attr: &Attribute, target: Target) { match target { Target::Method(MethodKind::Inherent) => { let Some(meta) = attr.meta() else { - return false; + return; }; let ast::MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { - return false; + return; }; let mut candidates = Vec::new(); @@ -2198,21 +2014,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> { hi: meta.span().shrink_to_hi(), }, }); - return false; + return; }; candidates.push(meta_lit.symbol); } if candidates.is_empty() { self.dcx().emit_err(errors::EmptyConfusables { span: attr.span }); - return false; } - - true } _ => { self.dcx().emit_err(errors::Confusables { attr_span: attr.span }); - false } } } From abb1ebaae11d10648c55d28e098e1d7e993f0986 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 30 Jul 2024 11:03:03 -0400 Subject: [PATCH 285/489] Revert "opt-dist: dont overrwite config.toml when verifying" This reverts commit c81a40bbc02bb44aa99b3a94322dbf07e7a62ce1. --- src/tools/opt-dist/src/tests.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index d03d1936e0867..46b0a54380255 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -59,17 +59,26 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> { .join(format!("llvm-config{}", executable_extension())); assert!(llvm_config.is_file()); - let rustc = format!("build.rustc={}", rustc_path.to_string().replace('\\', "/")); - let cargo = format!("build.cargo={}", cargo_path.to_string().replace('\\', "/")); - let llvm_config = - format!("target.{host_triple}.llvm-config={}", llvm_config.to_string().replace('\\', "/")); + let config_content = format!( + r#"profile = "user" +change-id = 115898 - log::info!("Set the following configurations for running tests:"); - log::info!("\t{rustc}"); - log::info!("\t{cargo}"); - log::info!("\t{llvm_config}"); +[build] +rustc = "{rustc}" +cargo = "{cargo}" + +[target.{host_triple}] +llvm-config = "{llvm_config}" +"#, + rustc = rustc_path.to_string().replace('\\', "/"), + cargo = cargo_path.to_string().replace('\\', "/"), + llvm_config = llvm_config.to_string().replace('\\', "/") + ); + log::info!("Using following `config.toml` for running tests:\n{config_content}"); // Simulate a stage 0 compiler with the extracted optimized dist artifacts. + std::fs::write("config.toml", config_content)?; + let x_py = env.checkout_path().join("x.py"); let mut args = vec![ env.python_binary(), @@ -88,12 +97,6 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> { "tests/run-pass-valgrind", "tests/ui", "tests/crashes", - "--set", - &rustc, - "--set", - &cargo, - "--set", - &llvm_config, ]; for test_path in env.skipped_tests() { args.extend(["--skip", test_path]); From bb584882070f2f45b35f0af172069e7c00d63983 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 26 Jul 2024 23:35:48 +0100 Subject: [PATCH 286/489] Rewrite binary search implementation This restores the original binary search implementation from #45333 which has the nice property of having a loop count that only depends on the size of the slice. This, along with explicit conditional moves from #128250, means that the entire binary search loop can be perfectly predicted by the branch predictor. Additionally, LLVM is able to unroll the loop when the slice length is known at compile-time. This results in a very compact code sequence of 3-4 instructions per binary search step and zero branches. Fixes #53823 --- library/core/src/slice/mod.rs | 75 ++++++++++++++++++++--------------- library/core/tests/slice.rs | 12 +++--- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 0b0a416ea2439..45dc828eb2ed9 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -7,7 +7,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::cmp::Ordering::{self, Equal, Greater, Less}; -use crate::intrinsics::{exact_div, unchecked_sub}; +use crate::intrinsics::{exact_div, select_unpredictable, unchecked_sub}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{Bound, OneSidedRange, Range, RangeBounds}; @@ -2770,41 +2770,54 @@ impl [T] { where F: FnMut(&'a T) -> Ordering, { - // INVARIANTS: - // - 0 <= left <= left + size = right <= self.len() - // - f returns Less for everything in self[..left] - // - f returns Greater for everything in self[right..] let mut size = self.len(); - let mut left = 0; - let mut right = size; - while left < right { - let mid = left + size / 2; - - // SAFETY: the while condition means `size` is strictly positive, so - // `size/2 < size`. Thus `left + size/2 < left + size`, which - // coupled with the `left + size <= self.len()` invariant means - // we have `left + size/2 < self.len()`, and this is in-bounds. + if size == 0 { + return Err(0); + } + let mut base = 0usize; + + // This loop intentionally doesn't have an early exit if the comparison + // returns Equal. We want the number of loop iterations to depend *only* + // on the size of the input slice so that the CPU can reliably predict + // the loop count. + while size > 1 { + let half = size / 2; + let mid = base + half; + + // SAFETY: the call is made safe by the following inconstants: + // - `mid >= 0`: by definition + // - `mid < size`: `mid = size / 2 + size / 4 + size / 8 ...` let cmp = f(unsafe { self.get_unchecked(mid) }); - // This control flow produces conditional moves, which results in - // fewer branches and instructions than if/else or matching on - // cmp::Ordering. - // This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx. - left = if cmp == Less { mid + 1 } else { left }; - right = if cmp == Greater { mid } else { right }; - if cmp == Equal { - // SAFETY: same as the `get_unchecked` above - unsafe { hint::assert_unchecked(mid < self.len()) }; - return Ok(mid); - } - - size = right - left; + // Binary search interacts poorly with branch prediction, so force + // the compiler to use conditional moves if supported by the target + // architecture. + base = select_unpredictable(cmp == Greater, base, mid); + + // This is imprecise in the case where `size` is odd and the + // comparison returns Greater: the mid element still gets included + // by `size` even though it's known to be larger than the element + // being searched for. + // + // This is fine though: we gain more performance by keeping the + // loop iteration count invariant (and thus predictable) than we + // lose from considering one additional element. + size -= half; } - // SAFETY: directly true from the overall invariant. - // Note that this is `<=`, unlike the assume in the `Ok` path. - unsafe { hint::assert_unchecked(left <= self.len()) }; - Err(left) + // SAFETY: base is always in [0, size) because base <= mid. + let cmp = f(unsafe { self.get_unchecked(base) }); + if cmp == Equal { + // SAFETY: same as the `get_unchecked` above. + unsafe { hint::assert_unchecked(base < self.len()) }; + Ok(base) + } else { + let result = base + (cmp == Less) as usize; + // SAFETY: same as the `get_unchecked` above. + // Note that this is `<=`, unlike the assume in the `Ok` path. + unsafe { hint::assert_unchecked(result <= self.len()) }; + Err(result) + } } /// Binary searches this slice with a key extraction function. diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index acabedcdc2668..cdefb5d3eb201 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -69,13 +69,13 @@ fn test_binary_search() { assert_eq!(b.binary_search(&8), Err(5)); let b = [(); usize::MAX]; - assert_eq!(b.binary_search(&()), Ok(usize::MAX / 2)); + assert_eq!(b.binary_search(&()), Ok(usize::MAX - 1)); } #[test] fn test_binary_search_by_overflow() { let b = [(); usize::MAX]; - assert_eq!(b.binary_search_by(|_| Ordering::Equal), Ok(usize::MAX / 2)); + assert_eq!(b.binary_search_by(|_| Ordering::Equal), Ok(usize::MAX - 1)); assert_eq!(b.binary_search_by(|_| Ordering::Greater), Err(0)); assert_eq!(b.binary_search_by(|_| Ordering::Less), Err(usize::MAX)); } @@ -87,13 +87,13 @@ fn test_binary_search_implementation_details() { let b = [1, 1, 2, 2, 3, 3, 3]; assert_eq!(b.binary_search(&1), Ok(1)); assert_eq!(b.binary_search(&2), Ok(3)); - assert_eq!(b.binary_search(&3), Ok(5)); + assert_eq!(b.binary_search(&3), Ok(6)); let b = [1, 1, 1, 1, 1, 3, 3, 3, 3]; assert_eq!(b.binary_search(&1), Ok(4)); - assert_eq!(b.binary_search(&3), Ok(7)); + assert_eq!(b.binary_search(&3), Ok(8)); let b = [1, 1, 1, 1, 3, 3, 3, 3, 3]; - assert_eq!(b.binary_search(&1), Ok(2)); - assert_eq!(b.binary_search(&3), Ok(4)); + assert_eq!(b.binary_search(&1), Ok(3)); + assert_eq!(b.binary_search(&3), Ok(8)); } #[test] From 4feb949617c9a24f8750d8a69197f086b0005cee Mon Sep 17 00:00:00 2001 From: binarycat Date: Wed, 24 Jul 2024 14:05:58 -0400 Subject: [PATCH 287/489] migrate fmt-write-bloat to rmake --- src/tools/run-make-support/src/env.rs | 7 +++ src/tools/run-make-support/src/lib.rs | 1 + src/tools/run-make-support/src/symbols.rs | 43 +++++++++++++++++++ .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/fmt-write-bloat/Makefile | 25 ----------- tests/run-make/fmt-write-bloat/rmake.rs | 35 +++++++++++++++ 6 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 src/tools/run-make-support/src/symbols.rs delete mode 100644 tests/run-make/fmt-write-bloat/Makefile create mode 100644 tests/run-make/fmt-write-bloat/rmake.rs diff --git a/src/tools/run-make-support/src/env.rs b/src/tools/run-make-support/src/env.rs index f52524e7d54cd..e6460fb93d3e9 100644 --- a/src/tools/run-make-support/src/env.rs +++ b/src/tools/run-make-support/src/env.rs @@ -17,3 +17,10 @@ pub fn env_var_os(name: &str) -> OsString { None => panic!("failed to retrieve environment variable {name:?}"), } } + +/// Check if `NO_DEBUG_ASSERTIONS` is set (usually this may be set in CI jobs). +#[track_caller] +#[must_use] +pub fn no_debug_assertions() -> bool { + std::env::var_os("NO_DEBUG_ASSERTIONS").is_some() +} diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 085120764b463..36ea6125f2780 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -21,6 +21,7 @@ pub mod run; pub mod scoped_run; pub mod string; pub mod targets; +pub mod symbols; // Internally we call our fs-related support module as `fs`, but re-export its content as `rfs` // to tests to avoid colliding with commonly used `use std::fs;`. diff --git a/src/tools/run-make-support/src/symbols.rs b/src/tools/run-make-support/src/symbols.rs new file mode 100644 index 0000000000000..52119ba4991a8 --- /dev/null +++ b/src/tools/run-make-support/src/symbols.rs @@ -0,0 +1,43 @@ +use object::{self, Object, ObjectSymbol, SymbolIterator}; +use std::path::Path; + +/// Iterate through the symbols in an object file. +/// +/// Uses a callback because `SymbolIterator` does not own its data. +/// +/// Panics if `path` is not a valid object file readable by the current user. +pub fn with_symbol_iter(path: P, func: F) -> R +where + P: AsRef, + F: FnOnce(&mut SymbolIterator<'_, '_>) -> R, +{ + let raw_bytes = crate::fs::read(path); + let f = object::File::parse(raw_bytes.as_slice()).expect("unable to parse file"); + let mut iter = f.symbols(); + func(&mut iter) +} + +/// Check an object file's symbols for substrings. +/// +/// Returns `true` if any of the symbols found in the object file at +/// `path` contain a substring listed in `substrings`. +/// +/// Panics if `path` is not a valid object file readable by the current user. +pub fn any_symbol_contains(path: impl AsRef, substrings: &[&str]) -> bool { + with_symbol_iter(path, |syms| { + for sym in syms { + for substring in substrings { + if sym + .name_bytes() + .unwrap() + .windows(substring.len()) + .any(|x| x == substring.as_bytes()) + { + eprintln!("{:?} contains {}", sym, substring); + return true; + } + } + } + false + }) +} diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a84b89ff4a113..db06040de2b3a 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -10,7 +10,6 @@ run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile -run-make/fmt-write-bloat/Makefile run-make/foreign-double-unwind/Makefile run-make/foreign-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile diff --git a/tests/run-make/fmt-write-bloat/Makefile b/tests/run-make/fmt-write-bloat/Makefile deleted file mode 100644 index 70e04b9af51fe..0000000000000 --- a/tests/run-make/fmt-write-bloat/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -include ../tools.mk - -# ignore-windows - -ifeq ($(shell $(RUSTC) -vV | grep 'host: $(TARGET)'),) - -# Don't run this test when cross compiling. -all: - -else - -NM = nm - -PANIC_SYMS = panic_bounds_check Debug - -# Allow for debug_assert!() in debug builds of std. -ifdef NO_DEBUG_ASSERTIONS -PANIC_SYMS += panicking panic_fmt pad_integral Display Debug -endif - -all: main.rs - $(RUSTC) $< -O - $(NM) $(call RUN_BINFILE,main) | $(CGREP) -v $(PANIC_SYMS) - -endif diff --git a/tests/run-make/fmt-write-bloat/rmake.rs b/tests/run-make/fmt-write-bloat/rmake.rs new file mode 100644 index 0000000000000..120c1cbccdd3c --- /dev/null +++ b/tests/run-make/fmt-write-bloat/rmake.rs @@ -0,0 +1,35 @@ +//! Before #78122, writing any `fmt::Arguments` would trigger the inclusion of `usize` formatting +//! and padding code in the resulting binary, because indexing used in `fmt::write` would generate +//! code using `panic_bounds_check`, which prints the index and length. +//! +//! These bounds checks are not necessary, as `fmt::Arguments` never contains any out-of-bounds +//! indexes. The test is a `run-make` test, because it needs to check the result after linking. A +//! codegen or assembly test doesn't check the parts that will be pulled in from `core` by the +//! linker. +//! +//! In this test, we try to check that the `usize` formatting and padding code are not present in +//! the final binary by checking that panic symbols such as `panic_bounds_check` are **not** +//! present. +//! +//! Some CI jobs try to run faster by disabling debug assertions (through setting +//! `NO_DEBUG_ASSERTIONS=1`). If debug assertions are disabled, then we can check for the absence of +//! additional `usize` formatting and padding related symbols. + +// Reason: This test is `ignore-windows` because the `no_std` test (using `#[link(name = "c")])` +// doesn't link on windows. +//@ ignore-windows +//@ ignore-cross-compile + +use run_make_support::{env::no_debug_assertions, rustc, symbols::any_symbol_contains}; + +fn main() { + rustc().input("main.rs").opt().run(); + // panic machinery identifiers, these should not appear in the final binary + let mut panic_syms = vec!["panic_bounds_check", "Debug"]; + if no_debug_assertions() { + // if debug assertions are allowed, we need to allow these, + // otherwise, add them to the list of symbols to deny. + panic_syms.extend_from_slice(&["panicking", "panic_fmt", "pad_integral", "Display"]); + } + assert!(!any_symbol_contains("main", &panic_syms)); +} From 689bb118ce3f24da8fa2ce20a0c34e4d76097a26 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 27 Jun 2024 16:32:54 -0400 Subject: [PATCH 288/489] rewrite symbol-visibility to rmake --- src/tools/compiletest/src/command-list.rs | 1 + src/tools/run-make-support/src/command.rs | 2 + .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/symbol-visibility/Makefile | 123 ------------- tests/run-make/symbol-visibility/rmake.rs | 168 ++++++++++++++++++ 5 files changed, 171 insertions(+), 124 deletions(-) delete mode 100644 tests/run-make/symbol-visibility/Makefile create mode 100644 tests/run-make/symbol-visibility/rmake.rs diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index c356f4266f016..288f90ea12399 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -117,6 +117,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-watchos", "ignore-windows", "ignore-windows-gnu", + "ignore-windows-msvc", "ignore-x32", "ignore-x86", "ignore-x86_64", diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index fb94ff996f0d6..86d2e4a852a30 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -163,11 +163,13 @@ pub struct CompletedProcess { impl CompletedProcess { #[must_use] + #[track_caller] pub fn stdout_utf8(&self) -> String { String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8") } #[must_use] + #[track_caller] pub fn stderr_utf8(&self) -> String { String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8") } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a84b89ff4a113..6bb9ba0428eca 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -52,7 +52,6 @@ run-make/split-debuginfo/Makefile run-make/stable-symbol-names/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/symbol-mangling-hashed/Makefile -run-make/symbol-visibility/Makefile run-make/sysroot-crates-are-unstable/Makefile run-make/thumb-none-cortex-m/Makefile run-make/thumb-none-qemu/Makefile diff --git a/tests/run-make/symbol-visibility/Makefile b/tests/run-make/symbol-visibility/Makefile deleted file mode 100644 index 9159af214ca7b..0000000000000 --- a/tests/run-make/symbol-visibility/Makefile +++ /dev/null @@ -1,123 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-windows-msvc - -NM=nm -D -CDYLIB_NAME=liba_cdylib.so -RDYLIB_NAME=liba_rust_dylib.so -PROC_MACRO_NAME=liba_proc_macro.so -EXE_NAME=an_executable -COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.so - -ifeq ($(UNAME),Darwin) -NM=nm -gU -CDYLIB_NAME=liba_cdylib.dylib -RDYLIB_NAME=liba_rust_dylib.dylib -PROC_MACRO_NAME=liba_proc_macro.dylib -EXE_NAME=an_executable -COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dylib -endif - -ifdef IS_WINDOWS -NM=nm -g -CDYLIB_NAME=liba_cdylib.dll.a -RDYLIB_NAME=liba_rust_dylib.dll.a -PROC_MACRO_NAME=liba_proc_macro.dll -EXE_NAME=an_executable.exe -COMBINED_CDYLIB_NAME=libcombined_rlib_dylib.dll.a -endif - -# `grep` regex for symbols produced by either `legacy` or `v0` mangling -RE_ANY_RUST_SYMBOL="_ZN.*h.*E\|_R[a-zA-Z0-9_]+" - -all: - $(RUSTC) -Zshare-generics=no an_rlib.rs - $(RUSTC) -Zshare-generics=no a_cdylib.rs - $(RUSTC) -Zshare-generics=no a_rust_dylib.rs - $(RUSTC) -Zshare-generics=no a_proc_macro.rs - $(RUSTC) -Zshare-generics=no an_executable.rs - $(RUSTC) -Zshare-generics=no a_cdylib.rs --crate-name combined_rlib_dylib --crate-type=rlib,cdylib - - # Check that a cdylib exports its public #[no_mangle] functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] - # Check that a cdylib exports the public #[no_mangle] functions of dependencies - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] - # Check that a cdylib DOES NOT export any public Rust functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] - - # Check that a Rust dylib exports its monomorphic functions - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rust_dylib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] - # Check that a Rust dylib does not export generics if -Zshare-generics=no - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rust_dylib)" -eq "0" ] - - - # Check that a Rust dylib exports the monomorphic functions from its dependencies - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ] - # Check that a Rust dylib does not export generics if -Zshare-generics=no - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "0" ] - - # Check that a proc macro exports its public #[no_mangle] functions - # FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] - # Check that a proc macro exports the public #[no_mangle] functions of dependencies - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] - # Check that a proc macro DOES NOT export any public Rust functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] - -# FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 -ifndef IS_WINDOWS - # Check that an executable does not export any dynamic symbols - [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ] - [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_rust_function_from_exe)" -eq "0" ] -endif - - - # Check the combined case, where we generate a cdylib and an rlib in the same - # compilation session: - # Check that a cdylib exports its public #[no_mangle] functions - [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] - # Check that a cdylib exports the public #[no_mangle] functions of dependencies - [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] - # Check that a cdylib DOES NOT export any public Rust functions - [ "$$($(NM) $(TMPDIR)/$(COMBINED_CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] - - - $(RUSTC) -Zshare-generics=yes an_rlib.rs - $(RUSTC) -Zshare-generics=yes a_cdylib.rs - $(RUSTC) -Zshare-generics=yes a_rust_dylib.rs - $(RUSTC) -Zshare-generics=yes a_proc_macro.rs - $(RUSTC) -Zshare-generics=yes an_executable.rs - - # Check that a cdylib exports its public #[no_mangle] functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] - # Check that a cdylib exports the public #[no_mangle] functions of dependencies - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] - # Check that a cdylib DOES NOT export any public Rust functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] - - # Check that a Rust dylib exports its monomorphic functions, including generics this time - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rust_dylib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rust_dylib)" -eq "1" ] - - # Check that a Rust dylib exports the monomorphic functions from its dependencies - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_rust_function_from_rlib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -v __imp_ | grep -c public_generic_function_from_rlib)" -eq "1" ] - - # Check that a proc macro exports its public #[no_mangle] functions - # FIXME(#99978) avoid exporting #[no_mangle] symbols for proc macros - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_cdylib)" -eq "1" ] - # Check that a proc macro exports the public #[no_mangle] functions of dependencies - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "1" ] - # Check that a proc macro DOES NOT export any public Rust functions - [ "$$($(NM) $(TMPDIR)/$(CDYLIB_NAME) | grep -v __imp_ | grep -c $(RE_ANY_RUST_SYMBOL))" -eq "0" ] - -ifndef IS_WINDOWS - # Check that an executable does not export any dynamic symbols - [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_c_function_from_rlib)" -eq "0" ] - [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -v __imp_ | grep -c public_rust_function_from_exe)" -eq "0" ] -endif diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs new file mode 100644 index 0000000000000..5fff89e071e11 --- /dev/null +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -0,0 +1,168 @@ +// Dynamic libraries on Rust used to export a very high amount of symbols, +// going as far as filling the output with mangled names and generic function +// names. After the rework of #38117, this test checks that no mangled Rust symbols +// are exported, and that generics are only shown if explicitely requested. +// See https://github.com/rust-lang/rust/issues/37530 + +//@ ignore-windows-msvc + +use run_make_support::{bin_name, dynamic_lib_name, is_windows, llvm_readobj, regex, rustc}; + +fn main() { + let mut cdylib_name = dynamic_lib_name("a_cdylib"); + let mut rdylib_name = dynamic_lib_name("a_rust_dylib"); + let exe_name = bin_name("an_executable"); + let mut combined_cdylib_name = dynamic_lib_name("combined_rlib_dylib"); + rustc().arg("-Zshare-generics=no").input("an_rlib.rs").run(); + rustc().arg("-Zshare-generics=no").input("a_cdylib.rs").run(); + rustc().arg("-Zshare-generics=no").input("a_rust_dylib.rs").run(); + rustc().arg("-Zshare-generics=no").input("a_proc_macro.rs").run(); + rustc().arg("-Zshare-generics=no").input("an_executable.rs").run(); + rustc() + .arg("-Zshare-generics=no") + .input("a_cdylib.rs") + .crate_name("combined_rlib_dylib") + .crate_type("rlib,cdylib") + .run(); + + // Check that a cdylib exports its public #[no_mangle] functions + symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true); + // Check that a cdylib exports the public #[no_mangle] functions of dependencies + symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true); + // Check that a cdylib DOES NOT export any public Rust functions + symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false); + + // Check that a Rust dylib exports its monomorphic functions + symbols_check( + &rdylib_name, + SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"), + true, + ); + symbols_check( + &rdylib_name, + SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"), + true, + ); + // Check that a Rust dylib does not export generics if -Zshare-generics=no + symbols_check( + &rdylib_name, + SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"), + false, + ); + + // Check that a Rust dylib exports the monomorphic functions from its dependencies + symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true); + symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), true); + // Check that a Rust dylib does not export generics if -Zshare-generics=no + symbols_check( + &rdylib_name, + SymbolCheckType::StrSymbol("public_generic_function_from_rlib"), + false, + ); + + // FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 + // if is_windows() { + // // Check that an executable does not export any dynamic symbols + // symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib") + //, false); + // symbols_check( + // &exe_name, + // SymbolCheckType::StrSymbol("public_rust_function_from_exe"), + // false, + // ); + // } + + // Check the combined case, where we generate a cdylib and an rlib in the same + // compilation session: + // Check that a cdylib exports its public //[no_mangle] functions + symbols_check( + &combined_cdylib_name, + SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), + true, + ); + // Check that a cdylib exports the public //[no_mangle] functions of dependencies + symbols_check( + &combined_cdylib_name, + SymbolCheckType::StrSymbol("public_c_function_from_rlib"), + true, + ); + // Check that a cdylib DOES NOT export any public Rust functions + symbols_check(&combined_cdylib_name, SymbolCheckType::AnyRustSymbol, false); + + rustc().arg("-Zshare-generics=yes").input("an_rlib.rs").run(); + rustc().arg("-Zshare-generics=yes").input("a_cdylib.rs").run(); + rustc().arg("-Zshare-generics=yes").input("a_rust_dylib.rs").run(); + rustc().arg("-Zshare-generics=yes").input("an_executable.rs").run(); + + // Check that a cdylib exports its public //[no_mangle] functions + symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true); + // Check that a cdylib exports the public //[no_mangle] functions of dependencies + symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true); + // Check that a cdylib DOES NOT export any public Rust functions + symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false); + + // Check that a Rust dylib exports its monomorphic functions, including generics this time + symbols_check( + &rdylib_name, + SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"), + true, + ); + symbols_check( + &rdylib_name, + SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"), + true, + ); + symbols_check( + &rdylib_name, + SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"), + true, + ); + + // Check that a Rust dylib exports the monomorphic functions from its dependencies + symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true); + symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), true); + symbols_check( + &rdylib_name, + SymbolCheckType::StrSymbol("public_generic_function_from_rlib"), + true, + ); + + // FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 + // if is_windows() { + // // Check that an executable does not export any dynamic symbols + // symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib") + //, false); + // symbols_check( + // &exe_name, + // SymbolCheckType::StrSymbol("public_rust_function_from_exe"), + // false, + // ); + // } +} + +#[track_caller] +fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) { + let out = llvm_readobj().arg("--dyn-symbols").input(path).run().stdout_utf8(); + assert_eq!( + out.lines() + .filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type)) + .count() + == 1, + exists_once + ); +} + +fn has_symbol(line: &str, symbol_check_type: SymbolCheckType) -> bool { + if let SymbolCheckType::StrSymbol(expected) = symbol_check_type { + line.contains(expected) + } else { + let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap(); + regex.is_match(line) + } +} + +#[derive(Clone, Copy)] +enum SymbolCheckType { + StrSymbol(&'static str), + AnyRustSymbol, +} From dcaa17a661d5101c7ee79703f0c4a14e8ddcb5f5 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 15 Jul 2024 11:52:37 -0400 Subject: [PATCH 289/489] invalid stdout_utf8 handling in run_make_support --- src/tools/run-make-support/src/command.rs | 6 ++++++ tests/run-make/symbol-visibility/rmake.rs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index 86d2e4a852a30..532e3b8e048a0 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -168,6 +168,12 @@ impl CompletedProcess { String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8") } + #[must_use] + #[track_caller] + pub fn invalid_stdout_utf8(&self) -> String { + String::from_utf8_lossy(&self.output.stdout.clone()).to_string() + } + #[must_use] #[track_caller] pub fn stderr_utf8(&self) -> String { diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs index 5fff89e071e11..cd085cf05d0ed 100644 --- a/tests/run-make/symbol-visibility/rmake.rs +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -142,7 +142,7 @@ fn main() { #[track_caller] fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) { - let out = llvm_readobj().arg("--dyn-symbols").input(path).run().stdout_utf8(); + let out = llvm_readobj().arg("--dyn-symbols").input(path).run().invalid_stdout_utf8(); assert_eq!( out.lines() .filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type)) From ebd6718218642b8b63584214e35f7d69d24ae845 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 30 Jul 2024 13:33:25 -0400 Subject: [PATCH 290/489] tidy this commit cannot easily be squashed, since there is already a PR based on the previous commit. --- src/tools/run-make-support/src/symbols.rs | 3 ++- tests/run-make/fmt-write-bloat/rmake.rs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tools/run-make-support/src/symbols.rs b/src/tools/run-make-support/src/symbols.rs index 52119ba4991a8..fd0c866bcc927 100644 --- a/src/tools/run-make-support/src/symbols.rs +++ b/src/tools/run-make-support/src/symbols.rs @@ -1,6 +1,7 @@ -use object::{self, Object, ObjectSymbol, SymbolIterator}; use std::path::Path; +use object::{self, Object, ObjectSymbol, SymbolIterator}; + /// Iterate through the symbols in an object file. /// /// Uses a callback because `SymbolIterator` does not own its data. diff --git a/tests/run-make/fmt-write-bloat/rmake.rs b/tests/run-make/fmt-write-bloat/rmake.rs index 120c1cbccdd3c..4ae226ec0e234 100644 --- a/tests/run-make/fmt-write-bloat/rmake.rs +++ b/tests/run-make/fmt-write-bloat/rmake.rs @@ -20,7 +20,9 @@ //@ ignore-windows //@ ignore-cross-compile -use run_make_support::{env::no_debug_assertions, rustc, symbols::any_symbol_contains}; +use run_make_support::env::no_debug_assertions; +use run_make_support::rustc; +use run_make_support::symbols::any_symbol_contains; fn main() { rustc().input("main.rs").opt().run(); From a2555b976ac8994ede5f148d91a8751550e3ba03 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 31 Jul 2024 02:36:44 +0900 Subject: [PATCH 291/489] fix: Errors on method call inferences with elided lifetimes --- .../crates/hir-ty/src/infer/expr.rs | 64 ++++++++++++------- .../crates/hir-ty/src/tests/regression.rs | 32 ++++++++++ 2 files changed, 72 insertions(+), 24 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index 24479a027fd6e..3d762b174ace0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -12,7 +12,7 @@ use hir_def::{ ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp, }, lang_item::{LangItem, LangItemTarget}, - path::{GenericArgs, Path}, + path::{GenericArg, GenericArgs, Path}, BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId, }; use hir_expand::name::Name; @@ -1851,29 +1851,45 @@ impl InferenceContext<'_> { if let Some(generic_args) = generic_args { // if args are provided, it should be all of them, but we can't rely on that let self_params = type_params + const_params + lifetime_params; - for (arg, kind_id) in - generic_args.args.iter().zip(def_generics.iter_self_id()).take(self_params) - { - let arg = generic_arg_to_chalk( - self.db, - kind_id, - arg, - self, - |this, type_ref| this.make_ty(type_ref), - |this, c, ty| { - const_or_path_to_chalk( - this.db, - &this.resolver, - this.owner.into(), - ty, - c, - ParamLoweringMode::Placeholder, - || this.generics(), - DebruijnIndex::INNERMOST, - ) - }, - |this, lt_ref| this.make_lifetime(lt_ref), - ); + + let mut args = generic_args.args.iter().peekable(); + for kind_id in def_generics.iter_self_id().take(self_params) { + let arg = args.peek(); + let arg = match (kind_id, arg) { + // Lifetimes can be elided. + // Once we have implemented lifetime elision correctly, + // this should be handled in a proper way. + ( + GenericParamId::LifetimeParamId(_), + None | Some(GenericArg::Type(_) | GenericArg::Const(_)), + ) => error_lifetime().cast(Interner), + + // If we run out of `generic_args`, stop pushing substs + (_, None) => break, + + // Normal cases + (_, Some(_)) => generic_arg_to_chalk( + self.db, + kind_id, + args.next().unwrap(), // `peek()` is `Some(_)`, so guaranteed no panic + self, + |this, type_ref| this.make_ty(type_ref), + |this, c, ty| { + const_or_path_to_chalk( + this.db, + &this.resolver, + this.owner.into(), + ty, + c, + ParamLoweringMode::Placeholder, + || this.generics(), + DebruijnIndex::INNERMOST, + ) + }, + |this, lt_ref| this.make_lifetime(lt_ref), + ), + }; + substs.push(arg); } }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index aa7b00b8deb4a..540e219920c9c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -2041,3 +2041,35 @@ fn main() { "#, ); } + +#[test] +fn issue_17734() { + check_types( + r#" +fn test() { + let x = S::foo::<'static, &()>(&S); + // ^ Wrap<'?, ()> + let x = S::foo::<&()>(&S); + // ^ Wrap<'?, ()> + let x = S.foo::<&()>(); + // ^ Wrap<'?, ()> +} + +struct S; + +impl S { + pub fn foo<'a, T: Trait<'a>>(&'a self) -> T::Proj { + loop {} + } +} + +struct Wrap<'a, T>(T); +trait Trait<'a> { + type Proj; +} +impl<'a, T> Trait<'a> for &'a T { + type Proj = Wrap<'a, T>; +} +"#, + ) +} From 01a266206b4c923a8fbbc49b3be7d630e48eef86 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 11 Jul 2024 16:00:15 -0400 Subject: [PATCH 292/489] rewrite and rename issue-69368 to rmake --- src/tools/compiletest/src/command-list.rs | 1 + .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../a.rs | 0 .../b.rs | 0 .../c.rs | 0 .../crate-circular-deps-link/rmake.rs | 20 +++++++++++++++++++ tests/run-make/issue-69368/Makefile | 19 ------------------ .../link-eh-frame-terminator/rmake.rs | 11 ++++++---- 8 files changed, 28 insertions(+), 24 deletions(-) rename tests/run-make/{issue-69368 => crate-circular-deps-link}/a.rs (100%) rename tests/run-make/{issue-69368 => crate-circular-deps-link}/b.rs (100%) rename tests/run-make/{issue-69368 => crate-circular-deps-link}/c.rs (100%) create mode 100644 tests/run-make/crate-circular-deps-link/rmake.rs delete mode 100644 tests/run-make/issue-69368/Makefile diff --git a/src/tools/compiletest/src/command-list.rs b/src/tools/compiletest/src/command-list.rs index c356f4266f016..288f90ea12399 100644 --- a/src/tools/compiletest/src/command-list.rs +++ b/src/tools/compiletest/src/command-list.rs @@ -117,6 +117,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-watchos", "ignore-windows", "ignore-windows-gnu", + "ignore-windows-msvc", "ignore-x32", "ignore-x86", "ignore-x86_64", diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index beff9de23719b..5306e2368b706 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -18,7 +18,6 @@ run-make/foreign-exceptions/Makefile run-make/foreign-rust-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile run-make/issue-36710/Makefile -run-make/issue-69368/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/issue-88756-default-output/Makefile run-make/jobserver-error/Makefile diff --git a/tests/run-make/issue-69368/a.rs b/tests/run-make/crate-circular-deps-link/a.rs similarity index 100% rename from tests/run-make/issue-69368/a.rs rename to tests/run-make/crate-circular-deps-link/a.rs diff --git a/tests/run-make/issue-69368/b.rs b/tests/run-make/crate-circular-deps-link/b.rs similarity index 100% rename from tests/run-make/issue-69368/b.rs rename to tests/run-make/crate-circular-deps-link/b.rs diff --git a/tests/run-make/issue-69368/c.rs b/tests/run-make/crate-circular-deps-link/c.rs similarity index 100% rename from tests/run-make/issue-69368/c.rs rename to tests/run-make/crate-circular-deps-link/c.rs diff --git a/tests/run-make/crate-circular-deps-link/rmake.rs b/tests/run-make/crate-circular-deps-link/rmake.rs new file mode 100644 index 0000000000000..7cc28ac93e148 --- /dev/null +++ b/tests/run-make/crate-circular-deps-link/rmake.rs @@ -0,0 +1,20 @@ +// Test that previously triggered a linker failure with root cause +// similar to one found in the issue #69368. +// +// The crate that provides oom lang item is missing some other lang +// items. Necessary to prevent the use of start-group / end-group. +// +// The weak lang items are defined in a separate compilation units, +// so that linker could omit them if not used. +// +// The crates that need those weak lang items are dependencies of +// crates that provide them. +// See https://github.com/rust-lang/rust/issues/69371 + +use run_make_support::rustc; + +fn main() { + rustc().input("a.rs").run(); + rustc().input("b.rs").run(); + rustc().input("c.rs").run(); +} diff --git a/tests/run-make/issue-69368/Makefile b/tests/run-make/issue-69368/Makefile deleted file mode 100644 index b1229d1b07fc7..0000000000000 --- a/tests/run-make/issue-69368/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Test that previously triggered a linker failure with root cause -# similar to one found in the issue #69368. -# -# The crate that provides oom lang item is missing some other lang -# items. Necessary to prevent the use of start-group / end-group. -# -# The weak lang items are defined in a separate compilation units, -# so that linker could omit them if not used. -# -# The crates that need those weak lang items are dependencies of -# crates that provide them. - -all: - $(RUSTC) a.rs - $(RUSTC) b.rs - $(RUSTC) c.rs diff --git a/tests/run-make/link-eh-frame-terminator/rmake.rs b/tests/run-make/link-eh-frame-terminator/rmake.rs index 750d068ac98cf..6bfae386ea1ab 100644 --- a/tests/run-make/link-eh-frame-terminator/rmake.rs +++ b/tests/run-make/link-eh-frame-terminator/rmake.rs @@ -4,17 +4,20 @@ // after the fix in #85395. // See https://github.com/rust-lang/rust/issues/47551 -//FIXME(Oneirical): See if it works on anything other than only linux and 64 bit -// maybe riscv64gc-unknown-linux-gnu +//@ only-linux +// Reason: the ZERO terminator is unique to the Linux architecture. +//@ ignore-32bit +// Reason: the usage of a large array in the test causes an out-of-memory +// error on 32 bit systems. -use run_make_support::{llvm_objdump, run, rustc}; +use run_make_support::{bin_name, llvm_objdump, run, rustc}; fn main() { rustc().input("eh_frame-terminator.rs").run(); run("eh_frame-terminator").assert_stdout_contains("1122334455667788"); llvm_objdump() .arg("--dwarf=frames") - .input("eh_frame-terminator") + .input(bin_name("eh_frame-terminator")) .run() .assert_stdout_contains("ZERO terminator"); } From e7f89a7eea766af95604405d666e089a42cd4b48 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Sat, 13 Jul 2024 20:14:22 +0800 Subject: [PATCH 293/489] derive(SmartPointer): rewrite bounds in where and generic bounds --- .../src/deriving/smart_ptr.rs | 244 ++++++++++++++++-- .../deriving-smart-pointer-expanded.rs | 22 ++ .../deriving-smart-pointer-expanded.stdout | 44 ++++ .../smart-pointer-bounds-issue-127647.rs | 78 ++++++ 4 files changed, 371 insertions(+), 17 deletions(-) create mode 100644 tests/ui/deriving/deriving-smart-pointer-expanded.rs create mode 100644 tests/ui/deriving/deriving-smart-pointer-expanded.stdout create mode 100644 tests/ui/deriving/smart-pointer-bounds-issue-127647.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index bbc7cd3962720..02555bd799c42 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -1,14 +1,18 @@ use std::mem::swap; +use ast::ptr::P; use ast::HasAttrs; +use rustc_ast::mut_visit::MutVisitor; +use rustc_ast::visit::BoundKind; use rustc_ast::{ self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem, - TraitBoundModifiers, VariantData, + TraitBoundModifiers, VariantData, WherePredicate, }; use rustc_attr as attr; +use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::symbol::{sym, Ident}; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; use smallvec::{smallvec, SmallVec}; use thin_vec::{thin_vec, ThinVec}; @@ -141,33 +145,239 @@ pub fn expand_deriving_smart_ptr( alt_self_params[pointee_param_idx] = GenericArg::Type(s_ty.clone()); let alt_self_type = cx.ty_path(cx.path_all(span, false, vec![name_ident], alt_self_params)); + // # Add `Unsize<__S>` bound to `#[pointee]` at the generic parameter location + // // Find the `#[pointee]` parameter and add an `Unsize<__S>` bound to it. let mut impl_generics = generics.clone(); + let pointee_ty_ident = generics.params[pointee_param_idx].ident; + let mut self_bounds; { - let p = &mut impl_generics.params[pointee_param_idx]; + let pointee = &mut impl_generics.params[pointee_param_idx]; + self_bounds = pointee.bounds.clone(); let arg = GenericArg::Type(s_ty.clone()); let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]); - p.bounds.push(cx.trait_bound(unsize, false)); + pointee.bounds.push(cx.trait_bound(unsize, false)); let mut attrs = thin_vec![]; - swap(&mut p.attrs, &mut attrs); - p.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect(); + swap(&mut pointee.attrs, &mut attrs); + // Drop `#[pointee]` attribute since it should not be recognized outside `derive(SmartPointer)` + pointee.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect(); } - // Add the `__S: ?Sized` extra parameter to the impl block. + // # Rewrite generic parameter bounds + // For each bound `U: ..` in `struct`, make a new bound with `__S` in place of `#[pointee]` + // Example: + // ``` + // struct< + // U: Trait, + // #[pointee] T: Trait, + // V: Trait> ... + // ``` + // ... generates this `impl` generic parameters + // ``` + // impl< + // U: Trait + Trait<__S>, + // T: Trait + Unsize<__S>, // (**) + // __S: Trait<__S> + ?Sized, // (*) + // V: Trait + Trait<__S>> ... + // ``` + // The new bound marked with (*) has to be done separately. + // See next section + for (idx, (params, orig_params)) in + impl_generics.params.iter_mut().zip(&generics.params).enumerate() + { + // Default type parameters are rejected for `impl` block. + // We should drop them now. + match &mut params.kind { + ast::GenericParamKind::Const { default, .. } => *default = None, + ast::GenericParamKind::Type { default } => *default = None, + ast::GenericParamKind::Lifetime => {} + } + // We CANNOT rewrite `#[pointee]` type parameter bounds. + // This has been set in stone. (**) + // So we skip over it. + // Otherwise, we push extra bounds involving `__S`. + if idx != pointee_param_idx { + for bound in &orig_params.bounds { + let mut bound = bound.clone(); + let mut substitution = TypeSubstitution { + from_name: pointee_ty_ident.name, + to_ty: &s_ty, + rewritten: false, + }; + substitution.visit_param_bound(&mut bound, BoundKind::Bound); + if substitution.rewritten { + // We found use of `#[pointee]` somewhere, + // so we make a new bound using `__S` in place of `#[pointee]` + params.bounds.push(bound); + } + } + } + } + + // # Insert `__S` type parameter + // + // We now insert `__S` with the missing bounds marked with (*) above. + // We should also write the bounds from `#[pointee]` to `__S` as required by `Unsize<__S>`. let sized = cx.path_global(span, path!(span, core::marker::Sized)); - let bound = GenericBound::Trait( - cx.poly_trait_ref(span, sized), - TraitBoundModifiers { - polarity: ast::BoundPolarity::Maybe(span), - constness: ast::BoundConstness::Never, - asyncness: ast::BoundAsyncness::Normal, - }, - ); - let extra_param = cx.typaram(span, Ident::new(sym::__S, span), vec![bound], None); - impl_generics.params.push(extra_param); + // For some reason, we are not allowed to write `?Sized` bound twice like `__S: ?Sized + ?Sized`. + if !contains_maybe_sized_bound(&self_bounds) + && !contains_maybe_sized_bound_on_pointee( + &generics.where_clause.predicates, + pointee_ty_ident.name, + ) + { + self_bounds.push(GenericBound::Trait( + cx.poly_trait_ref(span, sized), + TraitBoundModifiers { + polarity: ast::BoundPolarity::Maybe(span), + constness: ast::BoundConstness::Never, + asyncness: ast::BoundAsyncness::Normal, + }, + )); + } + { + let mut substitution = + TypeSubstitution { from_name: pointee_ty_ident.name, to_ty: &s_ty, rewritten: false }; + for bound in &mut self_bounds { + substitution.visit_param_bound(bound, BoundKind::Bound); + } + } + + // # Rewrite `where` clauses + // + // Move on to `where` clauses. + // Example: + // ``` + // struct MyPointer<#[pointee] T, ..> + // where + // U: Trait + Trait, + // Companion: Trait, + // T: Trait, + // { .. } + // ``` + // ... will have a impl prelude like so + // ``` + // impl<..> .. + // where + // U: Trait + Trait, + // U: Trait<__S>, + // Companion: Trait, + // Companion<__S>: Trait<__S>, + // T: Trait, + // __S: Trait<__S>, + // ``` + // + // We should also write a few new `where` bounds from `#[pointee] T` to `__S` + // as well as any bound that indirectly involves the `#[pointee] T` type. + for bound in &generics.where_clause.predicates { + if let ast::WherePredicate::BoundPredicate(bound) = bound { + let mut substitution = TypeSubstitution { + from_name: pointee_ty_ident.name, + to_ty: &s_ty, + rewritten: false, + }; + let mut predicate = ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + span: bound.span, + bound_generic_params: bound.bound_generic_params.clone(), + bounded_ty: bound.bounded_ty.clone(), + bounds: bound.bounds.clone(), + }); + substitution.visit_where_predicate(&mut predicate); + if substitution.rewritten { + impl_generics.where_clause.predicates.push(predicate); + } + } + } + + let extra_param = cx.typaram(span, Ident::new(sym::__S, span), self_bounds, None); + impl_generics.params.insert(pointee_param_idx + 1, extra_param); // Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`. let gen_args = vec![GenericArg::Type(alt_self_type.clone())]; add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone()); add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args.clone()); } + +fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee: Symbol) -> bool { + for bound in predicates { + if let ast::WherePredicate::BoundPredicate(bound) = bound + && bound.bounded_ty.kind.is_simple_path().is_some_and(|name| name == pointee) + { + for bound in &bound.bounds { + if is_maybe_sized_bound(bound) { + return true; + } + } + } + } + false +} + +fn is_maybe_sized_bound(bound: &GenericBound) -> bool { + if let GenericBound::Trait( + trait_ref, + TraitBoundModifiers { polarity: ast::BoundPolarity::Maybe(_), .. }, + ) = bound + { + is_sized_marker(&trait_ref.trait_ref.path) + } else { + false + } +} + +fn contains_maybe_sized_bound(bounds: &[GenericBound]) -> bool { + bounds.iter().any(is_maybe_sized_bound) +} + +fn path_segment_is_exact_match(path_segments: &[ast::PathSegment], syms: &[Symbol]) -> bool { + path_segments.iter().zip(syms).all(|(segment, &symbol)| segment.ident.name == symbol) +} + +fn is_sized_marker(path: &ast::Path) -> bool { + const CORE_UNSIZE: [Symbol; 3] = [sym::core, sym::marker, sym::Sized]; + const STD_UNSIZE: [Symbol; 3] = [sym::std, sym::marker, sym::Sized]; + if path.segments.len() == 4 && path.is_global() { + path_segment_is_exact_match(&path.segments[1..], &CORE_UNSIZE) + || path_segment_is_exact_match(&path.segments[1..], &STD_UNSIZE) + } else if path.segments.len() == 3 { + path_segment_is_exact_match(&path.segments, &CORE_UNSIZE) + || path_segment_is_exact_match(&path.segments, &STD_UNSIZE) + } else { + *path == sym::Sized + } +} + +struct TypeSubstitution<'a> { + from_name: Symbol, + to_ty: &'a ast::Ty, + rewritten: bool, +} + +impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> { + fn visit_ty(&mut self, ty: &mut P) { + if let Some(name) = ty.kind.is_simple_path() + && name == self.from_name + { + **ty = self.to_ty.clone(); + self.rewritten = true; + } else { + ast::mut_visit::walk_ty(self, ty); + } + } + + fn visit_where_predicate(&mut self, where_predicate: &mut ast::WherePredicate) { + match where_predicate { + rustc_ast::WherePredicate::BoundPredicate(bound) => { + bound + .bound_generic_params + .flat_map_in_place(|param| self.flat_map_generic_param(param)); + self.visit_ty(&mut bound.bounded_ty); + for bound in &mut bound.bounds { + self.visit_param_bound(bound, BoundKind::Bound) + } + } + rustc_ast::WherePredicate::RegionPredicate(_) + | rustc_ast::WherePredicate::EqPredicate(_) => {} + } + } +} diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.rs b/tests/ui/deriving/deriving-smart-pointer-expanded.rs new file mode 100644 index 0000000000000..b78258c25290e --- /dev/null +++ b/tests/ui/deriving/deriving-smart-pointer-expanded.rs @@ -0,0 +1,22 @@ +//@ check-pass +//@ compile-flags: -Zunpretty=expanded +#![feature(derive_smart_pointer)] +use std::marker::SmartPointer; + +pub trait MyTrait {} + +#[derive(SmartPointer)] +#[repr(transparent)] +struct MyPointer<'a, #[pointee] T: ?Sized> { + ptr: &'a T, +} + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct MyPointer2<'a, Y, Z: MyTrait, #[pointee] T: ?Sized + MyTrait, X: MyTrait = ()> +where + Y: MyTrait, +{ + data: &'a mut T, + x: core::marker::PhantomData, +} diff --git a/tests/ui/deriving/deriving-smart-pointer-expanded.stdout b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout new file mode 100644 index 0000000000000..3c7e719818042 --- /dev/null +++ b/tests/ui/deriving/deriving-smart-pointer-expanded.stdout @@ -0,0 +1,44 @@ +#![feature(prelude_import)] +#![no_std] +//@ check-pass +//@ compile-flags: -Zunpretty=expanded +#![feature(derive_smart_pointer)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +use std::marker::SmartPointer; + +pub trait MyTrait {} + +#[repr(transparent)] +struct MyPointer<'a, #[pointee] T: ?Sized> { + ptr: &'a T, +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::DispatchFromDyn> for MyPointer<'a, T> { +} +#[automatically_derived] +impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> + ::core::ops::CoerceUnsized> for MyPointer<'a, T> { +} + +#[repr(transparent)] +pub struct MyPointer2<'a, Y, Z: MyTrait, #[pointee] T: ?Sized + MyTrait, + X: MyTrait = ()> where Y: MyTrait { + data: &'a mut T, + x: core::marker::PhantomData, +} +#[automatically_derived] +impl<'a, Y, Z: MyTrait + MyTrait<__S>, T: ?Sized + MyTrait + + ::core::marker::Unsize<__S>, __S: ?Sized + MyTrait<__S>, X: MyTrait + + MyTrait<__S>> ::core::ops::DispatchFromDyn> + for MyPointer2<'a, Y, Z, T, X> where Y: MyTrait, Y: MyTrait<__S> { +} +#[automatically_derived] +impl<'a, Y, Z: MyTrait + MyTrait<__S>, T: ?Sized + MyTrait + + ::core::marker::Unsize<__S>, __S: ?Sized + MyTrait<__S>, X: MyTrait + + MyTrait<__S>> ::core::ops::CoerceUnsized> for + MyPointer2<'a, Y, Z, T, X> where Y: MyTrait, Y: MyTrait<__S> { +} diff --git a/tests/ui/deriving/smart-pointer-bounds-issue-127647.rs b/tests/ui/deriving/smart-pointer-bounds-issue-127647.rs new file mode 100644 index 0000000000000..4cae1b32896fb --- /dev/null +++ b/tests/ui/deriving/smart-pointer-bounds-issue-127647.rs @@ -0,0 +1,78 @@ +//@ check-pass + +#![feature(derive_smart_pointer)] + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct Ptr<'a, #[pointee] T: OnDrop + ?Sized, X> { + data: &'a mut T, + x: core::marker::PhantomData, +} + +pub trait OnDrop { + fn on_drop(&mut self); +} + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct Ptr2<'a, #[pointee] T: ?Sized, X> +where + T: OnDrop, +{ + data: &'a mut T, + x: core::marker::PhantomData, +} + +pub trait MyTrait {} + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct Ptr3<'a, #[pointee] T: ?Sized, X> +where + T: MyTrait, +{ + data: &'a mut T, + x: core::marker::PhantomData, +} + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct Ptr4<'a, #[pointee] T: MyTrait + ?Sized, X> { + data: &'a mut T, + x: core::marker::PhantomData, +} + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct Ptr5<'a, #[pointee] T: ?Sized, X> +where + Ptr5Companion: MyTrait, + Ptr5Companion2: MyTrait, +{ + data: &'a mut T, + x: core::marker::PhantomData, +} + +pub struct Ptr5Companion(core::marker::PhantomData); +pub struct Ptr5Companion2; + +#[derive(core::marker::SmartPointer)] +#[repr(transparent)] +pub struct Ptr6<'a, #[pointee] T: ?Sized, X: MyTrait = (), const PARAM: usize = 0> { + data: &'a mut T, + x: core::marker::PhantomData, +} + +// a reduced example from https://lore.kernel.org/all/20240402-linked-list-v1-1-b1c59ba7ae3b@google.com/ +#[repr(transparent)] +#[derive(core::marker::SmartPointer)] +pub struct ListArc<#[pointee] T, const ID: u64 = 0> +where + T: ListArcSafe + ?Sized, +{ + arc: *const T, +} + +pub trait ListArcSafe {} + +fn main() {} From a75d2f9d384135c5f0f6bd6d26ec2ba9aa76745a Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 24 Jul 2024 22:02:48 +0000 Subject: [PATCH 294/489] Cleanup sys module to match house style --- .../std/src/{sys/anonymous_pipe => pipe}/tests.rs | 1 + library/std/src/sys/anonymous_pipe/mod.rs | 14 +++++--------- library/std/src/sys/anonymous_pipe/unix.rs | 8 ++++---- library/std/src/sys/anonymous_pipe/unsupported.rs | 2 +- library/std/src/sys/anonymous_pipe/windows.rs | 8 ++++---- library/std/src/sys/mod.rs | 1 - 6 files changed, 15 insertions(+), 19 deletions(-) rename library/std/src/{sys/anonymous_pipe => pipe}/tests.rs (90%) diff --git a/library/std/src/sys/anonymous_pipe/tests.rs b/library/std/src/pipe/tests.rs similarity index 90% rename from library/std/src/sys/anonymous_pipe/tests.rs rename to library/std/src/pipe/tests.rs index 865d24ec85596..9c38e10678752 100644 --- a/library/std/src/sys/anonymous_pipe/tests.rs +++ b/library/std/src/pipe/tests.rs @@ -2,6 +2,7 @@ use crate::io::{Read, Write}; use crate::pipe::pipe; #[test] +#[cfg(all(windows, unix, not(miri)))] fn pipe_creation_clone_and_rw() { let (rx, tx) = pipe().unwrap(); diff --git a/library/std/src/sys/anonymous_pipe/mod.rs b/library/std/src/sys/anonymous_pipe/mod.rs index 74875677cf3e7..aa14c8b650d34 100644 --- a/library/std/src/sys/anonymous_pipe/mod.rs +++ b/library/std/src/sys/anonymous_pipe/mod.rs @@ -1,18 +1,14 @@ +#![forbid(unsafe_op_in_unsafe_fn)] + cfg_if::cfg_if! { if #[cfg(unix)] { mod unix; - pub(crate) use unix::{AnonPipe, pipe}; - - #[cfg(all(test, not(miri)))] - mod tests; + pub use unix::{AnonPipe, pipe}; } else if #[cfg(windows)] { mod windows; - pub(crate) use windows::{AnonPipe, pipe}; - - #[cfg(all(test, not(miri)))] - mod tests; + pub use windows::{AnonPipe, pipe}; } else { mod unsupported; - pub(crate) use unsupported::{AnonPipe, pipe}; + pub use unsupported::{AnonPipe, pipe}; } } diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs index 7c0e75208c43c..9168024730e67 100644 --- a/library/std/src/sys/anonymous_pipe/unix.rs +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -6,10 +6,10 @@ use crate::sys::fd::FileDesc; use crate::sys::pipe::anon_pipe; use crate::sys_common::{FromInner, IntoInner}; -pub(crate) type AnonPipe = FileDesc; +pub type AnonPipe = FileDesc; #[inline] -pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { +pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner())) } @@ -34,7 +34,7 @@ impl From for OwnedFd { #[unstable(feature = "anonymous_pipe", issue = "127154")] impl FromRawFd for PipeReader { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self(FileDesc::from_raw_fd(raw_fd)) + unsafe { Self(FileDesc::from_raw_fd(raw_fd)) } } } #[unstable(feature = "anonymous_pipe", issue = "127154")] @@ -71,7 +71,7 @@ impl From for OwnedFd { #[unstable(feature = "anonymous_pipe", issue = "127154")] impl FromRawFd for PipeWriter { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self(FileDesc::from_raw_fd(raw_fd)) + unsafe { Self(FileDesc::from_raw_fd(raw_fd)) } } } #[unstable(feature = "anonymous_pipe", issue = "127154")] diff --git a/library/std/src/sys/anonymous_pipe/unsupported.rs b/library/std/src/sys/anonymous_pipe/unsupported.rs index f3c826d2f8dfb..da04e8e6b25af 100644 --- a/library/std/src/sys/anonymous_pipe/unsupported.rs +++ b/library/std/src/sys/anonymous_pipe/unsupported.rs @@ -4,7 +4,7 @@ use crate::process::Stdio; pub(crate) use crate::sys::pipe::AnonPipe; #[inline] -pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { +pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { Err(io::Error::UNSUPPORTED_PLATFORM) } diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs index 0f746b1082baf..1b63e9a9b920b 100644 --- a/library/std/src/sys/anonymous_pipe/windows.rs +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -8,10 +8,10 @@ use crate::sys::handle::Handle; use crate::sys::pipe::unnamed_anon_pipe; use crate::sys_common::{FromInner, IntoInner}; -pub(crate) type AnonPipe = Handle; +pub type AnonPipe = Handle; #[inline] -pub(crate) fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { +pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { unnamed_anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner())) } @@ -31,7 +31,7 @@ impl AsRawHandle for PipeReader { #[unstable(feature = "anonymous_pipe", issue = "127154")] impl FromRawHandle for PipeReader { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { - Self(Handle::from_raw_handle(raw_handle)) + unsafe { Self(Handle::from_raw_handle(raw_handle)) } } } #[unstable(feature = "anonymous_pipe", issue = "127154")] @@ -70,7 +70,7 @@ impl AsRawHandle for PipeWriter { #[unstable(feature = "anonymous_pipe", issue = "127154")] impl FromRawHandle for PipeWriter { unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { - Self(Handle::from_raw_handle(raw_handle)) + unsafe { Self(Handle::from_raw_handle(raw_handle)) } } } #[unstable(feature = "anonymous_pipe", issue = "127154")] diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 202997b749513..a86b3628f249a 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -7,7 +7,6 @@ mod pal; mod personality; -#[unstable(feature = "anonymous_pipe", issue = "127154")] pub mod anonymous_pipe; pub mod backtrace; pub mod cmath; From fe6478cc539cfe17b4f5fc10f46928c6b16e6ef0 Mon Sep 17 00:00:00 2001 From: beetrees Date: Tue, 30 Jul 2024 12:38:06 +0100 Subject: [PATCH 295/489] Match LLVM ABI in `extern "C"` functions for `f128` on Windows --- .../rustc_target/src/abi/call/x86_win64.rs | 10 +++-- library/std/build.rs | 4 +- tests/assembly/x86_64-windows-float-abi.rs | 39 +++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 tests/assembly/x86_64-windows-float-abi.rs diff --git a/compiler/rustc_target/src/abi/call/x86_win64.rs b/compiler/rustc_target/src/abi/call/x86_win64.rs index 90de1a42bc06b..4e19460bd28c2 100644 --- a/compiler/rustc_target/src/abi/call/x86_win64.rs +++ b/compiler/rustc_target/src/abi/call/x86_win64.rs @@ -1,5 +1,5 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg}; -use crate::abi::Abi; +use crate::abi::{Abi, Float, Primitive}; // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing @@ -18,8 +18,12 @@ pub fn compute_abi_info(fn_abi: &mut FnAbi<'_, Ty>) { // FIXME(eddyb) there should be a size cap here // (probably what clang calls "illegal vectors"). } - Abi::Scalar(_) => { - if a.layout.size.bytes() > 8 { + Abi::Scalar(scalar) => { + // Match what LLVM does for `f128` so that `compiler-builtins` builtins match up + // with what LLVM expects. + if a.layout.size.bytes() > 8 + && !matches!(scalar.primitive(), Primitive::Float(Float::F128)) + { a.make_indirect(); } else { a.extend_integer_width_to(32); diff --git a/library/std/build.rs b/library/std/build.rs index c542ba81eedc1..9b58dd53ba20a 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -94,7 +94,7 @@ fn main() { // Unsupported ("arm64ec", _) => false, // MinGW ABI bugs - ("x86", "windows") => false, + ("x86_64", "windows") => false, // x86 has ABI bugs that show up with optimizations. This should be partially fixed with // the compiler-builtins update. ("x86" | "x86_64", _) => false, @@ -122,6 +122,8 @@ fn main() { ("nvptx64", _) => false, // ABI unsupported ("sparc", _) => false, + // MinGW ABI bugs + ("x86_64", "windows") => false, // 64-bit Linux is about the only platform to have f128 symbols by default (_, "linux") if target_pointer_width == 64 => true, // Same as for f16, except MacOS is also missing f128 symbols. diff --git a/tests/assembly/x86_64-windows-float-abi.rs b/tests/assembly/x86_64-windows-float-abi.rs new file mode 100644 index 0000000000000..1381d492fa593 --- /dev/null +++ b/tests/assembly/x86_64-windows-float-abi.rs @@ -0,0 +1,39 @@ +//@ assembly-output: emit-asm +//@ compile-flags: -O +//@ only-windows +//@ only-x86_64 + +#![feature(f16, f128)] +#![crate_type = "lib"] + +// CHECK-LABEL: second_f16 +// CHECK: movaps %xmm1, %xmm0 +// CHECK-NEXT: retq +#[no_mangle] +pub extern "C" fn second_f16(_: f16, x: f16) -> f16 { + x +} + +// CHECK-LABEL: second_f32 +// CHECK: movaps %xmm1, %xmm0 +// CHECK-NEXT: retq +#[no_mangle] +pub extern "C" fn second_f32(_: f32, x: f32) -> f32 { + x +} + +// CHECK-LABEL: second_f64 +// CHECK: movaps %xmm1, %xmm0 +// CHECK-NEXT: retq +#[no_mangle] +pub extern "C" fn second_f64(_: f64, x: f64) -> f64 { + x +} + +// CHECK-LABEL: second_f128 +// CHECK: movaps %xmm1, %xmm0 +// CHECK-NEXT: retq +#[no_mangle] +pub extern "C" fn second_f128(_: f128, x: f128) -> f128 { + x +} From 9169622027f1dcb702f789076da1b8b98c01a215 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 24 Jul 2024 22:22:09 +0000 Subject: [PATCH 296/489] Move Windows implementation of anon pipe --- library/std/src/sys/anonymous_pipe/windows.rs | 16 ++++++++++++---- library/std/src/sys/pal/windows/pipe.rs | 17 ----------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs index 1b63e9a9b920b..a48198f8a812b 100644 --- a/library/std/src/sys/anonymous_pipe/windows.rs +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -1,18 +1,26 @@ -use crate::io; use crate::os::windows::io::{ AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, }; use crate::pipe::{PipeReader, PipeWriter}; use crate::process::Stdio; +use crate::sys::c; use crate::sys::handle::Handle; -use crate::sys::pipe::unnamed_anon_pipe; use crate::sys_common::{FromInner, IntoInner}; +use crate::{io, ptr}; pub type AnonPipe = Handle; -#[inline] pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { - unnamed_anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner())) + let mut read_pipe = c::INVALID_HANDLE_VALUE; + let mut write_pipe = c::INVALID_HANDLE_VALUE; + + let ret = unsafe { c::CreatePipe(&mut read_pipe, &mut write_pipe, ptr::null_mut(), 0) }; + + if ret == 0 { + Err(io::Error::last_os_error()) + } else { + unsafe { Ok((Handle::from_raw_handle(read_pipe), Handle::from_raw_handle(write_pipe))) } + } } #[unstable(feature = "anonymous_pipe", issue = "127154")] diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index 9eb19fcf2d7a2..7d1b5aca1d5fe 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -36,23 +36,6 @@ pub struct Pipes { pub theirs: AnonPipe, } -/// Create true unnamed anonymous pipe. -pub fn unnamed_anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { - let mut read_pipe = c::INVALID_HANDLE_VALUE; - let mut write_pipe = c::INVALID_HANDLE_VALUE; - - let ret = unsafe { c::CreatePipe(&mut read_pipe, &mut write_pipe, ptr::null_mut(), 0) }; - - if ret == 0 { - Err(io::Error::last_os_error()) - } else { - Ok(( - AnonPipe::from_inner(unsafe { Handle::from_raw_handle(read_pipe) }), - AnonPipe::from_inner(unsafe { Handle::from_raw_handle(write_pipe) }), - )) - } -} - /// Although this looks similar to `anon_pipe` in the Unix module it's actually /// subtly different. Here we'll return two pipes in the `Pipes` return value, /// but one is intended for "us" where as the other is intended for "someone From 6283c4dae6ea2609aa2c167fcebf03ec6e459073 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 30 Jul 2024 22:32:33 +0200 Subject: [PATCH 297/489] FD: refactor API names a little --- src/tools/miri/src/shims/unix/fd.rs | 22 +++++++++---------- src/tools/miri/src/shims/unix/fs.rs | 4 ++-- src/tools/miri/src/shims/unix/linux/epoll.rs | 2 +- .../miri/src/shims/unix/linux/eventfd.rs | 2 +- src/tools/miri/src/shims/unix/socket.rs | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 74e690a5f1433..ba17a53933b52 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -240,25 +240,25 @@ impl FdTable { } pub(crate) fn init(mute_stdout_stderr: bool) -> FdTable { let mut fds = FdTable::new(); - fds.insert_fd(io::stdin()); + fds.insert_new(io::stdin()); if mute_stdout_stderr { - assert_eq!(fds.insert_fd(NullOutput), 1); - assert_eq!(fds.insert_fd(NullOutput), 2); + assert_eq!(fds.insert_new(NullOutput), 1); + assert_eq!(fds.insert_new(NullOutput), 2); } else { - assert_eq!(fds.insert_fd(io::stdout()), 1); - assert_eq!(fds.insert_fd(io::stderr()), 2); + assert_eq!(fds.insert_new(io::stdout()), 1); + assert_eq!(fds.insert_new(io::stderr()), 2); } fds } /// Insert a new file description to the FdTable. - pub fn insert_fd(&mut self, fd: impl FileDescription) -> i32 { + pub fn insert_new(&mut self, fd: impl FileDescription) -> i32 { let file_handle = FileDescriptionRef::new(fd); - self.insert_fd_with_min_fd(file_handle, 0) + self.insert_ref_with_min_fd(file_handle, 0) } - /// Insert a new FD that is at least `min_fd`. - fn insert_fd_with_min_fd(&mut self, file_handle: FileDescriptionRef, min_fd: i32) -> i32 { + /// Insert a file description, giving it a file descriptor that is at least `min_fd`. + fn insert_ref_with_min_fd(&mut self, file_handle: FileDescriptionRef, min_fd: i32) -> i32 { // Find the lowest unused FD, starting from min_fd. If the first such unused FD is in // between used FDs, the find_map combinator will return it. If the first such unused FD // is after all other used FDs, the find_map combinator will return None, and we will use @@ -316,7 +316,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Some(dup_fd) = this.machine.fds.dup(old_fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; - Ok(Scalar::from_i32(this.machine.fds.insert_fd_with_min_fd(dup_fd, 0))) + Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, 0))) } fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> { @@ -410,7 +410,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match this.machine.fds.dup(fd) { Some(dup_fd) => - Ok(Scalar::from_i32(this.machine.fds.insert_fd_with_min_fd(dup_fd, start))), + Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, start))), None => Ok(Scalar::from_i32(this.fd_not_found()?)), } } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") { diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 7891b65a9d4fb..5606e3d85b71a 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -545,7 +545,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let fd = options .open(path) - .map(|file| this.machine.fds.insert_fd(FileHandle { file, writable })); + .map(|file| this.machine.fds.insert_new(FileHandle { file, writable })); Ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?)) } @@ -1634,7 +1634,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match file { Ok(f) => { - let fd = this.machine.fds.insert_fd(FileHandle { file: f, writable: true }); + let fd = this.machine.fds.insert_new(FileHandle { file: f, writable: true }); return Ok(Scalar::from_i32(fd)); } Err(e) => diff --git a/src/tools/miri/src/shims/unix/linux/epoll.rs b/src/tools/miri/src/shims/unix/linux/epoll.rs index ad35d67876ccb..9127db3d00420 100644 --- a/src/tools/miri/src/shims/unix/linux/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux/epoll.rs @@ -64,7 +64,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } - let fd = this.machine.fds.insert_fd(Epoll::default()); + let fd = this.machine.fds.insert_new(Epoll::default()); Ok(Scalar::from_i32(fd)) } diff --git a/src/tools/miri/src/shims/unix/linux/eventfd.rs b/src/tools/miri/src/shims/unix/linux/eventfd.rs index 0fc28c72bb6fb..4ab8760d9306a 100644 --- a/src/tools/miri/src/shims/unix/linux/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux/eventfd.rs @@ -178,7 +178,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("eventfd: encountered unknown unsupported flags {:#x}", flags); } - let fd = this.machine.fds.insert_fd(Event { + let fd = this.machine.fds.insert_new(Event { counter: val.into(), is_nonblock, clock: VClock::default(), diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs index cc0f932e03829..455820a9e6e5a 100644 --- a/src/tools/miri/src/shims/unix/socket.rs +++ b/src/tools/miri/src/shims/unix/socket.rs @@ -219,8 +219,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; let fds = &mut this.machine.fds; - let sv0 = fds.insert_fd(socketpair_0); - let sv1 = fds.insert_fd(socketpair_1); + let sv0 = fds.insert_new(socketpair_0); + let sv1 = fds.insert_new(socketpair_1); let sv0 = Scalar::from_int(sv0, sv.layout.size); let sv1 = Scalar::from_int(sv1, sv.layout.size); From e65777301b108aed53b54b4625041d6e8631327f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 16:42:53 -0400 Subject: [PATCH 298/489] Remove crate_level_only from ELIDED_LIFETIMES_IN_PATHS --- compiler/rustc_lint_defs/src/builtin.rs | 3 +-- tests/ui/lifetimes/elided-lint-in-mod.rs | 11 +++++++++++ tests/ui/lifetimes/elided-lint-in-mod.stderr | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lifetimes/elided-lint-in-mod.rs create mode 100644 tests/ui/lifetimes/elided-lint-in-mod.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 246b516076461..a6f6a63fb55d8 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1836,8 +1836,7 @@ declare_lint! { /// [placeholder lifetime]: https://doc.rust-lang.org/reference/lifetime-elision.html#lifetime-elision-in-functions pub ELIDED_LIFETIMES_IN_PATHS, Allow, - "hidden lifetime parameters in types are deprecated", - crate_level_only + "hidden lifetime parameters in types are deprecated" } declare_lint! { diff --git a/tests/ui/lifetimes/elided-lint-in-mod.rs b/tests/ui/lifetimes/elided-lint-in-mod.rs new file mode 100644 index 0000000000000..afe85cb607d40 --- /dev/null +++ b/tests/ui/lifetimes/elided-lint-in-mod.rs @@ -0,0 +1,11 @@ +struct Foo<'a>(&'a ()); + +fn test(_: Foo) {} + +#[deny(elided_lifetimes_in_paths)] +mod w { + fn test2(_: super::Foo) {} + //~^ ERROR hidden lifetime parameters in types are deprecated +} + +fn main() {} diff --git a/tests/ui/lifetimes/elided-lint-in-mod.stderr b/tests/ui/lifetimes/elided-lint-in-mod.stderr new file mode 100644 index 0000000000000..1fee18028c66f --- /dev/null +++ b/tests/ui/lifetimes/elided-lint-in-mod.stderr @@ -0,0 +1,20 @@ +error: hidden lifetime parameters in types are deprecated + --> $DIR/elided-lint-in-mod.rs:7:24 + | +LL | fn test2(_: super::Foo) {} + | -------^^^ + | | + | expected lifetime parameter + | +note: the lint level is defined here + --> $DIR/elided-lint-in-mod.rs:5:8 + | +LL | #[deny(elided_lifetimes_in_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +LL | fn test2(_: super::Foo<'_>) {} + | ++++ + +error: aborting due to 1 previous error + From 3659d9d2e4736e11c7ed8b4a5d528180d4a7cff8 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 13 Jun 2024 18:29:09 -0700 Subject: [PATCH 299/489] bump-stage0: use IndexMap for determinism When it used `HashMap`, `bump-stage0` would change `src/stage0` every time it ran, whereas `IndexMap` will keep insertion order -- matching the manifest file. --- src/tools/bump-stage0/src/main.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs index fed225f2f2dc6..f8c75ca722609 100644 --- a/src/tools/bump-stage0/src/main.rs +++ b/src/tools/bump-stage0/src/main.rs @@ -1,7 +1,5 @@ #![deny(unused_variables)] -use std::collections::HashMap; - use anyhow::{Context, Error}; use build_helper::stage0_parser::{parse_stage0_file, Stage0Config, VersionMetadata}; use curl::easy::Easy; @@ -217,13 +215,13 @@ enum Channel { #[derive(Debug, serde::Serialize, serde::Deserialize)] struct Manifest { date: String, - pkg: HashMap, + pkg: IndexMap, } #[derive(Debug, serde::Serialize, serde::Deserialize)] struct ManifestPackage { version: String, - target: HashMap, + target: IndexMap, } #[derive(Debug, serde::Serialize, serde::Deserialize)] From 2e9298b2fccf8465a504351bbc60b1beb573bfa2 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 30 Jul 2024 15:16:35 -0700 Subject: [PATCH 300/489] Bump src/stage0 with determinism --- src/stage0 | 722 ++++++++++++++++++++++++++--------------------------- 1 file changed, 361 insertions(+), 361 deletions(-) diff --git a/src/stage0 b/src/stage0 index 41fabb23cbf14..dcc22673f13ed 100644 --- a/src/stage0 +++ b/src/stage0 @@ -16,446 +16,446 @@ nightly_branch=master compiler_date=2024-07-26 compiler_version=beta -rustfmt_date=2024-07-26 +rustfmt_date=2024-07-30 rustfmt_version=nightly -dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=6e58397829f67bf952037c94894409032e52ac8ccdf3858346d131fff6175a50 -dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=8e834602e7cd1fcd585f51ab280266b4ffc57e0c974a1a26b901701b5127135d +dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.gz=a265d7831284938f090ef34cf2fb374f4d2b946c52829de8e53a06b7373c3d7e +dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.xz=f2420846f82f474892776f0bea176fbb2f1850a1fb9f51a1afe40ae6de8bbc17 +dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=e3e0e2b8d1f8804cc2b5785765cc6807bbf7120fb010d74453097b5931c82e96 +dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=1270aaea2f20a378e68d26518e1d34810ed346a4d4c272138c8aef67e3c386d5 dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=02bcdc3eed81ba17e485556f1c4d5a00e851afb75a20f860ce7b6d22cb8f9e99 dist/2024-07-26/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=52b72cc7270fe75e023ca9c40d095a84cb0ce31657357cd7676d6570ca59bc1c -dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=904029f0c81ec9679851d952f0f0f616cc183028882c6686f5b5bb665ca00cef -dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=31f3f895d665acf082a6dbb40e91fd97f823f84c8e62074dfa82e60f22606f5b dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.gz=b47ba6f2214f238cf8df3c386765e7816bc86e1166f27ddb6c0ce678ec716939 dist/2024-07-26/rustc-beta-aarch64-unknown-linux-musl.tar.xz=95537778025708922b4bf27f34f0634a61a1d963a8424f8a06c82564c74e849a -dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=70eb8f65e91068ac20366fca1fc30227f36cb2b2ce1abdaa72504583cc7865c7 -dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=3372e272cf9620191000a95fff23e417586e6b894e211d44e4f658c241c3d014 -dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=94a8a08495b8093db5d9a32c3258c9f97ea8b0f57947d7ca642664c06cfb438d -dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=8d057c7167cffeebeddabf25f08a50de8dbad5ed7cfffce625c81a99d757e998 -dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.gz=045fe2478c5a5341d7b7a05b9df23ef8f81ddbe0faa78e3f2107341a0e8189f6 -dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.xz=d7f3888692210b6024ed72864015d1c101f28814dec5b60c9e32a772f11f3b47 -dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=840131ab570c68c0d46244eac743f7d8a1f470d1926068868d288307a488b3c9 -dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=6513a144014807bd258d2a90fa4618aabdb4e265268e408d5cb699a610b78c31 -dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.gz=a265d7831284938f090ef34cf2fb374f4d2b946c52829de8e53a06b7373c3d7e -dist/2024-07-26/rustc-beta-aarch64-apple-darwin.tar.xz=f2420846f82f474892776f0bea176fbb2f1850a1fb9f51a1afe40ae6de8bbc17 -dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.gz=ef5a0d34b78848962e83ed468934d7cbedff778a89e50f2128ba25d0943e25ed -dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.xz=5cccc7bbb15b63d422dfd2c8ac25e2103906880e843feccd318ba8b8c614d3b4 -dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=7b037163f1c19a0fbbf4029d12a7b3764e747c9ea7944f1e45a6f91a068df224 -dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=f5044d8f3784e5bc682b03ccbe7389abf5b254a01074fa67eb824d2dfc9fd3ad +dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=d79c8b744d00b174be7630a54f9ee23562f8977d7e09e2ee46a9d72a80eef514 +dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0f7d3d0773a3c1f94e8252d95b134f7f5e727a884ece54aa0f77e5edec5c6e29 dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=5e0d51532c4bb0c29fd01ef5d931c229f711c9326df0bdcb2b88c75aa72dc210 dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=5fe623cab0afd5f7bdd664a593ac02791915e30cfc9ca76a02ffd70e1e865ede -dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=40b7312ce424dcbde5537da50d17854c255c3ed535a124f4f0102cf62bc86b5a -dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=222a86f97d9bf2db38ebea9f45901790429658154d3448d05e7f0ddd9833ff18 dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=1df1e1a44170d6c9ab4988e9841ab56ee00248ca5cbf7e38b69677bd5b2de585 dist/2024-07-26/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=70791fcd1aef6686e012740017a0e5bb4441eb4018f875e8e50d5597c183291d -dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.gz=81fe4bef33afb3010fdd7af42653fbf5dd9abf0d69268576dfe144c88c7b9944 -dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.xz=c4785475e3f7087cbab405937c0ca3ebc08455dd36df156680cea1ed38fcce5b +dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.gz=045fe2478c5a5341d7b7a05b9df23ef8f81ddbe0faa78e3f2107341a0e8189f6 +dist/2024-07-26/rustc-beta-i686-pc-windows-gnu.tar.xz=d7f3888692210b6024ed72864015d1c101f28814dec5b60c9e32a772f11f3b47 +dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.gz=5b2988c87d91013cd92ebca43fd6cf5d49250fc0452830ea46622e418984041e +dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.xz=b9d65cca6691baf2841432d6d2d566face171c460cf161f39a21acf7c0b033c1 +dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.gz=7b037163f1c19a0fbbf4029d12a7b3764e747c9ea7944f1e45a6f91a068df224 +dist/2024-07-26/rustc-beta-i686-unknown-linux-gnu.tar.xz=f5044d8f3784e5bc682b03ccbe7389abf5b254a01074fa67eb824d2dfc9fd3ad +dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=840131ab570c68c0d46244eac743f7d8a1f470d1926068868d288307a488b3c9 +dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=6513a144014807bd258d2a90fa4618aabdb4e265268e408d5cb699a610b78c31 +dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=d703a904da3604e553ba0a74775f8005e9f52615be3266197b71362b20414def +dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=8ab79d34b3c182a4349fd01a50aa13ca064ecea64c2ab09f7a9ec38046741c7a +dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=70eb8f65e91068ac20366fca1fc30227f36cb2b2ce1abdaa72504583cc7865c7 +dist/2024-07-26/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=3372e272cf9620191000a95fff23e417586e6b894e211d44e4f658c241c3d014 dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=e8f09f56c43ae6e99a42a8c430492157415fa6baee2c3f8f86f94ab4279634cd dist/2024-07-26/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=599fcd5c57687e29eec085f7cc2733965a8e8fe5eac6499abd92ffda64f6e500 -dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=d79c8b744d00b174be7630a54f9ee23562f8977d7e09e2ee46a9d72a80eef514 -dist/2024-07-26/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=0f7d3d0773a3c1f94e8252d95b134f7f5e727a884ece54aa0f77e5edec5c6e29 -dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=5e6fae2fd75e1780995fa9839593044539fac3f095c8948ba446b7024f632ec9 -dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=9eb16965a7f1f7be7751fb61280f272c2497765e552fc0dd653700d551a04539 +dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=904029f0c81ec9679851d952f0f0f616cc183028882c6686f5b5bb665ca00cef +dist/2024-07-26/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=31f3f895d665acf082a6dbb40e91fd97f823f84c8e62074dfa82e60f22606f5b dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=4d374e60b8ac2f3fddd5ba9b46ab80555bc5b19f080b86604dde994087b00ed9 dist/2024-07-26/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=c905a880b98d1eaabfb306d5b6dda018e5025b42028cbb12bad408f4d469f3ae -dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=d703a904da3604e553ba0a74775f8005e9f52615be3266197b71362b20414def -dist/2024-07-26/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=8ab79d34b3c182a4349fd01a50aa13ca064ecea64c2ab09f7a9ec38046741c7a dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.gz=69f0228799685960f36f31eb4c139cbd7925f5180468e2d4a435ecbad63e9535 dist/2024-07-26/rustc-beta-s390x-unknown-linux-gnu.tar.xz=1da1caf5b2ad149ef82af58278dea6c381c372366c48cda8ca7f520cc8752b2c -dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.gz=e3e0e2b8d1f8804cc2b5785765cc6807bbf7120fb010d74453097b5931c82e96 -dist/2024-07-26/rustc-beta-aarch64-pc-windows-msvc.tar.xz=1270aaea2f20a378e68d26518e1d34810ed346a4d4c272138c8aef67e3c386d5 +dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.gz=81fe4bef33afb3010fdd7af42653fbf5dd9abf0d69268576dfe144c88c7b9944 +dist/2024-07-26/rustc-beta-x86_64-apple-darwin.tar.xz=c4785475e3f7087cbab405937c0ca3ebc08455dd36df156680cea1ed38fcce5b +dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.gz=6e58397829f67bf952037c94894409032e52ac8ccdf3858346d131fff6175a50 +dist/2024-07-26/rustc-beta-x86_64-pc-windows-gnu.tar.xz=8e834602e7cd1fcd585f51ab280266b4ffc57e0c974a1a26b901701b5127135d +dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.gz=94a8a08495b8093db5d9a32c3258c9f97ea8b0f57947d7ca642664c06cfb438d +dist/2024-07-26/rustc-beta-x86_64-pc-windows-msvc.tar.xz=8d057c7167cffeebeddabf25f08a50de8dbad5ed7cfffce625c81a99d757e998 dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.gz=dcc93e7b76ca7a469544597885a7b5f4b5f822e05a89b2d7a093e06dede9f52b dist/2024-07-26/rustc-beta-x86_64-unknown-freebsd.tar.xz=3efb7d4d97dc9b13a0178464e79bbf96bb71763a588b48c587746acd456ceb8d -dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.gz=5b2988c87d91013cd92ebca43fd6cf5d49250fc0452830ea46622e418984041e -dist/2024-07-26/rustc-beta-i686-pc-windows-msvc.tar.xz=b9d65cca6691baf2841432d6d2d566face171c460cf161f39a21acf7c0b033c1 +dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.gz=ef5a0d34b78848962e83ed468934d7cbedff778a89e50f2128ba25d0943e25ed +dist/2024-07-26/rustc-beta-x86_64-unknown-illumos.tar.xz=5cccc7bbb15b63d422dfd2c8ac25e2103906880e843feccd318ba8b8c614d3b4 dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=a9b352f61f8124c1fba0c76ecc8c1c972e61e97f5299f3b86bc17f035351ced5 dist/2024-07-26/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=a8fced9a5de02bb660491b440f6596e4baf6eb9114b8dd8d93ac7ada6266d274 -dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=2cc32752932477945f248dee4d277754928b982815e2e2e0d27883522fb9b8d2 -dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=e40eae93c31c1fa06517a21cfbdd2dd18e2f740aee1251bcc9bdc680a565241c -dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=975917e862347f7e1472cdaa2258de16cb9981e3a8256f9b7860104740076187 -dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=bb89062b05f025a964e0110fcfc8fdf57300b23314409924cd4a05e9af9614af -dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=e487752db0ecd837fb1ecb57064ef2464f7f85ed5fdc9d47322e7b5c37c32300 -dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=e74a462d598c55822b5841bdc35cb2605b4aa7993e305246b3adf079ae79ea1d -dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=905d378e6fd4387381fc166718ff31f017c99e725a9c8461bbac39d5571e246f -dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=6c5fc29004bda36ddfb0280636ac2b2c28c538f33cadb07a55174fadb068daa5 -dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=0228f8d7e0913cca5db975e0b9ec4807e817dcbc0cd0bd64b64826c9537f25e5 -dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=d37d5ae3605d745a393fc71c5f0e169cee283aa840edb9543682b339cd040310 -dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=1bd5a11163f5fb9325e21c425d5d2fb3e1f845d265cbf7736679c3bb9c8d22a7 -dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=d858d0077df0fa7363258994e76a1bc0ff850734de6a0fbe955c3c9b9cd46cb7 -dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=ae56b334234ba51cf68be42d0fd58cf3487673dbe747bb3efa01e8563b9b8a90 -dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=1468622e9bb6384a6ab7006863d2b7d55307e74239befc8e72dfd39f83c0af1e -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=d1e861a9176a5cb934270592f7b98528283c363d135736477a844499015ac44a -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=c5f548845c6ccbee1980892e630ab06ec1bef498fb7f6fc80b4ced4a84c23f85 -dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=95244114ed2d6dd2de488f49115b11a25b008134f1fa1c8f2e2a62849b51f213 -dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=fcb3280dabb4aae920a14c7f4fec52dc3f11bc68f5143961fa88347aa020bb9a +dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.gz=5e6fae2fd75e1780995fa9839593044539fac3f095c8948ba446b7024f632ec9 +dist/2024-07-26/rustc-beta-x86_64-unknown-linux-musl.tar.xz=9eb16965a7f1f7be7751fb61280f272c2497765e552fc0dd653700d551a04539 +dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.gz=40b7312ce424dcbde5537da50d17854c255c3ed535a124f4f0102cf62bc86b5a +dist/2024-07-26/rustc-beta-x86_64-unknown-netbsd.tar.xz=222a86f97d9bf2db38ebea9f45901790429658154d3448d05e7f0ddd9833ff18 +dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.gz=a9b3cfe03b3053cd533ff02fb54f95db009396802464f32840b3369e9a3e6afc +dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.xz=9ddb6b8291ade9224cc76f4d946c179bdc6e25f5819a4ba1ebe1f207d4c663ac dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.gz=8c129310921ed45d3cdfc30e60d93403adf8158a6661de96ee5d4a63119cf3e5 dist/2024-07-26/rust-std-beta-aarch64-apple-ios.tar.xz=e1fcee4b062f25b0350e5e74064615c354ee8b399adf792d46319ee782857398 -dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.gz=68fe7b30550cf1ccc44a1669f26620ae418b48cd6283b716aff3dee91acfcbec -dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.xz=81f24aedc06a25c8dfce729132a77e90adc5fe2aec86a3a9548aec9458127ce1 -dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=6dd97a7215bdc8145cee5856957bf3f20719f65c73033006243ac2a9e347394b -dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d7541a8e83f7b8a9761988c3ac295a665e21e4d5dc9e2284ef48314f6c784166 -dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.gz=f20ecabfab9d8ecbab44d661018b865e449137993726e76b20c7749db4d0986e -dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.xz=7da2cf413c0665b07b3083862747c9815a78b3775c2bee6cd1f7551e7f2e4c8a -dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ba1b4f772faf2e738d2696eb576f74bdbd1fed1a073053eee341ec6423b6e1c6 -dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=f3f3eaafd9ecb1ee0ba68259d88d65ced56f20323a4f542fc85993e92a044206 -dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=38c8b07558734a9fff1807a823af72faaf8ab5ea47042f1b88a38d6c3648c43b -dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=e30e0000336449a8aabf60839cba4ecca32cf82b02ed0a7a23935793072679f4 -dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.gz=676786bd5e7f0739d18d40d99158045fcba746dc306485c0f15ce49ef2b63b0b -dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.xz=d7fdba095ca515454034891c8a862aaa563ee7451289138ce32b10691dbfe38a -dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.gz=c12bc5543c262645f7000cc84247518033f15fcbdfed510eb92393d723906eb1 -dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.xz=a5fc26dd6068cdb28ee2a252af545a34dd2be6e075e7d0aac2d03796c07579f4 -dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=dc20c2fc14b2211bf4517464109871f940a227298302d2ec84eaca539a19e9b4 -dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=5a7fa24ca3f7b43526c116a5ebce60f29116640ad51c1ed426f9aee705b10897 -dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=db784556ebf56a79e6330de3204ce6ce5422eca2543b872ed55c238aedbfedae -dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=373efe8c55e85aae60dfac234471b76fefbc2ba722d97e0338ec593b7c70cce3 -dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=809d7f027aecc4a131921181418e66b956ad0a2a7170a3ec3649e21659c5a524 -dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=1b9589a72d2902cd4491406d93c599d2e850fa2ba19b1bcc6bdc5cc7196f9643 -dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=3ea692ffe99c953d0049c0a16b71eb0bc3da492b9f9308463311dc0143af84dd -dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=97005f0d686a6481c5a532b6e1ea14befc794ed89394a8f1c94ad39257ebdaa8 -dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=6d7210503568d9fa02231ac2d9a1b400d00a37f38ec8f00bfcfe45c325aeed02 -dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=cdd81201e38226750f2b4292b099b5d78fe0115cedb4c28bf20200144297d8b6 -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=44ce7faad791029b670a9d815766a647d488dbbb56eb09024a09a595427fd19b -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=cd7011512df191100d31caef920d1a5c6d5ec2a771e0b52078d5d60b45e9a497 -dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.gz=b40dbc6ba0f3f80414bdc11260f291f067acbceb50d84597a9366746cff53348 -dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.xz=1564c3215b173956bae41cda7312ed7912812e0fbb65dd8d75808a1d5084fc8d -dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=0da01efb79d43140515c48561cbe7a2fdb83895fe4351f2fffaaf108fb163268 -dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=baa52bf16290d71b1b89f12ddcee5adf18c480071f9fd4daf3fcab72f92fad4a -dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.gz=dd38446053d1500f3bdc325ae5cd52d0434c618d79a7c0a0473c76691353bac4 -dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.xz=5b82a2f970be59563cc4f550e4202be802cbe21dcbf14de413ed8f30b0e22020 -dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=33fe3c61aa2e93c6a925b132fabc11c24e102cc070260d5f89a66e374e9a4d23 -dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=f50bb682fe484f23ae1ae9b2466c450b8fe9ecc3694fb68e162ce43cc8917af7 -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=58dcb73ba02fa38742d255bd346a77340cf634247904624c7af9b11e769a364c -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=ea4417de121ab7e869659b26efd144baf2fd839a956da4acb30121d1bc9132aa -dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=fea794a4c8aec3e5357199db7a9b701ceedded1dbb50167b002d368a6ae09cc7 -dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=47fc6e497bd4c8013f708ed052701129c308b657d28ee2dce877cb63ccb1b06b -dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.gz=4169c938b638faff18a5db1bed5e7d2036f45d25ec9799dc2967ad1589d447a9 -dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.xz=8cbda8eeb98be575b78170e9895390e9406c4de41db8363988185dd24e276427 -dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=bc6ae4d5e93b47828678f1af55efc1baae2d76975be3259854272a566f5489c9 -dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=51cf1d675e61aaeedf895e52a9a81b188aa066a68d599963e0435bddfd2f6a5b +dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=40d6d48dea64407bf31be39f9e0316a1e47648ee75bc0d3361edb961e062aa6b +dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=3e01648f45e0c7cb040d3c293024477801930d5078d54c6291ba13aa8eb4e1f6 +dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.gz=da310568bee0d4868132589399c9229df5ac575a028f2409f51fd1f8c9e81779 +dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.xz=f3079ebecbe5b9f23495fe0966fc39fee1d38869287695804c3c04d53df07496 dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=9dce2956e4b01d867ef6c229dbff9319a779a80e43a29fe1f8b10a333049264d dist/2024-07-26/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=b64e7b87027dceba21283ba71430a8053a918bfaf6c071cc70d5f5da00155944 -dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.gz=c675df742bd9fbc01f67411a19926e2814412f12e09b53d1492e8c7250f3e685 -dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.xz=d5b9c3783f6d2dbdf25e0495e32a295c4820bbc5b65a44f19f018b1141e85371 -dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=fb33110ad649aac6f55310e6f03d03d4d75ccdca43ada93fb97a717975ef867f -dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=cef39c2886fffef2986e9fe8f3be58f0d7f3846466a35443bc0d49464bdef98a -dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.gz=a9b3cfe03b3053cd533ff02fb54f95db009396802464f32840b3369e9a3e6afc -dist/2024-07-26/rust-std-beta-aarch64-apple-darwin.tar.xz=9ddb6b8291ade9224cc76f4d946c179bdc6e25f5819a4ba1ebe1f207d4c663ac -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=b3226669f49ee8fc89c1f84855c29f8416df3e32d3276547f521f738179164a6 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=9a5711743a0984ab7baed2a50f87e50d7facff2ef05f5b936b7b25f5a5992734 -dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=151863cece818be834261e6c148eeabbb1c796c991065c84b813bac64e73fef7 -dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=94cbae695036a4a1fa1faac12a6dd5ebeea18ec2d6e7b01c311d340ce7ddba39 -dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=c6147e9c6c39501d133a344972dbb8108bdc45bb2fe8ad624162ad04a9c00c6e -dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=6207bdfe0796e4bd4e7d25457d67559f15aa2e8bb91b05284ed147f8799de869 -dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f971daa3f8c3d0773fb6667cb7a544f96ebd049e9b5d1b5ac4bd3ea0c342467b -dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=3cd2f4ad7d9f41e9f903aa49eb86d142bb5ef69c2c39d9ba16a00a39d74046f1 dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=0d103e0c4ec8039dd42be09bb9c74f269a9567fe7dfacfc54106912cd2aeb35b dist/2024-07-26/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=4b3627e9e363e9b2fd85222c677a7250b12a5d32919f38a31ed7375637a79a81 -dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=748dfafeb6b953017b9129be9697d02a73d5bc8b1371a6a00bbfa20b7b45033c -dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=0c9a0717054858fa821e4c418b9e99cb0a0f852ec3c866951c1d1795cc1e8152 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=85c3684f175642463777aa69889a20391e39afc0d6356baa3ac0445f7aa25119 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=a8d67436a8ee232d57e2924f8f9e5cb0050c71740d57a4e677674adb75093f31 -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=99a14bf8cffa0c736a25ce117bc5d4ab64963d81c9d9ac377f118a77a6a3c4b6 -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=9902878b75b3f6cf944909cf6d17efc26dc820708b164b34757d841e89c948bd -dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=f2840d36b089fdbcff5f6f9f7a6e576cf21836824957cdf2d1ef2c75a1f5c11f -dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=5723cf48a1ff47fb764cc5ad921356e490997aa09ecd86404e370ffdacfa4b31 -dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=53a17d10d498f1b6ebd6852987f304b2e1187544f2c9e91b69d0fdbf88630910 -dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=fb97e6f2b047d6251eb6e34891b64f20d0dbc648beb78bb7364fe563670d7de8 -dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=b319ee87ee034a6a2a67dc2efdc72f8285c73d9bd1bd893586170ac54049151a -dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c751e65bbdfd72de07abf138162ab64dcbce51ba50375cef5ca8f35945d9ac7b -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=a63c5d40bcf8b0702c1a91e992c042130916edfdcf94fb4615ba10c89dad6642 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4706424b53063b768223880d87bbec0cf57e524374a6ef053ebef02d096484e4 +dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=061fdac14ee0bd3abba36269f68e9ad25a243ac7062f946155f98680f484a84c +dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=8acc12f14ac643b822595a6a07c7e5ac65855b83938ac122e3278f64769eeb13 +dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=199498df7d94989d4ff1773fdfe86e97ac99ead487f402d020f78688bc6dfba4 +dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=1337c2f00e9bec2e0a553234d74daea67a9781459d0abe3c8de954981d9354d2 +dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=a7116c13a413989f2ed874d45780aced3299c4ef8ce8e3bc99efe960a73cadb3 +dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=80ef87143ee2339e90842c4893284217ddfa56926524baf94341277c1210dd07 dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=c47cab4bb196e749f07d03f6f6c8f2fe538c84a055a298f0b505ab98dadf4a1c dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=b36aa3f0bab63ac21fb69610d379a87fbd1ee87041153eb1e6886a237d22b171 -dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=ed1b9141bd68b8c13e295904ac66d18ca92c5b92a263fa5109262d15065aeded -dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=0c036271c4c4e04357b630146cad296dc6a57363f7dc0cd2f3142ead13bf0602 -dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.gz=da310568bee0d4868132589399c9229df5ac575a028f2409f51fd1f8c9e81779 -dist/2024-07-26/rust-std-beta-aarch64-linux-android.tar.xz=f3079ebecbe5b9f23495fe0966fc39fee1d38869287695804c3c04d53df07496 +dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.gz=92de36c897dbf90f9986396da1f8a954ad7b4fdab3e466d63974c82611e76d47 +dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.xz=fb5d50ce34bd222c1b624e5aa2248776f8926f3ee360b7c4c1e0bd412d01bae2 +dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=fea794a4c8aec3e5357199db7a9b701ceedded1dbb50167b002d368a6ae09cc7 +dist/2024-07-26/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=47fc6e497bd4c8013f708ed052701129c308b657d28ee2dce877cb63ccb1b06b +dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=17eb45b10a0c9cc702e7fb4f0c7926591d3ad0f052f2bded9cf852ea082cd2bb +dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=1f6b1a3082fc29546e4d8dcb20675f62ead20fe96112998dcb1260e206e93cbc dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.gz=baad78bda532ed77dbf3e4265595b9dac82f6fdc27dc6deaf7386a60b981b927 dist/2024-07-26/rust-std-beta-arm-linux-androideabi.tar.xz=cf4283b1224d4dac3c55da905608c5bba7639b6511977f3de344a999ae39e571 -dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=e84526736c1a48dbec3b122b8c01458ff549afdbdd0f73e705c76cca1bd1f767 -dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=df8d9909b0afd0e02b9c027f12e28aa2c40716d7c8a8f5e82b7521d2e145fbf8 -dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.gz=1f11ad1a66d01a09c7237da76327b70ae2e2a9f7647a3ee0de58d563576efacf -dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.xz=960fb614a927e1b3d1d8e4a9fb7220ae675d0e8219fdde204bc6454fbe69a0a9 -dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.gz=8d56f1aa8661047f854806278b83a514fa79b7a5097635cd095943b3f848ea74 -dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.xz=78609204d01e0d0bcbc1fb5dd3d9cfcac60db23bfbd2428f1e021d1b05793519 -dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.gz=84d03b1c1fc7338895f82f54fdccb18ea6c4ceb43f47c3d46fadb014aa0c9549 -dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.xz=f28cbf9552e3c680342364087e7305a12417a92ed6b6696d71d476e1c1d8d4e7 -dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=44463b4a17c87a2de8554e2629eed8172b60b078ccca7e78bb2b0a20324f51ef -dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=1e4c3a1d8585aac5aa3e66541b4aef03a0b429a6067300c58f6cf588eac19fa6 -dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.gz=6142ea4cdff99902181379fdb9a651fd9d1ab6276ebc104e73b2280a6d9f380f -dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.xz=bbf4c74f6b6a32f01d03bf101f69dd19b909717036117064fa2c8cdd0b4146da -dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9d957edfba201b541bd589ca4085e26bf6f890b3970817fe9af6ccf5f2eb0854 -dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=0f867e1391009d1d0caefb6b9217fc8e9f3e087a7dd9b22a157719bdc44ac074 +dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=0da01efb79d43140515c48561cbe7a2fdb83895fe4351f2fffaaf108fb163268 +dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=baa52bf16290d71b1b89f12ddcee5adf18c480071f9fd4daf3fcab72f92fad4a dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=2325e8bc225a24a0a8c16da6dded16d4befb671b913051a7cce12ee3e183eac7 dist/2024-07-26/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=ab9ad0ec7057deda5c29e5d7de317eb32512fb95b62ba628b91b5246dde9c90d -dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.gz=40d6d48dea64407bf31be39f9e0316a1e47648ee75bc0d3361edb961e062aa6b -dist/2024-07-26/rust-std-beta-aarch64-apple-ios-sim.tar.xz=3e01648f45e0c7cb040d3c293024477801930d5078d54c6291ba13aa8eb4e1f6 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=710be82238e9ad617b2d5f52ef37976b415e7b6ba3d5f3677080f2ccf78b9d44 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=2cd0956277cf963f95ffa0104bdcd60cb4e6c4bb2a443a683d67f41726408159 -dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.gz=9758806233e59d7d40eeda0740559d9838f9a6c608309567af61245ea57dc212 -dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.xz=4266b69d61a46c0c6f6d3aeb2b3378ff88201039df50cd8d3a51c9ff910be181 -dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d931a3611003cbe61003ca4feeb637449f1d10f7969cd27ca37f11cf5536e465 -dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3c7a3a9e1e03c2fe097e2e7353d00d02e864d3964db559f6a08a3d33f1fb7927 -dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=a02ccac46574fad8929b419eff7510b8a773211d3ccce9ca96f0485e2dab8eaa -dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=b70f37cddd519d0d207e28089b469f702bfe72ba5d32a631c85270db75b83d61 -dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=3f7529ea5dcb17c18efa949916dd1ebc29b123a265cc8839cee4fe4e637f19be -dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=d2a30f8659cc66d48da0e6c1919707943321d7f3ac0e2d58a9078aec16c86ef7 -dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=34b21aec2cc1b92b2911211fe3c798918ea6c99d51975f6a979c2da3a09b0a05 -dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=50ba48e76e60ffbfb2bb0ba0b8e12418b7f6a9d7cde31b508bb4656536934e82 -dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.gz=3af955fc52feaee2d89d6d50e0df4d00417897679f0d607a0f146a8d34c20496 -dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.xz=cb607387d0524bc84610cd6cc0a0070e0dadc379a7fb1a736f3f336cf0458b8d -dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.gz=a62be7f900cec101b1b7444c7466e8fe0b823d708fadd92bce8bd531866b4938 -dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.xz=993875efe27c1018bbcb8326665247a33eda6fc0e934f71124b0a08d72685474 -dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=07b356cd0ec3f18617e8f5be04d784847acfca43d6fa2101821dcdee18aada36 -dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=aecacd11945e6e053fe27faab2c0816628b392cb06c41feb8ed693d43043eba4 -dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.gz=17eb45b10a0c9cc702e7fb4f0c7926591d3ad0f052f2bded9cf852ea082cd2bb -dist/2024-07-26/rust-std-beta-aarch64-unknown-uefi.tar.xz=1f6b1a3082fc29546e4d8dcb20675f62ead20fe96112998dcb1260e206e93cbc dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=be6d9a01609152eb815cef9462023f0ca2f2950ed03d914629d8e6e3a96af8ab dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=75ec6023cf9a43ec7ed0f52a1633b56154d9505c5d5d769153b48b9991ce99a8 -dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.gz=6bd4089f30f05d9902d667a2d48028345bd558e7365bd3957bc554a4d0c1f939 -dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.xz=2a7e9250e3bea7f7e502131012139eadb66c71e95e8cec1698e22b21e7c9fbcd -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=3f8df0e35e2e8d5e0f8181f20f0639323aa8e8c21da60697599447c0d77f783a -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=d0e727d9176abdbef02b1276b3b1acf69068b9c0fc0477fb3248fd06c99292b5 -dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=3f6677ecdb1a2f016e9941234c221b06fd0a21cd9bae83a59bdcfde055c4878a -dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=60eae08756d92a70b740ecd8a1412138a9a14486289d73440bf7ee068586f9c4 -dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=7bf6bdb443503d48cb711f8b3e2670fe20e02f71ae940c2f1b273ab1d15452b7 -dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=9ed34d7467722660d625e9a048fcb843bdb80aac407b0395a693a5698f6c1465 -dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.gz=92de36c897dbf90f9986396da1f8a954ad7b4fdab3e466d63974c82611e76d47 -dist/2024-07-26/rust-std-beta-aarch64-unknown-none.tar.xz=fb5d50ce34bd222c1b624e5aa2248776f8926f3ee360b7c4c1e0bd412d01bae2 -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=73ba835c5c4c9fcabbcb4e1460d402cf0c0aa9b2e01342521897abd9769dcc02 -dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=64e6fc64ccfd0adb2fabc610eba6e877ab83f2de49532363deef4579728baf6f -dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=940eef037faceb2b9bdb1094eac6b175843094d3a3ab3c9850eb28742643e92d -dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=c892b8a80db788d1f4bf64ec6f740bb1168a8b9dc88d105366892a476ad3c244 -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=54b83918128c3d19b09a4e1801783500266794395e6a6f138ad647bd890b79f6 -dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=2b0ed80c922e25f3783fbc0ce181b76b7f758d2a1b85b823851b7ac35c6872df -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=fd2db70418d432c7b32bed92f5af0f301baa3a71c171d0ee8b0798bbc8e239e2 -dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=97922d70b37e1e2ff6dc447625b3482094824910a1d7a483cc707985406560ee +dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=cc1d361b775e966c700d122f925a9f2feacecaf7d2891d9c5c5a4a1060336408 +dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=934c10c58db5d7644bd0b7df6c3a128cc53b88b412128c33de5932fa0194f4bb dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=949a18d9d8b4c7cb3442ec4e387c91feddf0cc26f1fe602ec6c2c484312c9845 dist/2024-07-26/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=7adb9a93d35002d0335b3449b8d9af35a80a35524fe98bd86c3896481f020597 +dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.gz=b40dbc6ba0f3f80414bdc11260f291f067acbceb50d84597a9366746cff53348 +dist/2024-07-26/rust-std-beta-armebv7r-none-eabi.tar.xz=1564c3215b173956bae41cda7312ed7912812e0fbb65dd8d75808a1d5084fc8d +dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.gz=809d7f027aecc4a131921181418e66b956ad0a2a7170a3ec3649e21659c5a524 +dist/2024-07-26/rust-std-beta-armebv7r-none-eabihf.tar.xz=1b9589a72d2902cd4491406d93c599d2e850fa2ba19b1bcc6bdc5cc7196f9643 +dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=f2840d36b089fdbcff5f6f9f7a6e576cf21836824957cdf2d1ef2c75a1f5c11f +dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=5723cf48a1ff47fb764cc5ad921356e490997aa09ecd86404e370ffdacfa4b31 +dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=fb33110ad649aac6f55310e6f03d03d4d75ccdca43ada93fb97a717975ef867f +dist/2024-07-26/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=cef39c2886fffef2986e9fe8f3be58f0d7f3846466a35443bc0d49464bdef98a +dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.gz=68fe7b30550cf1ccc44a1669f26620ae418b48cd6283b716aff3dee91acfcbec +dist/2024-07-26/rust-std-beta-armv7-linux-androideabi.tar.xz=81f24aedc06a25c8dfce729132a77e90adc5fe2aec86a3a9548aec9458127ce1 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=a63c5d40bcf8b0702c1a91e992c042130916edfdcf94fb4615ba10c89dad6642 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=4706424b53063b768223880d87bbec0cf57e524374a6ef053ebef02d096484e4 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=85c3684f175642463777aa69889a20391e39afc0d6356baa3ac0445f7aa25119 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=a8d67436a8ee232d57e2924f8f9e5cb0050c71740d57a4e677674adb75093f31 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=b3226669f49ee8fc89c1f84855c29f8416df3e32d3276547f521f738179164a6 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=9a5711743a0984ab7baed2a50f87e50d7facff2ef05f5b936b7b25f5a5992734 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=fd2db70418d432c7b32bed92f5af0f301baa3a71c171d0ee8b0798bbc8e239e2 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=97922d70b37e1e2ff6dc447625b3482094824910a1d7a483cc707985406560ee +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=710be82238e9ad617b2d5f52ef37976b415e7b6ba3d5f3677080f2ccf78b9d44 +dist/2024-07-26/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=2cd0956277cf963f95ffa0104bdcd60cb4e6c4bb2a443a683d67f41726408159 +dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.gz=dd38446053d1500f3bdc325ae5cd52d0434c618d79a7c0a0473c76691353bac4 +dist/2024-07-26/rust-std-beta-armv7a-none-eabi.tar.xz=5b82a2f970be59563cc4f550e4202be802cbe21dcbf14de413ed8f30b0e22020 +dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.gz=9758806233e59d7d40eeda0740559d9838f9a6c608309567af61245ea57dc212 +dist/2024-07-26/rust-std-beta-armv7r-none-eabi.tar.xz=4266b69d61a46c0c6f6d3aeb2b3378ff88201039df50cd8d3a51c9ff910be181 +dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.gz=6142ea4cdff99902181379fdb9a651fd9d1ab6276ebc104e73b2280a6d9f380f +dist/2024-07-26/rust-std-beta-armv7r-none-eabihf.tar.xz=bbf4c74f6b6a32f01d03bf101f69dd19b909717036117064fa2c8cdd0b4146da +dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.gz=2cc32752932477945f248dee4d277754928b982815e2e2e0d27883522fb9b8d2 +dist/2024-07-26/rust-std-beta-i586-pc-windows-msvc.tar.xz=e40eae93c31c1fa06517a21cfbdd2dd18e2f740aee1251bcc9bdc680a565241c +dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.gz=6d7210503568d9fa02231ac2d9a1b400d00a37f38ec8f00bfcfe45c325aeed02 +dist/2024-07-26/rust-std-beta-i586-unknown-linux-gnu.tar.xz=cdd81201e38226750f2b4292b099b5d78fe0115cedb4c28bf20200144297d8b6 +dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.gz=95244114ed2d6dd2de488f49115b11a25b008134f1fa1c8f2e2a62849b51f213 +dist/2024-07-26/rust-std-beta-i586-unknown-linux-musl.tar.xz=fcb3280dabb4aae920a14c7f4fec52dc3f11bc68f5143961fa88347aa020bb9a dist/2024-07-26/rust-std-beta-i686-linux-android.tar.gz=d36c3baba2df9d69e197a773f752bc36e107c2411d78037a357039a856e35aa5 dist/2024-07-26/rust-std-beta-i686-linux-android.tar.xz=14b9bedd1bb95e1bac2bb028670b1d9dbe6998bb6ad0cfab1db0be0cd9e3d4cf -dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=7b671c5257a7653481fe6bc090c55398607590292590e0fdf5973f5f9b7b18b1 -dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=7f4d1a8e757fd29f4f58005032608df709003098eb661fe98a0b3116b7237e6a -dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=a1c1e3e15bea1c4e6c70b8a56c4fef1c231b6ab5528c32cb69ded38456b3fa21 -dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=43b31f7dd50621faff96c13a2246c80e84fc4da4076d4aedca4e9a6bf63ca43b -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=a7116c13a413989f2ed874d45780aced3299c4ef8ce8e3bc99efe960a73cadb3 -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=80ef87143ee2339e90842c4893284217ddfa56926524baf94341277c1210dd07 +dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.gz=44463b4a17c87a2de8554e2629eed8172b60b078ccca7e78bb2b0a20324f51ef +dist/2024-07-26/rust-std-beta-i686-pc-windows-gnu.tar.xz=1e4c3a1d8585aac5aa3e66541b4aef03a0b429a6067300c58f6cf588eac19fa6 +dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=b1d9d5967c039721eda402a7227074ba6e6e8f2877be49eed961ecbce00004ed +dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=2436343b99d81abae0e6bba16850dbc1c005ebba5defb991c3a0e99834410746 +dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.gz=c6147e9c6c39501d133a344972dbb8108bdc45bb2fe8ad624162ad04a9c00c6e +dist/2024-07-26/rust-std-beta-i686-pc-windows-msvc.tar.xz=6207bdfe0796e4bd4e7d25457d67559f15aa2e8bb91b05284ed147f8799de869 +dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.gz=c675df742bd9fbc01f67411a19926e2814412f12e09b53d1492e8c7250f3e685 +dist/2024-07-26/rust-std-beta-i686-unknown-freebsd.tar.xz=d5b9c3783f6d2dbdf25e0495e32a295c4820bbc5b65a44f19f018b1141e85371 +dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.gz=748dfafeb6b953017b9129be9697d02a73d5bc8b1371a6a00bbfa20b7b45033c +dist/2024-07-26/rust-std-beta-i686-unknown-linux-gnu.tar.xz=0c9a0717054858fa821e4c418b9e99cb0a0f852ec3c866951c1d1795cc1e8152 dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.gz=96afb9b33c86a6007f9c02f1f418d28f13014ec5154b648ceb7f725449dcbddf dist/2024-07-26/rust-std-beta-i686-unknown-linux-musl.tar.xz=7ed52c039fdd13a7477ed211ad8432cfd2fab98832174c8a534e5ac280f28572 +dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.gz=676786bd5e7f0739d18d40d99158045fcba746dc306485c0f15ce49ef2b63b0b +dist/2024-07-26/rust-std-beta-i686-unknown-uefi.tar.xz=d7fdba095ca515454034891c8a862aaa563ee7451289138ce32b10691dbfe38a dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=ff2eb11f284da7883dbf6ae465af86e50a9cd98c9b7d22b1e710626716e07db5 dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=953fedb9dac336cb796290f619919f4ff9b2a6fcce09e23072f93a40b5498bdd -dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=061fdac14ee0bd3abba36269f68e9ad25a243ac7062f946155f98680f484a84c -dist/2024-07-26/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=8acc12f14ac643b822595a6a07c7e5ac65855b83938ac122e3278f64769eeb13 +dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=ba1b4f772faf2e738d2696eb576f74bdbd1fed1a073053eee341ec6423b6e1c6 +dist/2024-07-26/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=f3f3eaafd9ecb1ee0ba68259d88d65ced56f20323a4f542fc85993e92a044206 +dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.gz=f20ecabfab9d8ecbab44d661018b865e449137993726e76b20c7749db4d0986e +dist/2024-07-26/rust-std-beta-loongarch64-unknown-none.tar.xz=7da2cf413c0665b07b3083862747c9815a78b3775c2bee6cd1f7551e7f2e4c8a +dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=3f7529ea5dcb17c18efa949916dd1ebc29b123a265cc8839cee4fe4e637f19be +dist/2024-07-26/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=d2a30f8659cc66d48da0e6c1919707943321d7f3ac0e2d58a9078aec16c86ef7 +dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=f971daa3f8c3d0773fb6667cb7a544f96ebd049e9b5d1b5ac4bd3ea0c342467b +dist/2024-07-26/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=3cd2f4ad7d9f41e9f903aa49eb86d142bb5ef69c2c39d9ba16a00a39d74046f1 +dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=b319ee87ee034a6a2a67dc2efdc72f8285c73d9bd1bd893586170ac54049151a +dist/2024-07-26/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=c751e65bbdfd72de07abf138162ab64dcbce51ba50375cef5ca8f35945d9ac7b +dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=0228f8d7e0913cca5db975e0b9ec4807e817dcbc0cd0bd64b64826c9537f25e5 +dist/2024-07-26/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=d37d5ae3605d745a393fc71c5f0e169cee283aa840edb9543682b339cd040310 +dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=6dd97a7215bdc8145cee5856957bf3f20719f65c73033006243ac2a9e347394b +dist/2024-07-26/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=d7541a8e83f7b8a9761988c3ac295a665e21e4d5dc9e2284ef48314f6c784166 +dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=34b21aec2cc1b92b2911211fe3c798918ea6c99d51975f6a979c2da3a09b0a05 +dist/2024-07-26/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=50ba48e76e60ffbfb2bb0ba0b8e12418b7f6a9d7cde31b508bb4656536934e82 +dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=e84526736c1a48dbec3b122b8c01458ff549afdbdd0f73e705c76cca1bd1f767 +dist/2024-07-26/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=df8d9909b0afd0e02b9c027f12e28aa2c40716d7c8a8f5e82b7521d2e145fbf8 +dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=7b671c5257a7653481fe6bc090c55398607590292590e0fdf5973f5f9b7b18b1 +dist/2024-07-26/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=7f4d1a8e757fd29f4f58005032608df709003098eb661fe98a0b3116b7237e6a +dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=9d957edfba201b541bd589ca4085e26bf6f890b3970817fe9af6ccf5f2eb0854 +dist/2024-07-26/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=0f867e1391009d1d0caefb6b9217fc8e9f3e087a7dd9b22a157719bdc44ac074 +dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=a02ccac46574fad8929b419eff7510b8a773211d3ccce9ca96f0485e2dab8eaa +dist/2024-07-26/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=b70f37cddd519d0d207e28089b469f702bfe72ba5d32a631c85270db75b83d61 +dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=151863cece818be834261e6c148eeabbb1c796c991065c84b813bac64e73fef7 +dist/2024-07-26/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=94cbae695036a4a1fa1faac12a6dd5ebeea18ec2d6e7b01c311d340ce7ddba39 +dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=3c8ca657208a4d96eff193363375a33d966dc319cd329dd7a0d379e052ab43bc +dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=037f7b599421eca888332dadd797509d81af04743eac06120a9882b27aff5ca2 +dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=d931a3611003cbe61003ca4feeb637449f1d10f7969cd27ca37f11cf5536e465 +dist/2024-07-26/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=3c7a3a9e1e03c2fe097e2e7353d00d02e864d3964db559f6a08a3d33f1fb7927 dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=f877200e388345c10d3b0f5b8c484dd42905e769dcc1e21692e1cf7f2d59317e dist/2024-07-26/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=1052e8e5681c95ed3c004adee2492ff19d109965e9441a3362df876719899486 +dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=e487752db0ecd837fb1ecb57064ef2464f7f85ed5fdc9d47322e7b5c37c32300 +dist/2024-07-26/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=e74a462d598c55822b5841bdc35cb2605b4aa7993e305246b3adf079ae79ea1d +dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.gz=3ea692ffe99c953d0049c0a16b71eb0bc3da492b9f9308463311dc0143af84dd +dist/2024-07-26/rust-std-beta-sparcv9-sun-solaris.tar.xz=97005f0d686a6481c5a532b6e1ea14befc794ed89394a8f1c94ad39257ebdaa8 dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.gz=2aa967414bd03764774338e377c4714b8d169b1bbc651624a20158441b8111c3 dist/2024-07-26/rust-std-beta-thumbv6m-none-eabi.tar.xz=d1a3b6ccbc55d1d9555674d1596a0c9f489304f9cb211e0c4645c17256ada4d1 +dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.gz=33fe3c61aa2e93c6a925b132fabc11c24e102cc070260d5f89a66e374e9a4d23 +dist/2024-07-26/rust-std-beta-thumbv7em-none-eabi.tar.xz=f50bb682fe484f23ae1ae9b2466c450b8fe9ecc3694fb68e162ce43cc8917af7 +dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.gz=53a17d10d498f1b6ebd6852987f304b2e1187544f2c9e91b69d0fdbf88630910 +dist/2024-07-26/rust-std-beta-thumbv7em-none-eabihf.tar.xz=fb97e6f2b047d6251eb6e34891b64f20d0dbc648beb78bb7364fe563670d7de8 +dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.gz=940eef037faceb2b9bdb1094eac6b175843094d3a3ab3c9850eb28742643e92d +dist/2024-07-26/rust-std-beta-thumbv7m-none-eabi.tar.xz=c892b8a80db788d1f4bf64ec6f740bb1168a8b9dc88d105366892a476ad3c244 +dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=905d378e6fd4387381fc166718ff31f017c99e725a9c8461bbac39d5571e246f +dist/2024-07-26/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=6c5fc29004bda36ddfb0280636ac2b2c28c538f33cadb07a55174fadb068daa5 +dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=38c8b07558734a9fff1807a823af72faaf8ab5ea47042f1b88a38d6c3648c43b +dist/2024-07-26/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=e30e0000336449a8aabf60839cba4ecca32cf82b02ed0a7a23935793072679f4 +dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=db784556ebf56a79e6330de3204ce6ce5422eca2543b872ed55c238aedbfedae +dist/2024-07-26/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=373efe8c55e85aae60dfac234471b76fefbc2ba722d97e0338ec593b7c70cce3 +dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=1bd5a11163f5fb9325e21c425d5d2fb3e1f845d265cbf7736679c3bb9c8d22a7 +dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=d858d0077df0fa7363258994e76a1bc0ff850734de6a0fbe955c3c9b9cd46cb7 +dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=07b356cd0ec3f18617e8f5be04d784847acfca43d6fa2101821dcdee18aada36 +dist/2024-07-26/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=aecacd11945e6e053fe27faab2c0816628b392cb06c41feb8ed693d43043eba4 +dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.gz=7bf6bdb443503d48cb711f8b3e2670fe20e02f71ae940c2f1b273ab1d15452b7 +dist/2024-07-26/rust-std-beta-wasm32-unknown-emscripten.tar.xz=9ed34d7467722660d625e9a048fcb843bdb80aac407b0395a693a5698f6c1465 dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.gz=5144fe563c42205ba777678291950bd1b8c2b010b9aae28e2fe96e14e93e28cb dist/2024-07-26/rust-std-beta-wasm32-unknown-unknown.tar.xz=6e55e79f65a02abf37e1533c2590f53dfe56b474b58a3220d88f3d1458b6dcdc -dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=b1d9d5967c039721eda402a7227074ba6e6e8f2877be49eed961ecbce00004ed -dist/2024-07-26/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=2436343b99d81abae0e6bba16850dbc1c005ebba5defb991c3a0e99834410746 -dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=cc1d361b775e966c700d122f925a9f2feacecaf7d2891d9c5c5a4a1060336408 -dist/2024-07-26/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=934c10c58db5d7644bd0b7df6c3a128cc53b88b412128c33de5932fa0194f4bb -dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=3c8ca657208a4d96eff193363375a33d966dc319cd329dd7a0d379e052ab43bc -dist/2024-07-26/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=037f7b599421eca888332dadd797509d81af04743eac06120a9882b27aff5ca2 -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=199498df7d94989d4ff1773fdfe86e97ac99ead487f402d020f78688bc6dfba4 -dist/2024-07-26/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=1337c2f00e9bec2e0a553234d74daea67a9781459d0abe3c8de954981d9354d2 -dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=53c64845abe4582a90041b2128b3f931ce636d01fc9a8509b35ded5dd7ae0a35 -dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=61805cfca6e7f602eaab0fde2be48cfed244105b2f4b5bff798752ce06d62713 +dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.gz=84d03b1c1fc7338895f82f54fdccb18ea6c4ceb43f47c3d46fadb014aa0c9549 +dist/2024-07-26/rust-std-beta-wasm32-wasi.tar.xz=f28cbf9552e3c680342364087e7305a12417a92ed6b6696d71d476e1c1d8d4e7 +dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.gz=8d56f1aa8661047f854806278b83a514fa79b7a5097635cd095943b3f848ea74 +dist/2024-07-26/rust-std-beta-wasm32-wasip1.tar.xz=78609204d01e0d0bcbc1fb5dd3d9cfcac60db23bfbd2428f1e021d1b05793519 +dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.gz=ed1b9141bd68b8c13e295904ac66d18ca92c5b92a263fa5109262d15065aeded +dist/2024-07-26/rust-std-beta-wasm32-wasip1-threads.tar.xz=0c036271c4c4e04357b630146cad296dc6a57363f7dc0cd2f3142ead13bf0602 +dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.gz=c12bc5543c262645f7000cc84247518033f15fcbdfed510eb92393d723906eb1 +dist/2024-07-26/rust-std-beta-x86_64-apple-darwin.tar.xz=a5fc26dd6068cdb28ee2a252af545a34dd2be6e075e7d0aac2d03796c07579f4 +dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.gz=a62be7f900cec101b1b7444c7466e8fe0b823d708fadd92bce8bd531866b4938 +dist/2024-07-26/rust-std-beta-x86_64-apple-ios.tar.xz=993875efe27c1018bbcb8326665247a33eda6fc0e934f71124b0a08d72685474 +dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=bc6ae4d5e93b47828678f1af55efc1baae2d76975be3259854272a566f5489c9 +dist/2024-07-26/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=51cf1d675e61aaeedf895e52a9a81b188aa066a68d599963e0435bddfd2f6a5b +dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.gz=6bd4089f30f05d9902d667a2d48028345bd558e7365bd3957bc554a4d0c1f939 +dist/2024-07-26/rust-std-beta-x86_64-linux-android.tar.xz=2a7e9250e3bea7f7e502131012139eadb66c71e95e8cec1698e22b21e7c9fbcd +dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.gz=4169c938b638faff18a5db1bed5e7d2036f45d25ec9799dc2967ad1589d447a9 +dist/2024-07-26/rust-std-beta-x86_64-pc-solaris.tar.xz=8cbda8eeb98be575b78170e9895390e9406c4de41db8363988185dd24e276427 +dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=99a14bf8cffa0c736a25ce117bc5d4ab64963d81c9d9ac377f118a77a6a3c4b6 +dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=9902878b75b3f6cf944909cf6d17efc26dc820708b164b34757d841e89c948bd +dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=54b83918128c3d19b09a4e1801783500266794395e6a6f138ad647bd890b79f6 +dist/2024-07-26/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=2b0ed80c922e25f3783fbc0ce181b76b7f758d2a1b85b823851b7ac35c6872df +dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=44ce7faad791029b670a9d815766a647d488dbbb56eb09024a09a595427fd19b +dist/2024-07-26/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=cd7011512df191100d31caef920d1a5c6d5ec2a771e0b52078d5d60b45e9a497 +dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.gz=dc20c2fc14b2211bf4517464109871f940a227298302d2ec84eaca539a19e9b4 +dist/2024-07-26/rust-std-beta-x86_64-unknown-freebsd.tar.xz=5a7fa24ca3f7b43526c116a5ebce60f29116640ad51c1ed426f9aee705b10897 +dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=975917e862347f7e1472cdaa2258de16cb9981e3a8256f9b7860104740076187 +dist/2024-07-26/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=bb89062b05f025a964e0110fcfc8fdf57300b23314409924cd4a05e9af9614af +dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.gz=a1c1e3e15bea1c4e6c70b8a56c4fef1c231b6ab5528c32cb69ded38456b3fa21 +dist/2024-07-26/rust-std-beta-x86_64-unknown-illumos.tar.xz=43b31f7dd50621faff96c13a2246c80e84fc4da4076d4aedca4e9a6bf63ca43b +dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=3f8df0e35e2e8d5e0f8181f20f0639323aa8e8c21da60697599447c0d77f783a +dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=d0e727d9176abdbef02b1276b3b1acf69068b9c0fc0477fb3248fd06c99292b5 +dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=73ba835c5c4c9fcabbcb4e1460d402cf0c0aa9b2e01342521897abd9769dcc02 +dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=64e6fc64ccfd0adb2fabc610eba6e877ab83f2de49532363deef4579728baf6f +dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=58dcb73ba02fa38742d255bd346a77340cf634247904624c7af9b11e769a364c +dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=ea4417de121ab7e869659b26efd144baf2fd839a956da4acb30121d1bc9132aa +dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=d1e861a9176a5cb934270592f7b98528283c363d135736477a844499015ac44a +dist/2024-07-26/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=c5f548845c6ccbee1980892e630ab06ec1bef498fb7f6fc80b4ced4a84c23f85 +dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.gz=3f6677ecdb1a2f016e9941234c221b06fd0a21cd9bae83a59bdcfde055c4878a +dist/2024-07-26/rust-std-beta-x86_64-unknown-netbsd.tar.xz=60eae08756d92a70b740ecd8a1412138a9a14486289d73440bf7ee068586f9c4 +dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.gz=1f11ad1a66d01a09c7237da76327b70ae2e2a9f7647a3ee0de58d563576efacf +dist/2024-07-26/rust-std-beta-x86_64-unknown-none.tar.xz=960fb614a927e1b3d1d8e4a9fb7220ae675d0e8219fdde204bc6454fbe69a0a9 +dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.gz=3af955fc52feaee2d89d6d50e0df4d00417897679f0d607a0f146a8d34c20496 +dist/2024-07-26/rust-std-beta-x86_64-unknown-redox.tar.xz=cb607387d0524bc84610cd6cc0a0070e0dadc379a7fb1a736f3f336cf0458b8d +dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.gz=ae56b334234ba51cf68be42d0fd58cf3487673dbe747bb3efa01e8563b9b8a90 +dist/2024-07-26/rust-std-beta-x86_64-unknown-uefi.tar.xz=1468622e9bb6384a6ab7006863d2b7d55307e74239befc8e72dfd39f83c0af1e dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.gz=62f687da4c02bef3e114b92c75b62fc6f7fdfcd210fb66329f6d4780f7dbcd70 dist/2024-07-26/cargo-beta-aarch64-apple-darwin.tar.xz=f9346e9ed4e5638f58dc237b22aef9e1b25b23bb588c736dceaa25b7b935f2bb +dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=f2442eab2908bb90c551f56da8889e39ce44a31936ce63e13a54432105a67cf9 +dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ffc8c803668d09333fdfee996fa72c8874e91d92567f0b4eff9077d7b9a3070a +dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=97f6b771f7e559df03f00f8665c6580535499d4afa7bf2a252a145b1aa0e2c0b +dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=3ee58d5c57ba00e27428392dab1d69655bf7e997a0d3aa6629bb32f4f863396b +dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=b36871d3c88eca54e4c24d50171fd649d10a92f689d4812ebef7b510f0c3d799 +dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ee550d60ae217fe7aec12feada1ba1f84222427677de42382d192ec748f73f18 +dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6599270c877164e76ef30f00a9b47da1a021fdaf1d4f7fdb194500f861ca8d21 +dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=46429528039b5499c6ac4618c4b73fcdfabf7fdd5ed9f9f3d64ccde0428d78c0 dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=01ba37e80e18e673c275538fc0db63b667ef52a72000dcbe76ac68018bd585e8 dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=004f5119454fa53c2a7a58f6d176f65903b3c5bfc8eb1f894f6ca4e9bc32b7a1 +dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=2bb2e69563684bf64607d3f584b4216b24fe190dd2eabd6c00c2044290beabde +dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=454b0dafb3cd62788dc541ddfea5b484ac799253937602f6456e853c2a293707 +dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.gz=779d704f8f64a7290227631d1e396fe00bdada3cfb7f3e6c775a0bb00047cb97 +dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.xz=8cce8e286ff04f4d58235e8716a0ca05aedfeb9db6fb8952c523264ea649e542 +dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.gz=58b31a781da4f5215b0fbb5f355cbc3c5b2212971c68a1e00de19b851698fda3 +dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.xz=008125eca7351844707c9c14637030da45441a68d74f6e2752ee713f6403f03b dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.gz=cbfc580db37b135a20f42f9da02517ec8cf0a286b7274252c23c6a4947ba6755 dist/2024-07-26/cargo-beta-i686-unknown-linux-gnu.tar.xz=dc2198fabb6fe6f68353c268698dece4ca3d6901b424a7cc2c68850f81f75f20 -dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=bcd0e100d4c66784a2357be74813551c68d4e3b5e6846bfd1bbcb316e5c82c53 -dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=cc31bb9f5a67359f4af4743afbdf9b694e40cd209211d4ea819c94183de6ab60 dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=46ea726328e1700cf2b7d0ddeb16e25ebb648267c76268ba2f4aecb75ba47661 dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=520ee25c1f18d80b4e4ce25e8fd961a19c0dd2ee0274e9d9cd3201f7c57c6f77 -dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.gz=b36871d3c88eca54e4c24d50171fd649d10a92f689d4812ebef7b510f0c3d799 -dist/2024-07-26/cargo-beta-aarch64-unknown-linux-musl.tar.xz=ee550d60ae217fe7aec12feada1ba1f84222427677de42382d192ec748f73f18 -dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=f48bb7b7d13862edaa8949be046b5bd2b8c63b0aab8e29bffb1940ec149eb123 -dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=0a6e09604fe291d0a9a0845a8ac7f434c9f4ffbb698c042ba83a070c23f804fb -dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=1bf5d0201ca87a76de8044dd8222517bd130ef3db631dc60a84e2fceced465d7 -dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=2eaeb6863c655047e6c938e208ae952df4da2d8b4326aeda60918414764aa7b6 -dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=92ac04de9689176a42e5f0ccf1e44ce78b64bcd15d6e570c171d51c44cf8c6ce -dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=59a371de4343d330b79e84f629c98b5cb9dc58bd9706d1a7a9ff474b28394851 -dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.gz=521f03a968c6e0640de6f09ecbc6328ea57b2815f353a14e1d4dd09925e98366 -dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.xz=14b733585cc768d26a822de630d990f519b6d6b4ae079f09bacd51b7449c18a4 -dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.gz=58b31a781da4f5215b0fbb5f355cbc3c5b2212971c68a1e00de19b851698fda3 -dist/2024-07-26/cargo-beta-i686-pc-windows-msvc.tar.xz=008125eca7351844707c9c14637030da45441a68d74f6e2752ee713f6403f03b -dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.gz=f2442eab2908bb90c551f56da8889e39ce44a31936ce63e13a54432105a67cf9 -dist/2024-07-26/cargo-beta-aarch64-pc-windows-msvc.tar.xz=ffc8c803668d09333fdfee996fa72c8874e91d92567f0b4eff9077d7b9a3070a +dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=fb710b6ae058619042bdf80ef5c2a56457076692a122b4155e0a53f382e8ad83 +dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=ac15e80c28c7a4570bb4a99fa70522a3ae5ba602ce25e96b8e82d097f8b42904 +dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=6907a40c1e7b18146ff2a60c6d44c9716f31cd4aeaae4fe858032aa26c359d27 +dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=4287d73ae2b3272a1893c2ffa32d007edf0b05ff2dbf1da92aa20f2b857e0eab +dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=edbdd5fc1e9bc5fdea67e7c2fda3fa9f3eb3f599c307a278bc7bf45ff97d1f48 +dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=9c7d487f65a6273b76970b2c057b8120abbd89ba67a2f92dd446ecbacf218576 dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=74e57cbc139d548202d94262170ee45e33ae01331358ac2eaa9fa67c968ea1ea dist/2024-07-26/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=6cf99b689e32ff0caa56e9704dd185f6c268b484ccb657eff212e66fe64d1c10 dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=ed13a39d74e9d814d585ce7fb1aafd093f94317d6ead76e4b43c03b01e210086 dist/2024-07-26/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=b5379d677d6596ffcbd7f3ebef2fd6d968096228101104a45565b170fb050042 -dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.gz=12f6a8d3d17b54ea260f6f5b19be9e208111b0ad37518ae6b6eae558d77a1dc5 -dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.xz=221c9cf9d1fce2b5c50bcf8f435f5335f1c5e9533f51d52b941593d6a964b4c8 dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.gz=1a29502881e6512a8bea566a90781870181f5727359668fa3bed2b3210a21b8d dist/2024-07-26/cargo-beta-s390x-unknown-linux-gnu.tar.xz=95970245a7f304c6b83b8dad58b4c877ad2c9b0ca6bfc0090151561ce53a217b -dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=97f6b771f7e559df03f00f8665c6580535499d4afa7bf2a252a145b1aa0e2c0b -dist/2024-07-26/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=3ee58d5c57ba00e27428392dab1d69655bf7e997a0d3aa6629bb32f4f863396b -dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=edbdd5fc1e9bc5fdea67e7c2fda3fa9f3eb3f599c307a278bc7bf45ff97d1f48 -dist/2024-07-26/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=9c7d487f65a6273b76970b2c057b8120abbd89ba67a2f92dd446ecbacf218576 +dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.gz=521f03a968c6e0640de6f09ecbc6328ea57b2815f353a14e1d4dd09925e98366 +dist/2024-07-26/cargo-beta-x86_64-apple-darwin.tar.xz=14b733585cc768d26a822de630d990f519b6d6b4ae079f09bacd51b7449c18a4 +dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.gz=1bf5d0201ca87a76de8044dd8222517bd130ef3db631dc60a84e2fceced465d7 +dist/2024-07-26/cargo-beta-x86_64-pc-windows-gnu.tar.xz=2eaeb6863c655047e6c938e208ae952df4da2d8b4326aeda60918414764aa7b6 dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.gz=7b7ef80aa6131ddcb8bfec0f9493417e9a1e617a8f599a27de52ee914d022f95 dist/2024-07-26/cargo-beta-x86_64-pc-windows-msvc.tar.xz=647a6d0ff8f38dd4404c0006e5ed7b3a981dc89bbc334b1bd53225cc4f5511c8 -dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=6599270c877164e76ef30f00a9b47da1a021fdaf1d4f7fdb194500f861ca8d21 -dist/2024-07-26/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=46429528039b5499c6ac4618c4b73fcdfabf7fdd5ed9f9f3d64ccde0428d78c0 -dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.gz=779d704f8f64a7290227631d1e396fe00bdada3cfb7f3e6c775a0bb00047cb97 -dist/2024-07-26/cargo-beta-i686-pc-windows-gnu.tar.xz=8cce8e286ff04f4d58235e8716a0ca05aedfeb9db6fb8952c523264ea649e542 -dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=2bb2e69563684bf64607d3f584b4216b24fe190dd2eabd6c00c2044290beabde -dist/2024-07-26/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=454b0dafb3cd62788dc541ddfea5b484ac799253937602f6456e853c2a293707 -dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=fb710b6ae058619042bdf80ef5c2a56457076692a122b4155e0a53f382e8ad83 -dist/2024-07-26/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=ac15e80c28c7a4570bb4a99fa70522a3ae5ba602ce25e96b8e82d097f8b42904 -dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=6907a40c1e7b18146ff2a60c6d44c9716f31cd4aeaae4fe858032aa26c359d27 -dist/2024-07-26/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=4287d73ae2b3272a1893c2ffa32d007edf0b05ff2dbf1da92aa20f2b857e0eab -dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=101e3118bf23246195b159abab59ee5626e767977d97f00e71fc5e67dfbf7784 -dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e40c0c15a7b195ed03c5e1167c2cb5e765ef643b0f6621c36643faf87bf46369 -dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=f794412df97e19240f628037f5d1d7391dd09ee1a6de02f4dbff72e2b03d94b6 -dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=49a78a14b9638cabd19ba4261f5bd04066646e1260146e3be288182b73fa1864 +dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.gz=bcd0e100d4c66784a2357be74813551c68d4e3b5e6846bfd1bbcb316e5c82c53 +dist/2024-07-26/cargo-beta-x86_64-unknown-freebsd.tar.xz=cc31bb9f5a67359f4af4743afbdf9b694e40cd209211d4ea819c94183de6ab60 +dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.gz=12f6a8d3d17b54ea260f6f5b19be9e208111b0ad37518ae6b6eae558d77a1dc5 +dist/2024-07-26/cargo-beta-x86_64-unknown-illumos.tar.xz=221c9cf9d1fce2b5c50bcf8f435f5335f1c5e9533f51d52b941593d6a964b4c8 +dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=53c64845abe4582a90041b2128b3f931ce636d01fc9a8509b35ded5dd7ae0a35 +dist/2024-07-26/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=61805cfca6e7f602eaab0fde2be48cfed244105b2f4b5bff798752ce06d62713 +dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.gz=92ac04de9689176a42e5f0ccf1e44ce78b64bcd15d6e570c171d51c44cf8c6ce +dist/2024-07-26/cargo-beta-x86_64-unknown-linux-musl.tar.xz=59a371de4343d330b79e84f629c98b5cb9dc58bd9706d1a7a9ff474b28394851 +dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.gz=f48bb7b7d13862edaa8949be046b5bd2b8c63b0aab8e29bffb1940ec149eb123 +dist/2024-07-26/cargo-beta-x86_64-unknown-netbsd.tar.xz=0a6e09604fe291d0a9a0845a8ac7f434c9f4ffbb698c042ba83a070c23f804fb dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.gz=4c8991c692f200c6a5f25957e6648e07b7271681cbd9c61749bc990216dbbe6f dist/2024-07-26/clippy-beta-aarch64-apple-darwin.tar.xz=51b5b85d46af2a3faeb53b81472c285eccc01f0c83575f62f37739cd48397fe2 -dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=57f7109bef934d0da06f7aea6eaca72b0e66f82d1160fbae05f53c2276da2b82 -dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=5ed50d8d088ae0d86ba51a03bf56040da027376f70b5114f593813daa4ce7a40 -dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=a2cd11651304ecf5ce6a1ee5fdd1acbfd36b1dbd2680cd76f2b9d3a86012b837 -dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=c8a8d9fe8badb1e06811412a15ce9cdfef07ecc59bf83cd578b33889751bb560 -dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=c2a30c78a6ab64d1655651fdd5c7f970dadcd6dfd1a585d130bd890190fe67f6 -dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=05c2a38fa5bca162e365218670a7c195ebd9b3491d14464282a273dfe93b0ad7 +dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=3a7755c10b32ee3b4f95875c974f21efad2be7ae27d317bbac056b3e5b9298b7 +dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=718692e6a1e00ca042d9767273e487c941c65440e64729844a46e42ec6a8abb2 +dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=18da4a1fac25597186bdc5c825c71bc6fe020e8e6552ac97dd307a0311acab20 +dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=86a7ec123586e0c953efd23b82aea5eab62ab8c065bf3596d3001a23b01243ce dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.gz=267b8dd0b5024152e36bcfb15af0b8ae3c68a71f559b8ecea1a3c9a8982e315b dist/2024-07-26/clippy-beta-aarch64-unknown-linux-musl.tar.xz=6aaae715599da14ca8cc405e51deed3bc160661ec56e929ae347ef1ead7ccf00 -dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.gz=d8712ca2ab26256c0fade4ecc8dd8e4ea6770d91e16e460ff2fe3f070febc59f -dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.xz=9d0c88881e0535f9cb4a48f59b389b1c2a0b5fa46ad8bfa37fbc540676a8f557 -dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=4009c19d557156e63ad7123d27264650d046cd20e723ec6cc8ffdb3fc1d3b8b1 -dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=9622117651423c53c35f69cb3087a5294cca098ac93aeb7c18bcab035a1e69ef -dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=89bd927bc9370a405561f6534c5cd88e0f6e06b0b512589e5722349b12a17763 -dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=732120c4fcdde08fadca139216a91af7a6abee15f0a41735dc8860b36039d88d +dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=f794412df97e19240f628037f5d1d7391dd09ee1a6de02f4dbff72e2b03d94b6 +dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=49a78a14b9638cabd19ba4261f5bd04066646e1260146e3be288182b73fa1864 dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=3dcd9775b46a100a50fbb00188dffdc6f07fca9843994c8406a2d053e41c1672 dist/2024-07-26/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=e069b852ace430b2f75486a291d3d7849439c67c3381f5eedc0d6a9e6cde56db +dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=57f7109bef934d0da06f7aea6eaca72b0e66f82d1160fbae05f53c2276da2b82 +dist/2024-07-26/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=5ed50d8d088ae0d86ba51a03bf56040da027376f70b5114f593813daa4ce7a40 +dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.gz=d8712ca2ab26256c0fade4ecc8dd8e4ea6770d91e16e460ff2fe3f070febc59f +dist/2024-07-26/clippy-beta-i686-pc-windows-gnu.tar.xz=9d0c88881e0535f9cb4a48f59b389b1c2a0b5fa46ad8bfa37fbc540676a8f557 dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.gz=ffa017562648e98c7229e43a7422602c265441228485f0e14e52ebaf48a13e91 dist/2024-07-26/clippy-beta-i686-pc-windows-msvc.tar.xz=292ab3d318a34e67463728752dc175f65cf5530f9368344dccaa79bad4df3b85 -dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d53fb59c723a2e76f1716cf1c82aacd2627e1694aebf70511c24529a4fe1ee99 -dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ffec66667d95cabc893cc87988218552eba8930f031419612f80144dcf2cc881 -dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=75ee727a80119a810193519535f962721d547297feb9b5597b397e59277de701 -dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=002b726868a14df5ea31fe8eb75fae24660fb1cfad73591e86f9179dd1bb2dc4 -dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.gz=edd631b7938dae6bb6c2694df0dab3ff6670e1a5ab3b5f0e6ce5bd7e992b6310 -dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.xz=e4bc44ff13cfdd70f94c5efe86e93de041599e570c19611141c00700a656b40c -dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=e467501c65651d519ae9a489e821e7d5dc82fdbeb2da2d4c75f093e1b898abd6 -dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=9dcbd07899af86db3c101275ab0f2fd3b5b0c43d4a92c5b5be05f0e4500d7535 -dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.gz=3a7755c10b32ee3b4f95875c974f21efad2be7ae27d317bbac056b3e5b9298b7 -dist/2024-07-26/clippy-beta-aarch64-pc-windows-msvc.tar.xz=718692e6a1e00ca042d9767273e487c941c65440e64729844a46e42ec6a8abb2 -dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=1b1aff83773de4dd972734cb03209eccfc3793f442a1a5dea51f451ca34cd1cc -dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=71c357ff694cd954314c47e3bd458465453c65e6022799827b8560ecae16fdc8 +dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.gz=89bd927bc9370a405561f6534c5cd88e0f6e06b0b512589e5722349b12a17763 +dist/2024-07-26/clippy-beta-i686-unknown-linux-gnu.tar.xz=732120c4fcdde08fadca139216a91af7a6abee15f0a41735dc8860b36039d88d +dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=101e3118bf23246195b159abab59ee5626e767977d97f00e71fc5e67dfbf7784 +dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=e40c0c15a7b195ed03c5e1167c2cb5e765ef643b0f6621c36643faf87bf46369 dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f6ed6391c8997f942d180cd32e81aca654450fb050cd865a8a1b13f77a892245 dist/2024-07-26/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=16e736f65b0ff029fe9fbafceec938123dff1b5a133f6c48b25edab379a20685 -dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=18da4a1fac25597186bdc5c825c71bc6fe020e8e6552ac97dd307a0311acab20 -dist/2024-07-26/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=86a7ec123586e0c953efd23b82aea5eab62ab8c065bf3596d3001a23b01243ce +dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=711fdb406a23ab5c3b1199e7af06608297bd071d7e48734a03bbc1f7a00b66dd +dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=36d05ba29927b56e0d815dd09b39a3db12b6395e9717e653c20449fa83aa636f +dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=d53fb59c723a2e76f1716cf1c82aacd2627e1694aebf70511c24529a4fe1ee99 +dist/2024-07-26/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=ffec66667d95cabc893cc87988218552eba8930f031419612f80144dcf2cc881 +dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=a2cd11651304ecf5ce6a1ee5fdd1acbfd36b1dbd2680cd76f2b9d3a86012b837 +dist/2024-07-26/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=c8a8d9fe8badb1e06811412a15ce9cdfef07ecc59bf83cd578b33889751bb560 dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=01ba50dae501edf3afa60aab59d8d81ccfd91126ded4cf7d45f7c4b13fb8c4aa dist/2024-07-26/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=a7e749bc581f9c64137a00dd891c4abff0d7f5684d2d501aad20ed1b01d9a312 dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.gz=f19081755c37e3dc43091b06bcdc59c82b28c6fa0a78ff02d800a25d6d9f22f2 dist/2024-07-26/clippy-beta-s390x-unknown-linux-gnu.tar.xz=d5f222e23f4f0ed4929e11684bc7b861c29fa183fffba0dbbfd5739b921f5234 +dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.gz=edd631b7938dae6bb6c2694df0dab3ff6670e1a5ab3b5f0e6ce5bd7e992b6310 +dist/2024-07-26/clippy-beta-x86_64-apple-darwin.tar.xz=e4bc44ff13cfdd70f94c5efe86e93de041599e570c19611141c00700a656b40c +dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.gz=1b1aff83773de4dd972734cb03209eccfc3793f442a1a5dea51f451ca34cd1cc +dist/2024-07-26/clippy-beta-x86_64-pc-windows-gnu.tar.xz=71c357ff694cd954314c47e3bd458465453c65e6022799827b8560ecae16fdc8 dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.gz=d4759993b9659ad8354d3fdf858cf99efebdf8202442505e11b55d24a54b31a0 dist/2024-07-26/clippy-beta-x86_64-pc-windows-msvc.tar.xz=e29eaea7b7f2e54b9285a2216f5b85440313650090c268048ce9e830e007fa92 +dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.gz=4009c19d557156e63ad7123d27264650d046cd20e723ec6cc8ffdb3fc1d3b8b1 +dist/2024-07-26/clippy-beta-x86_64-unknown-freebsd.tar.xz=9622117651423c53c35f69cb3087a5294cca098ac93aeb7c18bcab035a1e69ef dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.gz=a88fd4b3e30faaecf270936422e254a25ff5dba93b08ca4003a9978ee80d0838 dist/2024-07-26/clippy-beta-x86_64-unknown-illumos.tar.xz=f391b26009b7089f3d49d2f3409bb4e02e3de0700284727d2d26e7062bb18011 -dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=711fdb406a23ab5c3b1199e7af06608297bd071d7e48734a03bbc1f7a00b66dd -dist/2024-07-26/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=36d05ba29927b56e0d815dd09b39a3db12b6395e9717e653c20449fa83aa636f -dist/2024-07-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=b6e2e07fbfe9de4e41090cb45fa680d6c402f34e37d6f5144f90896643ed51b0 -dist/2024-07-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=b83c0f949d898df72c1a52eb41c1110bc02e101c391ffd49f67771d60b2010b8 -dist/2024-07-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=ef6245c042b255729112142b94a15082adbd172ecf465fd235aa747cbf29bb1d -dist/2024-07-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=c55ad9c9ef4f14929c00c3378ae9888e268c6ac40d53f811a8c4bd5f90bd9010 -dist/2024-07-26/rustfmt-nightly-x86_64-apple-darwin.tar.gz=5fcbe00f6adca3ed5d76a7c68e69af8103ef479b1ca09b6c81f1c0ebf3bd23fc -dist/2024-07-26/rustfmt-nightly-x86_64-apple-darwin.tar.xz=ef8d4b12b85935517ad767a6bfcddec9137560544503b4550b3d8b6d8d0b6d1e -dist/2024-07-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=d3fc0be767f6f1bf17fd7d98bae14a2a8b57d806b8f968120d2ef53d51809603 -dist/2024-07-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=7c32a2fc5724e5204287caf6e9ffa41b0dc9fd52de9258732b5fa875e53a700a -dist/2024-07-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=45b73c64128663c09841822c8fb3deb6a5a301ed263278df371ce01d8ad9042a -dist/2024-07-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=8c95bb793a4c527cba96032d6f23555d2e85ab29ac95d75642fcd297fef2daf1 -dist/2024-07-26/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=a5c15ab3650fdd6141a2cbdb9c830af716ee472d8900d140aaeb7032dec1aad6 -dist/2024-07-26/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=24c0f8efc889d76552f0ee80dc397fab2f6c142c0b6a1b72e3ef2975b9c05eb6 -dist/2024-07-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=7a703525762f4913715327edc4945a3d55aa5dec02d985432cce83aa9fef1470 -dist/2024-07-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=20258cc2bc456a689f6b6abe48eceb49993ff4632b138855390091bca83cbee9 -dist/2024-07-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=51080ea5308bb5ec3dd8be62dccb0ce04744b9b48a619c08805d35068858bb4b -dist/2024-07-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=ea11bab9e90c2bfccf734e138e8b75b997d14d5c471989d6e8fdcab279c8c16e -dist/2024-07-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=efadb18590ca310697a4897f7a441494495d01f235ce92fa9dfd3dedc1027a42 -dist/2024-07-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=c2c36fd4d8fb2be887db1f3f3304e3e0b7fd1359868d1d221414efec631a1beb -dist/2024-07-26/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=c07217e18d83f5afb4b57465861d1f7dde670c17167843f2af7f7a58d2e37a20 -dist/2024-07-26/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=2e2c8bc75b7691e4f1fca9b4fbfc3d6ab210ed216a334838ffda11c51ca19707 -dist/2024-07-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=66e882dfcc22f8b8293aec8ca5bd859a322c1430c6ae6556007e5b4f15e380c9 -dist/2024-07-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=8ed347717e758390d1f0a31412d8f86ced65002a316b15e48cde687e67ecd60d -dist/2024-07-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=84917b3c08566abca67f6039e483fa964b02c775459b3654e7b72b80df483d2b -dist/2024-07-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=6848d6b2aef03f51dc8564716c8a3761f0583b8e360d5223058ad746a366d91c -dist/2024-07-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=049c174a7a4f22865ec7d6bfa1dd84a70f2da83677aad3356ad2e007ab167be8 -dist/2024-07-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=29c1e5a2217ad531b86da6c01c1cb94cdf1b935fbc08d9dab8088b9985dee140 -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=68bfff981e0e8479a1335cd3a143d220a36091b08bf7d80d435fc999adc8e7d1 -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=ac4f1ad6528d295374083e4edfb6bb8139979a069f9946c863f7764d0a6a1a58 -dist/2024-07-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=427caba43e4aadf685d09e838aaff0e2b7f805afe6efa557b6ab6f65afc45900 -dist/2024-07-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=2d7447476440878540deb2e1f51876467b77b5591b3207edb313675377069a35 -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=1ac2c3f043bc410c5b6dbdd996ed4d1e1ec2d7513b4a21e9f0c6f51ffd5189c8 -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=ae904145eb7086de7c69c48a0958e1d925db9a9d51cbf6738a71218bfa684963 -dist/2024-07-26/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=476a6944de96dd26b9984ba7248dd5e9394784c2e5c0fe8ea13f79966d284240 -dist/2024-07-26/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=4f778cc234a97fc8cc1d877b3753e7f466f9f557216cc4e1c5eb7f157b6d3811 -dist/2024-07-26/rustfmt-nightly-aarch64-apple-darwin.tar.gz=bf52d6c3824151664479cef6cc9c57dd94f9b5a2c89f6f244a46dd4438158722 -dist/2024-07-26/rustfmt-nightly-aarch64-apple-darwin.tar.xz=d45ebae395b15a651ec7f6fd17f52f2cb9561d7e76faffef090d78ed47780442 -dist/2024-07-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=8275a2cc79013a9025ba221f5d02735285be022ea7d2e3aed4eeef3fd295cc34 -dist/2024-07-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=2dbfe4b19e9b82b249a5759202322fec4ecfc4a089f0aa14e55a245154dab6ea -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=bffcc6e98b736fa7876ce9634eafddc0508b22177e2a0510e665bb3e7219aff7 -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=8fc38e8a25724d21b8c1cfa2037abad5132f798b595989e8317104d28dadfa22 -dist/2024-07-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=8b924095a51e7c4a85377cf626c684aee29c8c9fea7dd3f6b3118bf07b45cac8 -dist/2024-07-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=527a9ffe420e944467485f8883437fd2a222c26285013a961079025817c39a08 -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=9337cb22df008b570ed28dd896c6dc042081b3ae06b3e02d5e728a8acb1dc467 -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=a84d203bc42be497149f03fafd9338392d1dcbf097012780a12cc285cd05b349 -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=02a86dd1e924fc4a87b728bba307bc66b871bb14c73dae70cfb72b4e617a9ecd -dist/2024-07-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=4a9f35ac0ae4fd6b5fa69f3152975b9eac3a8751e9e1ae87d10cd984a5f412a1 -dist/2024-07-26/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=3c2dd7afd93117932751cce5c016006b4104af85cd9997131e19268cda603050 -dist/2024-07-26/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=4b4fb076ab64d7f86b7f4dc77bba378357bb3f4d000528b47b80d2f8a0b84ec3 -dist/2024-07-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=384eec30f643dddd70d392a42adef611607d35bfc6f63665a8d90fbd9c493c8a -dist/2024-07-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=af18b698508d661b1cb5d725fb49794e0fcede1a8e0f5018a85d7e1e4f3d5486 -dist/2024-07-26/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=837e703a43897fede9a7ae5319bdd7c21990e901fc38f5f836dde347705c5788 -dist/2024-07-26/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=c91f5cd535e46b7e58829d5681ac04213da84aa4c219fe56822568599fe7ec76 -dist/2024-07-26/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=cca2302d56d4d2ee44167bcdb7a30c34f38b8f8541bbb2bb19abda3d3e7457fe -dist/2024-07-26/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=d943576b06db887441e7ac123c8b06fca2e84ddb1fa42ad40b4fc502f7158afe -dist/2024-07-26/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=edbbac62919265c23a8e2313cda9708039fa2d66c0db177e53716a8927d444ae -dist/2024-07-26/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=7bc3377545230cc80f1faf4f1dc5b07d64c57fe52beea95137dacee62faeb331 -dist/2024-07-26/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=b10d79eb7303b07f0d2f421881b642523b471fa0f9dc822000b439ba57935062 -dist/2024-07-26/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=a92a8a435f8c7c79d5e433ad7d4f559f483b352d3d7eece7ee0e58c927b1c8d9 -dist/2024-07-26/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=06ddc3690e06102f00977094c2f31d9e54814cf4a7905bee3772d082440063b3 -dist/2024-07-26/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=7702f544459e0e1faafc23e5b98061f52f783d1c9030f5d759f4bc27726b79c5 -dist/2024-07-26/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ef2eeee07a64200e3c7d2a6094e1530a014a1004d3cfd50de2445ab59b20b090 -dist/2024-07-26/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=35e43032e091c6e1fc217dcba407f2a23a84a57007d8fd72fc80abf12e1dafc2 -dist/2024-07-26/rustc-nightly-x86_64-unknown-illumos.tar.gz=814a373f59bd6a0b5e0252cc91a59b48a16f74973dd722e1e4a6699f37d9e2d5 -dist/2024-07-26/rustc-nightly-x86_64-unknown-illumos.tar.xz=231d060f5443b5b8b55771ec7d1a7fa99ddc34ed70112d227e2589137b6ecd61 -dist/2024-07-26/rustc-nightly-i686-unknown-linux-gnu.tar.gz=69fcdf5b9418a6a86ec3bd6385d5d77bc0be5a1ab371db10b390d2c78721e23b -dist/2024-07-26/rustc-nightly-i686-unknown-linux-gnu.tar.xz=c7f6b21175d19c7bb5077ccbddf58df36e1547934bfcb3e33db4902d4fbf4760 -dist/2024-07-26/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=b636e31098fba7dd8cbe1cd32866926c44c5ed61731a05f759a6255cafba92f2 -dist/2024-07-26/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=55a3d50acc5c81ed8a86148f67e311c9ec2fbd119f603dc5fba2f326a7ae0914 -dist/2024-07-26/rustc-nightly-aarch64-apple-darwin.tar.gz=fe5b69710fa6a918d43f41ca2e48fb87c3e03123e4e3fc22c713482682d88745 -dist/2024-07-26/rustc-nightly-aarch64-apple-darwin.tar.xz=1a21e5f9def991ba50d60e32e0c5865c7783280523abd1a72e35daf22316102d -dist/2024-07-26/rustc-nightly-i686-pc-windows-msvc.tar.gz=7f42d475dc8a82908869443a08df879be6cad396a802cc76b8cf475628a50e76 -dist/2024-07-26/rustc-nightly-i686-pc-windows-msvc.tar.xz=6f8745cbefeed0add770d368af3519dca65d15718a750579b706b18e6fb37198 -dist/2024-07-26/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=5669cd2fb73cb708f45ea5b75b72184430d26739b89da869a40b3e156e44ed18 -dist/2024-07-26/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=31ae9d43808729407ce75594fbc1144711efd1af56837117c596d58f5607dc79 -dist/2024-07-26/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=a2e4c919548dc864eb51dc8b6743a004129eded49e25ccec66838e5b252673da -dist/2024-07-26/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=67d09df96c68077a20e26626a6b3f5bd3d1f803c8d54eaed67c17003d50fe9a5 -dist/2024-07-26/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=939f37bdf5684f14fcd134dd569c0318e0f04d3820693576ac62a5621afa5d70 -dist/2024-07-26/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=c4bf7f89b1d7c94337d7c0a53ecd3c800d84123784ec019edc26393b8870628b -dist/2024-07-26/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=24bbdc9683594aae2ad12882fb0e102fda8a5c54c812ad66062b6e9ac1d686ff -dist/2024-07-26/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=48fb68d6a063b9973e42686ad7aa3104574972c95ed72386c68fb20e9aa33813 -dist/2024-07-26/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=d73fb553d6b3c8ffae4fc1d0f23bec0315de4e7546ce446eae015bef8c2e5c8f -dist/2024-07-26/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=3b5c48fba434f0a24c47de9ba95a74e16a0489e5c6184d44acf44ca88695c598 -dist/2024-07-26/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=f49139fb26a6d26f53653bc69a6665e47b4bef4bbbad3ca2150a486b95c5b2b0 -dist/2024-07-26/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=ce75c9f7edc0141d4cc5c09f1691e6beb476d1934df721d7edc357e46e6a5490 -dist/2024-07-26/rustc-nightly-x86_64-apple-darwin.tar.gz=e334d3ee6ff3d4da892dfa51dfedb15394159f9d21ab9e3ff7c82f9768dfe9c3 -dist/2024-07-26/rustc-nightly-x86_64-apple-darwin.tar.xz=43e2db93b5bd6e5ee4336db8f3fe9185c8ca1a2a049edc2e27a0768ff79766e8 -dist/2024-07-26/rustc-nightly-i686-pc-windows-gnu.tar.gz=8c63711b94e332f0f2304160b9dde73201e75105b1592470a1e0d1b24bddaec9 -dist/2024-07-26/rustc-nightly-i686-pc-windows-gnu.tar.xz=d20400d6c09ef1ea3e6d375d52c9b9eee8cf998f3c6c2fa79a14762db70e3285 -dist/2024-07-26/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=a28aeb05f0180e6e40bf3abe70030839ef0a48b088029915c5c1095160c8b45c -dist/2024-07-26/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=48cba7e5b56f93264c09c319bd5a14544acfa12e7c795291bc6d65507c23da07 -dist/2024-07-26/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=90ce5007ec9d24c5941d1d34c67f0abb3169fdd9bbad7b28c9a96ad95559027c -dist/2024-07-26/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=3ec63acac9d808b9dc4721d5a2c731d16e0514998c8d6e1eaa91419898496803 -dist/2024-07-26/rustc-nightly-x86_64-unknown-netbsd.tar.gz=f20db202866a639406090b456eea504eee53fe572a02b68295257c88fe9971f3 -dist/2024-07-26/rustc-nightly-x86_64-unknown-netbsd.tar.xz=909eddf1ccb61a7d80227dcf4e856f996346fa33d4a9e5d3df1f0247bc295174 -dist/2024-07-26/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=43fc6478e546f47f865e586d836a764b821d0543d069c8f1d5ea3f5b0b6b19ba -dist/2024-07-26/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=a6b89bf8d524c423a151b4221e01ef661f8b1810d13f41bdfa6be02908363805 -dist/2024-07-26/rustc-nightly-x86_64-unknown-freebsd.tar.gz=f2054204067683419dc553010cf063e91e4fefebdc7bff4c2e185416a94d5cd2 -dist/2024-07-26/rustc-nightly-x86_64-unknown-freebsd.tar.xz=fe549197eb863801f463eadcde86e85082a2dc655ade56fd425e8648012f82a8 -dist/2024-07-26/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3ac50b66d7d572efdb587f1f54069235f20de5273e3f5c670e1793371f925bd3 -dist/2024-07-26/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=ff576d6781e4bb8d1c48d985b7ea5fde440ab461e3cd9975557e1a465bbbaa50 \ No newline at end of file +dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=e467501c65651d519ae9a489e821e7d5dc82fdbeb2da2d4c75f093e1b898abd6 +dist/2024-07-26/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=9dcbd07899af86db3c101275ab0f2fd3b5b0c43d4a92c5b5be05f0e4500d7535 +dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.gz=c2a30c78a6ab64d1655651fdd5c7f970dadcd6dfd1a585d130bd890190fe67f6 +dist/2024-07-26/clippy-beta-x86_64-unknown-linux-musl.tar.xz=05c2a38fa5bca162e365218670a7c195ebd9b3491d14464282a273dfe93b0ad7 +dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.gz=75ee727a80119a810193519535f962721d547297feb9b5597b397e59277de701 +dist/2024-07-26/clippy-beta-x86_64-unknown-netbsd.tar.xz=002b726868a14df5ea31fe8eb75fae24660fb1cfad73591e86f9179dd1bb2dc4 +dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz=d3bb2f1fa20555373189caa7e58a8e3071c7ea6e7059bab15d6dd52dfef56c4f +dist/2024-07-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz=ba0019eb0766dd438069988156994270959c875b010afce0f455540a0bb2ee2f +dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=24bbbe80a998b78f04c15d82fcef9498315b1b8d0ddabeeb5b6729b14bafbf70 +dist/2024-07-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=cc396d3639c7213ab6442dc79ab6a1a42bb17910aa6d27046cc89ebeb6973231 +dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=e6dc772727a20920607923ff5a99526054e6244c40cc6c97fe68db58896de6fc +dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=eec95e09ec7bd64ab8a47e7311103f5bc58aa3499edcba052699686315f8441a +dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=fef3eb7d5dee7458daacfba9b97d579868864267fcdc85334f02384683ce0c17 +dist/2024-07-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=44f376f4d9e84645373b4cbfe17678c288a71b92622ab4091ca7b82ed6a21b57 +dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=5c17927f12149fa605e3f671d25ac456d1d2bdac796b5ca466bfa7fb8688d224 +dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=04783b1a2efc10696b0d32fde7c63437e17548d38b2272f928f28915107f4f18 +dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=1365d93efc4391f189726e69c7a968c8debb50411f29404da42d19bc9e053937 +dist/2024-07-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=db344c9f6d31ac5a2efc839cbb886c312534e9b1fe4b116629eaca74f79c316d +dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=049a2b666956a56365661d944a0fc030673bec5578062ddaad104363f4ff1031 +dist/2024-07-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=32d3bc08316c0cfc3c1ea689ccdc80978f744864c048863b9d51ae59b6e2f0c2 +dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=bc33833cd41bf5ac36730fc9d3ef9c87643d42b8e711de286138962fb5fac4a5 +dist/2024-07-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=feffb4527ad627a0239d788272edac9a0fbec704de3a67aabbd8a9cbb95d4fe3 +dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=0ffb98b839f6640ac75e094cbb469a06f2e45f51ced01efbeb51a3fba866a048 +dist/2024-07-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=d229ea866bf4d6c2d8d748630146c7bccedb4ba5a17056fbdc4558baf976f067 +dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=431de55efb797c75d8e440ba3da9ac70a04cccfc56b4e22b80b6488360915f90 +dist/2024-07-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=e9e4eac4205014b6b61c759a8326f7a5e44e8ff05726510a8bbefd656f78e97c +dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=99381507f8fc42d9bd00c545dd7ef4734e364a4e994d02bae148f78b94f50ab5 +dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=6e2cd283d9370beb9c208bd823ac2433df500adf7e70d8acfe5a261e62be2b4a +dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=761a9733f53ecba343139bd1c028a66242824ef8f7c54ae63e0aaf0e77cabcf9 +dist/2024-07-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=c2973a99220588ea78b7a052861c345f01254073d6bb77e96982b12382907e2b +dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=4288ee8fc5f650b3d5c24be2ea114e133d3bad8ddf7e2211cdb72151410c755a +dist/2024-07-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=2a31e1f211a26f6798acd4c779827bfa4e1ac4d77103a48be74617e5af1661a1 +dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=9598edeb1ff5eff934f1e4783b3ed263babb53d3513564ccccf453dada872ba1 +dist/2024-07-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=eb5392fce8ee4a016406efba546366ff91d4db8cda94dd131dbda70c553b6c06 +dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=0e9c55ee790eed653eda7b913e64d344ccbbe1681321377186d1e4882dc93bfc +dist/2024-07-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=c9a0b3eddac707c4e0c1cdc754d2821845e5f4bdcbd001b71d7287fe851cc44b +dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=99c264f806d4a6a1288a9cc7f28e178102520ebe4728fb0da3f8142c1d6720e0 +dist/2024-07-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=3f1835460dbf17a3dbf47f2772e182ebf6337fd6a946a033f9700fb38140eda6 +dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=385224b95c56de8598dd5b4eeb48d7d7a8eb920825c55bb4d7be54142d7e2857 +dist/2024-07-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=535220608ee858d46746c8de4c1e58f4f675061517b6b06c8af47004d5291f85 +dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz=aa19f1856befff101bcb433049e923486d7bc1a056638e478651936572e7e3bf +dist/2024-07-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz=2ed04cf9fddeafbb83d82988e00d3b7f5ae9382468ce1093cbb110bf46b04711 +dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=962dea60de3ac68a573f088f9c1b003816ce93f9088df15fe8cf7771a3abdc73 +dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=72f7b787644bd9008b13018512c0b09a425c15a337821dc9bded9ab7211c61de +dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=1096ba25a23461eed84804584eb9ffdff780e2c737cc9dce1e8929419dfd645b +dist/2024-07-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=854b9e410e65b953ab71f356bd5b618679aa7c1f5a3de7f81ec388720ed04f60 +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=03b4ab410c70fee3daa7a577c311b29344158a7d35ea87627233cb6165191338 +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=d755700cc17416c4488db2d582250b5ec329fc0c2b94e9db0e6688ca30a7316c +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b7448089c61c2f0a427416cd7521130c31a98c52e435bd0d04d6aad72d765ba6 +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=cb3f479897032ff9ec5e06913e8e4374ce46af7f8a9030299c7b0cab2dab2005 +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=0c7dbff79d04218a7ba3f5992f67d25043bc5f348038f37ab7385cbc4d0df00d +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=4f62cbc75a81d57748111a915ebb20f561f403c1b695141780d50c398b186fa6 +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=e5e8b07ae7ba0e1f526828a10f2515a68b0ed6023eed25e3bb10b80e21e8db76 +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=424ec90c59fca7e21b302efd7c6c7f7dbc5dcadd1afbb15e90efea38ea8a19cf +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=f22576893113958f6caabcf3ab3e38287fea010c1809a8bb1197220d6660ea4e +dist/2024-07-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=5e85141abe2a3c537cb4171c60cff5bdb11f075aa79212e0a958081d4648aec6 +dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.gz=f793e4645be9461fae09e82710bcfdfc6d749735be202f2e2cd6c2c643bb8925 +dist/2024-07-30/rustc-nightly-aarch64-apple-darwin.tar.xz=e42f52cc5a865ab92321b97aaeff4d39cbaad1a5b60a9a77de9f42e3b3231d21 +dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=0258ba5bf957d190ef3a384c5451ebbe8406c195a29b3a7ee2a4c48e0514f203 +dist/2024-07-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=788b7e9239562f43c0d96cfd66f543604eef1c9b40d22898c456fade608e9c31 +dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=94187df22d7b96a5c39c5c9a078f566b80d392abfd2a5d7059b836cfa0c446e1 +dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=ca1381c6de1a96f32a30736c28aa196f7e653b4f57f01ffe2db52fe238a9f202 +dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=1c72596862a133003f68590a8ae09bf6ab25a5f9667a6d245eafede1ebd8f450 +dist/2024-07-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=de0c216f229301bc88690b10b8f063b8e389915503980973b91bfe17b1fb6eda +dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=e00283a7ee9a702446456feb0156f1d1fc738fd013983f15c456fcafb8294309 +dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=03fab128bc3756676c645f637edc5051f8096b00780d8ef4de7a85b3f248933a +dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=105e06c0ca69b4a700980f2a588f831c23a9a9253268bd652110328b99918cb1 +dist/2024-07-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=0da27ffe5504a03923ae5858b69cdd6eb276e6bd2bfb504bcf13ebdda654316b +dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=edb1bec402f3799e05fd3e31f30763e7266d2e062e410af8eab7636440da272c +dist/2024-07-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=638a09ecfe0b66391ce6802e3e15bf15462aca1c8cfb2a49b948ec69eda0575c +dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.gz=456683fa10703ba8249f8b1735293c79edac0c32aec60c1a91315fb41c8e5ecc +dist/2024-07-30/rustc-nightly-i686-pc-windows-gnu.tar.xz=fd5d9a7bf543d3c61ca85340961d5e17b42b37c35fe45c666c2a0e125548f42e +dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.gz=2b75a4e15d1f98f123ef74aecab3570296aeb7e35f18548a2b3d1735e01b06e0 +dist/2024-07-30/rustc-nightly-i686-pc-windows-msvc.tar.xz=1163178e95180725bd31b7dabf1e9a9788a8e7cc576dd53148cfec32443e64a1 +dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz=0aad8dd79beca26278e1c1847dde17ee22ae64b78f2b02be65e12bc126de699b +dist/2024-07-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz=a548e90fbce90c26b6700cff7964d72c7e959a6f317e891db4f91ce7cd187c41 +dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=654ec9040afb20d660603adcd31824efeacef0ae2d48d342bb9504bd2f723453 +dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=998407bc1303eecb1ef4c6b14862ffdf31fb0cf991f5d169a822a23627b29352 +dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=5b4febf9a1802c2c756ef8a7693a9cfd83bf95284d79d9f9b9dd265234d6aebc +dist/2024-07-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=dbc2a6417fabcfb37f4fa42d50391c1cb29f18d1771321088c08afdf0a0e4809 +dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=2befcab4aa3e31064b87e4696aa2f1e76bd9c24067eb1921feb7f6497d58338c +dist/2024-07-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=508a3c1241507a53a0d6b27df2171eaf0a4df903773b5592f005ee4d39d91287 +dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=c4e8da248306be350f7a89b2522e976a12ab89d5ae2e19157ed3b148e3948c50 +dist/2024-07-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=5858e1cf6371f25ba3c381e07ba6f4551c2a13516011fc10dbdafc4caf1bff93 +dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3639bbb7aac353772171dcfaecd589352de3fd8cc7395e7628d7590830034af4 +dist/2024-07-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3cad5f0b74fc3f5be70cf496c93054c50e8a3f92cfc894a2febfbecc382dcb55 +dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=437fc8b815c09a3c5159735d9fec0e5d8dd64416149cb77c13a16863e6636412 +dist/2024-07-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=7bc2917e7816f7df1bc7faeda28010d247c923aba412b5ec1cc9c6757eec37d9 +dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=603e391a14c26a51f4f02020b5abbd307d29476fdc0689e5bf9570f2e6ac69a8 +dist/2024-07-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=d04ea4e522cf1ecaa6b2f3edcb32155142378bc648aa159a574838ed2d58b794 +dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.gz=0ed639da01e58645eb33a75e020d57c58c92651d817e89574cb67bae5b298d35 +dist/2024-07-30/rustc-nightly-x86_64-apple-darwin.tar.xz=b4010f38396e7b8acd67cf2234c94ede11cf78a226a134c809d504e594037311 +dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=7ec8aba7a7581d59c7ceaffdd374852d08b17bc7e02674c5bfd4f47f4a0aee39 +dist/2024-07-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=41c3ba0543220e11bc53282dd7d2a37acd6450a59683e1c83d2150dc798cfba7 +dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=67e5d75dda47c587a4be517db547354d1da0228110b7d5488d8822a7ef7cda20 +dist/2024-07-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=4b5f0c4101a783dd313c0cd1435d7eccfeac97452afaeaf42ba975805541dc74 +dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz=09e12b5003969b768b5c06b3e3b41a64429e28c32790ff28c12b8c5814f350c0 +dist/2024-07-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz=a4b3b402cf4beb3e7c7b9b6620f34d045ef42261514ae7d8483d3790d1dfd88a +dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.gz=c344d0c95aadac0e5e0100743b80768c9d0cd76b123ab07e6387ad1ea3e3efba +dist/2024-07-30/rustc-nightly-x86_64-unknown-illumos.tar.xz=ac0a79660227fe163c796e6b816596299f6d8b32ba008ce30cde492709efb7c0 +dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4090ff8086317662d3def1bc92d51e6f2decd2c64f4b6ede38604fd5029d3d02 +dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=e665bd4e3763b456576eaa45bcf188648cc6e6443ecdff8ef91a5c7649cbfd25 +dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=4fa994e08274599ae3bceb9310c584be89d11f231aad3e8fc1e2d6a6ddbb77bf +dist/2024-07-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=bd8d53403bf6337782bffc3050a46887fbe2568c850809c5b32c8d84492d2ee9 +dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz=606a430036fdda0b92dd4a4cb99830881389693e6ed02a01ddd51eaecdfdf463 +dist/2024-07-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz=fa34273b20336b8b373f686c88ee297033f635895ad225a2ca5271b6da3d7dea \ No newline at end of file From 49db8a5a999f0908b5bf74b88a2d72a4f4dddf48 Mon Sep 17 00:00:00 2001 From: carbotaniuman <41451839+carbotaniuman@users.noreply.github.com> Date: Tue, 9 Jul 2024 19:06:49 -0500 Subject: [PATCH 301/489] Add toggle for `parse_meta_item` unsafe parsing This makes it possible for the `unsafe(...)` syntax to only be valid at the top level, and the `NestedMetaItem`s will automatically reject `unsafe(...)`. --- compiler/rustc_builtin_macros/messages.ftl | 3 - compiler/rustc_builtin_macros/src/cfg.rs | 3 +- compiler/rustc_builtin_macros/src/derive.rs | 13 +-- compiler/rustc_builtin_macros/src/errors.rs | 7 -- compiler/rustc_expand/src/config.rs | 4 +- compiler/rustc_interface/src/interface.rs | 5 +- compiler/rustc_parse/messages.ftl | 1 + compiler/rustc_parse/src/errors.rs | 1 + compiler/rustc_parse/src/parser/attr.rs | 21 ++++- compiler/rustc_parse/src/validate_attr.rs | 82 +++++++++---------- .../unsafe/derive-unsafe-attributes.rs | 8 +- .../unsafe/derive-unsafe-attributes.stderr | 59 +++++++++++-- .../unsafe/double-unsafe-attributes.stderr | 2 +- .../extraneous-unsafe-attributes.stderr | 16 ++-- .../unsafe/proc-unsafe-attributes.rs | 10 +++ .../unsafe/proc-unsafe-attributes.stderr | 77 +++++++++++++++-- .../ui/attributes/unsafe/unsafe-attributes.rs | 6 ++ .../unsafe/unsafe-safe-attribute.stderr | 2 +- .../unsafe-safe-attribute_diagnostic.stderr | 2 +- 19 files changed, 226 insertions(+), 96 deletions(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index a30ab236213a0..ae3cce40f5daa 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -115,9 +115,6 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values .suggestion = remove the value -builtin_macros_derive_unsafe_path = traits in `#[derive(...)]` don't accept `unsafe(...)` - .suggestion = remove the `unsafe(...)` - builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time .cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead .custom = use `std::env::var({$var_expr})` to read the variable at run time diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index ceb62230ece96..de198115fa00b 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -6,6 +6,7 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; +use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_span::Span; use {rustc_ast as ast, rustc_attr as attr}; @@ -42,7 +43,7 @@ fn parse_cfg<'a>(cx: &ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span })); } - let cfg = p.parse_meta_item()?; + let cfg = p.parse_meta_item(AllowLeadingUnsafe::Yes)?; let _ = p.eat(&token::Comma); diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index c540ff4e1de82..57bddf0ab60ad 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,5 +1,5 @@ use rustc_ast as ast; -use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, Safety, StmtKind}; +use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_expand::base::{ Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier, }; @@ -62,7 +62,6 @@ impl MultiItemModifier for Expander { // Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the // paths. report_path_args(sess, meta); - report_unsafe_args(sess, meta); meta.path.clone() }) .map(|path| DeriveResolution { @@ -162,13 +161,3 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) { } } } - -fn report_unsafe_args(sess: &Session, meta: &ast::MetaItem) { - match meta.unsafety { - Safety::Unsafe(span) => { - sess.dcx().emit_err(errors::DeriveUnsafePath { span }); - } - Safety::Default => {} - Safety::Safe(_) => unreachable!(), - } -} diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 0a4f07709c7fd..93fc9bcb9d206 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -297,13 +297,6 @@ pub(crate) struct DerivePathArgsValue { pub(crate) span: Span, } -#[derive(Diagnostic)] -#[diag(builtin_macros_derive_unsafe_path)] -pub(crate) struct DeriveUnsafePath { - #[primary_span] - pub(crate) span: Span, -} - #[derive(Diagnostic)] #[diag(builtin_macros_no_default_variant)] #[help] diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index d46ec7a9ac0fe..f6bf9f5e89f2f 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -8,7 +8,9 @@ use rustc_ast::tokenstream::{ use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, NodeId}; use rustc_attr as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; -use rustc_feature::{AttributeSafety, Features, ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES}; +use rustc_feature::{ + AttributeSafety, Features, ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES, +}; use rustc_lint_defs::BuiltinLintDiag; use rustc_parse::validate_attr; use rustc_session::parse::feature_err; diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 886b043af2460..04e2b7d45dc93 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -15,6 +15,7 @@ use rustc_middle::ty; use rustc_middle::ty::CurrentGcx; use rustc_middle::util::Providers; use rustc_parse::new_parser_from_source_str; +use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; @@ -67,7 +68,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec) -> Cfg { } match new_parser_from_source_str(&psess, filename, s.to_string()) { - Ok(mut parser) => match parser.parse_meta_item() { + Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) { Ok(meta_item) if parser.token == token::Eof => { if meta_item.path.segments.len() != 1 { error!("argument key must be an identifier"); @@ -173,7 +174,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec) -> Ch } }; - let meta_item = match parser.parse_meta_item() { + let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::Yes) { Ok(meta_item) if parser.token == token::Eof => meta_item, Ok(..) => expected_error(), Err(err) => { diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 391a57917768d..e13306b9d9fe2 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -365,6 +365,7 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style parse_invalid_attr_unsafe = `{$name}` is not an unsafe attribute + .label = this is not an unsafe attribute .suggestion = remove the `unsafe(...)` .note = extraneous unsafe is not allowed in attributes diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 1076280370815..e5b0dc804a5e8 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3188,6 +3188,7 @@ pub(crate) struct DotDotRangeAttribute { #[note] pub struct InvalidAttrUnsafe { #[primary_span] + #[label] pub span: Span, pub name: Path, } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 12b9414d1f760..f34ef071e21ec 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -31,6 +31,12 @@ enum OuterAttributeType { Attribute, } +#[derive(Clone, Copy, PartialEq, Eq)] +pub enum AllowLeadingUnsafe { + Yes, + No, +} + impl<'a> Parser<'a> { /// Parses attributes that appear before an item. pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> { @@ -332,7 +338,7 @@ impl<'a> Parser<'a> { /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> { - let cfg_predicate = self.parse_meta_item()?; + let cfg_predicate = self.parse_meta_item(AllowLeadingUnsafe::No)?; self.expect(&token::Comma)?; // Presumably, the majority of the time there will only be one attr. @@ -368,7 +374,10 @@ impl<'a> Parser<'a> { /// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ; /// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ; /// ``` - pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { + pub fn parse_meta_item( + &mut self, + unsafe_allowed: AllowLeadingUnsafe, + ) -> PResult<'a, ast::MetaItem> { // We can't use `maybe_whole` here because it would bump in the `None` // case, which we don't want. if let token::Interpolated(nt) = &self.token.kind @@ -384,7 +393,11 @@ impl<'a> Parser<'a> { } let lo = self.token.span; - let is_unsafe = self.eat_keyword(kw::Unsafe); + let is_unsafe = if unsafe_allowed == AllowLeadingUnsafe::Yes { + self.eat_keyword(kw::Unsafe) + } else { + false + }; let unsafety = if is_unsafe { let unsafe_span = self.prev_token.span; self.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span); @@ -427,7 +440,7 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), // we provide a better error below } - match self.parse_meta_item() { + match self.parse_meta_item(AllowLeadingUnsafe::No) { Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)), Err(err) => err.cancel(), // we provide a better error below } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index af2db17184086..a64c00f3b6cbc 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -163,53 +163,53 @@ pub fn check_attribute_safety( safety: AttributeSafety, attr: &Attribute, ) { - if features.unsafe_attributes { - let attr_item = attr.get_normal_item(); + if !features.unsafe_attributes { + return; + } - if safety == AttributeSafety::Unsafe { - if let ast::Safety::Default = attr_item.unsafety { - let path_span = attr_item.path.span; + let attr_item = attr.get_normal_item(); - // If the `attr_item`'s span is not from a macro, then just suggest - // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the - // `unsafe(`, `)` right after and right before the opening and closing - // square bracket respectively. - let diag_span = if attr_item.span().can_be_used_for_suggestions() { - attr_item.span() - } else { - attr.span - .with_lo(attr.span.lo() + BytePos(2)) - .with_hi(attr.span.hi() - BytePos(1)) - }; + if safety == AttributeSafety::Unsafe { + if let ast::Safety::Default = attr_item.unsafety { + let path_span = attr_item.path.span; - if attr.span.at_least_rust_2024() { - psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe { - span: path_span, - suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { - left: diag_span.shrink_to_lo(), - right: diag_span.shrink_to_hi(), - }, - }); - } else { - psess.buffer_lint( - UNSAFE_ATTR_OUTSIDE_UNSAFE, - path_span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::UnsafeAttrOutsideUnsafe { - attribute_name_span: path_span, - sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), - }, - ); - } - } - } else { - if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { - psess.dcx().emit_err(errors::InvalidAttrUnsafe { - span: unsafe_span, - name: attr_item.path.clone(), + // If the `attr_item`'s span is not from a macro, then just suggest + // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the + // `unsafe(`, `)` right after and right before the opening and closing + // square bracket respectively. + let diag_span = if attr_item.span().can_be_used_for_suggestions() { + attr_item.span() + } else { + attr.span.with_lo(attr.span.lo() + BytePos(2)).with_hi(attr.span.hi() - BytePos(1)) + }; + + if attr.span.at_least_rust_2024() { + psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe { + span: path_span, + suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { + left: diag_span.shrink_to_lo(), + right: diag_span.shrink_to_hi(), + }, }); + } else { + psess.buffer_lint( + UNSAFE_ATTR_OUTSIDE_UNSAFE, + path_span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::UnsafeAttrOutsideUnsafe { + attribute_name_span: path_span, + sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), + }, + ); } } + } else { + if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { + psess.dcx().emit_err(errors::InvalidAttrUnsafe { + span: unsafe_span, + name: attr_item.path.clone(), + }); + } } } diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs index 7f0d6a0cf8b91..b8edb4aab907b 100644 --- a/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.rs @@ -1,6 +1,12 @@ #![feature(unsafe_attributes)] -#[derive(unsafe(Debug))] //~ ERROR: traits in `#[derive(...)]` don't accept `unsafe(...)` +#[derive(unsafe(Debug))] +//~^ ERROR: expected identifier, found keyword `unsafe` +//~| ERROR: traits in `#[derive(...)]` don't accept arguments +//~| ERROR: expected identifier, found keyword `unsafe` +//~| ERROR: expected identifier, found keyword `unsafe` +//~| ERROR: cannot find derive macro `r#unsafe` in this scope +//~| ERROR: cannot find derive macro `r#unsafe` in this scope struct Foo; #[unsafe(derive(Debug))] //~ ERROR: is not an unsafe attribute diff --git a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr index 22010c61b5f52..c40a5512fd5cd 100644 --- a/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr @@ -1,16 +1,65 @@ -error: traits in `#[derive(...)]` don't accept `unsafe(...)` +error: expected identifier, found keyword `unsafe` --> $DIR/derive-unsafe-attributes.rs:3:10 | LL | #[derive(unsafe(Debug))] - | ^^^^^^ + | ^^^^^^ expected identifier, found keyword + | +help: escape `unsafe` to use it as an identifier + | +LL | #[derive(r#unsafe(Debug))] + | ++ + +error: traits in `#[derive(...)]` don't accept arguments + --> $DIR/derive-unsafe-attributes.rs:3:16 + | +LL | #[derive(unsafe(Debug))] + | ^^^^^^^ help: remove the arguments error: `derive` is not an unsafe attribute - --> $DIR/derive-unsafe-attributes.rs:6:3 + --> $DIR/derive-unsafe-attributes.rs:12:3 | LL | #[unsafe(derive(Debug))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes -error: aborting due to 2 previous errors +error: expected identifier, found keyword `unsafe` + --> $DIR/derive-unsafe-attributes.rs:3:10 + | +LL | #[derive(unsafe(Debug))] + | ^^^^^^ expected identifier, found keyword + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: escape `unsafe` to use it as an identifier + | +LL | #[derive(r#unsafe(Debug))] + | ++ + +error: expected identifier, found keyword `unsafe` + --> $DIR/derive-unsafe-attributes.rs:3:10 + | +LL | #[derive(unsafe(Debug))] + | ^^^^^^ expected identifier, found keyword + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: escape `unsafe` to use it as an identifier + | +LL | #[derive(r#unsafe(Debug))] + | ++ + +error: cannot find derive macro `r#unsafe` in this scope + --> $DIR/derive-unsafe-attributes.rs:3:10 + | +LL | #[derive(unsafe(Debug))] + | ^^^^^^ + +error: cannot find derive macro `r#unsafe` in this scope + --> $DIR/derive-unsafe-attributes.rs:3:10 + | +LL | #[derive(unsafe(Debug))] + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 7 previous errors diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr index ea82bac6df07b..950b2636993c1 100644 --- a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr @@ -13,7 +13,7 @@ error: `r#unsafe` is not an unsafe attribute --> $DIR/double-unsafe-attributes.rs:3:3 | LL | #[unsafe(unsafe(no_mangle))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes diff --git a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr index a2e56087d1615..f39074b613d40 100644 --- a/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/extraneous-unsafe-attributes.stderr @@ -2,7 +2,7 @@ error: `cfg` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:5:3 | LL | #[unsafe(cfg(any()))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes @@ -10,7 +10,7 @@ error: `cfg_attr` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:8:3 | LL | #[unsafe(cfg_attr(any(), allow(dead_code)))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes @@ -18,7 +18,7 @@ error: `test` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:11:3 | LL | #[unsafe(test)] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes @@ -26,7 +26,7 @@ error: `ignore` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:14:3 | LL | #[unsafe(ignore = "test")] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes @@ -34,7 +34,7 @@ error: `should_panic` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:17:3 | LL | #[unsafe(should_panic(expected = "test"))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes @@ -42,7 +42,7 @@ error: `macro_use` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:20:3 | LL | #[unsafe(macro_use)] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes @@ -50,7 +50,7 @@ error: `macro_export` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:22:7 | LL | #[unsafe(macro_export)] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes @@ -58,7 +58,7 @@ error: `used` is not an unsafe attribute --> $DIR/extraneous-unsafe-attributes.rs:28:3 | LL | #[unsafe(used)] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs index caf6c6dc8ffde..f29a5b3252b0a 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs @@ -13,6 +13,7 @@ pub fn b() {} #[proc_macro_derive(unsafe(Foo))] //~^ ERROR attribute is only usable with crates of the `proc-macro` crate type +//~| ERROR: expected identifier, found keyword `unsafe` pub fn c() {} #[unsafe(proc_macro_attribute)] @@ -24,4 +25,13 @@ pub fn d() {} //~^ ERROR: is not an unsafe attribute pub fn e() {} +#[unsafe(allow(unsafe(dead_code)))] +//~^ ERROR: is not an unsafe attribute +//~| ERROR: malformed lint attribute input +//~| ERROR: malformed lint attribute input +//~| ERROR: expected identifier, found keyword `unsafe` +//~| ERROR: malformed lint attribute input +//~| ERROR: malformed lint attribute input +pub fn f() {} + fn main() {} diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr index 346d2c2e9ae69..79d34d458bd6c 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -1,8 +1,22 @@ +error[E0452]: malformed lint attribute input + --> $DIR/proc-unsafe-attributes.rs:28:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + +error[E0452]: malformed lint attribute input + --> $DIR/proc-unsafe-attributes.rs:28:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: `proc_macro` is not an unsafe attribute --> $DIR/proc-unsafe-attributes.rs:3:3 | LL | #[unsafe(proc_macro)] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes @@ -10,26 +24,56 @@ error: `proc_macro_derive` is not an unsafe attribute --> $DIR/proc-unsafe-attributes.rs:9:3 | LL | #[unsafe(proc_macro_derive(Foo))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes +error: expected identifier, found keyword `unsafe` + --> $DIR/proc-unsafe-attributes.rs:14:21 + | +LL | #[proc_macro_derive(unsafe(Foo))] + | ^^^^^^ expected identifier, found keyword + | +help: escape `unsafe` to use it as an identifier + | +LL | #[proc_macro_derive(r#unsafe(Foo))] + | ++ + error: `proc_macro_attribute` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:18:3 + --> $DIR/proc-unsafe-attributes.rs:19:3 | LL | #[unsafe(proc_macro_attribute)] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes error: `allow` is not an unsafe attribute - --> $DIR/proc-unsafe-attributes.rs:23:3 + --> $DIR/proc-unsafe-attributes.rs:24:3 | LL | #[unsafe(allow(dead_code))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes +error: `allow` is not an unsafe attribute + --> $DIR/proc-unsafe-attributes.rs:28:3 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^ this is not an unsafe attribute + | + = note: extraneous unsafe is not allowed in attributes + +error: expected identifier, found keyword `unsafe` + --> $DIR/proc-unsafe-attributes.rs:28:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^ expected identifier, found keyword + | +help: escape `unsafe` to use it as an identifier + | +LL | #[unsafe(allow(r#unsafe(dead_code)))] + | ++ + error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/proc-unsafe-attributes.rs:3:1 | @@ -49,10 +93,27 @@ LL | #[proc_macro_derive(unsafe(Foo))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/proc-unsafe-attributes.rs:18:1 + --> $DIR/proc-unsafe-attributes.rs:19:1 | LL | #[unsafe(proc_macro_attribute)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error[E0452]: malformed lint attribute input + --> $DIR/proc-unsafe-attributes.rs:28:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0452]: malformed lint attribute input + --> $DIR/proc-unsafe-attributes.rs:28:16 + | +LL | #[unsafe(allow(unsafe(dead_code)))] + | ^^^^^^^^^^^^^^^^^ bad attribute argument + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 15 previous errors +For more information about this error, try `rustc --explain E0452`. diff --git a/tests/ui/attributes/unsafe/unsafe-attributes.rs b/tests/ui/attributes/unsafe/unsafe-attributes.rs index e7620a18048e4..33a412add500c 100644 --- a/tests/ui/attributes/unsafe/unsafe-attributes.rs +++ b/tests/ui/attributes/unsafe/unsafe-attributes.rs @@ -4,4 +4,10 @@ #[unsafe(no_mangle)] fn a() {} +#[unsafe(export_name = "foo")] +fn b() {} + +#[cfg_attr(any(), unsafe(no_mangle))] +static VAR2: u32 = 1; + fn main() {} diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr index 0602af34e4f64..584b0ea797d0a 100644 --- a/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr +++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr @@ -2,7 +2,7 @@ error: `repr` is not an unsafe attribute --> $DIR/unsafe-safe-attribute.rs:3:3 | LL | #[unsafe(repr(C))] - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes diff --git a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr index 584dacf4d8c91..26b5e4e37b931 100644 --- a/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr +++ b/tests/ui/attributes/unsafe/unsafe-safe-attribute_diagnostic.stderr @@ -2,7 +2,7 @@ error: `diagnostic::on_unimplemented` is not an unsafe attribute --> $DIR/unsafe-safe-attribute_diagnostic.rs:3:3 | LL | #[unsafe(diagnostic::on_unimplemented( - | ^^^^^^ + | ^^^^^^ this is not an unsafe attribute | = note: extraneous unsafe is not allowed in attributes From bd23e0eb2694752f573eafd0d894a2b16d10fd7b Mon Sep 17 00:00:00 2001 From: EtomicBomb Date: Wed, 31 Jul 2024 00:20:56 +0000 Subject: [PATCH 302/489] canonicalize path in another place to fix #128411 --- src/tools/compiletest/src/runtest.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 55f676e708670..2b7601a7c73b5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2968,7 +2968,9 @@ impl<'test> TestCx<'test> { for _ in res.stdout.split('\n').filter(|s| s.starts_with("test ")).inspect(|s| { if let Some((left, right)) = s.split_once(" - ") { let path = left.rsplit("test ").next().unwrap(); - if let Some(ref mut v) = files.get_mut(&path.replace('\\', "/")) { + let path = fs::canonicalize(&path).expect("failed to canonicalize"); + let path = path.to_str().unwrap().replace('\\', "/"); + if let Some(ref mut v) = files.get_mut(&path) { tested += 1; let mut iter = right.split("(line "); iter.next(); From a0b4d6dfb87440c1454d475941f16ff2d09c5d37 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 26 Jun 2024 09:44:55 +0000 Subject: [PATCH 303/489] Do not normalize constants eagerly. --- compiler/rustc_mir_transform/src/gvn.rs | 5 +---- tests/incremental/hashes/for_loops.rs | 4 ++-- .../slice_len.main.GVN.32bit.panic-abort.diff | 9 +++------ .../slice_len.main.GVN.32bit.panic-unwind.diff | 9 +++------ .../slice_len.main.GVN.64bit.panic-abort.diff | 9 +++------ .../slice_len.main.GVN.64bit.panic-unwind.diff | 9 +++------ tests/mir-opt/const_prop/slice_len.rs | 2 +- ...t_invalid_constant.main.GVN.32bit.panic-abort.diff | 11 ++++------- ..._invalid_constant.main.GVN.32bit.panic-unwind.diff | 11 ++++------- ...t_invalid_constant.main.GVN.64bit.panic-abort.diff | 11 ++++------- ..._invalid_constant.main.GVN.64bit.panic-unwind.diff | 11 ++++------- 11 files changed, 32 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 336aa1fd43f06..96b2f9cbbdc94 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -773,10 +773,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { location: Location, ) -> Option { match *operand { - Operand::Constant(ref mut constant) => { - let const_ = constant.const_.normalize(self.tcx, self.param_env); - self.insert_constant(const_) - } + Operand::Constant(ref constant) => self.insert_constant(constant.const_), Operand::Copy(ref mut place) | Operand::Move(ref mut place) => { let value = self.simplify_place_value(place, location)?; if let Some(const_) = self.try_as_constant(value) { diff --git a/tests/incremental/hashes/for_loops.rs b/tests/incremental/hashes/for_loops.rs index 9cd99bf76b7ae..b827ad9cc6f89 100644 --- a/tests/incremental/hashes/for_loops.rs +++ b/tests/incremental/hashes/for_loops.rs @@ -103,9 +103,9 @@ pub fn change_iterable() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, promoted_mir, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, promoted_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, promoted_mir, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, promoted_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_iterable() { let mut _x = 0; diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff index 8415789de6ecd..21d91d0320ae2 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff @@ -22,12 +22,11 @@ StorageLive(_3); StorageLive(_4); _9 = const main::promoted[0]; -- _4 = _9; + _4 = _9; - _3 = _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); -+ _4 = const {ALLOC0: &[u32; 3]}; -+ _3 = const {ALLOC0: &[u32; 3]}; -+ _2 = const {ALLOC0: &[u32; 3]} as &[u32] (PointerCoercion(Unsize)); ++ _3 = _9; ++ _2 = _9 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; @@ -50,6 +49,4 @@ return; } } -+ -+ ALLOC0 (size: 12, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff index fea7caac3cdce..889114c986236 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff @@ -22,12 +22,11 @@ StorageLive(_3); StorageLive(_4); _9 = const main::promoted[0]; -- _4 = _9; + _4 = _9; - _3 = _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); -+ _4 = const {ALLOC0: &[u32; 3]}; -+ _3 = const {ALLOC0: &[u32; 3]}; -+ _2 = const {ALLOC0: &[u32; 3]} as &[u32] (PointerCoercion(Unsize)); ++ _3 = _9; ++ _2 = _9 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; @@ -50,6 +49,4 @@ return; } } -+ -+ ALLOC0 (size: 12, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff index 8415789de6ecd..21d91d0320ae2 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff @@ -22,12 +22,11 @@ StorageLive(_3); StorageLive(_4); _9 = const main::promoted[0]; -- _4 = _9; + _4 = _9; - _3 = _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); -+ _4 = const {ALLOC0: &[u32; 3]}; -+ _3 = const {ALLOC0: &[u32; 3]}; -+ _2 = const {ALLOC0: &[u32; 3]} as &[u32] (PointerCoercion(Unsize)); ++ _3 = _9; ++ _2 = _9 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; @@ -50,6 +49,4 @@ return; } } -+ -+ ALLOC0 (size: 12, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff index fea7caac3cdce..889114c986236 100644 --- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff @@ -22,12 +22,11 @@ StorageLive(_3); StorageLive(_4); _9 = const main::promoted[0]; -- _4 = _9; + _4 = _9; - _3 = _4; - _2 = move _3 as &[u32] (PointerCoercion(Unsize)); -+ _4 = const {ALLOC0: &[u32; 3]}; -+ _3 = const {ALLOC0: &[u32; 3]}; -+ _2 = const {ALLOC0: &[u32; 3]} as &[u32] (PointerCoercion(Unsize)); ++ _3 = _9; ++ _2 = _9 as &[u32] (PointerCoercion(Unsize)); StorageDead(_3); StorageLive(_6); _6 = const 1_usize; @@ -50,6 +49,4 @@ return; } } -+ -+ ALLOC0 (size: 12, align: 4) { .. } diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index 221fb18f92c61..3d1b58965ac4e 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -7,7 +7,7 @@ fn main() { // CHECK-LABEL: fn main( // CHECK: debug a => [[a:_.*]]; - // CHECK: [[slice:_.*]] = const {{.*}} as &[u32] (PointerCoercion(Unsize)); + // CHECK: [[slice:_.*]] = {{.*}} as &[u32] (PointerCoercion(Unsize)); // CHECK: assert(const true, // CHECK: [[a]] = const 2_u32; let a = (&[1u32, 2, 3] as &[u32])[1]; diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index 959efa2a54870..30c122ddea03b 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -73,13 +73,12 @@ StorageLive(_6); StorageLive(_7); _9 = const main::promoted[0]; -- _7 = _9; -+ _7 = const {ALLOC1: &std::alloc::Global}; + _7 = _9; StorageLive(_8); - _8 = _1; - _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { @@ -119,11 +118,9 @@ + nop; return; } - } ++ } + + ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ -+ } -+ -+ ALLOC1 (size: 0, align: 1) {} + } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff index 4a37c8603204b..93449462c3d08 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -81,13 +81,12 @@ StorageLive(_6); StorageLive(_7); _9 = const main::promoted[0]; -- _7 = _9; -+ _7 = const {ALLOC1: &std::alloc::Global}; + _7 = _9; StorageLive(_8); - _8 = _1; - _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; } bb5: { @@ -95,11 +94,9 @@ StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } - } ++ } + + ALLOC0 (size: 8, align: 4) { + 00 00 00 00 __ __ __ __ │ ....░░░░ -+ } -+ -+ ALLOC1 (size: 0, align: 1) {} + } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index 97f5245a8c927..44435956ec418 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -73,13 +73,12 @@ StorageLive(_6); StorageLive(_7); _9 = const main::promoted[0]; -- _7 = _9; -+ _7 = const {ALLOC1: &std::alloc::Global}; + _7 = _9; StorageLive(_8); - _8 = _1; - _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb4, unwind unreachable]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb4, unwind unreachable]; } bb4: { @@ -119,11 +118,9 @@ + nop; return; } - } ++ } + + ALLOC0 (size: 16, align: 8) { + 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ -+ } -+ -+ ALLOC1 (size: 0, align: 1) {} + } diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff index ec2e95fecb620..c958480a9c71b 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -81,13 +81,12 @@ StorageLive(_6); StorageLive(_7); _9 = const main::promoted[0]; -- _7 = _9; -+ _7 = const {ALLOC1: &std::alloc::Global}; + _7 = _9; StorageLive(_8); - _8 = _1; - _6 = std::alloc::Global::alloc_impl(move _7, move _8, const false) -> [return: bb5, unwind continue]; + _8 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}; -+ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(_9, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): std::ptr::alignment::AlignmentEnum) }}, const false) -> [return: bb5, unwind continue]; } bb5: { @@ -95,11 +94,9 @@ StorageDead(_7); _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; } - } ++ } + + ALLOC0 (size: 16, align: 8) { + 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ -+ } -+ -+ ALLOC1 (size: 0, align: 1) {} + } From 95986dd279d0bd7b292d0b0907fcb5e8d4b64c9c Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 26 Jun 2024 09:44:36 +0000 Subject: [PATCH 304/489] Indirect places can only appear as first projection in runtime MIR. --- compiler/rustc_mir_transform/src/gvn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 96b2f9cbbdc94..d9bfe44633ab7 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -671,7 +671,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn simplify_place_projection(&mut self, place: &mut Place<'tcx>, location: Location) { // If the projection is indirect, we treat the local as a value, so can replace it with // another local. - if place.is_indirect() + if place.is_indirect_first_projection() && let Some(base) = self.locals[place.local] && let Some(new_local) = self.try_as_local(base, location) && place.local != new_local From 70ee6e4b23f455b62554c3ee9365657f9e700abd Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 26 Jun 2024 09:44:03 +0000 Subject: [PATCH 305/489] Amortize growing rev_locals. --- compiler/rustc_mir_transform/src/gvn.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index d9bfe44633ab7..8eab9890d634f 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -293,9 +293,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let (index, new) = self.values.insert_full(value); let index = VnIndex::from_usize(index); if new { + // Grow `evaluated` and `rev_locals` here to amortize the allocations. let evaluated = self.eval_to_const(index); let _index = self.evaluated.push(evaluated); debug_assert_eq!(index, _index); + // No need to push to `rev_locals` if we finished listing assignments. + if self.next_opaque.is_some() { + let _index = self.rev_locals.push(SmallVec::new()); + debug_assert_eq!(index, _index); + } } index } @@ -332,7 +338,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let is_sized = !self.feature_unsized_locals || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); if is_sized { - self.rev_locals.ensure_contains_elem(value, SmallVec::new).push(local); + self.rev_locals[value].push(local); } } From 9d23c8617632690326ac04e25646ac669179de4b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 26 Jun 2024 12:16:40 +0000 Subject: [PATCH 306/489] Reduce allocations in GVN. --- compiler/rustc_mir_transform/src/gvn.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 8eab9890d634f..c290ad6fa2cbf 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -128,7 +128,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Clone dominators as we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let mut state = VnState::new(tcx, param_env, &ssa, &dominators, &body.local_decls); + let mut state = VnState::new(tcx, body, param_env, &ssa, &dominators, &body.local_decls); ssa.for_each_assignment_mut( body.basic_blocks.as_mut_preserves_cfg(), |local, value, location| { @@ -266,20 +266,28 @@ struct VnState<'body, 'tcx> { impl<'body, 'tcx> VnState<'body, 'tcx> { fn new( tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>, ssa: &'body SsaLocals, dominators: &'body Dominators, local_decls: &'body LocalDecls<'tcx>, ) -> Self { + // Compute a rough estimate of the number of values in the body from the number of + // statements. This is meant to reduce the number of allocations, but it's all right if + // we miss the exact amount. We estimate based on 2 values per statement (one in LHS and + // one in RHS) and 4 values per terminator (for call operands). + let num_values = + 2 * body.basic_blocks.iter().map(|bbdata| bbdata.statements.len()).sum::() + + 4 * body.basic_blocks.len(); VnState { tcx, ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), param_env, local_decls, locals: IndexVec::from_elem(None, local_decls), - rev_locals: IndexVec::default(), - values: FxIndexSet::default(), - evaluated: IndexVec::new(), + rev_locals: IndexVec::with_capacity(num_values), + values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()), + evaluated: IndexVec::with_capacity(num_values), next_opaque: Some(0), feature_unsized_locals: tcx.features().unsized_locals, ssa, From 61ef0441b8a618b80f72a6a5f0d4c8f7a983566e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 26 Jun 2024 13:27:38 +0000 Subject: [PATCH 307/489] Encode constant determinism in disambiguator. --- compiler/rustc_mir_transform/src/gvn.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index c290ad6fa2cbf..92a112ceff191 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -204,6 +204,7 @@ enum Value<'tcx> { value: Const<'tcx>, /// Some constants do not have a deterministic value. To avoid merging two instances of the /// same `Const`, we assign them an additional integer index. + // `disambiguator` is 0 iff the constant is deterministic. disambiguator: usize, }, /// An aggregate value, either tuple/closure/struct/enum. @@ -288,7 +289,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { rev_locals: IndexVec::with_capacity(num_values), values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()), evaluated: IndexVec::with_capacity(num_values), - next_opaque: Some(0), + next_opaque: Some(1), feature_unsized_locals: tcx.features().unsized_locals, ssa, dominators, @@ -360,6 +361,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let next_opaque = self.next_opaque.as_mut()?; let disambiguator = *next_opaque; *next_opaque += 1; + assert_ne!(disambiguator, 0); disambiguator }; Some(self.insert(Value::Constant { value, disambiguator })) @@ -1447,12 +1449,11 @@ impl<'tcx> VnState<'_, 'tcx> { /// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR. fn try_as_constant(&mut self, index: VnIndex) -> Option> { - // This was already constant in MIR, do not change it. - if let Value::Constant { value, disambiguator: _ } = *self.get(index) - // If the constant is not deterministic, adding an additional mention of it in MIR will - // not give the same value as the former mention. - && value.is_deterministic() - { + // This was already constant in MIR, do not change it. If the constant is not + // deterministic, adding an additional mention of it in MIR will not give the same value as + // the former mention. + if let Value::Constant { value, disambiguator: 0 } = *self.get(index) { + assert!(value.is_deterministic()); return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value }); } From 98c1ea8e82e276a42159c5ff75d3581ed33e7bec Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 26 Jun 2024 13:55:57 +0000 Subject: [PATCH 308/489] Simplify constant creation. --- compiler/rustc_mir_transform/src/gvn.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 92a112ceff191..7845fc6e4f6a4 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -361,7 +361,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let next_opaque = self.next_opaque.as_mut()?; let disambiguator = *next_opaque; *next_opaque += 1; - assert_ne!(disambiguator, 0); + // `disambiguator: 0` means deterministic. + debug_assert_ne!(disambiguator, 0); disambiguator }; Some(self.insert(Value::Constant { value, disambiguator })) @@ -369,12 +370,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn insert_bool(&mut self, flag: bool) -> VnIndex { // Booleans are deterministic. - self.insert(Value::Constant { value: Const::from_bool(self.tcx, flag), disambiguator: 0 }) + let value = Const::from_bool(self.tcx, flag); + debug_assert!(value.is_deterministic()); + self.insert(Value::Constant { value, disambiguator: 0 }) } fn insert_scalar(&mut self, scalar: Scalar, ty: Ty<'tcx>) -> VnIndex { - self.insert_constant(Const::from_scalar(self.tcx, scalar, ty)) - .expect("scalars are deterministic") + // Scalars are deterministic. + let value = Const::from_scalar(self.tcx, scalar, ty); + debug_assert!(value.is_deterministic()); + self.insert(Value::Constant { value, disambiguator: 0 }) } fn insert_tuple(&mut self, values: Vec) -> VnIndex { @@ -1453,7 +1458,7 @@ impl<'tcx> VnState<'_, 'tcx> { // deterministic, adding an additional mention of it in MIR will not give the same value as // the former mention. if let Value::Constant { value, disambiguator: 0 } = *self.get(index) { - assert!(value.is_deterministic()); + debug_assert!(value.is_deterministic()); return Some(ConstOperand { span: DUMMY_SP, user_ty: None, const_: value }); } From 4067795d8c88fd38f3295fc4f9fc2658ea4d9ff7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 26 Jun 2024 13:27:50 +0000 Subject: [PATCH 309/489] Do not intern if we have provenance. --- compiler/rustc_mir_transform/src/gvn.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 7845fc6e4f6a4..e16911d79c378 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1389,8 +1389,13 @@ fn op_to_prop_const<'tcx>( // If this constant has scalar ABI, return it as a `ConstValue::Scalar`. if let Abi::Scalar(abi::Scalar::Initialized { .. }) = op.layout.abi && let Ok(scalar) = ecx.read_scalar(op) - && scalar.try_to_scalar_int().is_ok() { + if !scalar.try_to_scalar_int().is_ok() { + // Check that we do not leak a pointer. + // Those pointers may lose part of their identity in codegen. + // FIXME: remove this hack once https://github.com/rust-lang/rust/issues/79738 is fixed. + return None; + } return Some(ConstValue::Scalar(scalar)); } From 7d7ad7b87484e37e6438bb88d044228fa350468b Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 30 Jul 2024 22:52:51 +0000 Subject: [PATCH 310/489] android: Remove libstd hacks for unsupported Android APIs Our minimum supported API version is 21, remove hacks to support older Android APIs. --- library/std/src/f32.rs | 2 +- library/std/src/f64.rs | 2 +- library/std/src/sys/pal/mod.rs | 18 ------ library/std/src/sys/pal/unix/android.rs | 81 ------------------------- library/std/src/sys/pal/unix/mod.rs | 5 -- 5 files changed, 2 insertions(+), 106 deletions(-) delete mode 100644 library/std/src/sys/pal/unix/android.rs diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index b3afeca1ed855..12433d25bfa45 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -574,7 +574,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f32 { - crate::sys::log2f32(self) + unsafe { intrinsics::log2f32(self) } } /// Returns the base 10 logarithm of the number. diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index c8a709c7768db..a343e19173e59 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -574,7 +574,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn log2(self) -> f64 { - crate::sys::log2f64(self) + unsafe { intrinsics::log2f64(self) } } /// Returns the base 10 logarithm of the number. diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index df0176244489a..9be018c8a5312 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -76,23 +76,5 @@ cfg_if::cfg_if! { } } -#[cfg(not(test))] -cfg_if::cfg_if! { - if #[cfg(target_os = "android")] { - pub use self::android::log2f32; - pub use self::android::log2f64; - } else { - #[inline] - pub fn log2f32(n: f32) -> f32 { - unsafe { crate::intrinsics::log2f32(n) } - } - - #[inline] - pub fn log2f64(n: f64) -> f64 { - unsafe { crate::intrinsics::log2f64(n) } - } - } -} - #[cfg(not(target_os = "uefi"))] pub type RawOsError = i32; diff --git a/library/std/src/sys/pal/unix/android.rs b/library/std/src/sys/pal/unix/android.rs deleted file mode 100644 index 0f704994f550a..0000000000000 --- a/library/std/src/sys/pal/unix/android.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Android ABI-compatibility module -//! -//! The ABI of Android has changed quite a bit over time, and std attempts to be -//! both forwards and backwards compatible as much as possible. We want to -//! always work with the most recent version of Android, but we also want to -//! work with older versions of Android for whenever projects need to. -//! -//! Our current minimum supported Android version is `android-9`, e.g., Android -//! with API level 9. We then in theory want to work on that and all future -//! versions of Android! -//! -//! Some of the detection here is done at runtime via `dlopen` and -//! introspection. Other times no detection is performed at all and we just -//! provide a fallback implementation as some versions of Android we support -//! don't have the function. -//! -//! You'll find more details below about why each compatibility shim is needed. - -#![cfg(target_os = "android")] - -use libc::{c_int, sighandler_t}; - -use super::weak::weak; - -// The `log2` and `log2f` functions apparently appeared in android-18, or at -// least you can see they're not present in the android-17 header [1] and they -// are present in android-18 [2]. -// -// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms -// /android-17/arch-arm/usr/include/math.h -// [2]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms -// /android-18/arch-arm/usr/include/math.h -// -// Note that these shims are likely less precise than directly calling `log2`, -// but hopefully that should be enough for now... -// -// Note that mathematically, for any arbitrary `y`: -// -// log_2(x) = log_y(x) / log_y(2) -// = log_y(x) / (1 / log_2(y)) -// = log_y(x) * log_2(y) -// -// Hence because `ln` (log_e) is available on all Android we just choose `y = e` -// and get: -// -// log_2(x) = ln(x) * log_2(e) - -#[cfg(not(test))] -pub fn log2f32(f: f32) -> f32 { - f.ln() * crate::f32::consts::LOG2_E -} - -#[cfg(not(test))] -pub fn log2f64(f: f64) -> f64 { - f.ln() * crate::f64::consts::LOG2_E -} - -// Back in the day [1] the `signal` function was just an inline wrapper -// around `bsd_signal`, but starting in API level android-20 the `signal` -// symbols was introduced [2]. Finally, in android-21 the API `bsd_signal` was -// removed [3]. -// -// Basically this means that if we want to be binary compatible with multiple -// Android releases (oldest being 9 and newest being 21) then we need to check -// for both symbols and not actually link against either. -// -// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms -// /android-18/arch-arm/usr/include/signal.h -// [2]: https://chromium.googlesource.com/android_tools/+/fbd420/ndk_experimental -// /platforms/android-20/arch-arm -// /usr/include/signal.h -// [3]: https://chromium.googlesource.com/android_tools/+/20ee6d/ndk/platforms -// /android-21/arch-arm/usr/include/signal.h -pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t { - weak!(fn signal(c_int, sighandler_t) -> sighandler_t); - weak!(fn bsd_signal(c_int, sighandler_t) -> sighandler_t); - - let f = signal.get().or_else(|| bsd_signal.get()); - let f = f.expect("neither `signal` nor `bsd_signal` symbols found"); - f(signum, handler) -} diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 3fc51ff59a936..b62129f4cdd26 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -8,7 +8,6 @@ use crate::io::ErrorKind; pub mod weak; pub mod alloc; -pub mod android; pub mod args; pub mod env; pub mod fd; @@ -237,12 +236,8 @@ pub unsafe fn cleanup() { } #[allow(unused_imports)] -#[cfg(not(target_os = "android"))] pub use libc::signal; -#[cfg(target_os = "android")] -pub use crate::sys::android::signal; - #[inline] pub(crate) fn is_interrupted(errno: i32) -> bool { errno == libc::EINTR From 33a36ea43851a767d8182938161b0dad4f9ae68c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 30 Jul 2024 18:25:05 -0700 Subject: [PATCH 311/489] Bless coverage/mcdc for line number changes --- tests/coverage/mcdc/condition-limit.cov-map | 8 +++--- tests/coverage/mcdc/if.cov-map | 28 +++++++++---------- .../coverage/mcdc/inlined_expressions.cov-map | 4 +-- tests/coverage/mcdc/nested_if.cov-map | 16 +++++------ tests/coverage/mcdc/non_control_flow.cov-map | 28 +++++++++---------- 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map index b4447a33691ad..b565353572a74 100644 --- a/tests/coverage/mcdc/condition-limit.cov-map +++ b/tests/coverage/mcdc/condition-limit.cov-map @@ -1,5 +1,5 @@ Function name: condition_limit::bad -Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 14, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02] +Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 15, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 44 @@ -48,7 +48,7 @@ Number of expressions: 44 - expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4) - expression 43 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 17 -- Code(Counter(0)) at (prev + 20, 1) to (start + 3, 9) +- Code(Counter(0)) at (prev + 21, 1) to (start + 3, 9) - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 3, 8) to (start + 0, 9) true = c1 false = (c0 - c1) @@ -88,7 +88,7 @@ Number of file 0 mappings: 17 = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1))) Function name: condition_limit::good -Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0c, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02] +Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0d, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 32 @@ -125,7 +125,7 @@ Number of expressions: 32 - expression 30 operands: lhs = Expression(31, Add), rhs = Counter(4) - expression 31 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 16 -- Code(Counter(0)) at (prev + 12, 1) to (start + 3, 9) +- Code(Counter(0)) at (prev + 13, 1) to (start + 3, 9) - MCDCDecision { bitmap_idx: 0, conditions_num: 6 } at (prev + 3, 8) to (start + 0, 34) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 6, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map index 9a7d15f700df0..ea8dedb0ac363 100644 --- a/tests/coverage/mcdc/if.cov-map +++ b/tests/coverage/mcdc/if.cov-map @@ -1,5 +1,5 @@ Function name: if::mcdc_check_a -Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 10, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -8,7 +8,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add) - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -24,7 +24,7 @@ Number of file 0 mappings: 8 = (c3 + (c2 + (c0 - c1))) Function name: if::mcdc_check_b -Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 18, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -33,7 +33,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add) - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -49,7 +49,7 @@ Number of file 0 mappings: 8 = (c3 + (c2 + (c0 - c1))) Function name: if::mcdc_check_both -Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 20, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -58,7 +58,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add) - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 32, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -74,7 +74,7 @@ Number of file 0 mappings: 8 = (c3 + (c2 + (c0 - c1))) Function name: if::mcdc_check_neither -Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 08, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -83,7 +83,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add) - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -99,7 +99,7 @@ Number of file 0 mappings: 8 = (c3 + (c2 + (c0 - c1))) Function name: if::mcdc_check_not_tree_decision -Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02] +Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 32, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -112,7 +112,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Counter(3), rhs = Expression(7, Sub) - expression 7 operands: lhs = Expression(0, Sub), rhs = Counter(2) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10) +- Code(Counter(0)) at (prev + 50, 1) to (start + 3, 10) - MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10) true = c1 @@ -134,7 +134,7 @@ Number of file 0 mappings: 10 = (c4 + (c3 + ((c0 - c1) - c2))) Function name: if::mcdc_check_tree_decision -Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02] +Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 28, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 8 @@ -147,7 +147,7 @@ Number of expressions: 8 - expression 6 operands: lhs = Counter(3), rhs = Counter(4) - expression 7 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9) +- Code(Counter(0)) at (prev + 40, 1) to (start + 3, 9) - MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -169,7 +169,7 @@ Number of file 0 mappings: 10 = ((c3 + c4) + (c2 + (c0 - c1))) Function name: if::mcdc_nested_if -Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02] +Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3c, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 13 @@ -187,7 +187,7 @@ Number of expressions: 13 - expression 11 operands: lhs = Counter(4), rhs = Counter(5) - expression 12 operands: lhs = Expression(0, Sub), rhs = Counter(2) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 60, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9) true = c1 diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map index 09b7291c96493..8bb488c0dc072 100644 --- a/tests/coverage/mcdc/inlined_expressions.cov-map +++ b/tests/coverage/mcdc/inlined_expressions.cov-map @@ -1,5 +1,5 @@ Function name: inlined_expressions::inlined_instance -Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 08, 01, 01, 06, 28, 00, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02] +Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 09, 01, 01, 06, 28, 00, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -7,7 +7,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub) - expression 2 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 6) +- Code(Counter(0)) at (prev + 9, 1) to (start + 1, 6) - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 5) to (start + 0, 6) true = c1 diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map index adeb6cbc1fb89..0bd2aef814c2b 100644 --- a/tests/coverage/mcdc/nested_if.cov-map +++ b/tests/coverage/mcdc/nested_if.cov-map @@ -1,5 +1,5 @@ Function name: nested_if::doubly_nested_if_in_condition -Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02] +Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 10, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 14 @@ -18,7 +18,7 @@ Number of expressions: 14 - expression 12 operands: lhs = Counter(3), rhs = Expression(13, Add) - expression 13 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 20 -- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -58,7 +58,7 @@ Number of file 0 mappings: 20 = (c3 + (c2 + (c0 - c1))) Function name: nested_if::nested_if_in_condition -Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02] +Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 08, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 11 @@ -74,7 +74,7 @@ Number of expressions: 11 - expression 9 operands: lhs = Counter(3), rhs = Expression(10, Add) - expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -103,7 +103,7 @@ Number of file 0 mappings: 14 = (c3 + (c2 + (c0 - c1))) Function name: nested_if::nested_in_then_block_in_condition -Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02] +Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 23, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 18 @@ -126,7 +126,7 @@ Number of expressions: 18 - expression 16 operands: lhs = Counter(3), rhs = Expression(17, Add) - expression 17 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 20 -- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9) +- Code(Counter(0)) at (prev + 35, 1) to (start + 1, 9) - MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 @@ -167,7 +167,7 @@ Number of file 0 mappings: 20 = (c3 + (c2 + (c0 - c1))) Function name: nested_if::nested_single_condition_decision -Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02] +Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 18, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 6 @@ -178,7 +178,7 @@ Number of expressions: 6 - expression 4 operands: lhs = Counter(3), rhs = Expression(5, Add) - expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub) Number of file 0 mappings: 11 -- Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9) +- Code(Counter(0)) at (prev + 24, 1) to (start + 4, 9) - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9) true = c1 diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map index f8576831e75f1..0c6928b684d6b 100644 --- a/tests/coverage/mcdc/non_control_flow.cov-map +++ b/tests/coverage/mcdc/non_control_flow.cov-map @@ -1,5 +1,5 @@ Function name: non_control_flow::assign_3 -Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 17, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -13,7 +13,7 @@ Number of expressions: 9 - expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4) - expression 8 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40) +- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 40) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = (c1 + ((c2 + c3) + c4)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) @@ -35,7 +35,7 @@ Number of file 0 mappings: 10 = (c1 + ((c2 + c3) + c4)) Function name: non_control_flow::assign_3_bis -Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1c, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -47,7 +47,7 @@ Number of expressions: 7 - expression 5 operands: lhs = Counter(1), rhs = Counter(2) - expression 6 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 10 -- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 44) +- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 44) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c2 + c3) + c4) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) @@ -68,7 +68,7 @@ Number of file 0 mappings: 10 = ((c2 + c3) + c4) Function name: non_control_flow::assign_and -Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0d, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -77,7 +77,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(0), rhs = Counter(1) - expression 3 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33) +- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 33) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c2 + c3) + (c0 - c1)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) @@ -93,7 +93,7 @@ Number of file 0 mappings: 8 = ((c2 + c3) + (c0 - c1)) Function name: non_control_flow::assign_or -Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 12, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -102,7 +102,7 @@ Number of expressions: 4 - expression 2 operands: lhs = Counter(0), rhs = Counter(1) - expression 3 operands: lhs = Counter(0), rhs = Counter(1) Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32) +- Code(Counter(0)) at (prev + 18, 1) to (start + 0, 32) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c1 + c2) + c3) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) @@ -119,15 +119,15 @@ Number of file 0 mappings: 8 = ((c1 + c2) + c3) Function name: non_control_flow::foo -Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 38, 1) to (start + 2, 2) Function name: non_control_flow::func_call -Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] +Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 2a, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 @@ -135,7 +135,7 @@ Number of expressions: 3 - expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub) - expression 2 operands: lhs = Counter(2), rhs = Counter(3) Number of file 0 mappings: 6 -- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) +- Code(Counter(0)) at (prev + 42, 1) to (start + 1, 10) - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15) - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10) true = c1 @@ -148,7 +148,7 @@ Number of file 0 mappings: 6 = ((c2 + c3) + (c0 - c1)) Function name: non_control_flow::right_comb_tree -Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] +Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 21, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 19 @@ -172,7 +172,7 @@ Number of expressions: 19 - expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5) - expression 18 operands: lhs = Counter(1), rhs = Counter(6) Number of file 0 mappings: 14 -- Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65) +- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 65) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) From d629d5f7b87f11f3db9310343caec4b18bb36593 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 30 Jul 2024 21:26:49 -0400 Subject: [PATCH 312/489] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index b5d44db1daf04..257b72b8adfb1 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit b5d44db1daf0469b227a6211b987162a39a54730 +Subproject commit 257b72b8adfb1f2aa9916cefca67285c21666276 From 1b058b796d5b711a13ec6918ea5a96f7031c6a5f Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Wed, 31 Jul 2024 10:47:13 +0900 Subject: [PATCH 313/489] Add a test case --- src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index 540e219920c9c..b371e5856b083 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -2051,6 +2051,8 @@ fn test() { // ^ Wrap<'?, ()> let x = S::foo::<&()>(&S); // ^ Wrap<'?, ()> + let x = S.foo::<'static, &()>(); + // ^ Wrap<'?, ()> let x = S.foo::<&()>(); // ^ Wrap<'?, ()> } From 281c2fd5bf1604392bde16e32c7d57d2772406e6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 12:08:55 +1000 Subject: [PATCH 314/489] Inline and remove `parse_local_mk`. It has a single use. This makes the `let` handling case in `parse_stmt_without_recovery` more similar to the statement path and statement expression cases. --- compiler/rustc_parse/src/parser/stmt.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 7b0daaa14335f..28122a3ae294a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -66,7 +66,12 @@ impl<'a> Parser<'a> { } Ok(Some(if self.token.is_keyword(kw::Let) { - self.parse_local_mk(lo, attrs, capture_semi, force_collect)? + self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { + this.expect_keyword(kw::Let)?; + let local = this.parse_local(attrs)?; + let trailing = capture_semi && this.token.kind == token::Semi; + Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) + })? } else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() { self.recover_stmt_local_after_let( lo, @@ -247,21 +252,6 @@ impl<'a> Parser<'a> { Ok(stmt) } - fn parse_local_mk( - &mut self, - lo: Span, - attrs: AttrWrapper, - capture_semi: bool, - force_collect: ForceCollect, - ) -> PResult<'a, Stmt> { - self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| { - this.expect_keyword(kw::Let)?; - let local = this.parse_local(attrs)?; - let trailing = capture_semi && this.token.kind == token::Semi; - Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) - }) - } - /// Parses a local variable declaration. fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; From fe647f053882f5745dfb339f22f13435bf8c4ca5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 12:56:25 +1000 Subject: [PATCH 315/489] Remove `LhsExpr`. `parse_expr_assoc_with` has an awkward structure -- sometimes the lhs is already parsed. This commit splits the post-lhs part into a new method `parse_expr_assoc_rest_with`, which makes everything shorter and simpler. --- compiler/rustc_parse/src/parser/expr.rs | 57 ++++++++++--------------- compiler/rustc_parse/src/parser/pat.rs | 7 +-- compiler/rustc_parse/src/parser/stmt.rs | 6 +-- 3 files changed, 28 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a242dc5cd582d..24e56c5bdee66 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -40,14 +40,6 @@ use super::{ }; use crate::{errors, maybe_recover_from_interpolated_ty_qpath}; -#[derive(Debug)] -pub(super) enum LhsExpr { - // Already parsed just the outer attributes. - Unparsed { attrs: AttrWrapper }, - // Already parsed the expression. - Parsed { expr: P, starts_statement: bool }, -} - #[derive(Debug)] enum DestructuredFloat { /// 1e2 @@ -113,30 +105,31 @@ impl<'a> Parser<'a> { r: Restrictions, attrs: AttrWrapper, ) -> PResult<'a, P> { - self.with_res(r, |this| this.parse_expr_assoc_with(0, LhsExpr::Unparsed { attrs })) + self.with_res(r, |this| this.parse_expr_assoc_with(0, attrs)) } /// Parses an associative expression with operators of at least `min_prec` precedence. pub(super) fn parse_expr_assoc_with( &mut self, min_prec: usize, - lhs: LhsExpr, + attrs: AttrWrapper, ) -> PResult<'a, P> { - let mut starts_stmt = false; - let mut lhs = match lhs { - LhsExpr::Parsed { expr, starts_statement } => { - starts_stmt = starts_statement; - expr - } - LhsExpr::Unparsed { attrs } => { - if self.token.is_range_separator() { - return self.parse_expr_prefix_range(attrs); - } else { - self.parse_expr_prefix(attrs)? - } - } + let lhs = if self.token.is_range_separator() { + return self.parse_expr_prefix_range(attrs); + } else { + self.parse_expr_prefix(attrs)? }; + self.parse_expr_assoc_rest_with(min_prec, false, lhs) + } + /// Parses the rest of an associative expression (i.e. the part after the lhs) with operators + /// of at least `min_prec` precedence. + pub(super) fn parse_expr_assoc_rest_with( + &mut self, + min_prec: usize, + starts_stmt: bool, + mut lhs: P, + ) -> PResult<'a, P> { if !self.should_continue_as_assoc_expr(&lhs) { return Ok(lhs); } @@ -272,7 +265,7 @@ impl<'a> Parser<'a> { }; let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with(prec + prec_adjustment, LhsExpr::Unparsed { attrs }) + this.parse_expr_assoc_with(prec + prec_adjustment, attrs) })?; let span = self.mk_expr_sp(&lhs, lhs_span, rhs.span); @@ -447,7 +440,7 @@ impl<'a> Parser<'a> { let maybe_lt = self.token.clone(); let attrs = self.parse_outer_attributes()?; Some( - self.parse_expr_assoc_with(prec + 1, LhsExpr::Unparsed { attrs }) + self.parse_expr_assoc_with(prec + 1, attrs) .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?, ) } else { @@ -504,12 +497,9 @@ impl<'a> Parser<'a> { let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() { // RHS must be parsed with more associativity than the dots. let attrs = this.parse_outer_attributes()?; - this.parse_expr_assoc_with( - op.unwrap().precedence() + 1, - LhsExpr::Unparsed { attrs }, - ) - .map(|x| (lo.to(x.span), Some(x))) - .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? + this.parse_expr_assoc_with(op.unwrap().precedence() + 1, attrs) + .map(|x| (lo.to(x.span), Some(x))) + .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))? } else { (lo, None) }; @@ -2645,10 +2635,7 @@ impl<'a> Parser<'a> { self.expect(&token::Eq)?; } let attrs = self.parse_outer_attributes()?; - let expr = self.parse_expr_assoc_with( - 1 + prec_let_scrutinee_needs_par(), - LhsExpr::Unparsed { attrs }, - )?; + let expr = self.parse_expr_assoc_with(1 + prec_let_scrutinee_needs_par(), attrs)?; let span = lo.to(expr.span); Ok(self.mk_expr(span, ExprKind::Let(pat, expr, span, recovered))) } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index b6f85cc90324c..5bfb8bdf776a0 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -25,7 +25,7 @@ use crate::errors::{ UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, }; -use crate::parser::expr::{could_be_unclosed_char_literal, LhsExpr}; +use crate::parser::expr::could_be_unclosed_char_literal; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; #[derive(PartialEq, Copy, Clone)] @@ -403,8 +403,9 @@ impl<'a> Parser<'a> { // Parse an associative expression such as `+ expr`, `% expr`, ... // Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`]. - let lhs = LhsExpr::Parsed { expr, starts_statement: false }; - if let Ok(expr) = snapshot.parse_expr_assoc_with(0, lhs).map_err(|err| err.cancel()) { + if let Ok(expr) = + snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel()) + { // We got a valid expression. self.restore_snapshot(snapshot); self.restrictions.remove(Restrictions::IS_PAT); diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 28122a3ae294a..e0676b72634e7 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -17,7 +17,6 @@ use thin_vec::{thin_vec, ThinVec}; use super::attr::InnerAttrForbiddenReason; use super::diagnostics::AttemptLocalParseRecovery; -use super::expr::LhsExpr; use super::pat::{PatternLocation, RecoverComma}; use super::path::PathStyle; use super::{ @@ -178,7 +177,7 @@ impl<'a> Parser<'a> { // Perform this outside of the `collect_tokens_trailing_token` closure, // since our outer attributes do not apply to this part of the expression let expr = self.with_res(Restrictions::STMT_EXPR, |this| { - this.parse_expr_assoc_with(0, LhsExpr::Parsed { expr, starts_statement: true }) + this.parse_expr_assoc_rest_with(0, true, expr) })?; Ok(self.mk_stmt(lo.to(self.prev_token.span), StmtKind::Expr(expr))) } else { @@ -211,8 +210,7 @@ impl<'a> Parser<'a> { let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac)); let e = self.maybe_recover_from_bad_qpath(e)?; let e = self.parse_expr_dot_or_call_with(attrs, e, lo)?; - let e = self - .parse_expr_assoc_with(0, LhsExpr::Parsed { expr: e, starts_statement: false })?; + let e = self.parse_expr_assoc_rest_with(0, false, e)?; StmtKind::Expr(e) }; Ok(self.mk_stmt(lo.to(hi), kind)) From f6f587e7ea7ce26418fdaca7dd05faff8c68fc9d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 11 Apr 2024 14:10:34 -0400 Subject: [PATCH 316/489] Introduce REDUNDANT_IMPORTS lint --- compiler/rustc_lint/messages.ftl | 8 +-- compiler/rustc_lint_defs/src/builtin.rs | 26 ++++++++++ compiler/rustc_resolve/src/imports.rs | 8 ++- compiler/rustc_resolve/src/lib.rs | 4 +- .../redundant-import-extern-prelude.rs | 7 +-- .../redundant-import-extern-prelude.stderr | 14 +++++ .../redundant-import-issue-121915-2015.rs | 5 +- .../redundant-import-issue-121915-2015.stderr | 17 ++++++ .../redundant-import-lang-prelude-attr.rs | 7 +-- .../redundant-import-lang-prelude-attr.stderr | 14 +++++ .../imports/redundant-import-lang-prelude.rs | 7 +-- .../redundant-import-lang-prelude.stderr | 14 +++++ .../ui/imports/suggest-remove-issue-121315.rs | 11 ++-- .../suggest-remove-issue-121315.stderr | 52 +++++++++++++++++-- tests/ui/lint/unused/issue-59896.rs | 5 +- tests/ui/lint/unused/issue-59896.stderr | 17 ++++++ .../use-redundant-glob-parent.rs | 4 +- .../use-redundant-glob-parent.stderr | 17 ++++++ .../lint/use-redundant/use-redundant-glob.rs | 4 +- .../use-redundant/use-redundant-glob.stderr | 16 ++++++ .../use-redundant-issue-71450.rs | 5 +- .../use-redundant-issue-71450.stderr | 17 ++++++ .../use-redundant-prelude-rust-2015.rs | 14 ++--- .../use-redundant-prelude-rust-2015.stderr | 44 ++++++++++++++++ .../use-redundant-prelude-rust-2021.rs | 8 ++- .../use-redundant-prelude-rust-2021.stderr | 26 ++++++++++ tests/ui/lint/use-redundant/use-redundant.rs | 4 +- .../lint/use-redundant/use-redundant.stderr | 19 ++++++- 28 files changed, 332 insertions(+), 62 deletions(-) create mode 100644 tests/ui/imports/redundant-import-extern-prelude.stderr create mode 100644 tests/ui/imports/redundant-import-issue-121915-2015.stderr create mode 100644 tests/ui/imports/redundant-import-lang-prelude-attr.stderr create mode 100644 tests/ui/imports/redundant-import-lang-prelude.stderr create mode 100644 tests/ui/lint/unused/issue-59896.stderr create mode 100644 tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr create mode 100644 tests/ui/lint/use-redundant/use-redundant-glob.stderr create mode 100644 tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr create mode 100644 tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr create mode 100644 tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 987dbf6db630a..7e4feb0a82716 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -700,10 +700,10 @@ lint_reason_must_be_string_literal = reason must be a string literal lint_reason_must_come_last = reason in lint attribute must come last lint_redundant_import = the item `{$ident}` is imported redundantly - .label_imported_here = the item `{ident}` is already imported here - .label_defined_here = the item `{ident}` is already defined here - .label_imported_prelude = the item `{ident}` is already imported by the extern prelude - .label_defined_prelude = the item `{ident}` is already defined by the extern prelude + .label_imported_here = the item `{$ident}` is already imported here + .label_defined_here = the item `{$ident}` is already defined here + .label_imported_prelude = the item `{$ident}` is already imported by the extern prelude + .label_defined_prelude = the item `{$ident}` is already defined by the extern prelude lint_redundant_import_visibility = glob import doesn't reexport anything with visibility `{$import_vis}` because no imported item is public enough .note = the most public imported item is `{$max_vis}` diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 246b516076461..3fdfb327c70cc 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -82,6 +82,7 @@ declare_lint_pass! { PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, PTR_CAST_ADD_AUTO_TO_OBJECT, PUB_USE_OF_PRIVATE_EXTERN_CRATE, + REDUNDANT_IMPORTS, REDUNDANT_LIFETIMES, REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE, @@ -426,6 +427,31 @@ declare_lint! { "imports that are never used" } +declare_lint! { + /// The `redundant_imports` lint detects imports that are redundant due to being + /// imported already; either through a previous import, or being present in + /// the prelude. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(redundant_imports)] + /// use std::option::Option::None; + /// fn foo() -> Option { None } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Redundant imports are unnecessary and can be removed to simplify code. + /// If you intended to re-export the item to make it available outside of the + /// module, add a visibility modifier like `pub`. + pub REDUNDANT_IMPORTS, + Allow, + "imports that are redundant due to being imported already" +} + declare_lint! { /// The `must_not_suspend` lint guards against values that shouldn't be held across suspend points /// (`.await`) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index f76fa62a0094f..0fa5cde9424b5 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -14,7 +14,7 @@ use rustc_middle::metadata::{ModChild, Reexport}; use rustc_middle::{span_bug, ty}; use rustc_session::lint::builtin::{ AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, - UNUSED_IMPORTS, + REDUNDANT_IMPORTS, UNUSED_IMPORTS, }; use rustc_session::lint::BuiltinLintDiag; use rustc_span::edit_distance::find_best_match_for_name; @@ -1387,14 +1387,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut redundant_spans: Vec<_> = redundant_span.present_items().collect(); redundant_spans.sort(); redundant_spans.dedup(); - /* FIXME(unused_imports): Add this back as a new lint - self.lint_buffer.buffer_lint_with_diagnostic( - UNUSED_IMPORTS, + self.lint_buffer.buffer_lint( + REDUNDANT_IMPORTS, id, import.span, BuiltinLintDiag::RedundantImport(redundant_spans, source), ); - */ return true; } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6aca0545e64de..a42083b9dea35 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -178,8 +178,8 @@ enum ImplTraitContext { /// Used for tracking import use types which will be used for redundant import checking. /// ### Used::Scope Example -/// ```rust,ignore (redundant_imports) -/// #![deny(unused_imports)] +/// ```rust,compile_fail +/// #![deny(redundant_imports)] /// use std::mem::drop; /// fn main() { /// let s = Box::new(32); diff --git a/tests/ui/imports/redundant-import-extern-prelude.rs b/tests/ui/imports/redundant-import-extern-prelude.rs index f1de06417aa5d..0064eaa931882 100644 --- a/tests/ui/imports/redundant-import-extern-prelude.rs +++ b/tests/ui/imports/redundant-import-extern-prelude.rs @@ -1,16 +1,17 @@ -//@ check-pass // Check that we detect imports that are redundant due to the extern prelude // and that we emit a reasonable diagnostic. // issue: rust-lang/rust#121915 +//~^^^ NOTE the item `aux_issue_121915` is already defined by the extern prelude // See also the discussion in . //@ compile-flags: --extern aux_issue_121915 --edition 2018 //@ aux-build: aux-issue-121915.rs -#[deny(unused_imports)] +#[deny(redundant_imports)] +//~^ NOTE the lint level is defined here fn main() { use aux_issue_121915; - //FIXME(unused_imports): ~^ ERROR the item `aux_issue_121915` is imported redundantly + //~^ ERROR the item `aux_issue_121915` is imported redundantly aux_issue_121915::item(); } diff --git a/tests/ui/imports/redundant-import-extern-prelude.stderr b/tests/ui/imports/redundant-import-extern-prelude.stderr new file mode 100644 index 0000000000000..6d2518c1284b6 --- /dev/null +++ b/tests/ui/imports/redundant-import-extern-prelude.stderr @@ -0,0 +1,14 @@ +error: the item `aux_issue_121915` is imported redundantly + --> $DIR/redundant-import-extern-prelude.rs:14:9 + | +LL | use aux_issue_121915; + | ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by the extern prelude + | +note: the lint level is defined here + --> $DIR/redundant-import-extern-prelude.rs:11:8 + | +LL | #[deny(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.rs b/tests/ui/imports/redundant-import-issue-121915-2015.rs index be3b8209ada99..dc499bc40b616 100644 --- a/tests/ui/imports/redundant-import-issue-121915-2015.rs +++ b/tests/ui/imports/redundant-import-issue-121915-2015.rs @@ -1,12 +1,11 @@ -//@ check-pass //@ compile-flags: --extern aux_issue_121915 --edition 2015 //@ aux-build: aux-issue-121915.rs extern crate aux_issue_121915; -#[deny(unused_imports)] +#[deny(redundant_imports)] fn main() { use aux_issue_121915; - //FIXME(unused_imports): ~^ ERROR the item `aux_issue_121915` is imported redundantly + //~^ ERROR the item `aux_issue_121915` is imported redundantly aux_issue_121915::item(); } diff --git a/tests/ui/imports/redundant-import-issue-121915-2015.stderr b/tests/ui/imports/redundant-import-issue-121915-2015.stderr new file mode 100644 index 0000000000000..f4e9f604896ab --- /dev/null +++ b/tests/ui/imports/redundant-import-issue-121915-2015.stderr @@ -0,0 +1,17 @@ +error: the item `aux_issue_121915` is imported redundantly + --> $DIR/redundant-import-issue-121915-2015.rs:8:9 + | +LL | extern crate aux_issue_121915; + | ------------------------------ the item `aux_issue_121915` is already imported here +... +LL | use aux_issue_121915; + | ^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/redundant-import-issue-121915-2015.rs:6:8 + | +LL | #[deny(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/redundant-import-lang-prelude-attr.rs b/tests/ui/imports/redundant-import-lang-prelude-attr.rs index 59cd570f44c25..f7ee91880bad5 100644 --- a/tests/ui/imports/redundant-import-lang-prelude-attr.rs +++ b/tests/ui/imports/redundant-import-lang-prelude-attr.rs @@ -1,6 +1,6 @@ -//@ check-pass // Check that we detect imports (of built-in attributes) that are redundant due to // the language prelude and that we emit a reasonable diagnostic. +//~^^ NOTE the item `allow` is already defined by the extern prelude // Note that we use the term "extern prelude" in the label even though "language prelude" // would be more correct. However, it's not worth special-casing this. @@ -9,9 +9,10 @@ //@ edition: 2018 -#![deny(unused_imports)] +#![deny(redundant_imports)] +//~^ NOTE the lint level is defined here -use allow; //FIXME(unused_imports): ~ ERROR the item `allow` is imported redundantly +use allow; //~ ERROR the item `allow` is imported redundantly #[allow(unused)] fn main() {} diff --git a/tests/ui/imports/redundant-import-lang-prelude-attr.stderr b/tests/ui/imports/redundant-import-lang-prelude-attr.stderr new file mode 100644 index 0000000000000..f0016f5fab41f --- /dev/null +++ b/tests/ui/imports/redundant-import-lang-prelude-attr.stderr @@ -0,0 +1,14 @@ +error: the item `allow` is imported redundantly + --> $DIR/redundant-import-lang-prelude-attr.rs:15:5 + | +LL | use allow; + | ^^^^^ the item `allow` is already defined by the extern prelude + | +note: the lint level is defined here + --> $DIR/redundant-import-lang-prelude-attr.rs:12:9 + | +LL | #![deny(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/redundant-import-lang-prelude.rs b/tests/ui/imports/redundant-import-lang-prelude.rs index 53d3b70996342..3f95ffbe02e7e 100644 --- a/tests/ui/imports/redundant-import-lang-prelude.rs +++ b/tests/ui/imports/redundant-import-lang-prelude.rs @@ -1,16 +1,17 @@ -//@ check-pass // Check that we detect imports that are redundant due to the language prelude // and that we emit a reasonable diagnostic. +//~^^ NOTE the item `u8` is already defined by the extern prelude // Note that we use the term "extern prelude" in the label even though "language prelude" // would be more correct. However, it's not worth special-casing this. // See also the discussion in . -#![deny(unused_imports)] +#![deny(redundant_imports)] +//~^ NOTE the lint level is defined here use std::primitive::u8; -//FIXME(unused_imports): ~^ ERROR the item `u8` is imported redundantly +//~^ ERROR the item `u8` is imported redundantly const _: u8 = 0; diff --git a/tests/ui/imports/redundant-import-lang-prelude.stderr b/tests/ui/imports/redundant-import-lang-prelude.stderr new file mode 100644 index 0000000000000..4fd576397812e --- /dev/null +++ b/tests/ui/imports/redundant-import-lang-prelude.stderr @@ -0,0 +1,14 @@ +error: the item `u8` is imported redundantly + --> $DIR/redundant-import-lang-prelude.rs:13:5 + | +LL | use std::primitive::u8; + | ^^^^^^^^^^^^^^^^^^ the item `u8` is already defined by the extern prelude + | +note: the lint level is defined here + --> $DIR/redundant-import-lang-prelude.rs:10:9 + | +LL | #![deny(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/suggest-remove-issue-121315.rs b/tests/ui/imports/suggest-remove-issue-121315.rs index 2bb82833a5bc3..ee3ceb6e3a380 100644 --- a/tests/ui/imports/suggest-remove-issue-121315.rs +++ b/tests/ui/imports/suggest-remove-issue-121315.rs @@ -1,20 +1,19 @@ //@ compile-flags: --edition 2021 - -#![deny(unused_imports)] +#![deny(unused_imports, redundant_imports)] #![allow(dead_code)] fn test0() { // Test remove FlatUnused use std::convert::TryFrom; - //FIXME(unused_imports): ~^ ERROR the item `TryFrom` is imported redundantly + //~^ ERROR the item `TryFrom` is imported redundantly let _ = u32::try_from(5i32); } fn test1() { // FIXME(yukang) Test remove NestedFullUnused use std::convert::{TryFrom, TryInto}; - //FIXME(unused_imports): ~^ ERROR the item `TryFrom` is imported redundantly - //FIXME(unused_imports): ~| ERROR the item `TryInto` is imported redundantly + //~^ ERROR the item `TryFrom` is imported redundantly + //~| ERROR the item `TryInto` is imported redundantly let _ = u32::try_from(5i32); let _a: i32 = u32::try_into(5u32).unwrap(); @@ -24,7 +23,7 @@ fn test2() { // FIXME(yukang): Test remove both redundant and unused use std::convert::{AsMut, Into}; //~^ ERROR unused import: `AsMut` - //FIXME(unused_imports): ~| ERROR the item `Into` is imported redundantly + //~| ERROR the item `Into` is imported redundantly let _a: u32 = (5u8).into(); } diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr index 5701514e1bd6e..5d0bf9bea6a94 100644 --- a/tests/ui/imports/suggest-remove-issue-121315.stderr +++ b/tests/ui/imports/suggest-remove-issue-121315.stderr @@ -1,20 +1,62 @@ +error: the item `TryFrom` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:7:9 + | +LL | use std::convert::TryFrom; + | ^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryFrom` is already defined here + | +note: the lint level is defined here + --> $DIR/suggest-remove-issue-121315.rs:2:25 + | +LL | #![deny(unused_imports, redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +error: the item `TryFrom` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:14:24 + | +LL | use std::convert::{TryFrom, TryInto}; + | ^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryFrom` is already defined here + +error: the item `TryInto` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:14:33 + | +LL | use std::convert::{TryFrom, TryInto}; + | ^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryInto` is already defined here + error: unused import: `AsMut` - --> $DIR/suggest-remove-issue-121315.rs:25:24 + --> $DIR/suggest-remove-issue-121315.rs:24:24 | LL | use std::convert::{AsMut, Into}; | ^^^^^ | note: the lint level is defined here - --> $DIR/suggest-remove-issue-121315.rs:3:9 + --> $DIR/suggest-remove-issue-121315.rs:2:9 | -LL | #![deny(unused_imports)] +LL | #![deny(unused_imports, redundant_imports)] | ^^^^^^^^^^^^^^ +error: the item `Into` is imported redundantly + --> $DIR/suggest-remove-issue-121315.rs:24:31 + | +LL | use std::convert::{AsMut, Into}; + | ^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Into` is already defined here + error: unused import: `From` - --> $DIR/suggest-remove-issue-121315.rs:34:24 + --> $DIR/suggest-remove-issue-121315.rs:33:24 | LL | use std::convert::{From, Infallible}; | ^^^^ -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/lint/unused/issue-59896.rs b/tests/ui/lint/unused/issue-59896.rs index a98017524f550..5624e7f02fb43 100644 --- a/tests/ui/lint/unused/issue-59896.rs +++ b/tests/ui/lint/unused/issue-59896.rs @@ -1,10 +1,9 @@ -//@ check-pass -#![deny(unused_imports)] +#![deny(redundant_imports)] struct S; fn main() { - use S; //FIXME(unused_imports): ~ ERROR the item `S` is imported redundantly + use S; //~ ERROR the item `S` is imported redundantly let _s = S; } diff --git a/tests/ui/lint/unused/issue-59896.stderr b/tests/ui/lint/unused/issue-59896.stderr new file mode 100644 index 0000000000000..363a6419d9c85 --- /dev/null +++ b/tests/ui/lint/unused/issue-59896.stderr @@ -0,0 +1,17 @@ +error: the item `S` is imported redundantly + --> $DIR/issue-59896.rs:6:9 + | +LL | struct S; + | --------- the item `S` is already defined here +... +LL | use S; + | ^ + | +note: the lint level is defined here + --> $DIR/issue-59896.rs:1:9 + | +LL | #![deny(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs b/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs index 797e57f48e9d2..c8c413dccd3f2 100644 --- a/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs +++ b/tests/ui/lint/use-redundant/use-redundant-glob-parent.rs @@ -1,5 +1,5 @@ //@ check-pass -#![warn(unused_imports)] +#![warn(redundant_imports)] pub mod bar { pub struct Foo(pub Bar); @@ -9,7 +9,7 @@ pub mod bar { use bar::*; pub fn warning() -> Foo { - use bar::Foo; //FIXME(unused_imports): ~ WARNING imported redundantly + use bar::Foo; //~ WARNING imported redundantly Foo(Bar('a')) } diff --git a/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr b/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr new file mode 100644 index 0000000000000..3b06b2df67454 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-glob-parent.stderr @@ -0,0 +1,17 @@ +warning: the item `Foo` is imported redundantly + --> $DIR/use-redundant-glob-parent.rs:12:9 + | +LL | use bar::*; + | ------ the item `Foo` is already imported here +... +LL | use bar::Foo; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/use-redundant-glob-parent.rs:2:9 + | +LL | #![warn(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-glob.rs b/tests/ui/lint/use-redundant/use-redundant-glob.rs index e5835be89d841..52383d4ceffc3 100644 --- a/tests/ui/lint/use-redundant/use-redundant-glob.rs +++ b/tests/ui/lint/use-redundant/use-redundant-glob.rs @@ -1,5 +1,5 @@ //@ check-pass -#![warn(unused_imports)] +#![warn(redundant_imports)] pub mod bar { pub struct Foo(pub Bar); @@ -8,7 +8,7 @@ pub mod bar { pub fn warning() -> bar::Foo { use bar::*; - use bar::Foo; //FIXME(unused_imports): ~ WARNING imported redundantly + use bar::Foo; //~ WARNING imported redundantly Foo(Bar('a')) } diff --git a/tests/ui/lint/use-redundant/use-redundant-glob.stderr b/tests/ui/lint/use-redundant/use-redundant-glob.stderr new file mode 100644 index 0000000000000..47b2ce54bb733 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-glob.stderr @@ -0,0 +1,16 @@ +warning: the item `Foo` is imported redundantly + --> $DIR/use-redundant-glob.rs:11:9 + | +LL | use bar::*; + | ------ the item `Foo` is already imported here +LL | use bar::Foo; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/use-redundant-glob.rs:2:9 + | +LL | #![warn(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs b/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs index 2db3435d46dbd..6a3ffa4522ae2 100644 --- a/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs +++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.rs @@ -1,6 +1,6 @@ //@ check-pass -#![warn(unused_imports)] +#![warn(redundant_imports)] mod foo { use std::fmt; @@ -23,8 +23,7 @@ mod foo { fn main() { { - use std::string::String; - //FIXME(unused_imports): ~^ WARNING the item `String` is imported redundantly + use std::string::String; //~ WARNING the item `String` is imported redundantly // 'String' from 'std::string::String'. let s = String::new(); println!("{}", s); diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr new file mode 100644 index 0000000000000..c14ab9e11e0fc --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr @@ -0,0 +1,17 @@ +warning: the item `String` is imported redundantly + --> $DIR/use-redundant-issue-71450.rs:26:13 + | +LL | use std::string::String; + | ^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `String` is already defined here + | +note: the lint level is defined here + --> $DIR/use-redundant-issue-71450.rs:3:9 + | +LL | #![warn(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs index 62f50c8a0df90..6abe3602abee7 100644 --- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.rs @@ -1,16 +1,12 @@ //@ check-pass -#![warn(unused_imports)] +#![warn(redundant_imports)] -use std::option::Option::Some; -//FIXME(unused_imports): ~^ WARNING the item `Some` is imported redundantly -use std::option::Option::None; -//FIXME(unused_imports): ~ WARNING the item `None` is imported redundantly +use std::option::Option::Some;//~ WARNING the item `Some` is imported redundantly +use std::option::Option::None; //~ WARNING the item `None` is imported redundantly -use std::result::Result::Ok; -//FIXME(unused_imports): ~^ WARNING the item `Ok` is imported redundantly -use std::result::Result::Err; -//FIXME(unused_imports): ~^ WARNING the item `Err` is imported redundantly +use std::result::Result::Ok;//~ WARNING the item `Ok` is imported redundantly +use std::result::Result::Err;//~ WARNING the item `Err` is imported redundantly use std::convert::{TryFrom, TryInto}; fn main() { diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr new file mode 100644 index 0000000000000..2b0e16a87dc06 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr @@ -0,0 +1,44 @@ +warning: the item `Some` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2015.rs:5:5 + | +LL | use std::option::Option::Some; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Some` is already defined here + | +note: the lint level is defined here + --> $DIR/use-redundant-prelude-rust-2015.rs:2:9 + | +LL | #![warn(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +warning: the item `None` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2015.rs:6:5 + | +LL | use std::option::Option::None; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `None` is already defined here + +warning: the item `Ok` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2015.rs:8:5 + | +LL | use std::result::Result::Ok; + | ^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Ok` is already defined here + +warning: the item `Err` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2015.rs:9:5 + | +LL | use std::result::Result::Err; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `Err` is already defined here + +warning: 4 warnings emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs index 1baa1ac1b8cd3..236ee032b677b 100644 --- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.rs @@ -1,11 +1,9 @@ //@ check-pass //@ edition:2021 -#![warn(unused_imports)] +#![warn(redundant_imports)] -use std::convert::TryFrom; -//FIXME(unused_imports): ~^ WARNING the item `TryFrom` is imported redundantly -use std::convert::TryInto; -//FIXME(unused_imports): ~^ WARNING the item `TryInto` is imported redundantly +use std::convert::TryFrom;//~ WARNING the item `TryFrom` is imported redundantly +use std::convert::TryInto;//~ WARNING the item `TryInto` is imported redundantly fn main() { let _e: Result = 8u8.try_into(); diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr new file mode 100644 index 0000000000000..526771c597aa7 --- /dev/null +++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr @@ -0,0 +1,26 @@ +warning: the item `TryFrom` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2021.rs:5:5 + | +LL | use std::convert::TryFrom; + | ^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryFrom` is already defined here + | +note: the lint level is defined here + --> $DIR/use-redundant-prelude-rust-2021.rs:3:9 + | +LL | #![warn(redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +warning: the item `TryInto` is imported redundantly + --> $DIR/use-redundant-prelude-rust-2021.rs:6:5 + | +LL | use std::convert::TryInto; + | ^^^^^^^^^^^^^^^^^^^^^ + --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL + | + = note: the item `TryInto` is already defined here + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/use-redundant/use-redundant.rs b/tests/ui/lint/use-redundant/use-redundant.rs index 9e4902af34b7d..0efed378f988b 100644 --- a/tests/ui/lint/use-redundant/use-redundant.rs +++ b/tests/ui/lint/use-redundant/use-redundant.rs @@ -1,5 +1,5 @@ //@ check-pass -#![warn(unused_imports)] +#![warn(unused_imports, redundant_imports)] use crate::foo::Bar; @@ -18,7 +18,7 @@ use m1::*; //~ WARNING unused import use m2::*; //~ WARNING unused import fn main() { - use crate::foo::Bar; //FIXME(unused_imports): ~ WARNING imported redundantly + use crate::foo::Bar; //~ WARNING imported redundantly let _a: Bar = 3; baz(); diff --git a/tests/ui/lint/use-redundant/use-redundant.stderr b/tests/ui/lint/use-redundant/use-redundant.stderr index 224e841123748..76846a1dca98d 100644 --- a/tests/ui/lint/use-redundant/use-redundant.stderr +++ b/tests/ui/lint/use-redundant/use-redundant.stderr @@ -7,7 +7,7 @@ LL | use m1::*; note: the lint level is defined here --> $DIR/use-redundant.rs:2:9 | -LL | #![warn(unused_imports)] +LL | #![warn(unused_imports, redundant_imports)] | ^^^^^^^^^^^^^^ warning: unused import: `m2::*` @@ -16,5 +16,20 @@ warning: unused import: `m2::*` LL | use m2::*; | ^^^^^ -warning: 2 warnings emitted +warning: the item `Bar` is imported redundantly + --> $DIR/use-redundant.rs:21:9 + | +LL | use crate::foo::Bar; + | --------------- the item `Bar` is already imported here +... +LL | use crate::foo::Bar; + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/use-redundant.rs:2:25 + | +LL | #![warn(unused_imports, redundant_imports)] + | ^^^^^^^^^^^^^^^^^ + +warning: 3 warnings emitted From 6f48edfd09df68e981fa6023cdc36b68b966c4f5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 31 Jul 2024 07:53:11 +0200 Subject: [PATCH 317/489] FD table: rename dup to get_ref --- src/tools/miri/src/shims/unix/fd.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index ba17a53933b52..464b4638c6337 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -294,7 +294,7 @@ impl FdTable { Some(fd.borrow_mut()) } - pub fn dup(&self, fd: i32) -> Option { + pub fn get_ref(&self, fd: i32) -> Option { let fd = self.fds.get(&fd)?; Some(fd.clone()) } @@ -313,7 +313,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(dup_fd) = this.machine.fds.dup(old_fd) else { + let Some(dup_fd) = this.machine.fds.get_ref(old_fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, 0))) @@ -322,7 +322,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let Some(dup_fd) = this.machine.fds.dup(old_fd) else { + let Some(dup_fd) = this.machine.fds.get_ref(old_fd) else { return Ok(Scalar::from_i32(this.fd_not_found()?)); }; if new_fd != old_fd { @@ -408,7 +408,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let start = this.read_scalar(&args[2])?.to_i32()?; - match this.machine.fds.dup(fd) { + match this.machine.fds.get_ref(fd) { Some(dup_fd) => Ok(Scalar::from_i32(this.machine.fds.insert_ref_with_min_fd(dup_fd, start))), None => Ok(Scalar::from_i32(this.fd_not_found()?)), @@ -481,7 +481,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let communicate = this.machine.communicate(); // We temporarily dup the FD to be able to retain mutable access to `this`. - let Some(fd) = this.machine.fds.dup(fd) else { + let Some(fd) = this.machine.fds.get_ref(fd) else { trace!("read: FD not found"); return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; @@ -546,7 +546,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned(); // We temporarily dup the FD to be able to retain mutable access to `this`. - let Some(fd) = this.machine.fds.dup(fd) else { + let Some(fd) = this.machine.fds.get_ref(fd) else { return Ok(Scalar::from_target_isize(this.fd_not_found()?, this)); }; From a2b3256374014947a5a8e6ded86527fe44dd79ea Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 30 Jul 2024 17:28:37 +1000 Subject: [PATCH 318/489] Print `thir::PatRange`, not its surrounding `thir::Pat` This further reduces the amount of code that relies on `thir::Pat` being printable. --- compiler/rustc_pattern_analysis/src/rustc.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 126e5357cd8b9..135017208589c 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1003,12 +1003,11 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { } // `pat` is an exclusive range like `lo..gap`. `gapped_with` contains ranges that start with // `gap+1`. - let suggested_range: thir::Pat<'_> = { + let suggested_range: String = { // Suggest `lo..=gap` instead. - let mut suggested_range = thir_pat.clone(); - let thir::PatKind::Range(range) = &mut suggested_range.kind else { unreachable!() }; - range.end = rustc_hir::RangeEnd::Included; - suggested_range + let mut suggested_range = PatRange::clone(range); + suggested_range.end = rustc_hir::RangeEnd::Included; + suggested_range.to_string() }; let gap_as_pat = self.hoist_pat_range(&gap, *pat.ty()); if gapped_with.is_empty() { @@ -1023,7 +1022,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { // That's the gap that isn't covered. max: gap_as_pat.to_string(), // Suggest `lo..=max` instead. - suggestion: suggested_range.to_string(), + suggestion: suggested_range, }, ); } else { @@ -1037,7 +1036,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { // That's the gap that isn't covered. gap: gap_as_pat.to_string(), // Suggest `lo..=gap` instead. - suggestion: suggested_range.to_string(), + suggestion: suggested_range, // All these ranges skipped over `gap` which we think is probably a // mistake. gap_with: gapped_with @@ -1045,7 +1044,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { .map(|pat| errors::GappedRange { span: pat.data().span, gap: gap_as_pat.to_string(), - first_range: thir_pat.to_string(), + first_range: range.to_string(), }) .collect(), }, From a9ea85e04422345020be7dfb7e655c911d458e6c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 30 Jul 2024 22:36:17 +1000 Subject: [PATCH 319/489] Revert "Make `thir::Pat` not implement `fmt::Display` directly" This reverts commit ae0ec731a86ac6a2f6d8d08c4996bb8a438afdc2. The original change in #128304 was intended to be a step towards being able to print `thir::Pat` even after switching to `PatId`. But because the only patterns that need to be printed are the synthetic ones created by pattern analysis (for diagnostic purposes only), it makes more sense to completely separate the printable patterns from the real THIR patterns. --- compiler/rustc_middle/src/thir.rs | 65 +++++++++---------------------- 1 file changed, 19 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 690c0121b2b36..33bc69fbc92dd 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -1073,33 +1073,8 @@ impl<'tcx> PatRangeBoundary<'tcx> { } } -impl<'tcx> Pat<'tcx> { - /// Prints a [`Pat`] to an owned string, for user-facing diagnostics. - /// - /// If we ever switch over to storing subpatterns as `PatId`, this will also - /// need to take a context that can resolve IDs to subpatterns. - pub fn to_string(&self) -> String { - format!("{}", self.display()) - } - - /// Used internally by [`fmt::Display`] for [`PatDisplay`]. - fn display(&self) -> PatDisplay<'_, 'tcx> { - PatDisplay { pat: self } - } -} - -/// Wrapper around [`&Pat<'tcx>`][`Pat`] that implements [`fmt::Display`]. -/// -/// If we ever switch over to storing subpatterns as `PatId`, this will also -/// need to hold a context that can resolve IDs to subpatterns. -struct PatDisplay<'pat, 'tcx> { - pat: &'pat Pat<'tcx>, -} - -impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> { +impl<'tcx> fmt::Display for Pat<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let &Self { pat } = self; - // Printing lists is a chore. let mut first = true; let mut start_or_continue = |s| { @@ -1112,22 +1087,20 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> { }; let mut start_or_comma = || start_or_continue(", "); - match pat.kind { + match self.kind { PatKind::Wild => write!(f, "_"), PatKind::Never => write!(f, "!"), - PatKind::AscribeUserType { ref subpattern, .. } => { - write!(f, "{}: _", subpattern.display()) - } + PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"), PatKind::Binding { name, mode, ref subpattern, .. } => { f.write_str(mode.prefix_str())?; write!(f, "{name}")?; if let Some(ref subpattern) = *subpattern { - write!(f, " @ {}", subpattern.display())?; + write!(f, " @ {subpattern}")?; } Ok(()) } PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => { - let variant_and_name = match pat.kind { + let variant_and_name = match self.kind { PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| { let variant = adt_def.variant(variant_index); let adt_did = adt_def.did(); @@ -1140,7 +1113,7 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> { }; Some((variant, name)) }), - _ => pat.ty.ty_adt_def().and_then(|adt_def| { + _ => self.ty.ty_adt_def().and_then(|adt_def| { if !adt_def.is_enum() { ty::tls::with(|tcx| { Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did()))) @@ -1165,11 +1138,11 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> { continue; } let name = variant.fields[p.field].name; - write!(f, "{}{}: {}", start_or_comma(), name, p.pattern.display())?; + write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?; printed += 1; } - let is_union = pat.ty.ty_adt_def().is_some_and(|adt| adt.is_union()); + let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union()); if printed < variant.fields.len() && (!is_union || printed == 0) { write!(f, "{}..", start_or_comma())?; } @@ -1188,14 +1161,14 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> { // Common case: the field is where we expect it. if let Some(p) = subpatterns.get(i) { if p.field.index() == i { - write!(f, "{}", p.pattern.display())?; + write!(f, "{}", p.pattern)?; continue; } } // Otherwise, we have to go looking for it. if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) { - write!(f, "{}", p.pattern.display())?; + write!(f, "{}", p.pattern)?; } else { write!(f, "_")?; } @@ -1206,45 +1179,45 @@ impl<'pat, 'tcx> fmt::Display for PatDisplay<'pat, 'tcx> { Ok(()) } PatKind::Deref { ref subpattern } => { - match pat.ty.kind() { + match self.ty.kind() { ty::Adt(def, _) if def.is_box() => write!(f, "box ")?, ty::Ref(_, _, mutbl) => { write!(f, "&{}", mutbl.prefix_str())?; } - _ => bug!("{} is a bad Deref pattern type", pat.ty), + _ => bug!("{} is a bad Deref pattern type", self.ty), } - write!(f, "{}", subpattern.display()) + write!(f, "{subpattern}") } PatKind::DerefPattern { ref subpattern, .. } => { - write!(f, "deref!({})", subpattern.display()) + write!(f, "deref!({subpattern})") } PatKind::Constant { value } => write!(f, "{value}"), PatKind::InlineConstant { def: _, ref subpattern } => { - write!(f, "{} (from inline const)", subpattern.display()) + write!(f, "{} (from inline const)", subpattern) } PatKind::Range(ref range) => write!(f, "{range}"), PatKind::Slice { ref prefix, ref slice, ref suffix } | PatKind::Array { ref prefix, ref slice, ref suffix } => { write!(f, "[")?; for p in prefix.iter() { - write!(f, "{}{}", start_or_comma(), p.display())?; + write!(f, "{}{}", start_or_comma(), p)?; } if let Some(ref slice) = *slice { write!(f, "{}", start_or_comma())?; match slice.kind { PatKind::Wild => {} - _ => write!(f, "{}", slice.display())?, + _ => write!(f, "{slice}")?, } write!(f, "..")?; } for p in suffix.iter() { - write!(f, "{}{}", start_or_comma(), p.display())?; + write!(f, "{}{}", start_or_comma(), p)?; } write!(f, "]") } PatKind::Or { ref pats } => { for pat in pats.iter() { - write!(f, "{}{}", start_or_continue(" | "), pat.display())?; + write!(f, "{}{}", start_or_continue(" | "), pat)?; } Ok(()) } From dd5a8d77142562250c4780b0b8b228a0c557498e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 30 Jul 2024 22:44:02 +1000 Subject: [PATCH 320/489] Use a separate pattern type for `rustc_pattern_analysis` diagnostics The pattern-analysis code needs to print patterns, as part of its user-visible diagnostics. But it never actually tries to print "real" patterns! Instead, it only ever prints synthetic patterns that it has reconstructed from its own internal represenations. We can therefore simultaneously remove two obstacles to changing `thir::Pat`, by having the pattern-analysis code use its own dedicated type for building printable patterns, and then making `thir::Pat` not printable at all. --- compiler/rustc_middle/src/thir.rs | 159 +-------------- compiler/rustc_pattern_analysis/src/rustc.rs | 26 ++- .../rustc_pattern_analysis/src/rustc/print.rs | 193 ++++++++++++++++++ 3 files changed, 209 insertions(+), 169 deletions(-) create mode 100644 compiler/rustc_pattern_analysis/src/rustc/print.rs diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 33bc69fbc92dd..f2ea32275f9b1 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -28,7 +28,7 @@ use rustc_middle::ty::{ TyCtxt, UpvarArgs, }; use rustc_span::def_id::LocalDefId; -use rustc_span::{sym, ErrorGuaranteed, Span, Symbol, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, Span, Symbol}; use rustc_target::abi::{FieldIdx, Integer, Size, VariantIdx}; use rustc_target::asm::InlineAsmRegOrRegClass; use tracing::instrument; @@ -597,10 +597,6 @@ pub struct Pat<'tcx> { } impl<'tcx> Pat<'tcx> { - pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self { - Pat { ty, span: DUMMY_SP, kind: PatKind::Wild } - } - pub fn simple_ident(&self) -> Option { match self.kind { PatKind::Binding { @@ -1073,159 +1069,6 @@ impl<'tcx> PatRangeBoundary<'tcx> { } } -impl<'tcx> fmt::Display for Pat<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Printing lists is a chore. - let mut first = true; - let mut start_or_continue = |s| { - if first { - first = false; - "" - } else { - s - } - }; - let mut start_or_comma = || start_or_continue(", "); - - match self.kind { - PatKind::Wild => write!(f, "_"), - PatKind::Never => write!(f, "!"), - PatKind::AscribeUserType { ref subpattern, .. } => write!(f, "{subpattern}: _"), - PatKind::Binding { name, mode, ref subpattern, .. } => { - f.write_str(mode.prefix_str())?; - write!(f, "{name}")?; - if let Some(ref subpattern) = *subpattern { - write!(f, " @ {subpattern}")?; - } - Ok(()) - } - PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => { - let variant_and_name = match self.kind { - PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| { - let variant = adt_def.variant(variant_index); - let adt_did = adt_def.did(); - let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did) - || tcx.get_diagnostic_item(sym::Result) == Some(adt_did) - { - variant.name.to_string() - } else { - format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name) - }; - Some((variant, name)) - }), - _ => self.ty.ty_adt_def().and_then(|adt_def| { - if !adt_def.is_enum() { - ty::tls::with(|tcx| { - Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did()))) - }) - } else { - None - } - }), - }; - - if let Some((variant, name)) = &variant_and_name { - write!(f, "{name}")?; - - // Only for Adt we can have `S {...}`, - // which we handle separately here. - if variant.ctor.is_none() { - write!(f, " {{ ")?; - - let mut printed = 0; - for p in subpatterns { - if let PatKind::Wild = p.pattern.kind { - continue; - } - let name = variant.fields[p.field].name; - write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?; - printed += 1; - } - - let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union()); - if printed < variant.fields.len() && (!is_union || printed == 0) { - write!(f, "{}..", start_or_comma())?; - } - - return write!(f, " }}"); - } - } - - let num_fields = - variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len()); - if num_fields != 0 || variant_and_name.is_none() { - write!(f, "(")?; - for i in 0..num_fields { - write!(f, "{}", start_or_comma())?; - - // Common case: the field is where we expect it. - if let Some(p) = subpatterns.get(i) { - if p.field.index() == i { - write!(f, "{}", p.pattern)?; - continue; - } - } - - // Otherwise, we have to go looking for it. - if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) { - write!(f, "{}", p.pattern)?; - } else { - write!(f, "_")?; - } - } - write!(f, ")")?; - } - - Ok(()) - } - PatKind::Deref { ref subpattern } => { - match self.ty.kind() { - ty::Adt(def, _) if def.is_box() => write!(f, "box ")?, - ty::Ref(_, _, mutbl) => { - write!(f, "&{}", mutbl.prefix_str())?; - } - _ => bug!("{} is a bad Deref pattern type", self.ty), - } - write!(f, "{subpattern}") - } - PatKind::DerefPattern { ref subpattern, .. } => { - write!(f, "deref!({subpattern})") - } - PatKind::Constant { value } => write!(f, "{value}"), - PatKind::InlineConstant { def: _, ref subpattern } => { - write!(f, "{} (from inline const)", subpattern) - } - PatKind::Range(ref range) => write!(f, "{range}"), - PatKind::Slice { ref prefix, ref slice, ref suffix } - | PatKind::Array { ref prefix, ref slice, ref suffix } => { - write!(f, "[")?; - for p in prefix.iter() { - write!(f, "{}{}", start_or_comma(), p)?; - } - if let Some(ref slice) = *slice { - write!(f, "{}", start_or_comma())?; - match slice.kind { - PatKind::Wild => {} - _ => write!(f, "{slice}")?, - } - write!(f, "..")?; - } - for p in suffix.iter() { - write!(f, "{}{}", start_or_comma(), p)?; - } - write!(f, "]") - } - PatKind::Or { ref pats } => { - for pat in pats.iter() { - write!(f, "{}{}", start_or_continue(" | "), pat)?; - } - Ok(()) - } - PatKind::Error(_) => write!(f, ""), - } - } -} - // Some nodes are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 135017208589c..6290aeb252312 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -7,7 +7,7 @@ use rustc_hir::HirId; use rustc_index::{Idx, IndexVec}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::mir::{self, Const}; -use rustc_middle::thir::{self, FieldPat, Pat, PatKind, PatRange, PatRangeBoundary}; +use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, @@ -26,6 +26,8 @@ use crate::pat_column::PatternColumn; use crate::usefulness::{compute_match_usefulness, PlaceValidity}; use crate::{errors, Captures, PatCx, PrivateUninhabitedField}; +mod print; + // Re-export rustc-specific versions of all these types. pub type Constructor<'p, 'tcx> = crate::constructor::Constructor>; pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet>; @@ -773,8 +775,9 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } } - /// Convert back to a `thir::Pat` for diagnostic purposes. - fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> Pat<'tcx> { + /// Convert to a [`print::Pat`] for diagnostic purposes. + fn hoist_pat_range(&self, range: &IntRange, ty: RevealedTy<'tcx>) -> print::Pat<'tcx> { + use print::{Pat, PatKind}; use MaybeInfiniteInt::*; let cx = self; let kind = if matches!((range.lo, range.hi), (NegInfinity, PosInfinity)) { @@ -808,19 +811,20 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { PatKind::Range(Box::new(PatRange { lo, hi, end, ty: ty.inner() })) }; - Pat { ty: ty.inner(), span: DUMMY_SP, kind } + Pat { ty: ty.inner(), kind } } /// Prints a [`WitnessPat`] to an owned string, for diagnostic purposes. pub fn print_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> String { - // This works by converting the witness pattern back to a `thir::Pat` + // This works by converting the witness pattern to a `print::Pat` // and then printing that, but callers don't need to know that. self.hoist_witness_pat(pat).to_string() } - /// Convert back to a `thir::Pat` for diagnostic purposes. This panics for patterns that don't + /// Convert to a [`print::Pat`] for diagnostic purposes. This panics for patterns that don't /// appear in diagnostics, like float ranges. - fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> Pat<'tcx> { + fn hoist_witness_pat(&self, pat: &WitnessPat<'p, 'tcx>) -> print::Pat<'tcx> { + use print::{FieldPat, Pat, PatKind}; let cx = self; let is_wildcard = |pat: &Pat<'_>| matches!(pat.kind, PatKind::Wild); let mut subpatterns = pat.iter_fields().map(|p| Box::new(cx.hoist_witness_pat(p))); @@ -840,7 +844,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { // the pattern is a box pattern. PatKind::Deref { subpattern: subpatterns.next().unwrap() } } - ty::Adt(adt_def, args) => { + ty::Adt(adt_def, _args) => { let variant_index = RustcPatCtxt::variant_index_for_adt(&pat.ctor(), *adt_def); let subpatterns = subpatterns .enumerate() @@ -848,7 +852,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { .collect(); if adt_def.is_enum() { - PatKind::Variant { adt_def: *adt_def, args, variant_index, subpatterns } + PatKind::Variant { adt_def: *adt_def, variant_index, subpatterns } } else { PatKind::Leaf { subpatterns } } @@ -885,7 +889,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } } let suffix: Box<[_]> = subpatterns.collect(); - let wild = Pat::wildcard_from_ty(pat.ty().inner()); + let wild = Pat { ty: pat.ty().inner(), kind: PatKind::Wild }; PatKind::Slice { prefix: prefix.into_boxed_slice(), slice: Some(Box::new(wild)), @@ -906,7 +910,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } }; - Pat { ty: pat.ty().inner(), span: DUMMY_SP, kind } + Pat { ty: pat.ty().inner(), kind } } } diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs new file mode 100644 index 0000000000000..4b76764e8b136 --- /dev/null +++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs @@ -0,0 +1,193 @@ +//! Pattern analysis sometimes wants to print patterns as part of a user-visible +//! diagnostic. +//! +//! Historically it did so by creating a synthetic [`thir::Pat`](rustc_middle::thir::Pat) +//! and printing that, but doing so was making it hard to modify the THIR pattern +//! representation for other purposes. +//! +//! So this module contains a forked copy of `thir::Pat` that is used _only_ +//! for diagnostics, and has been partly simplified to remove things that aren't +//! needed for printing. + +use std::fmt; + +use rustc_middle::thir::PatRange; +use rustc_middle::ty::{self, AdtDef, Ty}; +use rustc_middle::{bug, mir}; +use rustc_span::sym; +use rustc_target::abi::{FieldIdx, VariantIdx}; + +#[derive(Clone, Debug)] +pub(crate) struct FieldPat<'tcx> { + pub(crate) field: FieldIdx, + pub(crate) pattern: Box>, +} + +#[derive(Clone, Debug)] +pub(crate) struct Pat<'tcx> { + pub(crate) ty: Ty<'tcx>, + pub(crate) kind: PatKind<'tcx>, +} + +#[derive(Clone, Debug)] +pub(crate) enum PatKind<'tcx> { + Wild, + + Variant { + adt_def: AdtDef<'tcx>, + variant_index: VariantIdx, + subpatterns: Vec>, + }, + + Leaf { + subpatterns: Vec>, + }, + + Deref { + subpattern: Box>, + }, + + Constant { + value: mir::Const<'tcx>, + }, + + Range(Box>), + + Slice { + prefix: Box<[Box>]>, + slice: Option>>, + suffix: Box<[Box>]>, + }, + + Never, +} + +impl<'tcx> fmt::Display for Pat<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Printing lists is a chore. + let mut first = true; + let mut start_or_continue = |s| { + if first { + first = false; + "" + } else { + s + } + }; + let mut start_or_comma = || start_or_continue(", "); + + match self.kind { + PatKind::Wild => write!(f, "_"), + PatKind::Never => write!(f, "!"), + PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => { + let variant_and_name = match self.kind { + PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| { + let variant = adt_def.variant(variant_index); + let adt_did = adt_def.did(); + let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did) + || tcx.get_diagnostic_item(sym::Result) == Some(adt_did) + { + variant.name.to_string() + } else { + format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name) + }; + Some((variant, name)) + }), + _ => self.ty.ty_adt_def().and_then(|adt_def| { + if !adt_def.is_enum() { + ty::tls::with(|tcx| { + Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did()))) + }) + } else { + None + } + }), + }; + + if let Some((variant, name)) = &variant_and_name { + write!(f, "{name}")?; + + // Only for Adt we can have `S {...}`, + // which we handle separately here. + if variant.ctor.is_none() { + write!(f, " {{ ")?; + + let mut printed = 0; + for p in subpatterns { + if let PatKind::Wild = p.pattern.kind { + continue; + } + let name = variant.fields[p.field].name; + write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?; + printed += 1; + } + + let is_union = self.ty.ty_adt_def().is_some_and(|adt| adt.is_union()); + if printed < variant.fields.len() && (!is_union || printed == 0) { + write!(f, "{}..", start_or_comma())?; + } + + return write!(f, " }}"); + } + } + + let num_fields = + variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len()); + if num_fields != 0 || variant_and_name.is_none() { + write!(f, "(")?; + for i in 0..num_fields { + write!(f, "{}", start_or_comma())?; + + // Common case: the field is where we expect it. + if let Some(p) = subpatterns.get(i) { + if p.field.index() == i { + write!(f, "{}", p.pattern)?; + continue; + } + } + + // Otherwise, we have to go looking for it. + if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) { + write!(f, "{}", p.pattern)?; + } else { + write!(f, "_")?; + } + } + write!(f, ")")?; + } + + Ok(()) + } + PatKind::Deref { ref subpattern } => { + match self.ty.kind() { + ty::Adt(def, _) if def.is_box() => write!(f, "box ")?, + ty::Ref(_, _, mutbl) => { + write!(f, "&{}", mutbl.prefix_str())?; + } + _ => bug!("{} is a bad Deref pattern type", self.ty), + } + write!(f, "{subpattern}") + } + PatKind::Constant { value } => write!(f, "{value}"), + PatKind::Range(ref range) => write!(f, "{range}"), + PatKind::Slice { ref prefix, ref slice, ref suffix } => { + write!(f, "[")?; + for p in prefix.iter() { + write!(f, "{}{}", start_or_comma(), p)?; + } + if let Some(ref slice) = *slice { + write!(f, "{}", start_or_comma())?; + match slice.kind { + PatKind::Wild => {} + _ => write!(f, "{slice}")?, + } + write!(f, "..")?; + } + for p in suffix.iter() { + write!(f, "{}{}", start_or_comma(), p)?; + } + write!(f, "]") + } + } + } +} From 76b4a86b571408ba2f99e047e9f5972ae682cb99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 31 Jul 2024 12:39:23 +0200 Subject: [PATCH 321/489] refactor(pal/hermit): return `!` to satisfy rust-analyzer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This silences this rust-analyzer-specific error: `expected !, found ()` Signed-off-by: Martin Kröning --- library/std/src/sys/pal/hermit/mod.rs | 6 ++---- library/std/src/sys/pal/hermit/os.rs | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 55583b89d6714..2c9aeb480445c 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -49,9 +49,7 @@ pub fn unsupported_err() -> crate::io::Error { } pub fn abort_internal() -> ! { - unsafe { - hermit_abi::abort(); - } + unsafe { hermit_abi::abort() } } pub fn hashmap_random_keys() -> (u64, u64) { @@ -104,7 +102,7 @@ pub unsafe extern "C" fn runtime_entry( let result = main(argc as isize, argv); crate::sys::thread_local::destructors::run(); - hermit_abi::exit(result); + hermit_abi::exit(result) } #[inline] diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index 9631dac658c9c..50ce2f57b306e 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -190,9 +190,7 @@ pub fn home_dir() -> Option { } pub fn exit(code: i32) -> ! { - unsafe { - hermit_abi::exit(code); - } + unsafe { hermit_abi::exit(code) } } pub fn getpid() -> u32 { From 127b469b7eb3eb924bbe4551c968c14a10af6c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 31 Jul 2024 12:56:38 +0200 Subject: [PATCH 322/489] refactor(pal/hermit): use default impl of `GlobalAlloc::alloc_zeroed` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- library/std/src/sys/pal/hermit/alloc.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/library/std/src/sys/pal/hermit/alloc.rs b/library/std/src/sys/pal/hermit/alloc.rs index 2cd0db909403b..5daa5f9e49ffe 100644 --- a/library/std/src/sys/pal/hermit/alloc.rs +++ b/library/std/src/sys/pal/hermit/alloc.rs @@ -9,16 +9,6 @@ unsafe impl GlobalAlloc for System { hermit_abi::malloc(layout.size(), layout.align()) } - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - let addr = hermit_abi::malloc(layout.size(), layout.align()); - - if !addr.is_null() { - ptr::write_bytes(addr, 0x00, layout.size()); - } - - addr - } - #[inline] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { hermit_abi::free(ptr, layout.size(), layout.align()) From 34fcf92ea003e401606552907516d08f1c3b94da Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Wed, 31 Jul 2024 15:55:56 +0300 Subject: [PATCH 323/489] Add special-case for [T, 0] in dropck --- .../src/traits/query/dropck_outlives.rs | 11 +++++++-- tests/ui/dropck/dropck-empty-array.rs | 23 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/ui/dropck/dropck-empty-array.rs diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 37a16a43acdeb..d3a1ed52d2e62 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -42,8 +42,15 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Foreign(..) | ty::Error(_) => true, - // `T is PAT`, `[T; N]`, and `[T]` have same properties as T. - ty::Pat(ty, _) | ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty), + // `T is PAT` and `[T]` have same properties as T. + ty::Pat(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty), + ty::Array(ty, size) => { + // Empty array never has a dtor. See issue #110288. + match size.try_to_target_usize(tcx) { + Some(0) => true, + _ => trivial_dropck_outlives(tcx, *ty), + } + } // (T1..Tn) and closures have same properties as T1..Tn -- // check if *all* of them are trivial. diff --git a/tests/ui/dropck/dropck-empty-array.rs b/tests/ui/dropck/dropck-empty-array.rs new file mode 100644 index 0000000000000..f3eca6aed8d5e --- /dev/null +++ b/tests/ui/dropck/dropck-empty-array.rs @@ -0,0 +1,23 @@ +//@ run-pass + +#[allow(dead_code)] +struct Struct<'s>(&'s str); + +impl<'s> Drop for Struct<'s> { + fn drop(&mut self) {} +} + +fn to_array_zero(_: T) -> [T; 0] { + [] +} + +pub fn array_zero_in_tuple() { + let mut x = ([], String::new()); + { + let s = String::from("temporary"); + let p = Struct(&s); + x.0 = to_array_zero(p); + } +} + +fn main() {} From e84a7d91b7b618fe5bb8d3c0face3384c768fb2c Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 31 Jul 2024 13:45:14 +0000 Subject: [PATCH 324/489] Remove unneeded `pub(crate)` --- library/std/src/sys/anonymous_pipe/unsupported.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/anonymous_pipe/unsupported.rs b/library/std/src/sys/anonymous_pipe/unsupported.rs index da04e8e6b25af..dd51e70315e96 100644 --- a/library/std/src/sys/anonymous_pipe/unsupported.rs +++ b/library/std/src/sys/anonymous_pipe/unsupported.rs @@ -1,7 +1,7 @@ use crate::io; use crate::pipe::{PipeReader, PipeWriter}; use crate::process::Stdio; -pub(crate) use crate::sys::pipe::AnonPipe; +pub use crate::sys::pipe::AnonPipe; #[inline] pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { From 62d4998753ecf0f88105733b03152ef94deaee71 Mon Sep 17 00:00:00 2001 From: B I Mohammed Abbas Date: Wed, 31 Jul 2024 19:28:18 +0530 Subject: [PATCH 325/489] Add VxWorks platfrom support documents --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 12 ++--- src/doc/rustc/src/platform-support/vxworks.md | 51 +++++++++++++++++++ 3 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 src/doc/rustc/src/platform-support/vxworks.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 292b6032f8493..08460af15d4c7 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -74,6 +74,7 @@ - [*-unknown-openbsd](platform-support/openbsd.md) - [*-unknown-redox](platform-support/redox.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) + - [\*-wrs-vxworks](platform-support/vxworks.md) - [wasm32-wasip1](platform-support/wasm32-wasip1.md) - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md) - [wasm32-wasip2](platform-support/wasm32-wasip2.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 0c7f4e7bf1b43..cbb338f481172 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -263,7 +263,7 @@ target | std | host | notes [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD [`aarch64-unknown-redox`](platform-support/redox.md) | ✓ | | ARM64 Redox OS `aarch64-uwp-windows-msvc` | ✓ | | -`aarch64-wrs-vxworks` | ? | | +[`aarch64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | ARM64 VxWorks OS `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian) [`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian) @@ -281,7 +281,7 @@ target | std | host | notes [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat `armv7-unknown-freebsd` | ✓ | ✓ | Armv7-A FreeBSD [`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv7-A NetBSD w/hard-float -`armv7-wrs-vxworks-eabihf` | ? | | Armv7-A for VxWorks +[`armv7-wrs-vxworks-eabihf`](platform-support/vxworks.md) | ? | | Armv7-A for VxWorks [`armv7a-kmc-solid_asp3-eabi`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3 [`armv7a-kmc-solid_asp3-eabihf`](platform-support/kmc-solid.md) | ✓ | | ARM SOLID with TOPPERS/ASP3, hardfloat [`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * | | Bare Armv7-A, hardfloat @@ -307,7 +307,7 @@ target | std | host | notes `i686-uwp-windows-gnu` | ✓ | | [^x86_32-floats-return-ABI] `i686-uwp-windows-msvc` | ✓ | | [^x86_32-floats-return-ABI] [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI] -`i686-wrs-vxworks` | ? | | [^x86_32-floats-return-ABI] +[`i686-wrs-vxworks`](platform-support/vxworks.md) | ? | | [^x86_32-floats-return-ABI] [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) `mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl 1.2.3 @@ -333,8 +333,8 @@ target | std | host | notes `powerpc-unknown-linux-musl` | ? | | PowerPC Linux with musl 1.2.3 [`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems [`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | | -`powerpc-wrs-vxworks-spe` | ? | | -`powerpc-wrs-vxworks` | ? | | +[`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ? | | +[`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ? | | `powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2) `powerpc64le-unknown-freebsd` | | | PPC64LE FreeBSD `powerpc-unknown-freebsd` | | | PowerPC FreeBSD @@ -383,7 +383,7 @@ target | std | host | notes `x86_64-uwp-windows-gnu` | ✓ | | `x86_64-uwp-windows-msvc` | ✓ | | [`x86_64-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 64-bit Windows 7 support -`x86_64-wrs-vxworks` | ? | | +[`x86_64-wrs-vxworks`](platform-support/vxworks.md) | ? | | [`x86_64h-apple-darwin`](platform-support/x86_64h-apple-darwin.md) | ✓ | ✓ | macOS with late-gen Intel (at least Haswell) [`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * | | 64-bit Linux with no libc [`xtensa-esp32-none-elf`](platform-support/xtensa.md) | * | | Xtensa ESP32 diff --git a/src/doc/rustc/src/platform-support/vxworks.md b/src/doc/rustc/src/platform-support/vxworks.md new file mode 100644 index 0000000000000..c0a818558e0bf --- /dev/null +++ b/src/doc/rustc/src/platform-support/vxworks.md @@ -0,0 +1,51 @@ +# `*-wrs-vxworks` + +**Tier: 3** + +Targets for the VxWorks operating +system. + +Target triplets available: + +- `x86_64-wrs-vxworks` +- `aarch64-wrs-vxworks` +- `i686-wrs-vxworks` +- `armv7-wrs-vxworks-eabihf` +- `powerpc-wrs-vxworks` +- `powerpc-wrs-vxworks-spe` + +## Target maintainers + +- B I Mohammed Abbas ([@biabbas](https://github.com/biabbas)) + +## Requirements + +Rust for each target can be cross-compiled with its specific target vsb configuration. Std support is added but not yet fully tested. + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`. In addition the workbench and wr-cc have to configured and activated. + +```toml +[build] +build-stage = 1 +target = [ + "", + "x86_64-wrs-vxworks", + "aarch64-wrs-vxworks", + "i686-wrs-vxworks", + "armv7-wrs-vxworks-eabihf", + "powerpc-wrs-vxworks", + "powerpc-wrs-vxworks-spe", +] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for VxWorks. + +The easiest way to build and test programs for VxWorks is to use the shipped rustc and cargo in VxWorks workbench, following the official windriver guidelines. + +## Cross-compilation toolchains and C code + +The target supports C code. Pre-compiled C toolchains can be found in provided VxWorks workbench. From e8a90513de81c26eded9a18aacbed3c8c72b62af Mon Sep 17 00:00:00 2001 From: David Barsky Date: Wed, 31 Jul 2024 10:07:48 -0400 Subject: [PATCH 326/489] fix: remove AbsPath requirement from linkedProjects --- .../crates/rust-analyzer/src/config.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 8743c4faff691..2b29be7fa28c6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -1677,7 +1677,7 @@ impl Config { !self.linkedProjects(None).is_empty() } - pub fn linked_manifests(&self) -> impl Iterator + '_ { + pub fn linked_manifests(&self) -> impl Iterator + '_ { self.linkedProjects(None).iter().filter_map(|it| match it { ManifestOrProjectJson::Manifest(p) => Some(&**p), // despite having a buildfile, using this variant as a manifest @@ -2273,11 +2273,7 @@ mod single_or_array { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[serde(untagged)] enum ManifestOrProjectJson { - Manifest( - #[serde(serialize_with = "serialize_abs_pathbuf")] - #[serde(deserialize_with = "deserialize_abs_pathbuf")] - AbsPathBuf, - ), + Manifest(Utf8PathBuf), ProjectJson(ProjectJsonData), DiscoveredProjectJson { data: ProjectJsonData, @@ -2306,10 +2302,12 @@ where } impl ManifestOrProjectJson { - fn manifest(&self) -> Option<&AbsPath> { + fn manifest(&self) -> Option<&Utf8Path> { match self { ManifestOrProjectJson::Manifest(manifest) => Some(manifest), - ManifestOrProjectJson::DiscoveredProjectJson { buildfile, .. } => Some(buildfile), + ManifestOrProjectJson::DiscoveredProjectJson { buildfile, .. } => { + Some(buildfile.as_ref()) + } ManifestOrProjectJson::ProjectJson(_) => None, } } From ea04b0afbf3e5346c2df015b9c59ff1b0b3bc270 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 30 Jul 2024 13:07:49 -0400 Subject: [PATCH 327/489] use llvm-nm in symbol-visibility rmake test --- .../src/external_deps/llvm.rs | 30 +++++++++++++++++++ src/tools/run-make-support/src/lib.rs | 4 +-- tests/run-make/symbol-visibility/rmake.rs | 29 ++++++++++++------ 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index b116bd08e3a6c..259bb6159461b 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -36,6 +36,12 @@ pub fn llvm_ar() -> LlvmAr { LlvmAr::new() } +/// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available +/// at `$LLVM_BIN_DIR/llvm-nm`. +pub fn llvm_nm() -> LlvmNm { + LlvmNm::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] @@ -71,11 +77,19 @@ pub struct LlvmAr { cmd: Command, } +/// A `llvm-nm` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmNm { + cmd: Command, +} + crate::macros::impl_common_helpers!(LlvmReadobj); crate::macros::impl_common_helpers!(LlvmProfdata); crate::macros::impl_common_helpers!(LlvmFilecheck); crate::macros::impl_common_helpers!(LlvmObjdump); crate::macros::impl_common_helpers!(LlvmAr); +crate::macros::impl_common_helpers!(LlvmNm); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -244,3 +258,19 @@ impl LlvmAr { self } } + +impl LlvmNm { + /// Construct a new `llvm-nm` invocation. This assumes that `llvm-nm` is available + /// at `$LLVM_BIN_DIR/llvm-nm`. + pub fn new() -> Self { + let llvm_nm = llvm_bin_dir().join("llvm-nm"); + let cmd = Command::new(llvm_nm); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 085120764b463..9ced61932585c 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -48,8 +48,8 @@ pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ - llvm_ar, llvm_filecheck, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, LlvmFilecheck, - LlvmObjdump, LlvmProfdata, LlvmReadobj, + llvm_ar, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, + LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, }; pub use python::python_command; pub use rustc::{aux_build, bare_rustc, rustc, Rustc}; diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs index cd085cf05d0ed..b37ff44f4ead6 100644 --- a/tests/run-make/symbol-visibility/rmake.rs +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -6,13 +6,16 @@ //@ ignore-windows-msvc -use run_make_support::{bin_name, dynamic_lib_name, is_windows, llvm_readobj, regex, rustc}; +//FIXME(Oneirical): This currently uses llvm-nm for symbol detection. However, +// the custom Rust-based solution of #128314 may prove to be an interesting alternative. + +use run_make_support::{bin_name, dynamic_lib_name, is_darwin, is_windows, llvm_nm, regex, rustc}; fn main() { - let mut cdylib_name = dynamic_lib_name("a_cdylib"); - let mut rdylib_name = dynamic_lib_name("a_rust_dylib"); + let cdylib_name = dynamic_lib_name("a_cdylib"); + let rdylib_name = dynamic_lib_name("a_rust_dylib"); let exe_name = bin_name("an_executable"); - let mut combined_cdylib_name = dynamic_lib_name("combined_rlib_dylib"); + let combined_cdylib_name = dynamic_lib_name("combined_rlib_dylib"); rustc().arg("-Zshare-generics=no").input("an_rlib.rs").run(); rustc().arg("-Zshare-generics=no").input("a_cdylib.rs").run(); rustc().arg("-Zshare-generics=no").input("a_rust_dylib.rs").run(); @@ -74,13 +77,13 @@ fn main() { // Check the combined case, where we generate a cdylib and an rlib in the same // compilation session: - // Check that a cdylib exports its public //[no_mangle] functions + // Check that a cdylib exports its public #[no_mangle] functions symbols_check( &combined_cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true, ); - // Check that a cdylib exports the public //[no_mangle] functions of dependencies + // Check that a cdylib exports the public #[no_mangle] functions of dependencies symbols_check( &combined_cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), @@ -94,9 +97,9 @@ fn main() { rustc().arg("-Zshare-generics=yes").input("a_rust_dylib.rs").run(); rustc().arg("-Zshare-generics=yes").input("an_executable.rs").run(); - // Check that a cdylib exports its public //[no_mangle] functions + // Check that a cdylib exports its public #[no_mangle] functions symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true); - // Check that a cdylib exports the public //[no_mangle] functions of dependencies + // Check that a cdylib exports the public #[no_mangle] functions of dependencies symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true); // Check that a cdylib DOES NOT export any public Rust functions symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false); @@ -142,7 +145,15 @@ fn main() { #[track_caller] fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) { - let out = llvm_readobj().arg("--dyn-symbols").input(path).run().invalid_stdout_utf8(); + let mut nm = llvm_nm(); + if is_windows() { + nm.arg("--extern-only"); + } else if is_darwin() { + nm.arg("--extern-only").arg("--defined-only"); + } else { + nm.arg("--dynamic"); + } + let out = nm.input(path).run().stdout_utf8(); assert_eq!( out.lines() .filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type)) From f6c4110b9d0afdc1b20962fa06dc3d90df768ec5 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 31 Jul 2024 17:38:40 +0300 Subject: [PATCH 328/489] improve bootstrap to allow selecting llvm tools individually Everything works as before, + now bootstrap allows for individually selecting LLVM tools (e.g., `x dist opt llvm-dis`) to include in the dist artifact. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/dist.rs | 37 ++++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 967ddbc0d3483..58f86aa996dd1 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2122,8 +2122,13 @@ impl Step for LlvmTools { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = should_build_extended_tool(run.builder, "llvm-tools"); - // FIXME: allow using the names of the tools themselves? - run.alias("llvm-tools").default_condition(default) + + let mut run = run.alias("llvm-tools"); + for tool in LLVM_TOOLS { + run = run.alias(tool); + } + + run.default_condition(default) } fn make_run(run: RunConfig<'_>) { @@ -2131,6 +2136,32 @@ impl Step for LlvmTools { } fn run(self, builder: &Builder<'_>) -> Option { + fn tools_to_install(paths: &[PathBuf]) -> Vec<&'static str> { + let mut tools = vec![]; + + for path in paths { + let path = path.to_str().unwrap(); + + // Include all tools if path is 'llvm-tools'. + if path == "llvm-tools" { + return LLVM_TOOLS.to_owned(); + } + + for tool in LLVM_TOOLS { + if path == *tool { + tools.push(*tool); + } + } + } + + // If no specific tool is requested, include all tools. + if tools.is_empty() { + tools = LLVM_TOOLS.to_owned(); + } + + tools + } + let target = self.target; /* run only if llvm-config isn't used */ @@ -2151,7 +2182,7 @@ impl Step for LlvmTools { // Prepare the image directory let src_bindir = builder.llvm_out(target).join("bin"); let dst_bindir = format!("lib/rustlib/{}/bin", target.triple); - for tool in LLVM_TOOLS { + for tool in tools_to_install(&builder.paths) { let exe = src_bindir.join(exe(tool, target)); tarball.add_file(&exe, &dst_bindir, 0o755); } From 152db2760cbd21b6c4fcd2c22ee1dcb422fb9965 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 12:03:14 -0400 Subject: [PATCH 329/489] rewrite cross-lang-lto to rmake --- .../src/external_deps/llvm.rs | 36 ++++++ src/tools/run-make-support/src/lib.rs | 4 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/cross-lang-lto/Makefile | 57 --------- tests/run-make/cross-lang-lto/rmake.rs | 110 ++++++++++++++++++ 5 files changed, 148 insertions(+), 60 deletions(-) delete mode 100644 tests/run-make/cross-lang-lto/Makefile create mode 100644 tests/run-make/cross-lang-lto/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 259bb6159461b..c06cefa91a924 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -42,6 +42,12 @@ pub fn llvm_nm() -> LlvmNm { LlvmNm::new() } +/// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available +/// at `$LLVM_BIN_DIR/llvm-bcanalyzer`. +pub fn llvm_bcanalyzer() -> LlvmBcanalyzer { + LlvmBcanalyzer::new() +} + /// A `llvm-readobj` invocation builder. #[derive(Debug)] #[must_use] @@ -84,12 +90,20 @@ pub struct LlvmNm { cmd: Command, } +/// A `llvm-bcanalyzer` invocation builder. +#[derive(Debug)] +#[must_use] +pub struct LlvmBcanalyzer { + cmd: Command, +} + crate::macros::impl_common_helpers!(LlvmReadobj); crate::macros::impl_common_helpers!(LlvmProfdata); crate::macros::impl_common_helpers!(LlvmFilecheck); crate::macros::impl_common_helpers!(LlvmObjdump); crate::macros::impl_common_helpers!(LlvmAr); crate::macros::impl_common_helpers!(LlvmNm); +crate::macros::impl_common_helpers!(LlvmBcanalyzer); /// Generate the path to the bin directory of LLVM. #[must_use] @@ -250,6 +264,12 @@ impl LlvmAr { self } + /// Extract archive members back to files. + pub fn extract(&mut self) -> &mut Self { + self.cmd.arg("x"); + self + } + /// Provide an output, then an input file. Bundled in one function, as llvm-ar has /// no "--output"-style flag. pub fn output_input(&mut self, out: impl AsRef, input: impl AsRef) -> &mut Self { @@ -274,3 +294,19 @@ impl LlvmNm { self } } + +impl LlvmBcanalyzer { + /// Construct a new `llvm-bcanalyzer` invocation. This assumes that `llvm-bcanalyzer` is available + /// at `$LLVM_BIN_DIR/llvm-bcanalyzer`. + pub fn new() -> Self { + let llvm_bcanalyzer = llvm_bin_dir().join("llvm-bcanalyzer"); + let cmd = Command::new(llvm_bcanalyzer); + Self { cmd } + } + + /// Provide an input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } +} diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index f28f2a120a44b..2c9c3e175fe3f 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -48,8 +48,8 @@ pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ - llvm_ar, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, LlvmAr, - LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, + llvm_ar, llvm_bcanalyzer, llvm_filecheck, llvm_nm, llvm_objdump, llvm_profdata, llvm_readobj, + LlvmAr, LlvmBcanalyzer, LlvmFilecheck, LlvmNm, LlvmObjdump, LlvmProfdata, LlvmReadobj, }; pub use python::python_command; pub use rustc::{aux_build, bare_rustc, rustc, Rustc}; diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 84436e96767a2..9e1c520a2c00a 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -4,7 +4,6 @@ run-make/cdylib-dylib-linkage/Makefile run-make/cross-lang-lto-clang/Makefile run-make/cross-lang-lto-pgo-smoketest/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile -run-make/cross-lang-lto/Makefile run-make/dep-info-doesnt-run-much/Makefile run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile diff --git a/tests/run-make/cross-lang-lto/Makefile b/tests/run-make/cross-lang-lto/Makefile deleted file mode 100644 index 92058f952a9fc..0000000000000 --- a/tests/run-make/cross-lang-lto/Makefile +++ /dev/null @@ -1,57 +0,0 @@ - -include ../tools.mk - -# ignore windows due to libLLVM being present in PATH and the PATH and library path being the same -# (so fixing it is harder). See #57765 for context -ifndef IS_WINDOWS - -# This test makes sure that the object files we generate are actually -# LLVM bitcode files (as used by linker LTO plugins) when compiling with -# -Clinker-plugin-lto. - -# this only succeeds for bitcode files -ASSERT_IS_BITCODE_OBJ=("$(LLVM_BIN_DIR)"/llvm-bcanalyzer $(1)) -EXTRACT_OBJS=(cd $(TMPDIR); rm -f ./*.o; "$(LLVM_BIN_DIR)"/llvm-ar x $(1)) - -BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 -BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Clinker-plugin-lto -Ccodegen-units=1 --emit=obj - -all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib - -staticlib: lib.rs - $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a - $(call EXTRACT_OBJS, liblib.a) - for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done - -staticlib-fat-lto: lib.rs - $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat - $(call EXTRACT_OBJS, liblib-fat-lto.a) - for file in $(TMPDIR)/liblib-fat-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done - -staticlib-thin-lto: lib.rs - $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin - $(call EXTRACT_OBJS, liblib-thin-lto.a) - for file in $(TMPDIR)/liblib-thin-lto.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done - -rlib: lib.rs - $(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib - $(call EXTRACT_OBJS, liblib.rlib) - for file in $(TMPDIR)/liblib.*.rcgu.o; do $(call ASSERT_IS_BITCODE_OBJ, $$file); done - -cdylib: lib.rs - $(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o - $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/cdylib.o) - -rdylib: lib.rs - $(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o - $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/rdylib.o) - -exe: lib.rs - $(BUILD_EXE) -o $(TMPDIR)/exe.o - $(call ASSERT_IS_BITCODE_OBJ, $(TMPDIR)/exe.o) - -else - -all: - -endif diff --git a/tests/run-make/cross-lang-lto/rmake.rs b/tests/run-make/cross-lang-lto/rmake.rs new file mode 100644 index 0000000000000..dc376b561e43e --- /dev/null +++ b/tests/run-make/cross-lang-lto/rmake.rs @@ -0,0 +1,110 @@ +// This test checks that the object files we generate are actually +// LLVM bitcode files (as used by linker LTO plugins) when compiling with +// -Clinker-plugin-lto. +// See https://github.com/rust-lang/rust/pull/50000 + +#![feature(path_file_prefix)] + +use std::path::PathBuf; + +use run_make_support::{ + cwd, has_extension, has_prefix, llvm_ar, llvm_bcanalyzer, path, rfs, rust_lib_name, rustc, + shallow_find_files, static_lib_name, +}; + +fn main() { + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("staticlib"), + output: path(static_lib_name("liblib")), + lto: None, + emit_obj: false, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("staticlib"), + output: path(static_lib_name("liblib-fat-lto")), + lto: Some("fat"), + emit_obj: false, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("staticlib"), + output: path(static_lib_name("liblib-thin-lto")), + lto: Some("thin"), + emit_obj: false, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("rlib"), + output: path(rust_lib_name("liblib")), + lto: None, + emit_obj: false, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("cdylib"), + output: path("cdylib.o"), + lto: None, + emit_obj: true, + }); + check_bitcode(LibBuild { + source: path("lib.rs"), + crate_type: Some("dylib"), + output: path("rdylib.o"), + lto: None, + emit_obj: true, + }); + check_bitcode(LibBuild { + source: path("main.rs"), + crate_type: None, + output: path("exe.o"), + lto: None, + emit_obj: true, + }); +} + +#[track_caller] +fn check_bitcode(instructions: LibBuild) { + let mut rustc = rustc(); + rustc + .input(instructions.source) + .output(&instructions.output) + .opt_level("2") + .codegen_units(1) + .arg("-Clinker-plugin-lto"); + if instructions.emit_obj { + rustc.emit("obj"); + } + if let Some(crate_type) = instructions.crate_type { + rustc.crate_type(crate_type); + } + if let Some(lto) = instructions.lto { + rustc.arg(format!("-Clto={lto}")); + } + rustc.run(); + + if instructions.output.extension().unwrap() != "o" { + // Remove all potential leftover object files, then turn the output into an object file. + for object in shallow_find_files(cwd(), |path| has_extension(path, "o")) { + rfs::remove_file(object); + } + llvm_ar().extract().arg(&instructions.output).run(); + } + + for object in shallow_find_files(cwd(), |path| { + has_prefix(path, instructions.output.file_prefix().unwrap().to_str().unwrap()) + && has_extension(path, "o") + }) { + // All generated object files should be LLVM bitcode files - this will fail otherwise. + llvm_bcanalyzer().input(object).run(); + } +} + +struct LibBuild { + source: PathBuf, + crate_type: Option<&'static str>, + output: PathBuf, + lto: Option<&'static str>, + emit_obj: bool, +} From cf11f499b37e557e41f5eeac157c623d08e0068d Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 10 Jul 2024 14:12:58 +0200 Subject: [PATCH 330/489] std: implement the `once_wait` feature --- library/std/src/sync/once.rs | 41 ++++++ library/std/src/sync/once_lock.rs | 28 ++++ library/std/src/sys/sync/once/futex.rs | 124 ++++++++++++----- library/std/src/sys/sync/once/no_threads.rs | 6 + library/std/src/sys/sync/once/queue.rs | 142 ++++++++++++-------- 5 files changed, 247 insertions(+), 94 deletions(-) diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 9d969af8c6d84..17c56c8501658 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -264,6 +264,47 @@ impl Once { self.inner.is_completed() } + /// Blocks the current thread until initialization has completed. + /// + /// # Example + /// + /// ```rust + /// #![feature(once_wait)] + /// + /// use std::sync::Once; + /// use std::thread; + /// + /// static READY: Once = Once::new(); + /// + /// let thread = thread::spawn(|| { + /// READY.wait(); + /// println!("everything is ready"); + /// }); + /// + /// READY.call_once(|| println!("performing setup")); + /// ``` + /// + /// # Panics + /// + /// If this [`Once`] has been poisoned because an initialization closure has + /// panicked, this method will also panic. Use [`wait_force`](Self::wait_force) + /// if this behaviour is not desired. + #[unstable(feature = "once_wait", issue = "127527")] + pub fn wait(&self) { + if !self.inner.is_completed() { + self.inner.wait(false); + } + } + + /// Blocks the current thread until initialization has completed, ignoring + /// poisoning. + #[unstable(feature = "once_wait", issue = "127527")] + pub fn wait_force(&self) { + if !self.inner.is_completed() { + self.inner.wait(true); + } + } + /// Returns the current state of the `Once` instance. /// /// Since this takes a mutable reference, no initialization can currently diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 60e43a1cde10e..efc1f415edfc1 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -167,6 +167,34 @@ impl OnceLock { } } + /// Blocks the current thread until the cell is initialized. + /// + /// # Example + /// + /// Waiting for a computation on another thread to finish: + /// ```rust + /// #![feature(once_wait)] + /// + /// use std::thread; + /// use std::sync::OnceLock; + /// + /// let value = OnceLock::new(); + /// + /// thread::scope(|s| { + /// s.spawn(|| value.set(1 + 1)); + /// + /// let result = value.wait(); + /// assert_eq!(result, &2); + /// }) + /// ``` + #[inline] + #[unstable(feature = "once_wait", issue = "127527")] + pub fn wait(&self) -> &T { + self.once.wait_force(); + + unsafe { self.get_unchecked() } + } + /// Sets the contents of this cell to `value`. /// /// May block if another thread is currently attempting to initialize the cell. The cell is diff --git a/library/std/src/sys/sync/once/futex.rs b/library/std/src/sys/sync/once/futex.rs index e683777803f02..2c8a054282b01 100644 --- a/library/std/src/sys/sync/once/futex.rs +++ b/library/std/src/sys/sync/once/futex.rs @@ -6,7 +6,7 @@ use crate::sync::once::ExclusiveState; use crate::sys::futex::{futex_wait, futex_wake_all}; // On some platforms, the OS is very nice and handles the waiter queue for us. -// This means we only need one atomic value with 5 states: +// This means we only need one atomic value with 4 states: /// No initialization has run yet, and no thread is currently using the Once. const INCOMPLETE: u32 = 0; @@ -17,16 +17,20 @@ const POISONED: u32 = 1; /// Some thread is currently attempting to run initialization. It may succeed, /// so all future threads need to wait for it to finish. const RUNNING: u32 = 2; -/// Some thread is currently attempting to run initialization and there are threads -/// waiting for it to finish. -const QUEUED: u32 = 3; /// Initialization has completed and all future calls should finish immediately. -const COMPLETE: u32 = 4; +const COMPLETE: u32 = 3; -// Threads wait by setting the state to QUEUED and calling `futex_wait` on the state +// An additional bit indicates whether there are waiting threads: + +/// May only be set if the state is not COMPLETE. +const QUEUED: u32 = 4; + +// Threads wait by setting the QUEUED bit and calling `futex_wait` on the state // variable. When the running thread finishes, it will wake all waiting threads using // `futex_wake_all`. +const STATE_MASK: u32 = 0b11; + pub struct OnceState { poisoned: bool, set_state_to: Cell, @@ -45,7 +49,7 @@ impl OnceState { } struct CompletionGuard<'a> { - state: &'a AtomicU32, + state_and_queued: &'a AtomicU32, set_state_on_drop_to: u32, } @@ -54,32 +58,32 @@ impl<'a> Drop for CompletionGuard<'a> { // Use release ordering to propagate changes to all threads checking // up on the Once. `futex_wake_all` does its own synchronization, hence // we do not need `AcqRel`. - if self.state.swap(self.set_state_on_drop_to, Release) == QUEUED { - futex_wake_all(self.state); + if self.state_and_queued.swap(self.set_state_on_drop_to, Release) & QUEUED != 0 { + futex_wake_all(self.state_and_queued); } } } pub struct Once { - state: AtomicU32, + state_and_queued: AtomicU32, } impl Once { #[inline] pub const fn new() -> Once { - Once { state: AtomicU32::new(INCOMPLETE) } + Once { state_and_queued: AtomicU32::new(INCOMPLETE) } } #[inline] pub fn is_completed(&self) -> bool { // Use acquire ordering to make all initialization changes visible to the // current thread. - self.state.load(Acquire) == COMPLETE + self.state_and_queued.load(Acquire) == COMPLETE } #[inline] pub(crate) fn state(&mut self) -> ExclusiveState { - match *self.state.get_mut() { + match *self.state_and_queued.get_mut() { INCOMPLETE => ExclusiveState::Incomplete, POISONED => ExclusiveState::Poisoned, COMPLETE => ExclusiveState::Complete, @@ -87,31 +91,73 @@ impl Once { } } - // This uses FnMut to match the API of the generic implementation. As this - // implementation is quite light-weight, it is generic over the closure and - // so avoids the cost of dynamic dispatch. #[cold] #[track_caller] - pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) { - let mut state = self.state.load(Acquire); + pub fn wait(&self, ignore_poisoning: bool) { + let mut state_and_queued = self.state_and_queued.load(Acquire); loop { + let state = state_and_queued & STATE_MASK; + let queued = state_and_queued & QUEUED != 0; match state { + COMPLETE => return, + POISONED if !ignore_poisoning => { + // Panic to propagate the poison. + panic!("Once instance has previously been poisoned"); + } + _ => { + // Set the QUEUED bit if it has not already been set. + if !queued { + state_and_queued += QUEUED; + if let Err(new) = self.state_and_queued.compare_exchange_weak( + state, + state_and_queued, + Relaxed, + Acquire, + ) { + state_and_queued = new; + continue; + } + } + + futex_wait(&self.state_and_queued, state_and_queued, None); + state_and_queued = self.state_and_queued.load(Acquire); + } + } + } + } + + #[cold] + #[track_caller] + pub fn call(&self, ignore_poisoning: bool, f: &mut dyn FnMut(&public::OnceState)) { + let mut state_and_queued = self.state_and_queued.load(Acquire); + loop { + let state = state_and_queued & STATE_MASK; + let queued = state_and_queued & QUEUED != 0; + match state { + COMPLETE => return, POISONED if !ignore_poisoning => { // Panic to propagate the poison. panic!("Once instance has previously been poisoned"); } INCOMPLETE | POISONED => { // Try to register the current thread as the one running. - if let Err(new) = - self.state.compare_exchange_weak(state, RUNNING, Acquire, Acquire) - { - state = new; + let next = RUNNING + if queued { QUEUED } else { 0 }; + if let Err(new) = self.state_and_queued.compare_exchange_weak( + state_and_queued, + next, + Acquire, + Acquire, + ) { + state_and_queued = new; continue; } + // `waiter_queue` will manage other waiting threads, and // wake them up on drop. - let mut waiter_queue = - CompletionGuard { state: &self.state, set_state_on_drop_to: POISONED }; + let mut waiter_queue = CompletionGuard { + state_and_queued: &self.state_and_queued, + set_state_on_drop_to: POISONED, + }; // Run the function, letting it know if we're poisoned or not. let f_state = public::OnceState { inner: OnceState { @@ -123,21 +169,27 @@ impl Once { waiter_queue.set_state_on_drop_to = f_state.inner.set_state_to.get(); return; } - RUNNING | QUEUED => { - // Set the state to QUEUED if it is not already. - if state == RUNNING - && let Err(new) = - self.state.compare_exchange_weak(RUNNING, QUEUED, Relaxed, Acquire) - { - state = new; - continue; + _ => { + // All other values must be RUNNING. + assert!(state == RUNNING); + + // Set the QUEUED bit if it is not already set. + if !queued { + state_and_queued += QUEUED; + if let Err(new) = self.state_and_queued.compare_exchange_weak( + state, + state_and_queued, + Relaxed, + Acquire, + ) { + state_and_queued = new; + continue; + } } - futex_wait(&self.state, QUEUED, None); - state = self.state.load(Acquire); + futex_wait(&self.state_and_queued, state_and_queued, None); + state_and_queued = self.state_and_queued.load(Acquire); } - COMPLETE => return, - _ => unreachable!("state is never set to invalid values"), } } } diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs index 11fde1888ba7c..12c1d9f5a6c98 100644 --- a/library/std/src/sys/sync/once/no_threads.rs +++ b/library/std/src/sys/sync/once/no_threads.rs @@ -55,6 +55,12 @@ impl Once { } } + #[cold] + #[track_caller] + pub fn wait(&self, _ignore_poisoning: bool) { + panic!("not implementable on this target"); + } + #[cold] #[track_caller] pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) { diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index b04d252f8b91f..7a020c94080bf 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -56,20 +56,21 @@ // allowed, so no need for `SeqCst`. use crate::cell::Cell; -use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; +use crate::sync::atomic::Ordering::{AcqRel, Acquire, Release}; +use crate::sync::atomic::{AtomicBool, AtomicPtr}; use crate::sync::once::ExclusiveState; use crate::thread::{self, Thread}; use crate::{fmt, ptr, sync as public}; -type Masked = (); +type StateAndQueue = *mut (); pub struct Once { - state_and_queue: AtomicPtr, + state_and_queue: AtomicPtr<()>, } pub struct OnceState { poisoned: bool, - set_state_on_drop_to: Cell<*mut Masked>, + set_state_on_drop_to: Cell, } // Four states that a Once can be in, encoded into the lower bits of @@ -81,7 +82,8 @@ const COMPLETE: usize = 0x3; // Mask to learn about the state. All other bits are the queue of waiters if // this is in the RUNNING state. -const STATE_MASK: usize = 0x3; +const STATE_MASK: usize = 0b11; +const QUEUE_MASK: usize = !STATE_MASK; // Representation of a node in the linked list of waiters, used while in the // RUNNING state. @@ -93,15 +95,23 @@ const STATE_MASK: usize = 0x3; struct Waiter { thread: Cell>, signaled: AtomicBool, - next: *const Waiter, + next: Cell<*const Waiter>, } // Head of a linked list of waiters. // Every node is a struct on the stack of a waiting thread. // Will wake up the waiters when it gets dropped, i.e. also on panic. struct WaiterQueue<'a> { - state_and_queue: &'a AtomicPtr, - set_state_on_drop_to: *mut Masked, + state_and_queue: &'a AtomicPtr<()>, + set_state_on_drop_to: StateAndQueue, +} + +fn to_queue(current: StateAndQueue) -> *const Waiter { + current.mask(QUEUE_MASK).cast() +} + +fn to_state(current: StateAndQueue) -> usize { + current.addr() & STATE_MASK } impl Once { @@ -117,7 +127,7 @@ impl Once { // operations visible to us, and, this being a fast path, weaker // ordering helps with performance. This `Acquire` synchronizes with // `Release` operations on the slow path. - self.state_and_queue.load(Ordering::Acquire).addr() == COMPLETE + self.state_and_queue.load(Acquire).addr() == COMPLETE } #[inline] @@ -130,6 +140,25 @@ impl Once { } } + #[cold] + #[track_caller] + pub fn wait(&self, ignore_poisoning: bool) { + let mut current = self.state_and_queue.load(Acquire); + loop { + let state = to_state(current); + match state { + COMPLETE => return, + POISONED if !ignore_poisoning => { + // Panic to propagate the poison. + panic!("Once instance has previously been poisoned"); + } + _ => { + current = wait(&self.state_and_queue, current); + } + } + } + } + // This is a non-generic function to reduce the monomorphization cost of // using `call_once` (this isn't exactly a trivial or small implementation). // @@ -144,9 +173,10 @@ impl Once { #[cold] #[track_caller] pub fn call(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&public::OnceState)) { - let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire); + let mut current = self.state_and_queue.load(Acquire); loop { - match state_and_queue.addr() { + let state = to_state(current); + match state { COMPLETE => break, POISONED if !ignore_poisoning => { // Panic to propagate the poison. @@ -154,16 +184,16 @@ impl Once { } POISONED | INCOMPLETE => { // Try to register this thread as the one RUNNING. - let exchange_result = self.state_and_queue.compare_exchange( - state_and_queue, - ptr::without_provenance_mut(RUNNING), - Ordering::Acquire, - Ordering::Acquire, - ); - if let Err(old) = exchange_result { - state_and_queue = old; + if let Err(new) = self.state_and_queue.compare_exchange_weak( + current, + current.mask(QUEUE_MASK).wrapping_byte_add(RUNNING), + Acquire, + Acquire, + ) { + current = new; continue; } + // `waiter_queue` will manage other waiting threads, and // wake them up on drop. let mut waiter_queue = WaiterQueue { @@ -174,54 +204,53 @@ impl Once { // poisoned or not. let init_state = public::OnceState { inner: OnceState { - poisoned: state_and_queue.addr() == POISONED, + poisoned: state == POISONED, set_state_on_drop_to: Cell::new(ptr::without_provenance_mut(COMPLETE)), }, }; init(&init_state); waiter_queue.set_state_on_drop_to = init_state.inner.set_state_on_drop_to.get(); - break; + return; } _ => { // All other values must be RUNNING with possibly a // pointer to the waiter queue in the more significant bits. - assert!(state_and_queue.addr() & STATE_MASK == RUNNING); - wait(&self.state_and_queue, state_and_queue); - state_and_queue = self.state_and_queue.load(Ordering::Acquire); + assert!(state == RUNNING); + current = wait(&self.state_and_queue, current); } } } } } -fn wait(state_and_queue: &AtomicPtr, mut current_state: *mut Masked) { - // Note: the following code was carefully written to avoid creating a - // mutable reference to `node` that gets aliased. +fn wait(state_and_queue: &AtomicPtr<()>, mut current: StateAndQueue) -> StateAndQueue { + let node = &Waiter { + thread: Cell::new(Some(thread::current())), + signaled: AtomicBool::new(false), + next: Cell::new(ptr::null()), + }; + loop { - // Don't queue this thread if the status is no longer running, - // otherwise we will not be woken up. - if current_state.addr() & STATE_MASK != RUNNING { - return; + let state = to_state(current); + let queue = to_queue(current); + + // If initialization has finished, return. + if matches!(state, POISONED | COMPLETE) { + return current; } - // Create the node for our current thread. - let node = Waiter { - thread: Cell::new(Some(thread::current())), - signaled: AtomicBool::new(false), - next: current_state.with_addr(current_state.addr() & !STATE_MASK) as *const Waiter, - }; - let me = core::ptr::addr_of!(node) as *const Masked as *mut Masked; + // Update the node for our current thread. + node.next.set(queue); // Try to slide in the node at the head of the linked list, making sure // that another thread didn't just replace the head of the linked list. - let exchange_result = state_and_queue.compare_exchange( - current_state, - me.with_addr(me.addr() | RUNNING), - Ordering::Release, - Ordering::Relaxed, - ); - if let Err(old) = exchange_result { - current_state = old; + if let Err(new) = state_and_queue.compare_exchange_weak( + current, + ptr::from_ref(node).wrapping_byte_add(state) as StateAndQueue, + Release, + Acquire, + ) { + current = new; continue; } @@ -230,14 +259,15 @@ fn wait(state_and_queue: &AtomicPtr, mut current_state: *mut Masked) { // would drop our `Waiter` node and leave a hole in the linked list // (and a dangling reference). Guard against spurious wakeups by // reparking ourselves until we are signaled. - while !node.signaled.load(Ordering::Acquire) { + while !node.signaled.load(Acquire) { // If the managing thread happens to signal and unpark us before we // can park ourselves, the result could be this thread never gets // unparked. Luckily `park` comes with the guarantee that if it got // an `unpark` just before on an unparked thread it does not park. thread::park(); } - break; + + return state_and_queue.load(Acquire); } } @@ -251,11 +281,10 @@ impl fmt::Debug for Once { impl Drop for WaiterQueue<'_> { fn drop(&mut self) { // Swap out our state with however we finished. - let state_and_queue = - self.state_and_queue.swap(self.set_state_on_drop_to, Ordering::AcqRel); + let current = self.state_and_queue.swap(self.set_state_on_drop_to, AcqRel); // We should only ever see an old state which was RUNNING. - assert_eq!(state_and_queue.addr() & STATE_MASK, RUNNING); + assert_eq!(current.addr() & STATE_MASK, RUNNING); // Walk the entire linked list of waiters and wake them up (in lifo // order, last to register is first to wake up). @@ -264,16 +293,13 @@ impl Drop for WaiterQueue<'_> { // free `node` if there happens to be has a spurious wakeup. // So we have to take out the `thread` field and copy the pointer to // `next` first. - let mut queue = - state_and_queue.with_addr(state_and_queue.addr() & !STATE_MASK) as *const Waiter; + let mut queue = to_queue(current); while !queue.is_null() { - let next = (*queue).next; + let next = (*queue).next.get(); let thread = (*queue).thread.take().unwrap(); - (*queue).signaled.store(true, Ordering::Release); - // ^- FIXME (maybe): This is another case of issue #55005 - // `store()` has a potentially dangling ref to `signaled`. - queue = next; + (*queue).signaled.store(true, Release); thread.unpark(); + queue = next; } } } From 1d49aad8445881ac060cfae0e351207c05f82dfd Mon Sep 17 00:00:00 2001 From: joboet Date: Fri, 12 Jul 2024 13:17:43 +0200 Subject: [PATCH 331/489] std: fix busy-waiting in `Once::wait_force`, add more tests --- library/std/src/sync/once/tests.rs | 47 ++++++++++++++++++++++++++ library/std/src/sys/sync/once/queue.rs | 12 ++++--- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/library/std/src/sync/once/tests.rs b/library/std/src/sync/once/tests.rs index d43dabc1cf137..ce96468aeb6e1 100644 --- a/library/std/src/sync/once/tests.rs +++ b/library/std/src/sync/once/tests.rs @@ -1,5 +1,8 @@ use super::Once; +use crate::sync::atomic::AtomicBool; +use crate::sync::atomic::Ordering::Relaxed; use crate::sync::mpsc::channel; +use crate::time::Duration; use crate::{panic, thread}; #[test] @@ -113,3 +116,47 @@ fn wait_for_force_to_finish() { assert!(t1.join().is_ok()); assert!(t2.join().is_ok()); } + +#[test] +fn wait() { + for _ in 0..50 { + let val = AtomicBool::new(false); + let once = Once::new(); + + thread::scope(|s| { + for _ in 0..4 { + s.spawn(|| { + once.wait(); + assert!(val.load(Relaxed)); + }); + } + + once.call_once(|| val.store(true, Relaxed)); + }); + } +} + +#[test] +fn wait_on_poisoned() { + let once = Once::new(); + + panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err(); + panic::catch_unwind(|| once.wait()).unwrap_err(); +} + +#[test] +fn wait_force_on_poisoned() { + let once = Once::new(); + + thread::scope(|s| { + panic::catch_unwind(|| once.call_once(|| panic!())).unwrap_err(); + + s.spawn(|| { + thread::sleep(Duration::from_millis(100)); + + once.call_once_force(|_| {}); + }); + + once.wait_force(); + }) +} diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs index 7a020c94080bf..86f72c82008bc 100644 --- a/library/std/src/sys/sync/once/queue.rs +++ b/library/std/src/sys/sync/once/queue.rs @@ -153,7 +153,7 @@ impl Once { panic!("Once instance has previously been poisoned"); } _ => { - current = wait(&self.state_and_queue, current); + current = wait(&self.state_and_queue, current, !ignore_poisoning); } } } @@ -216,14 +216,18 @@ impl Once { // All other values must be RUNNING with possibly a // pointer to the waiter queue in the more significant bits. assert!(state == RUNNING); - current = wait(&self.state_and_queue, current); + current = wait(&self.state_and_queue, current, true); } } } } } -fn wait(state_and_queue: &AtomicPtr<()>, mut current: StateAndQueue) -> StateAndQueue { +fn wait( + state_and_queue: &AtomicPtr<()>, + mut current: StateAndQueue, + return_on_poisoned: bool, +) -> StateAndQueue { let node = &Waiter { thread: Cell::new(Some(thread::current())), signaled: AtomicBool::new(false), @@ -235,7 +239,7 @@ fn wait(state_and_queue: &AtomicPtr<()>, mut current: StateAndQueue) -> StateAnd let queue = to_queue(current); // If initialization has finished, return. - if matches!(state, POISONED | COMPLETE) { + if state == COMPLETE || (return_on_poisoned && state == POISONED) { return current; } From 9b097b2d44a8f953640ba42122a804485d651ea9 Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Wed, 31 Jul 2024 18:58:04 +0300 Subject: [PATCH 332/489] Delegation: second attempt to improve perf --- compiler/rustc_hir/src/hir.rs | 11 +++++++++++ .../src/collect/generics_of.rs | 17 ++++++++++------- .../src/collect/predicates_of.rs | 17 ++++++++++------- compiler/rustc_hir_analysis/src/delegation.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 13 +------------ 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 3b9aea087910a..9257be8647162 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2952,6 +2952,17 @@ pub struct FnDecl<'hir> { pub lifetime_elision_allowed: bool, } +impl<'hir> FnDecl<'hir> { + pub fn opt_delegation_sig_id(&self) -> Option { + if let FnRetTy::Return(ty) = self.output + && let TyKind::InferDelegation(sig_id, _) = ty.kind + { + return Some(sig_id); + } + None + } +} + /// Represents what type of implicit self a function has, if any. #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum ImplicitSelfKind { diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 80a65aa298851..71a6501de8b98 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -54,13 +54,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { }; } - // For a delegation item inherit generics from callee. - if let Some(sig_id) = tcx.hir().opt_delegation_sig_id(def_id) - && let Some(generics) = inherit_generics_for_delegation_item(tcx, def_id, sig_id) - { - return generics; - } - let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); @@ -234,6 +227,16 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // inherit the generics of the item. Some(parent.to_def_id()) } + ItemKind::Fn(sig, _, _) => { + // For a delegation item inherit generics from callee. + if let Some(sig_id) = sig.decl.opt_delegation_sig_id() + && let Some(generics) = + inherit_generics_for_delegation_item(tcx, def_id, sig_id) + { + return generics; + } + None + } _ => None, }, _ => None, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index ae52dbd56f9b7..a5a56cb845d79 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -115,13 +115,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen None => {} } - // For a delegation item inherit predicates from callee. - if let Some(sig_id) = tcx.hir().opt_delegation_sig_id(def_id) - && let Some(predicates) = inherit_predicates_for_delegation_item(tcx, def_id, sig_id) - { - return predicates; - } - let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); @@ -151,6 +144,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => { is_trait = Some(self_bounds); } + + ItemKind::Fn(sig, _, _) => { + // For a delegation item inherit predicates from callee. + if let Some(sig_id) = sig.decl.opt_delegation_sig_id() + && let Some(predicates) = + inherit_predicates_for_delegation_item(tcx, def_id, sig_id) + { + return predicates; + } + } _ => {} } }; diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index e21ed55bce3fc..ca62ef92b83de 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -242,7 +242,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> &'tcx [Ty<'tcx>] { - let sig_id = tcx.hir().delegation_sig_id(def_id); + let sig_id = tcx.hir().opt_delegation_sig_id(def_id).unwrap(); let caller_sig = tcx.fn_sig(sig_id); if let Err(err) = check_constraints(tcx, def_id, sig_id) { let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 1705c016437cc..4c243e6330b91 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -747,18 +747,7 @@ impl<'hir> Map<'hir> { } pub fn opt_delegation_sig_id(self, def_id: LocalDefId) -> Option { - if let Some(ret) = self.get_fn_output(def_id) - && let FnRetTy::Return(ty) = ret - && let TyKind::InferDelegation(sig_id, _) = ty.kind - { - return Some(sig_id); - } - None - } - - #[inline] - pub fn delegation_sig_id(self, def_id: LocalDefId) -> DefId { - self.opt_delegation_sig_id(def_id).unwrap() + self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id() } #[inline] From 74754b878621b42097de33f9579d7630fa704627 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Jul 2024 12:24:22 -0400 Subject: [PATCH 333/489] Properly mark loop as diverging if it has no breaks --- compiler/rustc_hir_typeck/src/expr.rs | 2 + .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 54 +++++++++++-------- tests/ui/async-await/unreachable-lint-2.rs | 15 ++++++ .../ui/async-await/unreachable-lint-2.stderr | 17 ++++++ 4 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 tests/ui/async-await/unreachable-lint-2.rs create mode 100644 tests/ui/async-await/unreachable-lint-2.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d75a5f8806bc9..e54f9486f6a89 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1306,6 +1306,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // No way to know whether it's diverging because // of a `break` or an outer `break` or `return`. self.diverges.set(Diverges::Maybe); + } else { + self.diverges.set(self.diverges.get() | Diverges::always(expr.span)); } // If we permit break with a value, then result type is diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index dea125bb9b1dd..40d9a2985da06 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -48,30 +48,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Produces warning on the given node, if the current point in the /// function is unreachable, and there hasn't been another warning. pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) { - // FIXME: Combine these two 'if' expressions into one once - // let chains are implemented - if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() { - // If span arose from a desugaring of `if` or `while`, then it is the condition itself, - // which diverges, that we are about to lint on. This gives suboptimal diagnostics. - // Instead, stop here so that the `if`- or `while`-expression's block is linted instead. - if !span.is_desugaring(DesugaringKind::CondTemporary) - && !span.is_desugaring(DesugaringKind::Async) - && !orig_span.is_desugaring(DesugaringKind::Await) - { - self.diverges.set(Diverges::WarnedAlways); + // If span arose from a desugaring of `if` or `while`, then it is the condition itself, + // which diverges, that we are about to lint on. This gives suboptimal diagnostics. + // Instead, stop here so that the `if`- or `while`-expression's block is linted instead. + if span.is_desugaring(DesugaringKind::CondTemporary) { + return; + } - debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); + // Don't lint if the result of an async block or async function is `!`. + // This does not affect the unreachable lints *within* the body. + if span.is_desugaring(DesugaringKind::Async) { + return; + } - let msg = format!("unreachable {kind}"); - self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| { - lint.primary_message(msg.clone()); - lint.span_label(span, msg).span_label( - orig_span, - custom_note.unwrap_or("any code following this expression is unreachable"), - ); - }) - } + // Don't lint *within* the `.await` operator, since that's all just desugaring junk. + // We only want to lint if there is a subsequent expression after the `.await`. + if span.is_desugaring(DesugaringKind::Await) { + return; } + + let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() else { + return; + }; + + // Don't warn twice. + self.diverges.set(Diverges::WarnedAlways); + + debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); + + let msg = format!("unreachable {kind}"); + self.tcx().node_span_lint(lint::builtin::UNREACHABLE_CODE, id, span, |lint| { + lint.primary_message(msg.clone()); + lint.span_label(span, msg).span_label( + orig_span, + custom_note.unwrap_or("any code following this expression is unreachable"), + ); + }) } /// Resolves type and const variables in `ty` if possible. Unlike the infcx diff --git a/tests/ui/async-await/unreachable-lint-2.rs b/tests/ui/async-await/unreachable-lint-2.rs new file mode 100644 index 0000000000000..137cb32481b9c --- /dev/null +++ b/tests/ui/async-await/unreachable-lint-2.rs @@ -0,0 +1,15 @@ +//@ edition:2018 + +#![deny(unreachable_code)] + +async fn foo() { + endless().await; + println!("this is unreachable!"); + //~^ ERROR unreachable statement +} + +async fn endless() -> ! { + loop {} +} + +fn main() { } diff --git a/tests/ui/async-await/unreachable-lint-2.stderr b/tests/ui/async-await/unreachable-lint-2.stderr new file mode 100644 index 0000000000000..cbebc9951f32d --- /dev/null +++ b/tests/ui/async-await/unreachable-lint-2.stderr @@ -0,0 +1,17 @@ +error: unreachable statement + --> $DIR/unreachable-lint-2.rs:7:5 + | +LL | endless().await; + | ----- any code following this expression is unreachable +LL | println!("this is unreachable!"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/unreachable-lint-2.rs:3:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + From 8b14b743f990d300995f0b1e7147f50512270af7 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 1 Aug 2024 02:20:52 +0900 Subject: [PATCH 334/489] fix: Apply `IndexMut` obligations for non-assigning mutable index usages, too --- .../crates/hir-ty/src/infer/mutability.rs | 27 +++++++++-- .../crates/hir-ty/src/tests/regression.rs | 47 +++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index abb702d15002f..fbc7570c7429a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -1,7 +1,7 @@ //! Finds if an expression is an immutable context or a mutable context, which is used in selecting //! between `Deref` and `DerefMut` or `Index` and `IndexMut` or similar. -use chalk_ir::Mutability; +use chalk_ir::{cast::Cast, Mutability}; use hir_def::{ hir::{Array, BinaryOp, BindingAnnotation, Expr, ExprId, PatId, Statement, UnaryOp}, lang_item::LangItem, @@ -9,7 +9,10 @@ use hir_def::{ use hir_expand::name::Name; use intern::sym; -use crate::{lower::lower_to_chalk_mutability, Adjust, Adjustment, AutoBorrow, OverloadedDeref}; +use crate::{ + infer::Expectation, lower::lower_to_chalk_mutability, Adjust, Adjustment, AutoBorrow, Interner, + OverloadedDeref, TyBuilder, TyKind, +}; use super::InferenceContext; @@ -115,6 +118,7 @@ impl InferenceContext<'_> { .method_by_name(&Name::new_symbol_root(sym::index_mut.clone())) { *f = index_fn; + let mut base_ty = None; let base_adjustments = self .result .expr_adjustments @@ -122,10 +126,27 @@ impl InferenceContext<'_> { .and_then(|it| it.last_mut()); if let Some(Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mutability)), - .. + target, }) = base_adjustments { *mutability = Mutability::Mut; + if let TyKind::Ref(_, _, ty) = target.kind(Interner) { + base_ty = Some(ty.clone()); + } + } + + if let Some(base_ty) = base_ty { + let index_ty = + if let Some(ty) = self.result.type_of_expr.get(index) { + ty.clone() + } else { + self.infer_expr(index, &Expectation::none()) + }; + let trait_ref = TyBuilder::trait_ref(self.db, index_trait) + .push(base_ty) + .fill(|_| index_ty.clone().cast(Interner)) + .build(); + self.push_obligation(trait_ref.cast(Interner)); } } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index b371e5856b083..ac2dfea1010d4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -2075,3 +2075,50 @@ impl<'a, T> Trait<'a> for &'a T { "#, ) } + +#[test] +fn issue_17738() { + check_types( + r#" +//- minicore: index +use core::ops::{Index, IndexMut}; + +struct Foo(K, V); + +struct Bar; + +impl Bar { + fn bar(&mut self) {} +} + +impl Foo { + fn new(_v: V) -> Self { + loop {} + } +} + +impl Index for Foo { + type Output = V; + fn index(&self, _index: B) -> &Self::Output { + loop {} + } +} + +impl IndexMut for Foo { + fn index_mut(&mut self, _index: K) -> &mut Self::Output { + loop {} + } +} + +fn test() { + let mut t1 = Foo::new(Bar); + // ^^^^^^ Foo<&'? (), Bar> + t1[&()] = Bar; + + let mut t2 = Foo::new(Bar); + // ^^^^^^ Foo<&'? (), Bar> + t2[&()].bar(); +} +"#, + ) +} From 840ca3cbef88919bfcacf0572f605145712195d7 Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 31 Jul 2024 19:36:47 +0200 Subject: [PATCH 335/489] Temporarily switch `ambiguous_negative_literals` lint to allow --- compiler/rustc_lint/src/precedence.rs | 3 ++- tests/ui/lint/negative_literals.rs | 2 ++ tests/ui/lint/negative_literals.stderr | 28 +++++++++++++++----------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_lint/src/precedence.rs b/compiler/rustc_lint/src/precedence.rs index eb2ba39727797..52321e25c7d43 100644 --- a/compiler/rustc_lint/src/precedence.rs +++ b/compiler/rustc_lint/src/precedence.rs @@ -16,6 +16,7 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail + /// # #![deny(ambiguous_negative_literals)] /// # #![allow(unused)] /// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1 /// ``` @@ -27,7 +28,7 @@ declare_lint! { /// Method calls take precedence over unary precedence. Setting the /// precedence explicitly makes the code clearer and avoid potential bugs. pub AMBIGUOUS_NEGATIVE_LITERALS, - Deny, + Allow, "ambiguous negative literals operations", report_in_external_macro } diff --git a/tests/ui/lint/negative_literals.rs b/tests/ui/lint/negative_literals.rs index 048fcd6ff57bc..5964bbb559a1e 100644 --- a/tests/ui/lint/negative_literals.rs +++ b/tests/ui/lint/negative_literals.rs @@ -1,5 +1,7 @@ //@ check-fail +#![deny(ambiguous_negative_literals)] + fn main() { let _ = -1i32.abs(); //~^ ERROR `-` has lower precedence than method calls diff --git a/tests/ui/lint/negative_literals.stderr b/tests/ui/lint/negative_literals.stderr index df000a7188255..b0323cc96a0ea 100644 --- a/tests/ui/lint/negative_literals.stderr +++ b/tests/ui/lint/negative_literals.stderr @@ -1,11 +1,15 @@ error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:4:13 + --> $DIR/negative_literals.rs:6:13 | LL | let _ = -1i32.abs(); | ^^^^^^^^^^^ | = note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4` - = note: `#[deny(ambiguous_negative_literals)]` on by default +note: the lint level is defined here + --> $DIR/negative_literals.rs:3:9 + | +LL | #![deny(ambiguous_negative_literals)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add parentheses around the `-` and the literal to call the method on a negative literal | LL | let _ = (-1i32).abs(); @@ -16,7 +20,7 @@ LL | let _ = -(1i32.abs()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:6:13 + --> $DIR/negative_literals.rs:8:13 | LL | let _ = -1f32.abs(); | ^^^^^^^^^^^ @@ -32,7 +36,7 @@ LL | let _ = -(1f32.abs()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:8:13 + --> $DIR/negative_literals.rs:10:13 | LL | let _ = -1f64.asin(); | ^^^^^^^^^^^^ @@ -48,7 +52,7 @@ LL | let _ = -(1f64.asin()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:10:13 + --> $DIR/negative_literals.rs:12:13 | LL | let _ = -1f64.asinh(); | ^^^^^^^^^^^^^ @@ -64,7 +68,7 @@ LL | let _ = -(1f64.asinh()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:12:13 + --> $DIR/negative_literals.rs:14:13 | LL | let _ = -1f64.tan(); | ^^^^^^^^^^^ @@ -80,7 +84,7 @@ LL | let _ = -(1f64.tan()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:14:13 + --> $DIR/negative_literals.rs:16:13 | LL | let _ = -1f64.tanh(); | ^^^^^^^^^^^^ @@ -96,7 +100,7 @@ LL | let _ = -(1f64.tanh()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:16:13 + --> $DIR/negative_literals.rs:18:13 | LL | let _ = -1.0_f64.cos().cos(); | ^^^^^^^^^^^^^^^^^^^^ @@ -112,7 +116,7 @@ LL | let _ = -(1.0_f64.cos().cos()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:18:13 + --> $DIR/negative_literals.rs:20:13 | LL | let _ = -1.0_f64.cos().sin(); | ^^^^^^^^^^^^^^^^^^^^ @@ -128,7 +132,7 @@ LL | let _ = -(1.0_f64.cos().sin()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:20:13 + --> $DIR/negative_literals.rs:22:13 | LL | let _ = -1.0_f64.sin().cos(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +148,7 @@ LL | let _ = -(1.0_f64.sin().cos()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:22:13 + --> $DIR/negative_literals.rs:24:13 | LL | let _ = -1f64.sin().sin(); | ^^^^^^^^^^^^^^^^^ @@ -160,7 +164,7 @@ LL | let _ = -(1f64.sin().sin()); | + + error: `-` has lower precedence than method calls, which might be unexpected - --> $DIR/negative_literals.rs:25:11 + --> $DIR/negative_literals.rs:27:11 | LL | dbg!( -1.0_f32.cos() ); | ^^^^^^^^^^^^^^ From 03357f12f8f2ad11dc643f20597c33bc117bd1cb Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Wed, 31 Jul 2024 10:40:36 -0700 Subject: [PATCH 336/489] Create COFF archives for non-LLVM backends --- compiler/rustc_codegen_ssa/src/back/archive.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index ae649cd77c420..638d90e1f9c42 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -224,11 +224,7 @@ impl<'a> ArArchiveBuilder<'a> { "gnu" => ArchiveKind::Gnu, "bsd" => ArchiveKind::Bsd, "darwin" => ArchiveKind::Darwin, - "coff" => { - // FIXME: ar_archive_writer doesn't support COFF archives yet. - // https://github.com/rust-lang/ar_archive_writer/issues/9 - ArchiveKind::Gnu - } + "coff" => ArchiveKind::Coff, "aix_big" => ArchiveKind::AixBig, kind => { self.sess.dcx().emit_fatal(UnknownArchiveKind { kind }); From 086065e56b83e54f1236be0c69fadd613e7363a8 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 1 Aug 2024 02:51:33 +0900 Subject: [PATCH 337/489] Prevent redundant obigation push for assignee exprs --- .../crates/hir-ty/src/infer/mutability.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index fbc7570c7429a..66267e08db62b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -104,7 +104,7 @@ impl InferenceContext<'_> { Expr::RecordLit { path: _, fields, spread, ellipsis: _, is_assignee_expr: _ } => { self.infer_mut_not_expr_iter(fields.iter().map(|it| it.expr).chain(*spread)) } - &Expr::Index { base, index, is_assignee_expr: _ } => { + &Expr::Index { base, index, is_assignee_expr } => { if mutability == Mutability::Mut { if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) { if let Some(index_trait) = self @@ -129,12 +129,16 @@ impl InferenceContext<'_> { target, }) = base_adjustments { - *mutability = Mutability::Mut; - if let TyKind::Ref(_, _, ty) = target.kind(Interner) { - base_ty = Some(ty.clone()); + // For assignee exprs `IndexMut` obiligations are already applied + if !is_assignee_expr { + if let TyKind::Ref(_, _, ty) = target.kind(Interner) { + base_ty = Some(ty.clone()); + } } + *mutability = Mutability::Mut; } + // Apply `IndexMut` obligation for non-assignee expr if let Some(base_ty) = base_ty { let index_ty = if let Some(ty) = self.result.type_of_expr.get(index) { From 14a0963f96a68fe4d0cb18cbe9ef052890a58e6e Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Wed, 31 Jul 2024 22:50:45 +0800 Subject: [PATCH 338/489] reject pointee without ?Sized --- .../src/deriving/smart_ptr.rs | 50 +++++++++---------- .../ui/deriving/deriving-smart-pointer-neg.rs | 30 +++++++++++ .../deriving-smart-pointer-neg.stderr | 26 ++++++---- 3 files changed, 69 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs index 02555bd799c42..7eb1f17a59ce3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs +++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs @@ -1,5 +1,3 @@ -use std::mem::swap; - use ast::ptr::P; use ast::HasAttrs; use rustc_ast::mut_visit::MutVisitor; @@ -154,13 +152,28 @@ pub fn expand_deriving_smart_ptr( { let pointee = &mut impl_generics.params[pointee_param_idx]; self_bounds = pointee.bounds.clone(); + if !contains_maybe_sized_bound(&self_bounds) + && !contains_maybe_sized_bound_on_pointee( + &generics.where_clause.predicates, + pointee_ty_ident.name, + ) + { + cx.dcx() + .struct_span_err( + pointee_ty_ident.span, + format!( + "`derive(SmartPointer)` requires {} to be marked `?Sized`", + pointee_ty_ident.name + ), + ) + .emit(); + return; + } let arg = GenericArg::Type(s_ty.clone()); let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]); pointee.bounds.push(cx.trait_bound(unsize, false)); - let mut attrs = thin_vec![]; - swap(&mut pointee.attrs, &mut attrs); // Drop `#[pointee]` attribute since it should not be recognized outside `derive(SmartPointer)` - pointee.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect(); + pointee.attrs.retain(|attr| !attr.has_name(sym::pointee)); } // # Rewrite generic parameter bounds @@ -169,14 +182,14 @@ pub fn expand_deriving_smart_ptr( // ``` // struct< // U: Trait, - // #[pointee] T: Trait, + // #[pointee] T: Trait + ?Sized, // V: Trait> ... // ``` // ... generates this `impl` generic parameters // ``` // impl< // U: Trait + Trait<__S>, - // T: Trait + Unsize<__S>, // (**) + // T: Trait + ?Sized + Unsize<__S>, // (**) // __S: Trait<__S> + ?Sized, // (*) // V: Trait + Trait<__S>> ... // ``` @@ -218,23 +231,6 @@ pub fn expand_deriving_smart_ptr( // // We now insert `__S` with the missing bounds marked with (*) above. // We should also write the bounds from `#[pointee]` to `__S` as required by `Unsize<__S>`. - let sized = cx.path_global(span, path!(span, core::marker::Sized)); - // For some reason, we are not allowed to write `?Sized` bound twice like `__S: ?Sized + ?Sized`. - if !contains_maybe_sized_bound(&self_bounds) - && !contains_maybe_sized_bound_on_pointee( - &generics.where_clause.predicates, - pointee_ty_ident.name, - ) - { - self_bounds.push(GenericBound::Trait( - cx.poly_trait_ref(span, sized), - TraitBoundModifiers { - polarity: ast::BoundPolarity::Maybe(span), - constness: ast::BoundConstness::Never, - asyncness: ast::BoundAsyncness::Normal, - }, - )); - } { let mut substitution = TypeSubstitution { from_name: pointee_ty_ident.name, to_ty: &s_ty, rewritten: false }; @@ -252,7 +248,7 @@ pub fn expand_deriving_smart_ptr( // where // U: Trait + Trait, // Companion: Trait, - // T: Trait, + // T: Trait + ?Sized, // { .. } // ``` // ... will have a impl prelude like so @@ -263,8 +259,8 @@ pub fn expand_deriving_smart_ptr( // U: Trait<__S>, // Companion: Trait, // Companion<__S>: Trait<__S>, - // T: Trait, - // __S: Trait<__S>, + // T: Trait + ?Sized, + // __S: Trait<__S> + ?Sized, // ``` // // We should also write a few new `where` bounds from `#[pointee] T` to `__S` diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.rs b/tests/ui/deriving/deriving-smart-pointer-neg.rs index bfb4e86b39601..04f52a154fe42 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.rs +++ b/tests/ui/deriving/deriving-smart-pointer-neg.rs @@ -1,5 +1,6 @@ #![feature(derive_smart_pointer, arbitrary_self_types)] +extern crate core; use std::marker::SmartPointer; #[derive(SmartPointer)] @@ -35,6 +36,13 @@ struct NotTransparent<'a, #[pointee] T: ?Sized> { ptr: &'a T, } +#[derive(SmartPointer)] +#[repr(transparent)] +struct NoMaybeSized<'a, #[pointee] T> { + //~^ ERROR: `derive(SmartPointer)` requires T to be marked `?Sized` + ptr: &'a T, +} + // However, reordering attributes should work nevertheless. #[repr(transparent)] #[derive(SmartPointer)] @@ -42,4 +50,26 @@ struct ThisIsAPossibleSmartPointer<'a, #[pointee] T: ?Sized> { ptr: &'a T, } +// Also, these paths to Sized should work +#[derive(SmartPointer)] +#[repr(transparent)] +struct StdSized<'a, #[pointee] T: ?std::marker::Sized> { + ptr: &'a T, +} +#[derive(SmartPointer)] +#[repr(transparent)] +struct CoreSized<'a, #[pointee] T: ?core::marker::Sized> { + ptr: &'a T, +} +#[derive(SmartPointer)] +#[repr(transparent)] +struct GlobalStdSized<'a, #[pointee] T: ?::std::marker::Sized> { + ptr: &'a T, +} +#[derive(SmartPointer)] +#[repr(transparent)] +struct GlobalCoreSized<'a, #[pointee] T: ?::core::marker::Sized> { + ptr: &'a T, +} + fn main() {} diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.stderr b/tests/ui/deriving/deriving-smart-pointer-neg.stderr index d994a6ee376b0..8b0f91d41fb88 100644 --- a/tests/ui/deriving/deriving-smart-pointer-neg.stderr +++ b/tests/ui/deriving/deriving-smart-pointer-neg.stderr @@ -1,5 +1,5 @@ error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]` - --> $DIR/deriving-smart-pointer-neg.rs:5:10 + --> $DIR/deriving-smart-pointer-neg.rs:6:10 | LL | #[derive(SmartPointer)] | ^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[derive(SmartPointer)] = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) error: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits - --> $DIR/deriving-smart-pointer-neg.rs:11:10 + --> $DIR/deriving-smart-pointer-neg.rs:12:10 | LL | #[derive(SmartPointer)] | ^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[derive(SmartPointer)] = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) error: `SmartPointer` can only be derived on `struct`s with at least one field - --> $DIR/deriving-smart-pointer-neg.rs:18:10 + --> $DIR/deriving-smart-pointer-neg.rs:19:10 | LL | #[derive(SmartPointer)] | ^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | #[derive(SmartPointer)] = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) error: `SmartPointer` can only be derived on `struct`s with at least one field - --> $DIR/deriving-smart-pointer-neg.rs:25:10 + --> $DIR/deriving-smart-pointer-neg.rs:26:10 | LL | #[derive(SmartPointer)] | ^^^^^^^^^^^^ @@ -31,15 +31,21 @@ LL | #[derive(SmartPointer)] = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]` - --> $DIR/deriving-smart-pointer-neg.rs:32:10 + --> $DIR/deriving-smart-pointer-neg.rs:33:10 | LL | #[derive(SmartPointer)] | ^^^^^^^^^^^^ | = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info) +error: `derive(SmartPointer)` requires T to be marked `?Sized` + --> $DIR/deriving-smart-pointer-neg.rs:41:36 + | +LL | struct NoMaybeSized<'a, #[pointee] T> { + | ^ + error[E0392]: lifetime parameter `'a` is never used - --> $DIR/deriving-smart-pointer-neg.rs:21:16 + --> $DIR/deriving-smart-pointer-neg.rs:22:16 | LL | struct NoField<'a, #[pointee] T: ?Sized> {} | ^^ unused lifetime parameter @@ -47,7 +53,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/deriving-smart-pointer-neg.rs:21:31 + --> $DIR/deriving-smart-pointer-neg.rs:22:31 | LL | struct NoField<'a, #[pointee] T: ?Sized> {} | ^ unused type parameter @@ -55,7 +61,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {} = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: lifetime parameter `'a` is never used - --> $DIR/deriving-smart-pointer-neg.rs:28:20 + --> $DIR/deriving-smart-pointer-neg.rs:29:20 | LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | ^^ unused lifetime parameter @@ -63,13 +69,13 @@ LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0392]: type parameter `T` is never used - --> $DIR/deriving-smart-pointer-neg.rs:28:35 + --> $DIR/deriving-smart-pointer-neg.rs:29:35 | LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>(); | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0392`. From f97aba2271baf1876940b42cc68f1b60ac97bf98 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 31 Jul 2024 20:26:08 +0200 Subject: [PATCH 339/489] raw_eq: using it on bytes with provenance is not UB (outside const-eval) --- compiler/rustc_const_eval/messages.ftl | 3 --- .../rustc_const_eval/src/interpret/intrinsics.rs | 3 --- library/core/src/intrinsics.rs | 6 ++++-- .../miri/tests/fail/intrinsics/raw_eq_on_ptr.rs | 10 ---------- .../tests/fail/intrinsics/raw_eq_on_ptr.stderr | 15 --------------- tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs | 2 +- .../intrinsics/intrinsic-raw_eq-const-bad.stderr | 5 ++++- 7 files changed, 9 insertions(+), 35 deletions(-) delete mode 100644 src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs delete mode 100644 src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 43f405b223504..18687dfdd3762 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -301,9 +301,6 @@ const_eval_range_upper = less or equal to {$hi} const_eval_range_wrapping = less or equal to {$hi}, or greater or equal to {$lo} const_eval_raw_bytes = the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"} -const_eval_raw_eq_with_provenance = - `raw_eq` on bytes with provenance - const_eval_raw_ptr_comparison = pointers cannot be reliably compared during const eval .note = see issue #53020 for more information diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1e3de224380b9..6b78e49aed296 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -693,9 +693,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // zero-sized access return Ok(&[]); }; - if alloc_ref.has_provenance() { - throw_ub_custom!(fluent::const_eval_raw_eq_with_provenance); - } alloc_ref.get_bytes_strip_provenance() }; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 13c7f0855d8f0..e9eacbcd25a0a 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -2436,11 +2436,13 @@ extern "rust-intrinsic" { /// /// # Safety /// - /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized or carry a - /// pointer value. + /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized. /// Note that this is a stricter criterion than just the *values* being /// fully-initialized: if `T` has padding, it's UB to call this intrinsic. /// + /// At compile-time, it is furthermore UB to call this if any of the bytes + /// in `*a` or `*b` have provenance. + /// /// (The implementation is allowed to branch on the results of comparisons, /// which is UB if any of their inputs are `undef`.) #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")] diff --git a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs b/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs deleted file mode 100644 index c14f86147dbb9..0000000000000 --- a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(intrinsics)] - -extern "rust-intrinsic" { - fn raw_eq(a: &T, b: &T) -> bool; -} - -fn main() { - let x = &0; - unsafe { raw_eq(&x, &x) }; //~ERROR: `raw_eq` on bytes with provenance -} diff --git a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr deleted file mode 100644 index 83f81fa726ea9..0000000000000 --- a/src/tools/miri/tests/fail/intrinsics/raw_eq_on_ptr.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: Undefined Behavior: `raw_eq` on bytes with provenance - --> $DIR/raw_eq_on_ptr.rs:LL:CC - | -LL | unsafe { raw_eq(&x, &x) }; - | ^^^^^^^^^^^^^^ `raw_eq` on bytes with provenance - | - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: - = note: inside `main` at $DIR/raw_eq_on_ptr.rs:LL:CC - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to 1 previous error - diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs index 0e894ef581c38..ab46fd796c535 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs @@ -10,7 +10,7 @@ const RAW_EQ_PADDING: bool = unsafe { const RAW_EQ_PTR: bool = unsafe { std::intrinsics::raw_eq(&(&0), &(&1)) //~^ ERROR evaluation of constant value failed -//~| `raw_eq` on bytes with provenance +//~| unable to turn pointer into integer }; pub fn main() { diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index 317466eb3226f..af16c2bc64a9d 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -8,7 +8,10 @@ error[E0080]: evaluation of constant value failed --> $DIR/intrinsic-raw_eq-const-bad.rs:11:5 | LL | std::intrinsics::raw_eq(&(&0), &(&1)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `raw_eq` on bytes with provenance + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer + | + = help: this code performed an operation that depends on the underlying bytes representing a pointer + = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error: aborting due to 2 previous errors From 276fa19c0a85a341c5b9fddb4ffb17282907532e Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Fri, 31 May 2024 16:47:30 +0000 Subject: [PATCH 340/489] rustc_parser: consider the in 2024 an expression This commit is adding the possibility to parse the `_` as an expression inside the esition 2024. Link: https://rust-lang.zulipchat.com/#narrow/stream/404510-wg-macros/topic/supporting.20.60_.60.20expressions Co-authored-by: Eric Holk Signed-off-by: Vincenzo Palazzo --- .../rustc_parse/src/parser/nonterminal.rs | 11 ++++++- .../expr_2024_underscore_expr.edi2021.stderr | 32 +++++++++++++++++++ .../expr_2024_underscore_expr.edi2024.stderr | 17 ++++++++++ tests/ui/macros/expr_2024_underscore_expr.rs | 24 ++++++++++++++ 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr create mode 100644 tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr create mode 100644 tests/ui/macros/expr_2024_underscore_expr.rs diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 886d6af173535..730b3a57142a2 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -38,6 +38,7 @@ impl<'a> Parser<'a> { } match kind { + // `expr_2021` and earlier NonterminalKind::Expr(Expr2021 { .. }) => { token.can_begin_expr() // This exception is here for backwards compatibility. @@ -45,8 +46,16 @@ impl<'a> Parser<'a> { // This exception is here for backwards compatibility. && !token.is_keyword(kw::Const) } + // Current edition expressions NonterminalKind::Expr(Expr) => { - token.can_begin_expr() + // In Edition 2024, `_` will be considered an expression, so we + // need to allow it here because `token.can_begin_expr()` does + // not consider `_` to be an expression. + // + // Because `can_begin_expr` is used elsewhere, we need to reduce + // the scope of where the `_` is considered an expression to + // just macro parsing code. + (token.can_begin_expr() || token.is_keyword(kw::Underscore)) // This exception is here for backwards compatibility. && !token.is_keyword(kw::Let) } diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr new file mode 100644 index 0000000000000..335b3f613434b --- /dev/null +++ b/tests/ui/macros/expr_2024_underscore_expr.edi2021.stderr @@ -0,0 +1,32 @@ +error: no rules expected the token `_` + --> $DIR/expr_2024_underscore_expr.rs:22:12 + | +LL | macro_rules! m2021 { + | ------------------ when calling this macro +... +LL | m2021!(_); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr_2021` + --> $DIR/expr_2024_underscore_expr.rs:10:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: no rules expected the token `_` + --> $DIR/expr_2024_underscore_expr.rs:23:12 + | +LL | macro_rules! m2024 { + | ------------------ when calling this macro +... +LL | m2024!(_); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr` + --> $DIR/expr_2024_underscore_expr.rs:16:6 + | +LL | ($e:expr) => { + | ^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr new file mode 100644 index 0000000000000..e6c2bef10e299 --- /dev/null +++ b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr @@ -0,0 +1,17 @@ +error: no rules expected the token `_` + --> $DIR/expr_2024_underscore_expr.rs:23:12 + | +LL | macro_rules! m2021 { + | ------------------ when calling this macro +... +LL | m2021!(_); + | ^ no rules expected this token in macro call + | +note: while trying to match meta-variable `$e:expr_2021` + --> $DIR/expr_2024_underscore_expr.rs:11:6 + | +LL | ($e:expr_2021) => { + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/macros/expr_2024_underscore_expr.rs b/tests/ui/macros/expr_2024_underscore_expr.rs new file mode 100644 index 0000000000000..b2129bf154f7e --- /dev/null +++ b/tests/ui/macros/expr_2024_underscore_expr.rs @@ -0,0 +1,24 @@ +//@ revisions: edi2021 edi2024 +//@[edi2024]compile-flags: --edition=2024 -Z unstable-options +//@[edi2021]compile-flags: --edition=2021 +// This test ensures that the `_` tok is considered an +// expression on edition 2024. +#![feature(expr_fragment_specifier_2024)] +#![allow(incomplete_features)] + +macro_rules! m2021 { + ($e:expr_2021) => { + $e = 1; + }; +} + +macro_rules! m2024 { + ($e:expr) => { + $e = 1; + }; +} + +fn main() { + m2021!(_); //~ ERROR: no rules expected the token `_` + m2024!(_); //[edi2021]~ ERROR: no rules expected the token `_` +} From 6b731c2e7d25965cbea9bdf34233a500acb594f3 Mon Sep 17 00:00:00 2001 From: Vincenzo Palazzo Date: Fri, 26 Jul 2024 20:56:41 +0000 Subject: [PATCH 341/489] tests: add the _ as expr test for cargo fix Co-authored-by: Eric Holk Signed-off-by: Vincenzo Palazzo --- tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr index e6c2bef10e299..9e49f66a89ae8 100644 --- a/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr +++ b/tests/ui/macros/expr_2024_underscore_expr.edi2024.stderr @@ -1,5 +1,5 @@ error: no rules expected the token `_` - --> $DIR/expr_2024_underscore_expr.rs:23:12 + --> $DIR/expr_2024_underscore_expr.rs:22:12 | LL | macro_rules! m2021 { | ------------------ when calling this macro @@ -8,7 +8,7 @@ LL | m2021!(_); | ^ no rules expected this token in macro call | note: while trying to match meta-variable `$e:expr_2021` - --> $DIR/expr_2024_underscore_expr.rs:11:6 + --> $DIR/expr_2024_underscore_expr.rs:10:6 | LL | ($e:expr_2021) => { | ^^^^^^^^^^^^ From 83fb140ec109013b299fb400d71ac2894c962cc4 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Wed, 31 Jul 2024 22:00:38 +0300 Subject: [PATCH 342/489] Fix docs for OnceLock::get_mut_or_init --- library/std/src/sync/once_lock.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 60e43a1cde10e..f8946aa9d42f3 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -281,9 +281,7 @@ impl OnceLock { /// Gets the mutable reference of the contents of the cell, initializing /// it with `f` if the cell was empty. /// - /// Many threads may call `get_mut_or_init` concurrently with different - /// initializing functions, but it is guaranteed that only one function - /// will be executed. + /// This method never blocks. /// /// # Panics /// @@ -373,6 +371,8 @@ impl OnceLock { /// it with `f` if the cell was empty. If the cell was empty and `f` failed, /// an error is returned. /// + /// This method never blocks. + /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and From 79ef91e879d15bf13b8903379c36c08ad4788587 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 31 Jul 2024 15:37:55 -0400 Subject: [PATCH 343/489] tweak comment on `NonterminalKind::Expr` Co-authored-by: Eric Holk --- compiler/rustc_parse/src/parser/nonterminal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 730b3a57142a2..54f4a4ead078c 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -48,7 +48,7 @@ impl<'a> Parser<'a> { } // Current edition expressions NonterminalKind::Expr(Expr) => { - // In Edition 2024, `_` will be considered an expression, so we + // In Edition 2024, `_` is considered an expression, so we // need to allow it here because `token.can_begin_expr()` does // not consider `_` to be an expression. // From 6d7bb127e6fab4e8d80b44826eca28f274139eed Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 31 Jul 2024 19:39:39 +0000 Subject: [PATCH 344/489] Emit an error if `#[optimize]` is applied to an incompatible item --- compiler/rustc_passes/messages.ftl | 4 ++++ compiler/rustc_passes/src/check_attr.rs | 22 +++++++++++++++++++ compiler/rustc_passes/src/errors.rs | 4 ++++ tests/ui/attributes/optimize.rs | 28 +++++++++++++++++++++++++ tests/ui/attributes/optimize.stderr | 20 ++++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 tests/ui/attributes/optimize.rs create mode 100644 tests/ui/attributes/optimize.stderr diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index bfe0d54e64521..1747307a1b2c5 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -542,6 +542,10 @@ passes_only_has_effect_on = *[unspecified] (unspecified--this is a compiler bug) } +passes_optimize_not_fn_or_closure = + attribute should be applied to function or closure + .label = not a function or closure + passes_outer_crate_level_attr = crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3a62ba66b54ed..86b18570f376b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -124,6 +124,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } [sym::inline] => self.check_inline(hir_id, attr, span, target), [sym::coverage] => self.check_coverage(attr, span, target), + [sym::optimize] => self.check_optimize(hir_id, attr, target), [sym::non_exhaustive] => self.check_non_exhaustive(hir_id, attr, span, target), [sym::marker] => self.check_marker(hir_id, attr, span, target), [sym::target_feature] => { @@ -373,6 +374,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } + /// Checks that `#[optimize(..)]` is applied to a function/closure/method, + /// or to an impl block or module. + fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) { + match target { + Target::Fn + | Target::Closure + | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) + | Target::Impl + | Target::Mod => {} + + _ => { + self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::OptimizeNotFnOrClosure, + ); + } + } + } + fn check_generic_attr( &self, hir_id: HirId, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index ff85be109d460..c4f3c8a0d6cf3 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -68,6 +68,10 @@ pub struct CoverageNotFnOrClosure { pub defn_span: Span, } +#[derive(LintDiagnostic)] +#[diag(passes_optimize_not_fn_or_closure)] +pub struct OptimizeNotFnOrClosure; + #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn)] pub struct AttrShouldBeAppliedToFn { diff --git a/tests/ui/attributes/optimize.rs b/tests/ui/attributes/optimize.rs new file mode 100644 index 0000000000000..b01806165c1f5 --- /dev/null +++ b/tests/ui/attributes/optimize.rs @@ -0,0 +1,28 @@ +#![feature(optimize_attribute)] +#![feature(stmt_expr_attributes)] +#![deny(unused_attributes)] +#![allow(dead_code)] + +#[optimize(speed)] //~ ERROR attribute should be applied to function or closure +struct F; + +fn invalid() { + #[optimize(speed)] //~ ERROR attribute should be applied to function or closure + { + 1 + }; +} + +#[optimize(speed)] +fn valid() {} + +#[optimize(speed)] +mod valid_module {} + +#[optimize(speed)] +impl F {} + +fn main() { + let _ = #[optimize(speed)] + (|| 1); +} diff --git a/tests/ui/attributes/optimize.stderr b/tests/ui/attributes/optimize.stderr new file mode 100644 index 0000000000000..3c445d73c2edb --- /dev/null +++ b/tests/ui/attributes/optimize.stderr @@ -0,0 +1,20 @@ +error: attribute should be applied to function or closure + --> $DIR/optimize.rs:6:1 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/optimize.rs:3:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: attribute should be applied to function or closure + --> $DIR/optimize.rs:10:5 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 1df27d84a1f4a45610ad2ba3e5fd982c532ea4fb Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Wed, 31 Jul 2024 16:10:42 -0700 Subject: [PATCH 345/489] docs: Fix JSON example for rust-analyzer.workspace.discoverConfig The user does not specify `{arg}` in their JSON, and be pedantic about commas in JSON sample. --- src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs | 7 +++---- src/tools/rust-analyzer/docs/user/generated_config.adoc | 7 +++---- src/tools/rust-analyzer/editors/code/package.json | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 2b29be7fa28c6..b9b8cfdfc9eab 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -341,13 +341,12 @@ config_data! { /// "rust-analyzer.workspace.discoverConfig": { /// "command": [ /// "rust-project", - /// "develop-json", - /// {arg} + /// "develop-json" /// ], /// "progressLabel": "rust-analyzer", /// "filesToWatch": [ - /// "BUCK", - /// ], + /// "BUCK" + /// ] /// } /// ``` /// diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 29342e4b673a4..ac95767ea5b79 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -1019,13 +1019,12 @@ Below is an example of a valid configuration: "rust-analyzer.workspace.discoverConfig": { "command": [ "rust-project", - "develop-json", - {arg} + "develop-json" ], "progressLabel": "rust-analyzer", "filesToWatch": [ - "BUCK", - ], + "BUCK" + ] } ``` diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 40552cab40a7a..4b594129a3662 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -2571,7 +2571,7 @@ "title": "workspace", "properties": { "rust-analyzer.workspace.discoverConfig": { - "markdownDescription": "Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`].\n\n[`DiscoverWorkspaceConfig`] also requires setting `progress_label` and `files_to_watch`.\n`progress_label` is used for the title in progress indicators, whereas `files_to_watch`\nis used to determine which build system-specific files should be watched in order to\nreload rust-analyzer.\n\nBelow is an example of a valid configuration:\n```json\n\"rust-analyzer.workspace.discoverConfig\": {\n \"command\": [\n \"rust-project\",\n \"develop-json\",\n {arg}\n ],\n \"progressLabel\": \"rust-analyzer\",\n \"filesToWatch\": [\n \"BUCK\",\n ],\n}\n```\n\n## On `DiscoverWorkspaceConfig::command`\n\n**Warning**: This format is provisional and subject to change.\n\n[`DiscoverWorkspaceConfig::command`] *must* return a JSON object\ncorresponding to `DiscoverProjectData::Finished`:\n\n```norun\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(tag = \"kind\")]\n#[serde(rename_all = \"snake_case\")]\nenum DiscoverProjectData {\n Finished { buildfile: Utf8PathBuf, project: ProjectJsonData },\n Error { error: String, source: Option },\n Progress { message: String },\n}\n```\n\nAs JSON, `DiscoverProjectData::Finished` is:\n\n```json\n{\n // the internally-tagged representation of the enum.\n \"kind\": \"finished\",\n // the file used by a non-Cargo build system to define\n // a package or target.\n \"buildfile\": \"rust-analyzer/BUILD\",\n // the contents of a rust-project.json, elided for brevity\n \"project\": {\n \"sysroot\": \"foo\",\n \"crates\": []\n }\n}\n```\n\nIt is encouraged, but not required, to use the other variants on\n`DiscoverProjectData` to provide a more polished end-user experience.\n\n`DiscoverWorkspaceConfig::command` may *optionally* include an `{arg}`,\nwhich will be substituted with the JSON-serialized form of the following\nenum:\n\n```norun\n#[derive(PartialEq, Clone, Debug, Serialize)]\n#[serde(rename_all = \"camelCase\")]\npub enum DiscoverArgument {\n Path(AbsPathBuf),\n Buildfile(AbsPathBuf),\n}\n```\n\nThe JSON representation of `DiscoverArgument::Path` is:\n\n```json\n{\n \"path\": \"src/main.rs\"\n}\n```\n\nSimilarly, the JSON representation of `DiscoverArgument::Buildfile` is:\n\n```\n{\n \"buildfile\": \"BUILD\"\n}\n```\n\n`DiscoverArgument::Path` is used to find and generate a `rust-project.json`,\nand therefore, a workspace, whereas `DiscoverArgument::buildfile` is used to\nto update an existing workspace. As a reference for implementors,\nbuck2's `rust-project` will likely be useful:\nhttps://github.com/facebook/buck2/tree/main/integrations/rust-project.", + "markdownDescription": "Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`].\n\n[`DiscoverWorkspaceConfig`] also requires setting `progress_label` and `files_to_watch`.\n`progress_label` is used for the title in progress indicators, whereas `files_to_watch`\nis used to determine which build system-specific files should be watched in order to\nreload rust-analyzer.\n\nBelow is an example of a valid configuration:\n```json\n\"rust-analyzer.workspace.discoverConfig\": {\n \"command\": [\n \"rust-project\",\n \"develop-json\"\n ],\n \"progressLabel\": \"rust-analyzer\",\n \"filesToWatch\": [\n \"BUCK\"\n ]\n}\n```\n\n## On `DiscoverWorkspaceConfig::command`\n\n**Warning**: This format is provisional and subject to change.\n\n[`DiscoverWorkspaceConfig::command`] *must* return a JSON object\ncorresponding to `DiscoverProjectData::Finished`:\n\n```norun\n#[derive(Debug, Clone, Deserialize, Serialize)]\n#[serde(tag = \"kind\")]\n#[serde(rename_all = \"snake_case\")]\nenum DiscoverProjectData {\n Finished { buildfile: Utf8PathBuf, project: ProjectJsonData },\n Error { error: String, source: Option },\n Progress { message: String },\n}\n```\n\nAs JSON, `DiscoverProjectData::Finished` is:\n\n```json\n{\n // the internally-tagged representation of the enum.\n \"kind\": \"finished\",\n // the file used by a non-Cargo build system to define\n // a package or target.\n \"buildfile\": \"rust-analyzer/BUILD\",\n // the contents of a rust-project.json, elided for brevity\n \"project\": {\n \"sysroot\": \"foo\",\n \"crates\": []\n }\n}\n```\n\nIt is encouraged, but not required, to use the other variants on\n`DiscoverProjectData` to provide a more polished end-user experience.\n\n`DiscoverWorkspaceConfig::command` may *optionally* include an `{arg}`,\nwhich will be substituted with the JSON-serialized form of the following\nenum:\n\n```norun\n#[derive(PartialEq, Clone, Debug, Serialize)]\n#[serde(rename_all = \"camelCase\")]\npub enum DiscoverArgument {\n Path(AbsPathBuf),\n Buildfile(AbsPathBuf),\n}\n```\n\nThe JSON representation of `DiscoverArgument::Path` is:\n\n```json\n{\n \"path\": \"src/main.rs\"\n}\n```\n\nSimilarly, the JSON representation of `DiscoverArgument::Buildfile` is:\n\n```\n{\n \"buildfile\": \"BUILD\"\n}\n```\n\n`DiscoverArgument::Path` is used to find and generate a `rust-project.json`,\nand therefore, a workspace, whereas `DiscoverArgument::buildfile` is used to\nto update an existing workspace. As a reference for implementors,\nbuck2's `rust-project` will likely be useful:\nhttps://github.com/facebook/buck2/tree/main/integrations/rust-project.", "default": null, "anyOf": [ { From 68df46c4c2b8056fd45ca792718ab048c9dbfb29 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 1 Aug 2024 13:31:25 +1000 Subject: [PATCH 346/489] Finish blessing `coverage/mcdc` tests after LLVM 19 upgrade --- tests/coverage/mcdc/condition-limit.coverage | 1 + tests/coverage/mcdc/if.coverage | 1 + tests/coverage/mcdc/inlined_expressions.coverage | 1 + tests/coverage/mcdc/nested_if.coverage | 1 + tests/coverage/mcdc/non_control_flow.coverage | 1 + 5 files changed, 5 insertions(+) diff --git a/tests/coverage/mcdc/condition-limit.coverage b/tests/coverage/mcdc/condition-limit.coverage index 4eb87432fab48..81e832d6a498c 100644 --- a/tests/coverage/mcdc/condition-limit.coverage +++ b/tests/coverage/mcdc/condition-limit.coverage @@ -1,6 +1,7 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 LL| |//@ min-llvm-version: 18 + LL| |//@ ignore-llvm-version: 19 - 99 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/if.coverage b/tests/coverage/mcdc/if.coverage index 91fff073d0cff..dc93319950b0d 100644 --- a/tests/coverage/mcdc/if.coverage +++ b/tests/coverage/mcdc/if.coverage @@ -1,6 +1,7 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 LL| |//@ min-llvm-version: 18 + LL| |//@ ignore-llvm-version: 19 - 99 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/inlined_expressions.coverage b/tests/coverage/mcdc/inlined_expressions.coverage index 5b083d6218680..4e4800310c98a 100644 --- a/tests/coverage/mcdc/inlined_expressions.coverage +++ b/tests/coverage/mcdc/inlined_expressions.coverage @@ -1,6 +1,7 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 LL| |//@ min-llvm-version: 18 + LL| |//@ ignore-llvm-version: 19 - 99 LL| |//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0 LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/nested_if.coverage b/tests/coverage/mcdc/nested_if.coverage index a273a713a8ab8..916bb94745daf 100644 --- a/tests/coverage/mcdc/nested_if.coverage +++ b/tests/coverage/mcdc/nested_if.coverage @@ -1,6 +1,7 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 LL| |//@ min-llvm-version: 18 + LL| |//@ ignore-llvm-version: 19 - 99 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | diff --git a/tests/coverage/mcdc/non_control_flow.coverage b/tests/coverage/mcdc/non_control_flow.coverage index 6ae796e8ed203..c64f61a153c19 100644 --- a/tests/coverage/mcdc/non_control_flow.coverage +++ b/tests/coverage/mcdc/non_control_flow.coverage @@ -1,6 +1,7 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 LL| |//@ min-llvm-version: 18 + LL| |//@ ignore-llvm-version: 19 - 99 LL| |//@ compile-flags: -Zcoverage-options=mcdc LL| |//@ llvm-cov-flags: --show-branches=count --show-mcdc LL| | From 36075eb7f3b82541d5323e4ddd0e854c0c9cbca1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Aug 2024 14:30:49 +1000 Subject: [PATCH 347/489] Ignore `use` declaration reformatting in `.git-blame-ignore-revs`. --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 663ace48e9e80..9fd8054a12e46 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -23,3 +23,5 @@ b2d2184edea578109a48ec3d8decbee5948e8f35 # test directives migration 6e48b96692d63a79a14563f27fe5185f122434f8 ec2cc761bc7067712ecc7734502f703fe3b024c8 +# format use declarations +84ac80f1921afc243d71fd0caaa4f2838c294102 From 5af27e4617590d82572e41867aac1a1cc8e41809 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Aug 2024 11:29:40 +0200 Subject: [PATCH 348/489] flock: a bit of cleanup --- src/tools/miri/src/shims/unix/fd.rs | 14 +++++++------- src/tools/miri/src/shims/unix/fs.rs | 4 ++-- .../miri/tests/pass-dep/libc/libc-fs-flock.rs | 1 - 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index 464b4638c6337..1b25ef05769b9 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -12,6 +12,13 @@ use rustc_target::abi::Size; use crate::shims::unix::*; use crate::*; +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub(crate) enum FlockOp { + SharedLock { nonblocking: bool }, + ExclusiveLock { nonblocking: bool }, + Unlock, +} + /// Represents an open file descriptor. pub trait FileDescription: std::fmt::Debug + Any { fn name(&self) -> &'static str; @@ -567,10 +574,3 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(Scalar::from_target_isize(this.try_unwrap_io_result(result)?, this)) } } - -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub(crate) enum FlockOp { - SharedLock { nonblocking: bool }, - ExclusiveLock { nonblocking: bool }, - Unlock, -} diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 5606e3d85b71a..ebe928018b09f 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -198,8 +198,8 @@ impl FileDescription for FileHandle { let code: u32 = err.raw_os_error().unwrap().try_into().unwrap(); if matches!(code, ERROR_IO_PENDING | ERROR_LOCK_VIOLATION) { if lock_nb { - // Replace error with a custom WouldBlock error, which later will be - // mapped in the `helpers` module + // The io error mapping does not know about these error codes, + // so we translate it to `WouldBlock` manually. let desc = format!("LockFileEx wouldblock error: {err}"); err = io::Error::new(io::ErrorKind::WouldBlock, desc); } else { diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs index c1b3b8f575c99..3f7f9b18be931 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-flock.rs @@ -1,4 +1,3 @@ -// Flock tests are separate since they don't in general work on a Windows host. //@ignore-target-windows: File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation From 2eb2ef1684e4df67389432fe0c1cc2776c790cd7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 31 Jul 2024 19:16:09 +1000 Subject: [PATCH 349/489] Streamline attribute stitching on AST nodes. It can be done more concisely. --- .../rustc_parse/src/parser/attr_wrapper.rs | 7 +++---- compiler/rustc_parse/src/parser/expr.rs | 18 +++++++----------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 611dbc0535c61..ba20bd9daf708 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -53,10 +53,9 @@ impl AttrWrapper { /// Prepend `self.attrs` to `attrs`. // FIXME: require passing an NT to prevent misuse of this method - pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) { - let mut self_attrs = self.attrs; - mem::swap(attrs, &mut self_attrs); - attrs.extend(self_attrs); + pub(crate) fn prepend_to_nt_inner(mut self, attrs: &mut AttrVec) { + mem::swap(attrs, &mut self.attrs); + attrs.extend(self.attrs); } pub fn is_empty(&self) -> bool { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 24e56c5bdee66..ae5c8af7c2d0d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -877,7 +877,7 @@ impl<'a> Parser<'a> { mut e: P, lo: Span, ) -> PResult<'a, P> { - let res = ensure_sufficient_stack(|| { + let mut res = ensure_sufficient_stack(|| { loop { let has_question = if self.prev_token.kind == TokenKind::Ident(kw::Return, IdentIsRaw::No) { @@ -924,17 +924,13 @@ impl<'a> Parser<'a> { // Stitch the list of outer attributes onto the return value. A little // bit ugly, but the best way given the current code structure. - if attrs.is_empty() { - res - } else { - res.map(|expr| { - expr.map(|mut expr| { - attrs.extend(expr.attrs); - expr.attrs = attrs; - expr - }) - }) + if !attrs.is_empty() + && let Ok(expr) = &mut res + { + mem::swap(&mut expr.attrs, &mut attrs); + expr.attrs.extend(attrs) } + res } pub(super) fn parse_dot_suffix_expr( From 9d77d17f7127def53c6a3555ae9a6a1f271a8e37 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Aug 2024 15:41:51 +1000 Subject: [PATCH 350/489] Move a comment to a better spot. --- compiler/rustc_parse/src/parser/stmt.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index e0676b72634e7..b3efb87a4a26a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -116,13 +116,12 @@ impl<'a> Parser<'a> { } } } else if let Some(item) = self.parse_item_common( - attrs.clone(), + attrs.clone(), // FIXME: unwanted clone of attrs false, true, FnParseMode { req_name: |_| true, req_body: true }, force_collect, )? { - // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { // Do not attempt to parse an expression if we're done here. From d1f05fd1848fc68ed89d17f7937e358dacd8aed4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Aug 2024 06:44:39 +1000 Subject: [PATCH 351/489] Distinguish the two kinds of token range. When collecting tokens there are two kinds of range: - a range relative to the parser's full token stream (which we get when we are parsing); - a range relative to a single AST node's token stream (which we use within `LazyAttrTokenStreamImpl` when replacing tokens). These are currently both represented with `Range` and it's easy to mix them up -- until now I hadn't properly understood the difference. This commit introduces `ParserRange` and `NodeRange` to distinguish them. This also requires splitting `ReplaceRange` in two, giving the new types `ParserReplacement` and `NodeReplacement`. (These latter two names reduce the overloading of the word "range".) The commit also rewrites some comments to be clearer. The end result is a little more verbose, but much clearer. --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 2 +- compiler/rustc_parse/src/parser/attr.rs | 6 +- .../rustc_parse/src/parser/attr_wrapper.rs | 124 ++++++++++-------- compiler/rustc_parse/src/parser/mod.rs | 70 +++++++--- 4 files changed, 124 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index dc1874bfecbda..4b05c144d37d7 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -202,7 +202,7 @@ impl CfgEval<'_> { } // Now that we have our re-parsed `AttrTokenStream`, recursively configuring - // our attribute target will correctly the tokens as well. + // our attribute target will correctly configure the tokens as well. flat_map_annotatable(self, annotatable) } } diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 12b9414d1f760..a98382efc3eba 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -8,7 +8,7 @@ use rustc_span::{sym, BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; -use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, ParserRange, PathStyle}; use crate::{errors, fluent_generated as fluent, maybe_whole}; // Public for rustfmt usage @@ -307,8 +307,8 @@ impl<'a> Parser<'a> { // inner attribute, for possible later processing in a `LazyAttrTokenStream`. if let Capturing::Yes = self.capture_state.capturing { let end_pos = self.num_bump_calls; - let range = start_pos..end_pos; - self.capture_state.inner_attr_ranges.insert(attr.id, range); + let parser_range = ParserRange(start_pos..end_pos); + self.capture_state.inner_attr_parser_ranges.insert(attr.id, parser_range); } attrs.push(attr); } else { diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index ba20bd9daf708..abf61036c2deb 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -10,7 +10,10 @@ use rustc_errors::PResult; use rustc_session::parse::ParseSess; use rustc_span::{sym, Span, DUMMY_SP}; -use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor}; +use super::{ + Capturing, FlatToken, ForceCollect, NodeRange, NodeReplacement, Parser, ParserRange, + TokenCursor, +}; /// A wrapper type to ensure that the parser handles outer attributes correctly. /// When we parse outer attributes, we need to ensure that we capture tokens @@ -28,8 +31,8 @@ use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCurso #[derive(Debug, Clone)] pub struct AttrWrapper { attrs: AttrVec, - // The start of the outer attributes in the token cursor. - // This allows us to create a `ReplaceRange` for the entire attribute + // The start of the outer attributes in the parser's token stream. + // This lets us create a `NodeReplacement` for the entire attribute // target, including outer attributes. start_pos: u32, } @@ -88,7 +91,7 @@ struct LazyAttrTokenStreamImpl { cursor_snapshot: TokenCursor, num_calls: u32, break_last_token: bool, - replace_ranges: Box<[ReplaceRange]>, + node_replacements: Box<[NodeReplacement]>, } impl ToAttrTokenStream for LazyAttrTokenStreamImpl { @@ -103,21 +106,24 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { .chain(iter::repeat_with(|| FlatToken::Token(cursor_snapshot.next()))) .take(self.num_calls as usize); - if self.replace_ranges.is_empty() { + if self.node_replacements.is_empty() { make_attr_token_stream(tokens, self.break_last_token) } else { let mut tokens: Vec<_> = tokens.collect(); - let mut replace_ranges = self.replace_ranges.to_vec(); - replace_ranges.sort_by_key(|(range, _)| range.start); + let mut node_replacements = self.node_replacements.to_vec(); + node_replacements.sort_by_key(|(range, _)| range.0.start); #[cfg(debug_assertions)] - for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() { + for [(node_range, tokens), (next_node_range, next_tokens)] in + node_replacements.array_windows() + { assert!( - range.end <= next_range.start || range.end >= next_range.end, - "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", - range, + node_range.0.end <= next_node_range.0.start + || node_range.0.end >= next_node_range.0.end, + "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})", + node_range, tokens, - next_range, + next_node_range, next_tokens, ); } @@ -135,20 +141,23 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl { // start position, we ensure that any (outer) replace range which // encloses another (inner) replace range will fully overwrite the // inner range's replacement. - for (range, target) in replace_ranges.into_iter().rev() { - assert!(!range.is_empty(), "Cannot replace an empty range: {range:?}"); + for (node_range, target) in node_replacements.into_iter().rev() { + assert!( + !node_range.0.is_empty(), + "Cannot replace an empty node range: {:?}", + node_range.0 + ); // Replace the tokens in range with zero or one `FlatToken::AttrsTarget`s, plus // enough `FlatToken::Empty`s to fill up the rest of the range. This keeps the // total length of `tokens` constant throughout the replacement process, allowing - // us to use all of the `ReplaceRanges` entries without adjusting indices. + // us to do all replacements without adjusting indices. let target_len = target.is_some() as usize; tokens.splice( - (range.start as usize)..(range.end as usize), - target - .into_iter() - .map(|target| FlatToken::AttrsTarget(target)) - .chain(iter::repeat(FlatToken::Empty).take(range.len() - target_len)), + (node_range.0.start as usize)..(node_range.0.end as usize), + target.into_iter().map(|target| FlatToken::AttrsTarget(target)).chain( + iter::repeat(FlatToken::Empty).take(node_range.0.len() - target_len), + ), ); } make_attr_token_stream(tokens.into_iter(), self.break_last_token) @@ -215,7 +224,7 @@ impl<'a> Parser<'a> { let cursor_snapshot = self.token_cursor.clone(); let start_pos = self.num_bump_calls; let has_outer_attrs = !attrs.attrs.is_empty(); - let replace_ranges_start = self.capture_state.replace_ranges.len(); + let parser_replacements_start = self.capture_state.parser_replacements.len(); // We set and restore `Capturing::Yes` on either side of the call to // `f`, so we can distinguish the outermost call to @@ -270,7 +279,7 @@ impl<'a> Parser<'a> { return Ok(ret); } - let replace_ranges_end = self.capture_state.replace_ranges.len(); + let parser_replacements_end = self.capture_state.parser_replacements.len(); assert!( !(self.break_last_token && capture_trailing), @@ -287,15 +296,16 @@ impl<'a> Parser<'a> { let num_calls = end_pos - start_pos; - // Take the captured ranges for any inner attributes that we parsed in - // `Parser::parse_inner_attributes`, and pair them in a `ReplaceRange` - // with `None`, which means the relevant tokens will be removed. (More - // details below.) - let mut inner_attr_replace_ranges = Vec::new(); + // Take the captured `ParserRange`s for any inner attributes that we parsed in + // `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`, + // which means the relevant tokens will be removed. (More details below.) + let mut inner_attr_parser_replacements = Vec::new(); for attr in ret.attrs() { if attr.style == ast::AttrStyle::Inner { - if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&attr.id) { - inner_attr_replace_ranges.push((attr_range, None)); + if let Some(inner_attr_parser_range) = + self.capture_state.inner_attr_parser_ranges.remove(&attr.id) + { + inner_attr_parser_replacements.push((inner_attr_parser_range, None)); } else { self.dcx().span_delayed_bug(attr.span, "Missing token range for attribute"); } @@ -304,37 +314,41 @@ impl<'a> Parser<'a> { // This is hot enough for `deep-vector` that checking the conditions for an empty iterator // is measurably faster than actually executing the iterator. - let replace_ranges: Box<[ReplaceRange]> = - if replace_ranges_start == replace_ranges_end && inner_attr_replace_ranges.is_empty() { - Box::new([]) - } else { - // Grab any replace ranges that occur *inside* the current AST node. We will - // perform the actual replacement only when we convert the `LazyAttrTokenStream` to - // an `AttrTokenStream`. - self.capture_state.replace_ranges[replace_ranges_start..replace_ranges_end] - .iter() - .cloned() - .chain(inner_attr_replace_ranges.iter().cloned()) - .map(|(range, data)| ((range.start - start_pos)..(range.end - start_pos), data)) - .collect() - }; + let node_replacements: Box<[_]> = if parser_replacements_start == parser_replacements_end + && inner_attr_parser_replacements.is_empty() + { + Box::new([]) + } else { + // Grab any replace ranges that occur *inside* the current AST node. Convert them + // from `ParserRange` form to `NodeRange` form. We will perform the actual + // replacement only when we convert the `LazyAttrTokenStream` to an + // `AttrTokenStream`. + self.capture_state.parser_replacements + [parser_replacements_start..parser_replacements_end] + .iter() + .cloned() + .chain(inner_attr_parser_replacements.iter().cloned()) + .map(|(parser_range, data)| (NodeRange::new(parser_range, start_pos), data)) + .collect() + }; // What is the status here when parsing the example code at the top of this method? // // When parsing `g`: // - `start_pos..end_pos` is `12..33` (`fn g { ... }`, excluding the outer attr). - // - `inner_attr_replace_ranges` has one entry (`5..15`, when counting from `fn`), to + // - `inner_attr_parser_replacements` has one entry (`ParserRange(17..27)`), to // delete the inner attr's tokens. - // - This entry is put into the lazy tokens for `g`, i.e. deleting the inner attr from - // those tokens (if they get evaluated). + // - This entry is converted to `NodeRange(5..15)` (relative to the `fn`) and put into + // the lazy tokens for `g`, i.e. deleting the inner attr from those tokens (if they get + // evaluated). // - Those lazy tokens are also put into an `AttrsTarget` that is appended to `self`'s // replace ranges at the bottom of this function, for processing when parsing `m`. - // - `replace_ranges_start..replace_ranges_end` is empty. + // - `parser_replacements_start..parser_replacements_end` is empty. // // When parsing `m`: // - `start_pos..end_pos` is `0..34` (`mod m`, excluding the `#[cfg_eval]` attribute). - // - `inner_attr_replace_ranges` is empty. - // - `replace_range_start..replace_ranges_end` has one entry. + // - `inner_attr_parser_replacements` is empty. + // - `parser_replacements_start..parser_replacements_end` has one entry. // - One `AttrsTarget` (added below when parsing `g`) to replace all of `g` (`3..33`, // including its outer attribute), with: // - `attrs`: includes the outer and the inner attr. @@ -345,7 +359,7 @@ impl<'a> Parser<'a> { num_calls, cursor_snapshot, break_last_token: self.break_last_token, - replace_ranges, + node_replacements, }); // If we support tokens and don't already have them, store the newly captured tokens. @@ -366,7 +380,7 @@ impl<'a> Parser<'a> { // What is the status here when parsing the example code at the top of this method? // // When parsing `g`, we add one entry: - // - The `start_pos..end_pos` (`3..33`) entry has a new `AttrsTarget` with: + // - The pushed entry (`ParserRange(3..33)`) has a new `AttrsTarget` with: // - `attrs`: includes the outer and the inner attr. // - `tokens`: lazy tokens for `g` (with its inner attr deleted). // @@ -377,12 +391,14 @@ impl<'a> Parser<'a> { // cfg-expand this AST node. let start_pos = if has_outer_attrs { attrs.start_pos } else { start_pos }; let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens }; - self.capture_state.replace_ranges.push((start_pos..end_pos, Some(target))); + self.capture_state + .parser_replacements + .push((ParserRange(start_pos..end_pos), Some(target))); } else if matches!(self.capture_state.capturing, Capturing::No) { // Only clear the ranges once we've finished capturing entirely, i.e. we've finished // the outermost call to this method. - self.capture_state.replace_ranges.clear(); - self.capture_state.inner_attr_ranges.clear(); + self.capture_state.parser_replacements.clear(); + self.capture_state.inner_attr_parser_ranges.clear(); } Ok(ret) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 26ee5bfdee42c..722fb41cd81ec 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -192,24 +192,54 @@ struct ClosureSpans { body: Span, } -/// Indicates a range of tokens that should be replaced by -/// the tokens in the provided `AttrsTarget`. This is used in two -/// places during token collection: +/// A token range within a `Parser`'s full token stream. +#[derive(Clone, Debug)] +struct ParserRange(Range); + +/// A token range within an individual AST node's (lazy) token stream, i.e. +/// relative to that node's first token. Distinct from `ParserRange` so the two +/// kinds of range can't be mixed up. +#[derive(Clone, Debug)] +struct NodeRange(Range); + +/// Indicates a range of tokens that should be replaced by an `AttrsTarget` +/// (replacement) or be replaced by nothing (deletion). This is used in two +/// places during token collection. +/// +/// 1. Replacement. During the parsing of an AST node that may have a +/// `#[derive]` attribute, when we parse a nested AST node that has `#[cfg]` +/// or `#[cfg_attr]`, we replace the entire inner AST node with +/// `FlatToken::AttrsTarget`. This lets us perform eager cfg-expansion on an +/// `AttrTokenStream`. /// -/// 1. During the parsing of an AST node that may have a `#[derive]` -/// attribute, we parse a nested AST node that has `#[cfg]` or `#[cfg_attr]` -/// In this case, we use a `ReplaceRange` to replace the entire inner AST node -/// with `FlatToken::AttrsTarget`, allowing us to perform eager cfg-expansion -/// on an `AttrTokenStream`. +/// 2. Deletion. We delete inner attributes from all collected token streams, +/// and instead track them through the `attrs` field on the AST node. This +/// lets us manipulate them similarly to outer attributes. When we create a +/// `TokenStream`, the inner attributes are inserted into the proper place +/// in the token stream. /// -/// 2. When we parse an inner attribute while collecting tokens. We -/// remove inner attributes from the token stream entirely, and -/// instead track them through the `attrs` field on the AST node. -/// This allows us to easily manipulate them (for example, removing -/// the first macro inner attribute to invoke a proc-macro). -/// When create a `TokenStream`, the inner attributes get inserted -/// into the proper place in the token stream. -type ReplaceRange = (Range, Option); +/// Each replacement starts off in `ParserReplacement` form but is converted to +/// `NodeReplacement` form when it is attached to a single AST node, via +/// `LazyAttrTokenStreamImpl`. +type ParserReplacement = (ParserRange, Option); + +/// See the comment on `ParserReplacement`. +type NodeReplacement = (NodeRange, Option); + +impl NodeRange { + // Converts a range within a parser's tokens to a range within a + // node's tokens beginning at `start_pos`. + // + // For example, imagine a parser with 50 tokens in its token stream, a + // function that spans `ParserRange(20..40)` and an inner attribute within + // that function that spans `ParserRange(30..35)`. We would find the inner + // attribute's range within the function's tokens by subtracting 20, which + // is the position of the function's start token. This gives + // `NodeRange(10..15)`. + fn new(ParserRange(parser_range): ParserRange, start_pos: u32) -> NodeRange { + NodeRange((parser_range.start - start_pos)..(parser_range.end - start_pos)) + } +} /// Controls how we capture tokens. Capturing can be expensive, /// so we try to avoid performing capturing in cases where @@ -226,8 +256,8 @@ enum Capturing { #[derive(Clone, Debug)] struct CaptureState { capturing: Capturing, - replace_ranges: Vec, - inner_attr_ranges: FxHashMap>, + parser_replacements: Vec, + inner_attr_parser_ranges: FxHashMap, } /// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that @@ -417,8 +447,8 @@ impl<'a> Parser<'a> { subparser_name, capture_state: CaptureState { capturing: Capturing::No, - replace_ranges: Vec::new(), - inner_attr_ranges: Default::default(), + parser_replacements: Vec::new(), + inner_attr_parser_ranges: Default::default(), }, current_closure: None, recovery: Recovery::Allowed, From 91175463e4168d3e100a9668a62ca0d0b97e7ba3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Aug 2024 12:26:17 +0200 Subject: [PATCH 352/489] when josh-proxy screws up the roundtrip, say what the involved commits are --- src/tools/miri/miri-script/src/commands.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 62a3ab2c34cf5..fc205040baf57 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -355,7 +355,10 @@ impl Command { let head = cmd!(sh, "git rev-parse HEAD").read()?; let fetch_head = cmd!(sh, "git rev-parse FETCH_HEAD").read()?; if head != fetch_head { - bail!("Josh created a non-roundtrip push! Do NOT merge this into rustc!"); + bail!( + "Josh created a non-roundtrip push! Do NOT merge this into rustc!\n\ + Expected {head}, got {fetch_head}." + ); } println!( "Confirmed that the push round-trips back to Miri properly. Please create a rustc PR:" From 70805f9a6b7af7b759effb2e104f186b9036e0ef Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Aug 2024 12:27:58 +0200 Subject: [PATCH 353/489] when josh-proxy screws up the roundtrip, say what the involved commits are --- src/tools/rust-analyzer/xtask/src/release.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/xtask/src/release.rs b/src/tools/rust-analyzer/xtask/src/release.rs index 3eda2bc0274b6..1a1364c7d10ee 100644 --- a/src/tools/rust-analyzer/xtask/src/release.rs +++ b/src/tools/rust-analyzer/xtask/src/release.rs @@ -202,7 +202,10 @@ impl flags::RustcPush { let head = cmd!(sh, "git rev-parse HEAD").read()?; let fetch_head = cmd!(sh, "git rev-parse FETCH_HEAD").read()?; if head != fetch_head { - bail!("Josh created a non-roundtrip push! Do NOT merge this into rustc!"); + bail!( + "Josh created a non-roundtrip push! Do NOT merge this into rustc!\n\ + Expected {head}, got {fetch_head}." + ); } println!("Confirmed that the push round-trips back to rust-analyzer properly. Please create a rustc PR:"); // https://github.com/github-linguist/linguist/compare/master...octocat:linguist:master From b21af629efb09c528c42f3523cb03c57d7aab244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 31 Jul 2024 13:14:29 +0200 Subject: [PATCH 354/489] refactor(pal/hermit): make `ENV` a non-mutable static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- library/std/src/sys/pal/hermit/os.rs | 34 ++++++++++++---------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index 50ce2f57b306e..f8ea80afa43f1 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -68,21 +68,21 @@ pub fn current_exe() -> io::Result { unsupported() } -static mut ENV: Option>> = None; +static ENV: Mutex>> = Mutex::new(None); pub fn init_environment(env: *const *const i8) { - unsafe { - ENV = Some(Mutex::new(HashMap::new())); + let mut guard = ENV.lock().unwrap(); + let map = guard.insert(HashMap::new()); - if env.is_null() { - return; - } + if env.is_null() { + return; + } - let mut guard = ENV.as_ref().unwrap().lock().unwrap(); + unsafe { let mut environ = env; while !(*environ).is_null() { if let Some((key, value)) = parse(CStr::from_ptr(*environ).to_bytes()) { - guard.insert(key, value); + map.insert(key, value); } environ = environ.add(1); } @@ -154,30 +154,26 @@ impl Iterator for Env { /// Returns a vector of (variable, value) byte-vector pairs for all the /// environment variables of the current process. pub fn env() -> Env { - unsafe { - let guard = ENV.as_ref().unwrap().lock().unwrap(); - let mut result = Vec::new(); + let guard = ENV.lock().unwrap(); + let env = guard.as_ref().unwrap(); - for (key, value) in guard.iter() { - result.push((key.clone(), value.clone())); - } + let result = env.iter().map(|(key, value)| (key.clone(), value.clone())).collect::>(); - return Env { iter: result.into_iter() }; - } + Env { iter: result.into_iter() } } pub fn getenv(k: &OsStr) -> Option { - unsafe { ENV.as_ref().unwrap().lock().unwrap().get_mut(k).cloned() } + ENV.lock().unwrap().as_ref().unwrap().get(k).cloned() } pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> { let (k, v) = (k.to_owned(), v.to_owned()); - ENV.as_ref().unwrap().lock().unwrap().insert(k, v); + ENV.lock().unwrap().as_mut().unwrap().insert(k, v); Ok(()) } pub unsafe fn unsetenv(k: &OsStr) -> io::Result<()> { - ENV.as_ref().unwrap().lock().unwrap().remove(k); + ENV.lock().unwrap().as_mut().unwrap().remove(k); Ok(()) } From 4da966c30e081a178b25e468b12586aa37579d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 31 Jul 2024 13:20:35 +0200 Subject: [PATCH 355/489] fix(pal/hermit): `deny(unsafe_op_in_unsafe_fn)` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- library/std/src/sys/pal/hermit/alloc.rs | 15 +++++++++++---- library/std/src/sys/pal/hermit/fd.rs | 3 ++- library/std/src/sys/pal/hermit/fs.rs | 3 ++- library/std/src/sys/pal/hermit/mod.rs | 15 ++++++++++----- library/std/src/sys/pal/hermit/thread.rs | 24 +++++++++++++++--------- 5 files changed, 40 insertions(+), 20 deletions(-) diff --git a/library/std/src/sys/pal/hermit/alloc.rs b/library/std/src/sys/pal/hermit/alloc.rs index 5daa5f9e49ffe..f10d5f9227e63 100644 --- a/library/std/src/sys/pal/hermit/alloc.rs +++ b/library/std/src/sys/pal/hermit/alloc.rs @@ -1,21 +1,28 @@ use super::hermit_abi; use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::ptr; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - hermit_abi::malloc(layout.size(), layout.align()) + let size = layout.size(); + let align = layout.align(); + unsafe { hermit_abi::malloc(size, align) } } #[inline] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - hermit_abi::free(ptr, layout.size(), layout.align()) + let size = layout.size(); + let align = layout.align(); + unsafe { + hermit_abi::free(ptr, size, align); + } } #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - hermit_abi::realloc(ptr, layout.size(), layout.align(), new_size) + let size = layout.size(); + let align = layout.align(); + unsafe { hermit_abi::realloc(ptr, size, align, new_size) } } } diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs index bdcf880484dfc..79fc13bd4a87f 100644 --- a/library/std/src/sys/pal/hermit/fd.rs +++ b/library/std/src/sys/pal/hermit/fd.rs @@ -111,7 +111,8 @@ impl FromInner for FileDesc { impl FromRawFd for FileDesc { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self { fd: FromRawFd::from_raw_fd(raw_fd) } + let fd = unsafe { OwnedFd::from_raw_fd(raw_fd) }; + Self { fd } } } diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs index cbdb942ac58ef..aaf1a044d0613 100644 --- a/library/std/src/sys/pal/hermit/fs.rs +++ b/library/std/src/sys/pal/hermit/fs.rs @@ -484,7 +484,8 @@ impl IntoRawFd for File { impl FromRawFd for File { unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - Self(FromRawFd::from_raw_fd(raw_fd)) + let file_desc = unsafe { FileDesc::from_raw_fd(raw_fd) }; + Self(file_desc) } } diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 2c9aeb480445c..ef406b9ec7f0d 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -13,7 +13,8 @@ //! compiling for wasm. That way it's a compile time error for something that's //! guaranteed to be a runtime error! -#![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)] +#![deny(unsafe_op_in_unsafe_fn)] +#![allow(missing_docs, nonstandard_style)] use crate::os::raw::c_char; @@ -78,7 +79,9 @@ pub extern "C" fn __rust_abort() { // SAFETY: must be called only once during runtime initialization. // NOTE: this is not guaranteed to run, for example when Rust code is called externally. pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { - args::init(argc, argv); + unsafe { + args::init(argc, argv); + } } // SAFETY: must be called only once during runtime cleanup. @@ -99,10 +102,12 @@ pub unsafe extern "C" fn runtime_entry( // initialize environment os::init_environment(env as *const *const i8); - let result = main(argc as isize, argv); + let result = unsafe { main(argc as isize, argv) }; - crate::sys::thread_local::destructors::run(); - hermit_abi::exit(result) + unsafe { + crate::sys::thread_local::destructors::run(); + } + unsafe { hermit_abi::exit(result) } } #[inline] diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index 95c13e53b470b..6321f92e3d9d0 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -25,18 +25,22 @@ impl Thread { core_id: isize, ) -> io::Result { let p = Box::into_raw(Box::new(p)); - let tid = hermit_abi::spawn2( - thread_start, - p.expose_provenance(), - hermit_abi::Priority::into(hermit_abi::NORMAL_PRIO), - stack, - core_id, - ); + let tid = unsafe { + hermit_abi::spawn2( + thread_start, + p.expose_provenance(), + hermit_abi::Priority::into(hermit_abi::NORMAL_PRIO), + stack, + core_id, + ) + }; return if tid == 0 { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. - drop(Box::from_raw(p)); + unsafe { + drop(Box::from_raw(p)); + } Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Unable to create thread!")) } else { Ok(Thread { tid: tid }) @@ -54,7 +58,9 @@ impl Thread { } pub unsafe fn new(stack: usize, p: Box) -> io::Result { - Thread::new_with_coreid(stack, p, -1 /* = no specific core */) + unsafe { + Thread::new_with_coreid(stack, p, -1 /* = no specific core */) + } } #[inline] From 820ec720ff1fe79672e11ec2307b068d9258fc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 31 Jul 2024 13:29:56 +0200 Subject: [PATCH 356/489] fix(os/hermit): `deny(unsafe_op_in_unsafe_fn)` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- library/std/src/os/hermit/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/os/hermit/mod.rs b/library/std/src/os/hermit/mod.rs index 02a4b2c3ab5e7..5812206a25759 100644 --- a/library/std/src/os/hermit/mod.rs +++ b/library/std/src/os/hermit/mod.rs @@ -1,4 +1,5 @@ #![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] #[allow(unused_extern_crates)] #[stable(feature = "rust1", since = "1.0.0")] From de78cb56b2fa62b7a5cbb036d05e638dd474c6c3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 29 Jul 2024 16:40:21 +0200 Subject: [PATCH 357/489] on a signed deref check, mention the right pointer in the error --- compiler/rustc_const_eval/messages.ftl | 35 +++++--- .../src/const_eval/machine.rs | 4 +- compiler/rustc_const_eval/src/errors.rs | 31 ++++--- .../src/interpret/intrinsics.rs | 4 +- .../rustc_const_eval/src/interpret/machine.rs | 13 ++- .../rustc_const_eval/src/interpret/memory.rs | 86 ++++++++++++------- .../rustc_const_eval/src/interpret/place.rs | 10 +-- .../src/interpret/validity.rs | 2 +- .../rustc_middle/src/mir/interpret/error.rs | 7 +- .../rustc_middle/src/mir/interpret/pointer.rs | 9 +- src/tools/miri/src/alloc_addresses/mod.rs | 14 ++- .../src/borrow_tracker/stacked_borrows/mod.rs | 4 +- .../src/borrow_tracker/tree_borrows/mod.rs | 2 +- src/tools/miri/src/concurrency/data_race.rs | 4 +- src/tools/miri/src/concurrency/weak_memory.rs | 8 +- src/tools/miri/src/machine.rs | 14 +-- src/tools/miri/src/shims/backtrace.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 18 ++-- .../miri/tests/fail-dep/libc/affinity.stderr | 4 +- .../issue-miri-1050-1.stack.stderr | 4 +- .../issue-miri-1050-1.tree.stderr | 4 +- .../out_of_bounds_project.stderr | 4 +- .../intrinsics/out_of_bounds_ptr_1.stderr | 4 +- .../fail/intrinsics/out_of_bounds_ptr_3.rs | 2 +- .../intrinsics/out_of_bounds_ptr_3.stderr | 4 +- .../ptr_offset_from_different_ints.stderr | 4 +- tests/ui/const-ptr/forbidden_slices.stderr | 4 +- tests/ui/consts/const-compare-bytes-ub.stderr | 4 +- .../consts/const-eval/raw-pointer-ub.stderr | 2 +- tests/ui/consts/const-eval/ub-nonnull.stderr | 2 +- tests/ui/consts/offset_from_ub.rs | 4 +- tests/ui/consts/offset_from_ub.stderr | 8 +- tests/ui/consts/offset_ub.rs | 2 +- tests/ui/consts/offset_ub.stderr | 10 +-- 34 files changed, 192 insertions(+), 141 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 43f405b223504..e02d6ebb18302 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -88,10 +88,18 @@ const_eval_exact_div_has_remainder = exact_div: {$a} cannot be divided by {$b} without remainder const_eval_expected_inbounds_pointer = - expected {$inbounds_size -> - [0] a pointer to some allocation - [1] a pointer to 1 byte of memory - *[x] a pointer to {$inbounds_size} bytes of memory + expected a pointer to {$inbounds_size_abs -> + [0] some allocation + *[x] {$inbounds_size_is_neg -> + [false] {$inbounds_size_abs -> + [1] 1 byte of memory + *[x] {$inbounds_size_abs} bytes of memory + } + *[true] the end of {$inbounds_size_abs -> + [1] 1 byte of memory + *[x] {$inbounds_size_abs} bytes of memory + } + } } const_eval_extern_static = @@ -243,7 +251,7 @@ const_eval_offset_from_different_allocations = const_eval_offset_from_overflow = `{$name}` called when first pointer is too far ahead of second const_eval_offset_from_test = - out-of-bounds `offset_from` + out-of-bounds `offset_from` origin const_eval_offset_from_underflow = `{$name}` called when first pointer is too far before second const_eval_offset_from_unsigned_overflow = @@ -274,12 +282,19 @@ const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic const_eval_pointer_out_of_bounds = {$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg -> [true] which points to before the beginning of the allocation - *[false] {$alloc_size_minus_ptr_offset -> - [0] which is at or beyond the end of the allocation of size {$alloc_size -> - [1] 1 byte - *[x] {$alloc_size} bytes + *[false] {$inbounds_size_is_neg -> + [true] {$ptr_offset_abs -> + [0] which is at the beginning of the allocation + *[other] which does not have enough space to the beginning of the allocation + } + *[false] {$alloc_size_minus_ptr_offset -> + [0] which is at or beyond the end of the allocation of size {$alloc_size -> + [1] 1 byte + *[x] {$alloc_size} bytes + } + [1] which is only 1 byte from the end of the allocation + *[x] which is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation } - *[x] and there are only {$alloc_size_minus_ptr_offset} bytes starting at that pointer } } const_eval_pointer_use_after_free = diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 65cbeab24ec00..901149825bfd6 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -295,7 +295,7 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { ); } - match self.ptr_try_get_alloc_id(ptr) { + match self.ptr_try_get_alloc_id(ptr, 0) { Ok((alloc_id, offset, _extra)) => { let (_size, alloc_align, _kind) = self.get_alloc_info(alloc_id); @@ -510,7 +510,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { // If an allocation is created in an another const, // we don't deallocate it. - let (alloc_id, _, _) = ecx.ptr_get_alloc_id(ptr)?; + let (alloc_id, _, _) = ecx.ptr_get_alloc_id(ptr, 0)?; let is_allocated_in_another_const = matches!( ecx.tcx.try_get_global_alloc(alloc_id), Some(interpret::GlobalAlloc::Memory(_)) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 2dd8640009a69..7afb92c08ec9a 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::fmt::Write; use either::Either; use rustc_errors::codes::*; @@ -15,7 +16,7 @@ use rustc_middle::mir::interpret::{ use rustc_middle::ty::{self, Mutability, Ty}; use rustc_span::Span; use rustc_target::abi::call::AdjustForForeignAbiError; -use rustc_target::abi::{Size, WrappingRange}; +use rustc_target::abi::WrappingRange; use crate::interpret::InternKind; @@ -575,18 +576,21 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { .arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, inbounds_size, msg } => { - diag.arg("alloc_size", alloc_size.bytes()) - .arg("inbounds_size", inbounds_size.bytes()) - .arg("bad_pointer_message", bad_pointer_message(msg, dcx)); - diag.arg( - "pointer", - Pointer::new( - Some(CtfeProvenance::from(alloc_id)), - Size::from_bytes(ptr_offset as u64), - ) - .to_string(), - ); + diag.arg("alloc_size", alloc_size.bytes()); + diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + diag.arg("pointer", { + let mut out = format!("{:?}", alloc_id); + if ptr_offset > 0 { + write!(out, "+{:#x}", ptr_offset).unwrap(); + } else if ptr_offset < 0 { + write!(out, "-{:#x}", ptr_offset.unsigned_abs()).unwrap(); + } + out + }); + diag.arg("inbounds_size_is_neg", inbounds_size < 0); + diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs()); diag.arg("ptr_offset_is_neg", ptr_offset < 0); + diag.arg("ptr_offset_abs", ptr_offset.unsigned_abs()); diag.arg( "alloc_size_minus_ptr_offset", alloc_size.bytes().saturating_sub(ptr_offset as u64), @@ -600,7 +604,8 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { ); } - diag.arg("inbounds_size", inbounds_size.bytes()); + diag.arg("inbounds_size_is_neg", inbounds_size < 0); + diag.arg("inbounds_size_abs", inbounds_size.unsigned_abs()); diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } AlignmentCheckFailed(Misalignment { required, has }, msg) => { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1e3de224380b9..7db376a4a3de9 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -243,7 +243,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (a_offset, b_offset, is_addr) = if M::Provenance::OFFSET_IS_ADDR { (a.addr().bytes(), b.addr().bytes(), /*is_addr*/ true) } else { - match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) { + match (self.ptr_try_get_alloc_id(a, 0), self.ptr_try_get_alloc_id(b, 0)) { (Err(a), Err(b)) => { // Neither pointer points to an allocation, so they are both absolute. (a, b, /*is_addr*/ true) @@ -312,7 +312,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // Check that the memory between them is dereferenceable at all, starting from the - // base pointer: `dist` is `a - b`, so it is based on `b`. + // origin pointer: `dist` is `a - b`, so it is based on `b`. self.check_ptr_access_signed(b, dist, CheckInAllocMsg::OffsetFromTest)?; // Then check that this is also dereferenceable from `a`. This ensures that they are // derived from the same allocation. diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index a82209514ec8f..4620b15d8d985 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -321,15 +321,21 @@ pub trait Machine<'tcx>: Sized { ptr: Pointer, ) -> InterpResult<'tcx>; - /// Convert a pointer with provenance into an allocation-offset pair - /// and extra provenance info. + /// Convert a pointer with provenance into an allocation-offset pair and extra provenance info. + /// `size` says how many bytes of memory are expected at that pointer. The *sign* of `size` can + /// be used to disambiguate situations where a wildcard pointer sits right in between two + /// allocations. /// - /// The returned `AllocId` must be the same as `ptr.provenance.get_alloc_id()`. + /// If `ptr.provenance.get_alloc_id()` is `Some(p)`, the returned `AllocId` must be `p`. + /// The resulting `AllocId` will just be used for that one step and the forgotten again + /// (i.e., we'll never turn the data returned here back into a `Pointer` that might be + /// stored in machine state). /// /// When this fails, that means the pointer does not point to a live allocation. fn ptr_get_alloc( ecx: &InterpCx<'tcx, Self>, ptr: Pointer, + size: i64, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)>; /// Called to adjust global allocations to the Provenance and AllocExtra of this machine. @@ -658,6 +664,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) { fn ptr_get_alloc( _ecx: &InterpCx<$tcx, Self>, ptr: Pointer, + _size: i64, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> { // We know `offset` is relative to the allocation, so we can use `into_parts`. let (prov, offset) = ptr.into_parts(); diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 859f30137dc4e..754bd00413caf 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -261,7 +261,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { new_align: Align, kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { - let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?; if offset.bytes() != 0 { throw_ub_custom!( fluent::const_eval_realloc_or_alloc_with_offset, @@ -291,7 +291,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { old_size_and_align: Option<(Size, Align)>, kind: MemoryKind, ) -> InterpResult<'tcx> { - let (alloc_id, offset, prov) = self.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, prov) = self.ptr_get_alloc_id(ptr, 0)?; trace!("deallocating: {alloc_id:?}"); if offset.bytes() != 0 { @@ -383,6 +383,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ptr: Pointer>, size: Size, ) -> InterpResult<'tcx, Option<(AllocId, Size, M::ProvenanceExtra)>> { + let size = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes self.check_and_deref_ptr( ptr, size, @@ -404,6 +405,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { size: Size, msg: CheckInAllocMsg, ) -> InterpResult<'tcx> { + let size = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes self.check_and_deref_ptr(ptr, size, msg, |alloc_id, _, _| { let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?; Ok((size, align, ())) @@ -420,19 +422,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { size: i64, msg: CheckInAllocMsg, ) -> InterpResult<'tcx> { - if let Ok(size) = u64::try_from(size) { - self.check_ptr_access(ptr, Size::from_bytes(size), msg) - } else { - // Compute the pointer at the beginning of the range, and do the standard - // dereferenceability check from there. - let begin_ptr = ptr.wrapping_signed_offset(size, self); - self.check_ptr_access(begin_ptr, Size::from_bytes(size.unsigned_abs()), msg) - } + self.check_and_deref_ptr(ptr, size, msg, |alloc_id, _, _| { + let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?; + Ok((size, align, ())) + })?; + Ok(()) } /// Low-level helper function to check if a ptr is in-bounds and potentially return a reference /// to the allocation it points to. Supports both shared and mutable references, as the actual - /// checking is offloaded to a helper closure. + /// checking is offloaded to a helper closure. Supports signed sizes for checks "to the left" of + /// a pointer. /// /// `alloc_size` will only get called for non-zero-sized accesses. /// @@ -440,7 +440,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn check_and_deref_ptr( &self, ptr: Pointer>, - size: Size, + size: i64, msg: CheckInAllocMsg, alloc_size: impl FnOnce( AllocId, @@ -449,24 +449,31 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx, (Size, Align, T)>, ) -> InterpResult<'tcx, Option> { // Everything is okay with size 0. - if size.bytes() == 0 { + if size == 0 { return Ok(None); } - Ok(match self.ptr_try_get_alloc_id(ptr) { + Ok(match self.ptr_try_get_alloc_id(ptr, size) { Err(addr) => { // We couldn't get a proper allocation. throw_ub!(DanglingIntPointer { addr, inbounds_size: size, msg }); } Ok((alloc_id, offset, prov)) => { let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?; - // Test bounds. - // It is sufficient to check this for the end pointer. Also check for overflow! - if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) { + let offset = offset.bytes(); + // Compute absolute begin and end of the range. + let (begin, end) = if size >= 0 { + (Some(offset), offset.checked_add(size as u64)) + } else { + (offset.checked_sub(size.unsigned_abs()), Some(offset)) + }; + // Ensure both are within bounds. + let in_bounds = begin.is_some() && end.is_some_and(|e| e <= alloc_size.bytes()); + if !in_bounds { throw_ub!(PointerOutOfBounds { alloc_id, alloc_size, - ptr_offset: self.target_usize_to_isize(offset.bytes()), + ptr_offset: self.target_usize_to_isize(offset), inbounds_size: size, msg, }) @@ -498,7 +505,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } #[inline] - fn offset_misalignment(offset: u64, align: Align) -> Option { + fn is_offset_misaligned(offset: u64, align: Align) -> Option { if offset % align.bytes() == 0 { None } else { @@ -508,8 +515,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } - match self.ptr_try_get_alloc_id(ptr) { - Err(addr) => offset_misalignment(addr, align), + match self.ptr_try_get_alloc_id(ptr, 0) { + Err(addr) => is_offset_misaligned(addr, align), Ok((alloc_id, offset, _prov)) => { let (_size, alloc_align, kind) = self.get_alloc_info(alloc_id); if let Some(misalign) = @@ -517,14 +524,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { { Some(misalign) } else if M::Provenance::OFFSET_IS_ADDR { - // `use_addr_for_alignment_check` can only be true if `OFFSET_IS_ADDR` is true. - offset_misalignment(ptr.addr().bytes(), align) + is_offset_misaligned(ptr.addr().bytes(), align) } else { // Check allocation alignment and offset alignment. if alloc_align.bytes() < align.bytes() { Some(Misalignment { has: alloc_align, required: align }) } else { - offset_misalignment(offset.bytes(), align) + is_offset_misaligned(offset.bytes(), align) } } } @@ -660,9 +666,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { size: Size, ) -> InterpResult<'tcx, Option>> { + let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes let ptr_and_alloc = self.check_and_deref_ptr( ptr, - size, + size_i64, CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, prov| { let alloc = self.get_alloc_raw(alloc_id)?; @@ -673,7 +680,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // accesses. That means we cannot rely on the closure above or the `Some` branch below. We // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked. if !self.memory.validation_in_progress.get() { - if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr) { + if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) { M::before_alloc_read(self, alloc_id)?; } } @@ -894,7 +901,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ptr: Pointer>, ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { trace!("get_ptr_fn({:?})", ptr); - let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?; if offset.bytes() != 0 { throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))) } @@ -910,7 +917,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { expected_trait: Option<&'tcx ty::List>>, ) -> InterpResult<'tcx, Ty<'tcx>> { trace!("get_ptr_vtable({:?})", ptr); - let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr, 0)?; if offset.bytes() != 0 { throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset))) } @@ -1391,7 +1398,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Err(_) => { // Can only happen during CTFE. let ptr = scalar.to_pointer(self)?; - match self.ptr_try_get_alloc_id(ptr) { + match self.ptr_try_get_alloc_id(ptr, 0) { Ok((alloc_id, offset, _)) => { let (size, _align, _kind) = self.get_alloc_info(alloc_id); // If the pointer is out-of-bounds, it may be null. @@ -1407,6 +1414,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Turning a "maybe pointer" into a proper pointer (and some information /// about where it points), or an absolute address. /// + /// `size` says how many bytes of memory are expected at that pointer. This is largely only used + /// for error messages; however, the *sign* of `size` can be used to disambiguate situations + /// where a wildcard pointer sits right in between two allocations. + /// It is almost always okay to just set the size to 0; this will be treated like a positive size + /// for handling wildcard pointers. + /// /// The result must be used immediately; it is not allowed to convert /// the returned data back into a `Pointer` and store that in machine state. /// (In fact that's not even possible since `M::ProvenanceExtra` is generic and @@ -1414,9 +1427,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn ptr_try_get_alloc_id( &self, ptr: Pointer>, + size: i64, ) -> Result<(AllocId, Size, M::ProvenanceExtra), u64> { match ptr.into_pointer_or_addr() { - Ok(ptr) => match M::ptr_get_alloc(self, ptr) { + Ok(ptr) => match M::ptr_get_alloc(self, ptr, size) { Some((alloc_id, offset, extra)) => Ok((alloc_id, offset, extra)), None => { assert!(M::Provenance::OFFSET_IS_ADDR); @@ -1430,6 +1444,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Turning a "maybe pointer" into a proper pointer (and some information about where it points). /// + /// `size` says how many bytes of memory are expected at that pointer. This is largely only used + /// for error messages; however, the *sign* of `size` can be used to disambiguate situations + /// where a wildcard pointer sits right in between two allocations. + /// It is almost always okay to just set the size to 0; this will be treated like a positive size + /// for handling wildcard pointers. + /// /// The result must be used immediately; it is not allowed to convert /// the returned data back into a `Pointer` and store that in machine state. /// (In fact that's not even possible since `M::ProvenanceExtra` is generic and @@ -1438,12 +1458,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn ptr_get_alloc_id( &self, ptr: Pointer>, + size: i64, ) -> InterpResult<'tcx, (AllocId, Size, M::ProvenanceExtra)> { - self.ptr_try_get_alloc_id(ptr).map_err(|offset| { + self.ptr_try_get_alloc_id(ptr, size).map_err(|offset| { err_ub!(DanglingIntPointer { addr: offset, - // We don't know the actually required size. - inbounds_size: Size::ZERO, + inbounds_size: size, msg: CheckInAllocMsg::InboundsTest }) .into() diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 9f79f4c55be85..4572c4dd2205c 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -13,10 +13,9 @@ use rustc_target::abi::{Abi, Align, HasDataLayout, Size}; use tracing::{instrument, trace}; use super::{ - alloc_range, mir_assign_valid_types, throw_ub, AllocRef, AllocRefMut, CheckAlignMsg, - CtfeProvenance, ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, - OffsetMode, OpTy, Operand, Pointer, PointerArithmetic, Projectable, Provenance, Readable, - Scalar, + alloc_range, mir_assign_valid_types, AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, + ImmTy, Immediate, InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, + Operand, Pointer, Projectable, Provenance, Readable, Scalar, }; #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] @@ -85,9 +84,6 @@ impl MemPlace { !meta.has_meta() || self.meta.has_meta(), "cannot use `offset_with_meta` to add metadata to a place" ); - if offset > ecx.data_layout().max_size_of_val() { - throw_ub!(PointerArithOverflow); - } let ptr = match mode { OffsetMode::Inbounds => { ecx.ptr_offset_inbounds(self.ptr, offset.bytes().try_into().unwrap())? diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index adb6ebabd73af..c8d59c5648da0 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -455,7 +455,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { }; // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. - if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr()) { + if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr(), 0) { let mut skip_recursive_check = false; if let Some(GlobalAlloc::Static(did)) = self.ecx.tcx.try_get_global_alloc(alloc_id) { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index d2d91333ffe33..69ce3e087350b 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -334,14 +334,15 @@ pub enum UndefinedBehaviorInfo<'tcx> { alloc_size: Size, ptr_offset: i64, /// The size of the memory range that was expected to be in-bounds. - inbounds_size: Size, + inbounds_size: i64, msg: CheckInAllocMsg, }, /// Using an integer as a pointer in the wrong way. DanglingIntPointer { addr: u64, - /// The size of the memory range that was expected to be in-bounds (or 0 if we don't know). - inbounds_size: Size, + /// The size of the memory range that was expected to be in-bounds (or 0 if we need an + /// allocation but not any actual memory there, e.g. for function pointers). + inbounds_size: i64, msg: CheckInAllocMsg, }, /// Used a pointer with bad alignment. diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 42f30c14cea88..faacc2457873a 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -181,12 +181,9 @@ impl Provenance for CtfeProvenance { fn fmt(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Print AllocId. fmt::Debug::fmt(&ptr.provenance.alloc_id(), f)?; // propagates `alternate` flag - // Print offset only if it is non-zero. Print it signed. - let signed_offset = ptr.offset.bytes() as i64; - if signed_offset > 0 { - write!(f, "+{:#x}", signed_offset)?; - } else if signed_offset < 0 { - write!(f, "-{:#x}", signed_offset.unsigned_abs())?; + // Print offset only if it is non-zero. + if ptr.offset.bytes() > 0 { + write!(f, "+{:#x}", ptr.offset.bytes())?; } // Print immutable status. if ptr.provenance.immutable() { diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index d0f977f81433f..81facdd34b62b 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -105,15 +105,17 @@ impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {} trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Returns the exposed `AllocId` that corresponds to the specified addr, // or `None` if the addr is out of bounds - fn alloc_id_from_addr(&self, addr: u64) -> Option { + fn alloc_id_from_addr(&self, addr: u64, size: i64) -> Option { let ecx = self.eval_context_ref(); let global_state = ecx.machine.alloc_addresses.borrow(); assert!(global_state.provenance_mode != ProvenanceMode::Strict); + // We always search the allocation to the right of this address. So if the size is structly + // negative, we have to search for `addr-1` instead. + let addr = if size >= 0 { addr } else { addr.saturating_sub(1) }; let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr); // Determine the in-bounds provenance for this pointer. - // (This is only called on an actual access, so in-bounds is the only possible kind of provenance.) let alloc_id = match pos { Ok(pos) => Some(global_state.int_to_ptr_map[pos].1), Err(0) => None, @@ -318,7 +320,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// When a pointer is used for a memory access, this computes where in which allocation the /// access is going. - fn ptr_get_alloc(&self, ptr: interpret::Pointer) -> Option<(AllocId, Size)> { + fn ptr_get_alloc( + &self, + ptr: interpret::Pointer, + size: i64, + ) -> Option<(AllocId, Size)> { let ecx = self.eval_context_ref(); let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance) @@ -327,7 +333,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { alloc_id } else { // A wildcard pointer. - ecx.alloc_id_from_addr(addr.bytes())? + ecx.alloc_id_from_addr(addr.bytes(), size)? }; // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 1d75486a78189..3f9c991df6af6 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -673,7 +673,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { // attempt to use it for a non-zero-sized access. // Dangling slices are a common case here; it's valid to get their length but with raw // pointer tagging for example all calls to get_unchecked on them are invalid. - if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr()) { + if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr(), 0) { log_creation(this, Some((alloc_id, base_offset, orig_tag)))?; // Still give it the new provenance, it got retagged after all. return Ok(Some(Provenance::Concrete { alloc_id, tag: new_tag })); @@ -685,7 +685,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { } } - let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr())?; + let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr(), 0)?; log_creation(this, Some((alloc_id, base_offset, orig_tag)))?; trace!( diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 123d4b407fb4c..44f42d5fb9cd9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -223,7 +223,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; trace!("Reborrow of size {:?}", ptr_size); - let (alloc_id, base_offset, parent_prov) = match this.ptr_try_get_alloc_id(place.ptr()) { + let (alloc_id, base_offset, parent_prov) = match this.ptr_try_get_alloc_id(place.ptr(), 0) { Ok(data) => { // Unlike SB, we *do* a proper retag for size 0 if can identify the allocation. // After all, the pointer may be lazily initialized outside this initial range. diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index 2baa09bec168b..9df0d95f1f275 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -1180,7 +1180,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { // We avoid `get_ptr_alloc` since we do *not* want to run the access hooks -- the actual // access will happen later. let (alloc_id, _offset, _prov) = this - .ptr_try_get_alloc_id(place.ptr()) + .ptr_try_get_alloc_id(place.ptr(), 0) .expect("there are no zero-sized atomic accesses"); if this.get_alloc_mutability(alloc_id)? == Mutability::Not { // See if this is fine. @@ -1307,7 +1307,7 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> { if let Some(data_race) = &this.machine.data_race { if data_race.race_detecting() { let size = place.layout.size; - let (alloc_id, base_offset, _prov) = this.ptr_get_alloc_id(place.ptr())?; + let (alloc_id, base_offset, _prov) = this.ptr_get_alloc_id(place.ptr(), 0)?; // Load and log the atomic operation. // Note that atomic loads are possible even from read-only allocations, so `get_alloc_extra_mut` is not an option. let alloc_meta = this.get_alloc_extra(alloc_id)?.data_race.as_ref().unwrap(); diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs index e92eaa8f91f75..6f4171584a8f7 100644 --- a/src/tools/miri/src/concurrency/weak_memory.rs +++ b/src/tools/miri/src/concurrency/weak_memory.rs @@ -468,7 +468,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { init: Scalar, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?; + let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; if let ( crate::AllocExtra { weak_memory: Some(alloc_buffers), .. }, crate::MiriMachine { data_race: Some(global), threads, .. }, @@ -495,7 +495,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_ref(); if let Some(global) = &this.machine.data_race { - let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?; + let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() { if atomic == AtomicReadOrd::SeqCst { global.sc_read(&this.machine.threads); @@ -535,7 +535,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { init: Scalar, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr())?; + let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr(), 0)?; if let ( crate::AllocExtra { weak_memory: Some(alloc_buffers), .. }, crate::MiriMachine { data_race: Some(global), threads, .. }, @@ -585,7 +585,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { global.sc_read(&this.machine.threads); } let size = place.layout.size; - let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr())?; + let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr(), 0)?; if let Some(alloc_buffers) = this.get_alloc_extra(alloc_id)?.weak_memory.as_ref() { let buffer = alloc_buffers .get_or_create_store_buffer(alloc_range(base_offset, size), init)?; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index e492793a65135..5f4aa9d2f5d21 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1198,19 +1198,23 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { } } - /// Convert a pointer with provenance into an allocation-offset pair, - /// or a `None` with an absolute address if that conversion is not possible. + /// Convert a pointer with provenance into an allocation-offset pair and extra provenance info. + /// `size` says how many bytes of memory are expected at that pointer. The *sign* of `size` can + /// be used to disambiguate situations where a wildcard pointer sits right in between two + /// allocations. /// - /// This is called when a pointer is about to be used for memory access, - /// an in-bounds check, or anything else that requires knowing which allocation it points to. + /// If `ptr.provenance.get_alloc_id()` is `Some(p)`, the returned `AllocId` must be `p`. /// The resulting `AllocId` will just be used for that one step and the forgotten again /// (i.e., we'll never turn the data returned here back into a `Pointer` that might be /// stored in machine state). + /// + /// When this fails, that means the pointer does not point to a live allocation. fn ptr_get_alloc( ecx: &MiriInterpCx<'tcx>, ptr: StrictPointer, + size: i64, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> { - let rel = ecx.ptr_get_alloc(ptr); + let rel = ecx.ptr_get_alloc(ptr, size); rel.map(|(alloc_id, size)| { let tag = match ptr.provenance { diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 24a4b5f26a950..42babb4c78dc5 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -116,7 +116,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let ptr = this.read_pointer(ptr)?; // Take apart the pointer, we need its pieces. The offset encodes the span. - let (alloc_id, offset, _prov) = this.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, _prov) = this.ptr_get_alloc_id(ptr, 0)?; // This has to be an actual global fn ptr, not a dlsym function. let fn_instance = if let Some(GlobalAlloc::Function { instance, .. }) = diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 9004f7efc8b5e..f0d8cc9a1cc23 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -278,7 +278,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "miri_get_alloc_id" => { let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; - let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr).map_err(|_e| { + let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err(|_e| { err_machine_stop!(TerminationInfo::Abort(format!( "pointer passed to `miri_get_alloc_id` must not be dangling, got {ptr:?}" ))) @@ -311,7 +311,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "miri_static_root" => { let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; - let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr)?; + let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr, 0)?; if offset != Size::ZERO { throw_unsup_format!( "pointer passed to `miri_static_root` must point to beginning of an allocated block" @@ -392,7 +392,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "`miri_promise_symbolic_alignment`: pointer is not actually aligned" ); } - if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr) { + if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr, 0) { let (_size, alloc_align, _kind) = this.get_alloc_info(alloc_id); // If the newly promised alignment is bigger than the native alignment of this // allocation, and bigger than the previously promised alignment, then set it. @@ -584,8 +584,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let n = Size::from_bytes(this.read_target_usize(n)?); // C requires that this must always be a valid pointer (C18 §7.1.4). - this.ptr_get_alloc_id(left)?; - this.ptr_get_alloc_id(right)?; + this.ptr_get_alloc_id(left, 0)?; + this.ptr_get_alloc_id(right, 0)?; let result = { let left_bytes = this.read_bytes_ptr_strip_provenance(left, n)?; @@ -612,7 +612,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let val = val as u8; // C requires that this must always be a valid pointer (C18 §7.1.4). - this.ptr_get_alloc_id(ptr)?; + this.ptr_get_alloc_id(ptr, 0)?; if let Some(idx) = this .read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(num))? @@ -639,7 +639,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let val = val as u8; // C requires that this must always be a valid pointer (C18 §7.1.4). - this.ptr_get_alloc_id(ptr)?; + this.ptr_get_alloc_id(ptr, 0)?; let idx = this .read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(num))? @@ -681,8 +681,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // C requires that this must always be a valid pointer, even if `n` is zero, so we better check that. // (This is more than Rust requires, so `mem_copy` is not sufficient.) - this.ptr_get_alloc_id(ptr_dest)?; - this.ptr_get_alloc_id(ptr_src)?; + this.ptr_get_alloc_id(ptr_dest, 0)?; + this.ptr_get_alloc_id(ptr_src, 0)?; this.mem_copy(ptr_src, ptr_dest, Size::from_bytes(n), true)?; this.write_pointer(ptr_dest, dest)?; diff --git a/src/tools/miri/tests/fail-dep/libc/affinity.stderr b/src/tools/miri/tests/fail-dep/libc/affinity.stderr index b9f79fdda89c4..38414623ccb94 100644 --- a/src/tools/miri/tests/fail-dep/libc/affinity.stderr +++ b/src/tools/miri/tests/fail-dep/libc/affinity.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC and there are only 128 bytes starting at that pointer +error: Undefined Behavior: memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC which is only 128 bytes from the end of the allocation --> $DIR/affinity.rs:LL:CC | LL | let err = unsafe { sched_setaffinity(PID, size_of::() + 1, &cpuset) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC and there are only 128 bytes starting at that pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 129 bytes of memory, but got ALLOC which is only 128 bytes from the end of the allocation | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr index 07bb3293989e7..64bbbfcd848b6 100644 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr +++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer +error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC which is only 2 bytes from the end of the allocation --> RUSTLIB/alloc/src/boxed.rs:LL:CC | LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC which is only 2 bytes from the end of the allocation | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr index 07bb3293989e7..64bbbfcd848b6 100644 --- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr +++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer +error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC which is only 2 bytes from the end of the allocation --> RUSTLIB/alloc/src/boxed.rs:LL:CC | LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC and there are only 2 bytes starting at that pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got ALLOC which is only 2 bytes from the end of the allocation | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr index bdd245e184948..4bfac8f96578d 100644 --- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr +++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_project.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC and there are only 4 bytes starting at that pointer +error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation --> $DIR/out_of_bounds_project.rs:LL:CC | LL | let _field = addr_of!((*ptr).2); - | ^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC and there are only 4 bytes starting at that pointer + | ^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr index ddc5ae8efbc01..c6a1e4710a8cd 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC and there are only 4 bytes starting at that pointer +error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation --> $DIR/out_of_bounds_ptr_1.rs:LL:CC | LL | let x = unsafe { x.offset(5) }; - | ^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC and there are only 4 bytes starting at that pointer + | ^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs index fc9fb3d35d610..bd1d5c064c065 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs @@ -1,6 +1,6 @@ fn main() { let v = [0i8; 4]; let x = &v as *const i8; - let x = unsafe { x.offset(-1) }; //~ERROR: expected a pointer to 1 byte of memory + let x = unsafe { x.offset(-1) }; //~ERROR: expected a pointer to the end of 1 byte of memory panic!("this should never print: {:?}", x); } diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr index 88963e712f4cc..ba7615da1deaa 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC-0x1 which points to before the beginning of the allocation +error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to the end of 1 byte of memory, but got ALLOC which is at the beginning of the allocation --> $DIR/out_of_bounds_ptr_3.rs:LL:CC | LL | let x = unsafe { x.offset(-1) }; - | ^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC-0x1 which points to before the beginning of the allocation + | ^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to the end of 1 byte of memory, but got ALLOC which is at the beginning of the allocation | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr index 649075dbc55de..bf36c54ac781c 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_different_ints.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: out-of-bounds `offset_from`: expected a pointer to 1 byte of memory, but got 0xa[noalloc] which is a dangling pointer (it has no provenance) +error: Undefined Behavior: out-of-bounds `offset_from` origin: expected a pointer to the end of 1 byte of memory, but got 0xb[noalloc] which is a dangling pointer (it has no provenance) --> $DIR/ptr_offset_from_different_ints.rs:LL:CC | LL | let _ = p1.byte_offset_from(p2); - | ^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: expected a pointer to 1 byte of memory, but got 0xa[noalloc] which is a dangling pointer (it has no provenance) + | ^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to the end of 1 byte of memory, but got 0xb[noalloc] which is a dangling pointer (it has no provenance) | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr index 034e8bd185264..fad078ad2b2bd 100644 --- a/tests/ui/const-ptr/forbidden_slices.stderr +++ b/tests/ui/const-ptr/forbidden_slices.stderr @@ -118,7 +118,7 @@ LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) }; error[E0080]: could not evaluate static initializer --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC10 and there are only 4 bytes starting at that pointer + = note: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC10 which is only 4 bytes from the end of the allocation | note: inside `std::ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -177,7 +177,7 @@ LL | pub static R7: &[u16] = unsafe { error[E0080]: could not evaluate static initializer --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC11+0x1 and there are only 7 bytes starting at that pointer + = note: out-of-bounds pointer arithmetic: expected a pointer to 8 bytes of memory, but got ALLOC11+0x1 which is only 7 bytes from the end of the allocation | note: inside `std::ptr::const_ptr::::add` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr index 8a923779a5bb4..7f83dee640969 100644 --- a/tests/ui/consts/const-compare-bytes-ub.stderr +++ b/tests/ui/consts/const-compare-bytes-ub.stderr @@ -20,13 +20,13 @@ error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:22:9 | LL | compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0 and there are only 3 bytes starting at that pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0 which is only 3 bytes from the end of the allocation error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:26:9 | LL | compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC1 and there are only 3 bytes starting at that pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC1 which is only 3 bytes from the end of the allocation error[E0080]: evaluation of constant value failed --> $DIR/const-compare-bytes-ub.rs:30:9 diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr index 5fce25701bdd1..aeb46725c0642 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr +++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr @@ -35,7 +35,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/raw-pointer-ub.rs:41:16 | LL | let _val = *ptr; - | ^^^^ memory access failed: expected a pointer to 8 bytes of memory, but got ALLOC0 and there are only 4 bytes starting at that pointer + | ^^^^ memory access failed: expected a pointer to 8 bytes of memory, but got ALLOC0 which is only 4 bytes from the end of the allocation error: aborting due to 5 previous errors diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index fe3060dda17df..0e4926eb49edf 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -13,7 +13,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/ub-nonnull.rs:20:29 | LL | let out_of_bounds_ptr = &ptr[255]; - | ^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 255 bytes of memory, but got ALLOC1 and there are only 1 bytes starting at that pointer + | ^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 255 bytes of memory, but got ALLOC1 which is only 1 byte from the end of the allocation error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:24:1 diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs index 66bb056ceb049..7efc5dd3e28ba 100644 --- a/tests/ui/consts/offset_from_ub.rs +++ b/tests/ui/consts/offset_from_ub.rs @@ -1,4 +1,4 @@ -//@ normalize-stderr-test: "to \d+ bytes of memory" -> "to $$BYTES bytes of memory" +//@ normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes" #![feature(const_ptr_sub_ptr)] #![feature(core_intrinsics)] @@ -55,7 +55,7 @@ const OUT_OF_BOUNDS_2: isize = { let end_ptr = (start_ptr).wrapping_add(length); // Second ptr is out of bounds unsafe { ptr_offset_from(start_ptr, end_ptr) } //~ERROR evaluation of constant value failed - //~| expected a pointer to 10 bytes of memory + //~| expected a pointer to the end of 10 bytes of memory }; pub const DIFFERENT_ALLOC_UNSIGNED: usize = { diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr index f2f27735630fe..ac4597ff0119a 100644 --- a/tests/ui/consts/offset_from_ub.stderr +++ b/tests/ui/consts/offset_from_ub.stderr @@ -27,19 +27,19 @@ error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:39:14 | LL | unsafe { ptr_offset_from(ptr2, ptr1) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: expected a pointer to $BYTES bytes of memory, but got 0x8[noalloc] which is a dangling pointer (it has no provenance) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got 0x8[noalloc] which is a dangling pointer (it has no provenance) error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:48:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: expected a pointer to $BYTES bytes of memory, but got ALLOC0 and there are only 4 bytes starting at that pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got ALLOC0 which is only $BYTES bytes from the end of the allocation error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:57:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: expected a pointer to $BYTES bytes of memory, but got ALLOC1 and there are only 4 bytes starting at that pointer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC1+0xa which does not have enough space to the beginning of the allocation error[E0080]: evaluation of constant value failed --> $DIR/offset_from_ub.rs:66:14 @@ -80,7 +80,7 @@ LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds `offset_from`: expected a pointer to $BYTES bytes of memory, but got a null pointer + = note: out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got a null pointer | note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL diff --git a/tests/ui/consts/offset_ub.rs b/tests/ui/consts/offset_ub.rs index b239b91e11cf6..5026d9a271322 100644 --- a/tests/ui/consts/offset_ub.rs +++ b/tests/ui/consts/offset_ub.rs @@ -2,7 +2,7 @@ use std::ptr; //@ normalize-stderr-test: "0xf+" -> "0xf..f" //@ normalize-stderr-test: "0x7f+" -> "0x7f..f" -//@ normalize-stderr-test: "to \d+ bytes of memory" -> "to $$BYTES bytes of memory" +//@ normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes" pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~NOTE diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr index b42d9482f8a01..4a9ffb46a3feb 100644 --- a/tests/ui/consts/offset_ub.stderr +++ b/tests/ui/consts/offset_ub.stderr @@ -14,7 +14,7 @@ LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC0 and there are only 1 bytes starting at that pointer + = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC0 which is only 1 byte from the end of the allocation | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -27,7 +27,7 @@ LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC1 and there are only 100 bytes starting at that pointer + = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC1 which is only $BYTES bytes from the end of the allocation | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -92,7 +92,7 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC2-0x4 which points to before the beginning of the allocation + = note: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC2-0x2 which points to before the beginning of the allocation | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -105,7 +105,7 @@ LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC3 which is at or beyond the end of the allocation of size 0 bytes + = note: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC3 which is at or beyond the end of the allocation of size $BYTES bytes | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -131,7 +131,7 @@ LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::::dangling().as_ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0x7f..f[noalloc] which is a dangling pointer (it has no provenance) + = note: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got 0xf..f[noalloc] which is a dangling pointer (it has no provenance) | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL From 5d5c97aad7cd2803b6dbecdd34293616065dc6b2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Aug 2024 10:19:13 +0200 Subject: [PATCH 358/489] interpret: simplify pointer arithmetic logic --- compiler/rustc_abi/src/lib.rs | 6 +- .../src/interpret/eval_context.rs | 11 --- .../src/interpret/intrinsics.rs | 9 +- .../rustc_const_eval/src/interpret/memory.rs | 2 +- .../rustc_const_eval/src/interpret/place.rs | 6 +- .../rustc_const_eval/src/interpret/step.rs | 2 +- compiler/rustc_lint/src/types.rs | 6 +- .../rustc_middle/src/mir/interpret/pointer.rs | 98 +++---------------- .../rustc_middle/src/mir/interpret/value.rs | 2 +- compiler/rustc_middle/src/ty/consts/int.rs | 4 +- compiler/rustc_middle/src/ty/util.rs | 2 +- src/tools/miri/src/alloc_addresses/mod.rs | 24 ++--- src/tools/miri/src/helpers.rs | 6 +- src/tools/miri/src/shims/foreign_items.rs | 4 +- src/tools/miri/src/shims/unix/env.rs | 2 +- src/tools/miri/src/shims/unix/fs.rs | 2 +- src/tools/miri/src/shims/unix/linux/mem.rs | 2 +- .../fail/intrinsics/out_of_bounds_ptr_2.rs | 6 -- .../intrinsics/out_of_bounds_ptr_2.stderr | 15 --- .../intrinsics/ptr_offset_int_plus_ptr.rs | 2 +- ...s_ptr_1.rs => ptr_offset_out_of_bounds.rs} | 1 - ...stderr => ptr_offset_out_of_bounds.stderr} | 6 +- ...r_3.rs => ptr_offset_out_of_bounds_neg.rs} | 0 ...rr => ptr_offset_out_of_bounds_neg.stderr} | 6 +- .../fail/intrinsics/ptr_offset_overflow.rs | 9 +- .../intrinsics/ptr_offset_overflow.stderr | 13 ++- tests/ui/consts/offset_ub.stderr | 14 +-- 27 files changed, 73 insertions(+), 187 deletions(-) delete mode 100644 src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.rs delete mode 100644 src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr rename src/tools/miri/tests/fail/intrinsics/{out_of_bounds_ptr_1.rs => ptr_offset_out_of_bounds.rs} (72%) rename src/tools/miri/tests/fail/intrinsics/{out_of_bounds_ptr_1.stderr => ptr_offset_out_of_bounds.stderr} (85%) rename src/tools/miri/tests/fail/intrinsics/{out_of_bounds_ptr_3.rs => ptr_offset_out_of_bounds_neg.rs} (100%) rename src/tools/miri/tests/fail/intrinsics/{out_of_bounds_ptr_3.stderr => ptr_offset_out_of_bounds_neg.stderr} (84%) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 378af8af50ec1..3dc548c4554a3 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -516,7 +516,7 @@ impl Size { /// Truncates `value` to `self` bits and then sign-extends it to 128 bits /// (i.e., if it is negative, fill with 1's on the left). #[inline] - pub fn sign_extend(self, value: u128) -> u128 { + pub fn sign_extend(self, value: u128) -> i128 { let size = self.bits(); if size == 0 { // Truncated until nothing is left. @@ -526,7 +526,7 @@ impl Size { let shift = 128 - size; // Shift the unsigned value to the left, then shift back to the right as signed // (essentially fills with sign bit on the left). - (((value << shift) as i128) >> shift) as u128 + ((value << shift) as i128) >> shift } /// Truncates `value` to `self` bits. @@ -544,7 +544,7 @@ impl Size { #[inline] pub fn signed_int_min(&self) -> i128 { - self.sign_extend(1_u128 << (self.bits() - 1)) as i128 + self.sign_extend(1_u128 << (self.bits() - 1)) } #[inline] diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 85f9b2341d91c..fc063b8bab055 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -560,17 +560,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.frame().body } - #[inline(always)] - pub fn sign_extend(&self, value: u128, ty: TyAndLayout<'_>) -> u128 { - assert!(ty.abi.is_signed()); - ty.size.sign_extend(value) - } - - #[inline(always)] - pub fn truncate(&self, value: u128, ty: TyAndLayout<'_>) -> u128 { - ty.size.truncate(value) - } - #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { ty.is_freeze(*self.tcx, self.param_env) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 7db376a4a3de9..3cf3bd87d3ddb 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -206,7 +206,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } else { (val_bits >> shift_bits) | (val_bits << inv_shift_bits) }; - let truncated_bits = self.truncate(result_bits, layout_val); + let truncated_bits = layout_val.size.truncate(result_bits); let result = Scalar::from_uint(truncated_bits, layout_val.size); self.write_scalar(result, dest)?; } @@ -580,13 +580,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ptr: Pointer>, offset_bytes: i64, ) -> InterpResult<'tcx, Pointer>> { - // We first compute the pointer with overflow checks, to get a specific error for when it - // overflows (though technically this is redundant with the following inbounds check). - let result = ptr.signed_offset(offset_bytes, self)?; // The offset must be in bounds starting from `ptr`. self.check_ptr_access_signed(ptr, offset_bytes, CheckInAllocMsg::PointerArithmeticTest)?; - // Done. - Ok(result) + // This also implies that there is no overflow, so we are done. + Ok(ptr.wrapping_signed_offset(offset_bytes, self)) } /// Copy `count*size_of::()` many bytes from `*src` to `*dst`. diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 754bd00413caf..b71e6ed8d2b65 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -473,7 +473,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { throw_ub!(PointerOutOfBounds { alloc_id, alloc_size, - ptr_offset: self.target_usize_to_isize(offset), + ptr_offset: self.sign_extend_to_target_isize(offset), inbounds_size: size, msg, }) diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 4572c4dd2205c..242f36363a58e 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -285,10 +285,8 @@ impl<'tcx, Prov: Provenance> Projectable<'tcx, Prov> for PlaceTy<'tcx, Prov> { // projections are type-checked and bounds-checked. assert!(offset + layout.size <= self.layout.size); - let new_offset = Size::from_bytes( - ecx.data_layout() - .offset(old_offset.unwrap_or(Size::ZERO).bytes(), offset.bytes())?, - ); + // Size `+`, ensures no overflow. + let new_offset = old_offset.unwrap_or(Size::ZERO) + offset; PlaceTy { place: Place::Local { local, offset: Some(new_offset), locals_addr }, diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 48433d95c5113..211a7b2300222 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -362,7 +362,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // of the first element. let elem_size = first.layout.size; let first_ptr = first.ptr(); - let rest_ptr = first_ptr.offset(elem_size, self)?; + let rest_ptr = first_ptr.wrapping_offset(elem_size, self); // No alignment requirement since `copy_op` above already checked it. self.mem_copy_repeatedly( first_ptr, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index e9f44f3af0272..f3196cfed533e 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -309,11 +309,7 @@ fn report_bin_hex_error( ) { let (t, actually) = match ty { attr::IntType::SignedInt(t) => { - let actually = if negative { - -(size.sign_extend(val) as i128) - } else { - size.sign_extend(val) as i128 - }; + let actually = if negative { -(size.sign_extend(val)) } else { size.sign_extend(val) }; (t.name_str(), actually.to_string()) } attr::IntType::UnsignedInt(t) => { diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index faacc2457873a..6cfd07d699c3e 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -5,7 +5,7 @@ use rustc_data_structures::static_assert_size; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_target::abi::{HasDataLayout, Size}; -use super::{AllocId, InterpResult}; +use super::AllocId; //////////////////////////////////////////////////////////////////////////////// // Pointer arithmetic @@ -40,62 +40,13 @@ pub trait PointerArithmetic: HasDataLayout { } #[inline] - fn target_usize_to_isize(&self, val: u64) -> i64 { - let val = val as i64; - // Now wrap-around into the machine_isize range. - if val > self.target_isize_max() { - // This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into - // i64. - debug_assert!(self.pointer_size().bits() < 64); - let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); - val - i64::try_from(max_usize_plus_1).unwrap() - } else { - val - } - } - - /// Helper function: truncate given value-"overflowed flag" pair to pointer size and - /// update "overflowed flag" if there was an overflow. - /// This should be called by all the other methods before returning! - #[inline] - fn truncate_to_ptr(&self, (val, over): (u64, bool)) -> (u64, bool) { - let val = u128::from(val); - let max_ptr_plus_1 = 1u128 << self.pointer_size().bits(); - (u64::try_from(val % max_ptr_plus_1).unwrap(), over || val >= max_ptr_plus_1) - } - - #[inline] - fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) { - // We do not need to check if i fits in a machine usize. If it doesn't, - // either the wrapping_add will wrap or res will not fit in a pointer. - let res = val.overflowing_add(i); - self.truncate_to_ptr(res) - } - - #[inline] - fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) { - // We need to make sure that i fits in a machine isize. - let n = i.unsigned_abs(); - if i >= 0 { - let (val, over) = self.overflowing_offset(val, n); - (val, over || i > self.target_isize_max()) - } else { - let res = val.overflowing_sub(n); - let (val, over) = self.truncate_to_ptr(res); - (val, over || i < self.target_isize_min()) - } - } - - #[inline] - fn offset<'tcx>(&self, val: u64, i: u64) -> InterpResult<'tcx, u64> { - let (res, over) = self.overflowing_offset(val, i); - if over { throw_ub!(PointerArithOverflow) } else { Ok(res) } + fn truncate_to_target_usize(&self, val: u64) -> u64 { + self.pointer_size().truncate(val.into()).try_into().unwrap() } #[inline] - fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> { - let (res, over) = self.overflowing_signed_offset(val, i); - if over { throw_ub!(PointerArithOverflow) } else { Ok(res) } + fn sign_extend_to_target_isize(&self, val: u64) -> i64 { + self.pointer_size().sign_extend(val.into()).try_into().unwrap() } } @@ -331,7 +282,7 @@ impl Pointer> { } } -impl<'tcx, Prov> Pointer { +impl Pointer { #[inline(always)] pub fn new(provenance: Prov, offset: Size) -> Self { Pointer { provenance, offset } @@ -349,43 +300,16 @@ impl<'tcx, Prov> Pointer { Pointer { provenance: f(self.provenance), ..self } } - #[inline] - pub fn offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { - Ok(Pointer { - offset: Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?), - ..self - }) - } - - #[inline] - pub fn overflowing_offset(self, i: Size, cx: &impl HasDataLayout) -> (Self, bool) { - let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes()); - let ptr = Pointer { offset: Size::from_bytes(res), ..self }; - (ptr, over) - } - #[inline(always)] pub fn wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self { - self.overflowing_offset(i, cx).0 - } - - #[inline] - pub fn signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { - Ok(Pointer { - offset: Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?), - ..self - }) - } - - #[inline] - pub fn overflowing_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> (Self, bool) { - let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i); - let ptr = Pointer { offset: Size::from_bytes(res), ..self }; - (ptr, over) + let res = + cx.data_layout().truncate_to_target_usize(self.offset.bytes().wrapping_add(i.bytes())); + Pointer { offset: Size::from_bytes(res), ..self } } #[inline(always)] pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self { - self.overflowing_signed_offset(i, cx).0 + // It's wrapping anyway, so we can just cast to `u64`. + self.wrapping_offset(Size::from_bytes(i as u64), cx) } } diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 491d7cbcfe09c..84c17b39a623e 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -393,7 +393,7 @@ impl<'tcx, Prov: Provenance> Scalar { #[inline] pub fn to_int(self, size: Size) -> InterpResult<'tcx, i128> { let b = self.to_bits(size)?; - Ok(size.sign_extend(b) as i128) + Ok(size.sign_extend(b)) } /// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer. diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 6bfdb3d973607..0024a2ae756ea 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -234,7 +234,7 @@ impl ScalarInt { let data = i.into(); // `into` performed sign extension, we have to truncate let r = Self::raw(size.truncate(data as u128), size); - (r, size.sign_extend(r.data) as i128 != data) + (r, size.sign_extend(r.data) != data) } #[inline] @@ -335,7 +335,7 @@ impl ScalarInt { #[inline] pub fn to_int(self, size: Size) -> i128 { let b = self.to_bits(size); - size.sign_extend(b) as i128 + size.sign_extend(b) } /// Converts the `ScalarInt` to i8. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8b6c9a4a10d65..3cf8531bb62d5 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -79,7 +79,7 @@ impl<'tcx> Discr<'tcx> { let (val, oflo) = if signed { let min = size.signed_int_min(); let max = size.signed_int_max(); - let val = size.sign_extend(self.val) as i128; + let val = size.sign_extend(self.val); assert!(n < (i128::MAX as u128)); let n = n as i128; let oflo = val > max - n; diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 81facdd34b62b..ed955e78c3e9a 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -11,7 +11,7 @@ use rand::Rng; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_span::Span; -use rustc_target::abi::{Align, HasDataLayout, Size}; +use rustc_target::abi::{Align, Size}; use crate::{concurrency::VClock, *}; @@ -307,15 +307,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) let alloc_id = prov.alloc_id(); - let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?; - // Add offset with the right kind of pointer-overflowing arithmetic. - let dl = ecx.data_layout(); - let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0; - Ok(interpret::Pointer::new( + // Get a pointer to the beginning of this allocation. + let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?; + let base_ptr = interpret::Pointer::new( Provenance::Concrete { alloc_id, tag }, - Size::from_bytes(absolute_addr), - )) + Size::from_bytes(base_addr), + ); + // Add offset with the right kind of pointer-overflowing arithmetic. + Ok(base_ptr.wrapping_offset(offset, ecx)) } /// When a pointer is used for a memory access, this computes where in which allocation the @@ -341,12 +341,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let base_addr = *ecx.machine.alloc_addresses.borrow().base_addr.get(&alloc_id).unwrap(); // Wrapping "addr - base_addr" - #[allow(clippy::cast_possible_wrap)] // we want to wrap here - let neg_base_addr = (base_addr as i64).wrapping_neg(); - Some(( - alloc_id, - Size::from_bytes(ecx.overflowing_signed_offset(addr.bytes(), neg_base_addr).0), - )) + let rel_offset = ecx.truncate_to_target_usize(addr.bytes().wrapping_sub(base_addr)); + Some((alloc_id, Size::from_bytes(rel_offset))) } } diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index ba094c988e5ab..8bc8188f05314 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -606,7 +606,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // The part between the end_ptr and the end of the place is also frozen. // So pretend there is a 0-sized `UnsafeCell` at the end. - unsafe_cell_action(&place.ptr().offset(size, this)?, Size::ZERO)?; + unsafe_cell_action(&place.ptr().wrapping_offset(size, this), Size::ZERO)?; // Done! return Ok(()); @@ -975,7 +975,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { loop { // FIXME: We are re-getting the allocation each time around the loop. // Would be nice if we could somehow "extend" an existing AllocRange. - let alloc = this.get_ptr_alloc(ptr.offset(len, this)?, size1)?.unwrap(); // not a ZST, so we will get a result + let alloc = this.get_ptr_alloc(ptr.wrapping_offset(len, this), size1)?.unwrap(); // not a ZST, so we will get a result let byte = alloc.read_integer(alloc_range(Size::ZERO, size1))?.to_u8()?; if byte == 0 { break; @@ -1039,7 +1039,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { break; } else { wchars.push(wchar_int.try_into().unwrap()); - ptr = ptr.offset(size, this)?; + ptr = ptr.wrapping_offset(size, this); } } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index f0d8cc9a1cc23..7f6f63ff5e79b 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -622,7 +622,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { { let idx = u64::try_from(idx).unwrap(); #[allow(clippy::arithmetic_side_effects)] // idx < num, so this never wraps - let new_ptr = ptr.offset(Size::from_bytes(num - idx - 1), this)?; + let new_ptr = ptr.wrapping_offset(Size::from_bytes(num - idx - 1), this); this.write_pointer(new_ptr, dest)?; } else { this.write_null(dest)?; @@ -646,7 +646,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { .iter() .position(|&c| c == val); if let Some(idx) = idx { - let new_ptr = ptr.offset(Size::from_bytes(idx as u64), this)?; + let new_ptr = ptr.wrapping_offset(Size::from_bytes(idx as u64), this); this.write_pointer(new_ptr, dest)?; } else { this.write_null(dest)?; diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs index 3b8ad65195b8a..08b9b4e8fa340 100644 --- a/src/tools/miri/src/shims/unix/env.rs +++ b/src/tools/miri/src/shims/unix/env.rs @@ -82,7 +82,7 @@ impl<'tcx> UnixEnvVars<'tcx> { }; // The offset is used to strip the "{name}=" part of the string. let var_ptr = var_ptr - .offset(Size::from_bytes(u64::try_from(name.len()).unwrap().strict_add(1)), ecx)?; + .wrapping_offset(Size::from_bytes(u64::try_from(name.len()).unwrap().strict_add(1)), ecx); Ok(Some(var_ptr)) } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 6923b39733f0b..f5695713dd33f 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -996,7 +996,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &this.ptr_to_mplace(entry, dirent64_layout), )?; - let name_ptr = entry.offset(Size::from_bytes(d_name_offset), this)?; + let name_ptr = entry.wrapping_offset(Size::from_bytes(d_name_offset), this); this.write_bytes_ptr(name_ptr, name_bytes.iter().copied())?; Some(entry) diff --git a/src/tools/miri/src/shims/unix/linux/mem.rs b/src/tools/miri/src/shims/unix/linux/mem.rs index c430eff0180ea..3b32612e8baf0 100644 --- a/src/tools/miri/src/shims/unix/linux/mem.rs +++ b/src/tools/miri/src/shims/unix/linux/mem.rs @@ -53,7 +53,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We just allocated this, the access is definitely in-bounds and fits into our address space. // mmap guarantees new mappings are zero-init. this.write_bytes_ptr( - ptr.offset(Size::from_bytes(old_size), this).unwrap().into(), + ptr.wrapping_offset(Size::from_bytes(old_size), this).into(), std::iter::repeat(0u8).take(usize::try_from(increase).unwrap()), ) .unwrap(); diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.rs b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.rs deleted file mode 100644 index 0d4eea9a5bdea..0000000000000 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn main() { - let v = [0i8; 4]; - let x = &v as *const i8; - let x = unsafe { x.offset(isize::MIN) }; //~ERROR: overflowing in-bounds pointer arithmetic - panic!("this should never print: {:?}", x); -} diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr deleted file mode 100644 index 97fa1f19af106..0000000000000 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_2.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: Undefined Behavior: overflowing in-bounds pointer arithmetic - --> $DIR/out_of_bounds_ptr_2.rs:LL:CC - | -LL | let x = unsafe { x.offset(isize::MIN) }; - | ^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic - | - = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior - = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: - = note: inside `main` at $DIR/out_of_bounds_ptr_2.rs:LL:CC - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to 1 previous error - diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs index c4b6f69dd2be6..29bf61e25c896 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs @@ -1,5 +1,5 @@ //@compile-flags: -Zmiri-permissive-provenance -//@normalize-stderr-test: "to \d+ bytes of memory" -> "to $$BYTES bytes of memory" +//@normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes" fn main() { let ptr = Box::into_raw(Box::new(0u32)); diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.rs similarity index 72% rename from src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs rename to src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.rs index f337090aa1e36..905fc678f6d50 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.rs @@ -1,7 +1,6 @@ fn main() { let v = [0i8; 4]; let x = &v as *const i8; - // The error is inside another function, so we cannot match it by line let x = unsafe { x.offset(5) }; //~ERROR: expected a pointer to 5 bytes of memory panic!("this should never print: {:?}", x); } diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.stderr similarity index 85% rename from src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr rename to src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.stderr index c6a1e4710a8cd..c4548200f0596 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation - --> $DIR/out_of_bounds_ptr_1.rs:LL:CC + --> $DIR/ptr_offset_out_of_bounds.rs:LL:CC | LL | let x = unsafe { x.offset(5) }; | ^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to 5 bytes of memory, but got ALLOC which is only 4 bytes from the end of the allocation @@ -7,12 +7,12 @@ LL | let x = unsafe { x.offset(5) }; = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information help: ALLOC was allocated here: - --> $DIR/out_of_bounds_ptr_1.rs:LL:CC + --> $DIR/ptr_offset_out_of_bounds.rs:LL:CC | LL | let v = [0i8; 4]; | ^ = note: BACKTRACE (of the first span): - = note: inside `main` at $DIR/out_of_bounds_ptr_1.rs:LL:CC + = note: inside `main` at $DIR/ptr_offset_out_of_bounds.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.rs similarity index 100% rename from src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.rs rename to src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.rs diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.stderr similarity index 84% rename from src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr rename to src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.stderr index ba7615da1deaa..8041e1542c68d 100644 --- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_out_of_bounds_neg.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to the end of 1 byte of memory, but got ALLOC which is at the beginning of the allocation - --> $DIR/out_of_bounds_ptr_3.rs:LL:CC + --> $DIR/ptr_offset_out_of_bounds_neg.rs:LL:CC | LL | let x = unsafe { x.offset(-1) }; | ^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to the end of 1 byte of memory, but got ALLOC which is at the beginning of the allocation @@ -7,12 +7,12 @@ LL | let x = unsafe { x.offset(-1) }; = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information help: ALLOC was allocated here: - --> $DIR/out_of_bounds_ptr_3.rs:LL:CC + --> $DIR/ptr_offset_out_of_bounds_neg.rs:LL:CC | LL | let v = [0i8; 4]; | ^ = note: BACKTRACE (of the first span): - = note: inside `main` at $DIR/out_of_bounds_ptr_3.rs:LL:CC + = note: inside `main` at $DIR/ptr_offset_out_of_bounds_neg.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.rs index c3db1e23b9bfb..6839431223270 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.rs @@ -1,5 +1,8 @@ +//@normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes" + fn main() { - let v = [1i8, 2]; - let x = &v[1] as *const i8; - let _val = unsafe { x.offset(isize::MIN) }; //~ERROR: overflowing in-bounds pointer arithmetic + let v = [0i8; 4]; + let x = &v as *const i8; + let x = unsafe { x.offset(isize::MIN) }; //~ERROR: out-of-bounds pointer arithmetic + panic!("this should never print: {:?}", x); } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr index 122529c30490a..ee5aebc6eaeef 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_overflow.stderr @@ -1,12 +1,17 @@ -error: Undefined Behavior: overflowing in-bounds pointer arithmetic +error: Undefined Behavior: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC which is at the beginning of the allocation --> $DIR/ptr_offset_overflow.rs:LL:CC | -LL | let _val = unsafe { x.offset(isize::MIN) }; - | ^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic +LL | let x = unsafe { x.offset(isize::MIN) }; + | ^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC which is at the beginning of the allocation | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information - = note: BACKTRACE: +help: ALLOC was allocated here: + --> $DIR/ptr_offset_overflow.rs:LL:CC + | +LL | let v = [0i8; 4]; + | ^ + = note: BACKTRACE (of the first span): = note: inside `main` at $DIR/ptr_offset_overflow.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr index 4a9ffb46a3feb..29327569323f9 100644 --- a/tests/ui/consts/offset_ub.stderr +++ b/tests/ui/consts/offset_ub.stderr @@ -1,7 +1,7 @@ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: overflowing in-bounds pointer arithmetic + = note: out-of-bounds pointer arithmetic: expected a pointer to the end of 1 byte of memory, but got ALLOC0 which is at the beginning of the allocation | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -14,7 +14,7 @@ LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC0 which is only 1 byte from the end of the allocation + = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC1 which is only 1 byte from the end of the allocation | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -27,7 +27,7 @@ LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC1 which is only $BYTES bytes from the end of the allocation + = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got ALLOC2 which is only $BYTES bytes from the end of the allocation | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -66,7 +66,7 @@ LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize: error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: overflowing in-bounds pointer arithmetic + = note: out-of-bounds pointer arithmetic: expected a pointer to $BYTES bytes of memory, but got 0xf..f[noalloc] which is a dangling pointer (it has no provenance) | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -79,7 +79,7 @@ LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *cons error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: overflowing in-bounds pointer arithmetic + = note: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance) | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -92,7 +92,7 @@ LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).of error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC2-0x2 which points to before the beginning of the allocation + = note: out-of-bounds pointer arithmetic: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC3-0x2 which points to before the beginning of the allocation | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -105,7 +105,7 @@ LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC3 which is at or beyond the end of the allocation of size $BYTES bytes + = note: out-of-bounds pointer arithmetic: expected a pointer to 1 byte of memory, but got ALLOC4 which is at or beyond the end of the allocation of size $BYTES bytes | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL From db1652e07b7e6f81692795e7cb3b8c02798b1756 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Aug 2024 14:38:58 +0200 Subject: [PATCH 359/489] fix the way we detect overflow for inbounds arithmetic (and tweak the error message) --- compiler/rustc_const_eval/messages.ftl | 2 +- .../src/interpret/operator.rs | 22 ++++++++++++------- tests/ui/consts/offset_ub.stderr | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index e02d6ebb18302..94cdd021d8d9f 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -277,7 +277,7 @@ const_eval_partial_pointer_copy = const_eval_partial_pointer_overwrite = unable to overwrite parts of a pointer in memory at {$ptr} const_eval_pointer_arithmetic_overflow = - overflowing in-bounds pointer arithmetic + overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize` const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic const_eval_pointer_out_of_bounds = {$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg -> diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 3263c90ec7265..fe5869ad7fa7a 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -7,7 +7,7 @@ use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::sym; use tracing::trace; -use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta}; +use super::{throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta}; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn three_way_compare(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> { @@ -298,17 +298,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Pointer ops that are always supported. Offset => { let ptr = left.to_scalar().to_pointer(self)?; - let offset_count = right.to_scalar().to_target_isize(self)?; let pointee_ty = left.layout.ty.builtin_deref(true).unwrap(); + let pointee_layout = self.layout_of(pointee_ty)?; + assert!(pointee_layout.abi.is_sized()); // We cannot overflow i64 as a type's size must be <= isize::MAX. - let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap(); - // The computed offset, in bytes, must not overflow an isize. - // `checked_mul` enforces a too small bound, but no actual allocation can be big enough for - // the difference to be noticeable. - let offset_bytes = - offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?; + let pointee_size = i64::try_from(pointee_layout.size.bytes()).unwrap(); + let pointee_size = ImmTy::from_int(pointee_size, right.layout); + // Multiply element size and element count. + let (val, overflowed) = self + .binary_op(mir::BinOp::MulWithOverflow, right, &pointee_size)? + .to_scalar_pair(); + // This must not overflow. + if overflowed.to_bool()? { + throw_ub!(PointerArithOverflow) + } + let offset_bytes = val.to_target_isize(self)?; let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?; Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout)) } diff --git a/tests/ui/consts/offset_ub.stderr b/tests/ui/consts/offset_ub.stderr index 29327569323f9..779cb9654f4d2 100644 --- a/tests/ui/consts/offset_ub.stderr +++ b/tests/ui/consts/offset_ub.stderr @@ -40,7 +40,7 @@ LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: overflowing in-bounds pointer arithmetic + = note: overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize` | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL @@ -53,7 +53,7 @@ LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize:: error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL | - = note: overflowing in-bounds pointer arithmetic + = note: overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize` | note: inside `std::ptr::const_ptr::::offset` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL From e157954cce4497738a728f8c295c71b229d35a66 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 1 Aug 2024 13:11:24 +0000 Subject: [PATCH 360/489] Fix removed `box_syntax` diagnostic if source isn't available --- compiler/rustc_parse/messages.ftl | 2 +- compiler/rustc_parse/src/errors.rs | 23 +++++++++++++------ compiler/rustc_parse/src/parser/expr.rs | 10 ++++---- .../removed-syntax/removed-syntax-box.stderr | 10 ++++---- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 391a57917768d..9d594120ec4fe 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -66,7 +66,7 @@ parse_box_not_pat = expected pattern, found {$descr} .suggestion = escape `box` to use it as an identifier parse_box_syntax_removed = `box_syntax` has been removed - .suggestion = use `Box::new()` instead +parse_box_syntax_removed_suggestion = use `Box::new()` instead parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index c5e7e0df6312e..dfe47dd0beb26 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2725,15 +2725,24 @@ impl HelpUseLatestEdition { #[derive(Diagnostic)] #[diag(parse_box_syntax_removed)] -pub struct BoxSyntaxRemoved<'a> { +pub struct BoxSyntaxRemoved { #[primary_span] - #[suggestion( - code = "Box::new({code})", - applicability = "machine-applicable", - style = "verbose" - )] pub span: Span, - pub code: &'a str, + #[subdiagnostic] + pub sugg: AddBoxNew, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + parse_box_syntax_removed_suggestion, + applicability = "machine-applicable", + style = "verbose" +)] +pub struct AddBoxNew { + #[suggestion_part(code = "Box::new(")] + pub box_kw_and_lo: Span, + #[suggestion_part(code = ")")] + pub hi: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a4d9d97045d2a..1b053c39e64b4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -618,10 +618,12 @@ impl<'a> Parser<'a> { /// Parse `box expr` - this syntax has been removed, but we still parse this /// for now to provide a more useful error fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> { - let (span, _) = self.parse_expr_prefix_common(box_kw)?; - let inner_span = span.with_lo(box_kw.hi()); - let code = self.psess.source_map().span_to_snippet(inner_span).unwrap(); - let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() }); + let (span, expr) = self.parse_expr_prefix_common(box_kw)?; + // Make a multipart suggestion instead of `span_to_snippet` in case source isn't available + let box_kw_and_lo = box_kw.until(self.interpolated_or_expr_span(&expr)); + let hi = span.shrink_to_hi(); + let sugg = errors::AddBoxNew { box_kw_and_lo, hi }; + let guar = self.dcx().emit_err(errors::BoxSyntaxRemoved { span, sugg }); Ok((span, ExprKind::Err(guar))) } diff --git a/tests/ui/parser/removed-syntax/removed-syntax-box.stderr b/tests/ui/parser/removed-syntax/removed-syntax-box.stderr index 46b891587d5a6..60c39fd37c434 100644 --- a/tests/ui/parser/removed-syntax/removed-syntax-box.stderr +++ b/tests/ui/parser/removed-syntax/removed-syntax-box.stderr @@ -7,7 +7,7 @@ LL | let _ = box (); help: use `Box::new()` instead | LL | let _ = Box::new(()); - | ~~~~~~~~~~~~ + | ~~~~~~~~~ + error: `box_syntax` has been removed --> $DIR/removed-syntax-box.rs:10:13 @@ -18,7 +18,7 @@ LL | let _ = box 1; help: use `Box::new()` instead | LL | let _ = Box::new(1); - | ~~~~~~~~~~~ + | ~~~~~~~~~ + error: `box_syntax` has been removed --> $DIR/removed-syntax-box.rs:11:13 @@ -29,7 +29,7 @@ LL | let _ = box T { a: 12, b: 18 }; help: use `Box::new()` instead | LL | let _ = Box::new(T { a: 12, b: 18 }); - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~ + error: `box_syntax` has been removed --> $DIR/removed-syntax-box.rs:12:13 @@ -40,7 +40,7 @@ LL | let _ = box [5; 30]; help: use `Box::new()` instead | LL | let _ = Box::new([5; 30]); - | ~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~ + error: `box_syntax` has been removed --> $DIR/removed-syntax-box.rs:13:22 @@ -51,7 +51,7 @@ LL | let _: Box<()> = box (); help: use `Box::new()` instead | LL | let _: Box<()> = Box::new(()); - | ~~~~~~~~~~~~ + | ~~~~~~~~~ + error: aborting due to 5 previous errors From 6d312d7bd17598153c018e4879ccaa657eb48853 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Aug 2024 14:01:17 +0200 Subject: [PATCH 361/489] MIR required_consts, mentioned_items: ensure we do not forget to fill these lists --- .../src/interpret/eval_context.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 48 ++++++++++++++++--- compiler/rustc_middle/src/mir/visit.rs | 8 ++-- .../rustc_mir_build/src/build/custom/mod.rs | 4 +- compiler/rustc_mir_transform/src/inline.rs | 13 +++-- compiler/rustc_mir_transform/src/lib.rs | 36 +++++++++----- .../src/mentioned_items.rs | 3 +- .../rustc_mir_transform/src/promote_consts.rs | 14 ++++-- .../src/required_consts.rs | 13 ++++- compiler/rustc_mir_transform/src/shim.rs | 12 +++-- compiler/rustc_monomorphize/src/collector.rs | 4 +- 11 files changed, 113 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 85f9b2341d91c..9b4a437bf775c 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -888,7 +888,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { body: &'tcx mir::Body<'tcx>, ) -> InterpResult<'tcx> { // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check). - for &const_ in &body.required_consts { + for &const_ in body.required_consts() { let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; c.eval(*self.tcx, self.param_env, const_.span).map_err(|err| { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index b9c93edcd80e4..46c4d586f6ad9 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -383,15 +383,17 @@ pub struct Body<'tcx> { /// Constants that are required to evaluate successfully for this MIR to be well-formed. /// We hold in this field all the constants we are not able to evaluate yet. + /// `None` indicates that the list has not been computed yet. /// /// This is soundness-critical, we make a guarantee that all consts syntactically mentioned in a /// function have successfully evaluated if the function ever gets executed at runtime. - pub required_consts: Vec>, + pub required_consts: Option>>, /// Further items that were mentioned in this function and hence *may* become monomorphized, /// depending on optimizations. We use this to avoid optimization-dependent compile errors: the /// collector recursively traverses all "mentioned" items and evaluates all their /// `required_consts`. + /// `None` indicates that the list has not been computed yet. /// /// This is *not* soundness-critical and the contents of this list are *not* a stable guarantee. /// All that's relevant is that this set is optimization-level-independent, and that it includes @@ -399,7 +401,7 @@ pub struct Body<'tcx> { /// set after drop elaboration, so some drop calls that can never be reached are not considered /// "mentioned".) See the documentation of `CollectionMode` in /// `compiler/rustc_monomorphize/src/collector.rs` for more context. - pub mentioned_items: Vec>>, + pub mentioned_items: Option>>>, /// Does this body use generic parameters. This is used for the `ConstEvaluatable` check. /// @@ -477,8 +479,8 @@ impl<'tcx> Body<'tcx> { spread_arg: None, var_debug_info, span, - required_consts: Vec::new(), - mentioned_items: Vec::new(), + required_consts: None, + mentioned_items: None, is_polymorphic: false, injection_phase: None, tainted_by_errors, @@ -507,8 +509,8 @@ impl<'tcx> Body<'tcx> { arg_count: 0, spread_arg: None, span: DUMMY_SP, - required_consts: Vec::new(), - mentioned_items: Vec::new(), + required_consts: None, + mentioned_items: None, var_debug_info: Vec::new(), is_polymorphic: false, injection_phase: None, @@ -785,6 +787,40 @@ impl<'tcx> Body<'tcx> { // No inlined `SourceScope`s, or all of them were `#[track_caller]`. caller_location.unwrap_or_else(|| from_span(source_info.span)) } + + #[track_caller] + pub fn set_required_consts(&mut self, required_consts: Vec>) { + assert!( + self.required_consts.is_none(), + "required_consts for {:?} have already been set", + self.source.def_id() + ); + self.required_consts = Some(required_consts); + } + #[track_caller] + pub fn required_consts(&self) -> &[ConstOperand<'tcx>] { + match &self.required_consts { + Some(l) => l, + None => panic!("required_consts for {:?} have not yet been set", self.source.def_id()), + } + } + + #[track_caller] + pub fn set_mentioned_items(&mut self, mentioned_items: Vec>>) { + assert!( + self.mentioned_items.is_none(), + "mentioned_items for {:?} have already been set", + self.source.def_id() + ); + self.mentioned_items = Some(mentioned_items); + } + #[track_caller] + pub fn mentioned_items(&self) -> &[Spanned>] { + match &self.mentioned_items { + Some(l) => l, + None => panic!("mentioned_items for {:?} have not yet been set", self.source.def_id()), + } + } } impl<'tcx> Index for Body<'tcx> { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0031ded244062..3921176873c81 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1066,9 +1066,11 @@ macro_rules! super_body { $self.visit_span($(& $mutability)? $body.span); - for const_ in &$($mutability)? $body.required_consts { - let location = Location::START; - $self.visit_const_operand(const_, location); + if let Some(required_consts) = &$($mutability)? $body.required_consts { + for const_ in required_consts { + let location = Location::START; + $self.visit_const_operand(const_, location); + } } } } diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 38acb6f44f95c..28477e527c721 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -54,8 +54,8 @@ pub(super) fn build_custom_mir<'tcx>( spread_arg: None, var_debug_info: Vec::new(), span, - required_consts: Vec::new(), - mentioned_items: Vec::new(), + required_consts: None, + mentioned_items: None, is_polymorphic: false, tainted_by_errors: None, injection_phase: None, diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 36b2b3b7c4466..f30732e6aaf3b 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -744,8 +744,8 @@ impl<'tcx> Inliner<'tcx> { // Copy required constants from the callee_body into the caller_body. Although we are only // pushing unevaluated consts to `required_consts`, here they may have been evaluated // because we are calling `instantiate_and_normalize_erasing_regions` -- so we filter again. - caller_body.required_consts.extend( - callee_body.required_consts.into_iter().filter(|ct| ct.const_.is_required_const()), + caller_body.required_consts.as_mut().unwrap().extend( + callee_body.required_consts().into_iter().filter(|ct| ct.const_.is_required_const()), ); // Now that we incorporated the callee's `required_consts`, we can remove the callee from // `mentioned_items` -- but we have to take their `mentioned_items` in return. This does @@ -755,12 +755,11 @@ impl<'tcx> Inliner<'tcx> { // We need to reconstruct the `required_item` for the callee so that we can find and // remove it. let callee_item = MentionedItem::Fn(func.ty(caller_body, self.tcx)); - if let Some(idx) = - caller_body.mentioned_items.iter().position(|item| item.node == callee_item) - { + let caller_mentioned_items = caller_body.mentioned_items.as_mut().unwrap(); + if let Some(idx) = caller_mentioned_items.iter().position(|item| item.node == callee_item) { // We found the callee, so remove it and add its items instead. - caller_body.mentioned_items.remove(idx); - caller_body.mentioned_items.extend(callee_body.mentioned_items); + caller_mentioned_items.remove(idx); + caller_mentioned_items.extend(callee_body.mentioned_items()); } else { // If we can't find the callee, there's no point in adding its items. Probably it // already got removed by being inlined elsewhere in the same function, so we already diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ac3a44c803a5f..1f214bc42cbe6 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -28,11 +28,10 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_index::IndexVec; -use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{ - traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, - LocalDecl, MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, - SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK, + AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, LocalDecl, + MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, + Statement, StatementKind, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_middle::util::Providers; @@ -339,12 +338,15 @@ fn mir_promoted( // Collect `required_consts` *before* promotion, so if there are any consts being promoted // we still add them to the list in the outer MIR body. - let mut required_consts = Vec::new(); - let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); - for (bb, bb_data) in traversal::reverse_postorder(&body) { - required_consts_visitor.visit_basic_block_data(bb, bb_data); + RequiredConstsVisitor::compute_required_consts(&mut body); + // If this has an associated by-move async closure body, that doesn't get run through these + // passes itself, it gets "tagged along" by the pass manager. `RequiredConstsVisitor` is not + // a regular pass so we have to also apply it manually to the other body. + if let Some(coroutine) = body.coroutine.as_mut() { + if let Some(by_move_body) = coroutine.by_move_body.as_mut() { + RequiredConstsVisitor::compute_required_consts(by_move_body); + } } - body.required_consts = required_consts; // What we need to run borrowck etc. let promote_pass = promote_consts::PromoteTemps::default(); @@ -561,9 +563,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { tcx, body, &[ - // Before doing anything, remember which items are being mentioned so that the set of items - // visited does not depend on the optimization level. - &mentioned_items::MentionedItems, // Add some UB checks before any UB gets optimized away. &check_alignment::CheckAlignment, // Before inlining: trim down MIR with passes to reduce inlining work. @@ -657,6 +656,19 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { return body; } + // Before doing anything, remember which items are being mentioned so that the set of items + // visited does not depend on the optimization level. + // We do not use `run_passes` for this as that might skip the pass if `injection_phase` is set. + mentioned_items::MentionedItems.run_pass(tcx, &mut body); + // If this has an associated by-move async closure body, that doesn't get run through these + // passes itself, it gets "tagged along" by the pass manager. Since we're not using the pass + // manager we have to do this by hand. + if let Some(coroutine) = body.coroutine.as_mut() { + if let Some(by_move_body) = coroutine.by_move_body.as_mut() { + mentioned_items::MentionedItems.run_pass(tcx, by_move_body); + } + } + // If `mir_drops_elaborated_and_const_checked` found that the current body has unsatisfiable // predicates, it will shrink the MIR to a single `unreachable` terminator. // More generally, if MIR is a lone `unreachable`, there is nothing to optimize. diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index e33bdd9942192..32c8064ebca50 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -23,10 +23,9 @@ impl<'tcx> MirPass<'tcx> for MentionedItems { } fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - debug_assert!(body.mentioned_items.is_empty()); let mut mentioned_items = Vec::new(); MentionedItemsVisitor { tcx, body, mentioned_items: &mut mentioned_items }.visit_body(body); - body.mentioned_items = mentioned_items; + body.set_mentioned_items(mentioned_items); } } diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index f8971387ea4d7..dc8e50ac8cd28 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -702,6 +702,9 @@ struct Promoter<'a, 'tcx> { temps: &'a mut IndexVec, extra_statements: &'a mut Vec<(Location, Statement<'tcx>)>, + /// Used to assemble the required_consts list while building the promoted. + required_consts: Vec>, + /// If true, all nested temps are also kept in the /// source MIR, not moved to the promoted MIR. keep_original: bool, @@ -924,11 +927,14 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = self.promoted.span; self.assign(RETURN_PLACE, rvalue, span); - // Now that we did promotion, we know whether we'll want to add this to `required_consts`. + // Now that we did promotion, we know whether we'll want to add this to `required_consts` of + // the surrounding MIR body. if self.add_to_required { - self.source.required_consts.push(promoted_op); + self.source.required_consts.as_mut().unwrap().push(promoted_op); } + self.promoted.set_required_consts(self.required_consts); + self.promoted } } @@ -947,7 +953,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, _location: Location) { if constant.const_.is_required_const() { - self.promoted.required_consts.push(*constant); + self.required_consts.push(*constant); } // Skipping `super_constant` as the visitor is otherwise only looking for locals. @@ -1011,9 +1017,9 @@ fn promote_candidates<'tcx>( extra_statements: &mut extra_statements, keep_original: false, add_to_required: false, + required_consts: Vec::new(), }; - // `required_consts` of the promoted itself gets filled while building the MIR body. let mut promoted = promoter.promote_candidate(candidate, promotions.len()); promoted.source.promoted = Some(promotions.next_index()); promotions.push(promoted); diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs index 00bfb5e66008b..50637e2ac03bb 100644 --- a/compiler/rustc_mir_transform/src/required_consts.rs +++ b/compiler/rustc_mir_transform/src/required_consts.rs @@ -1,14 +1,23 @@ use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{ConstOperand, Location}; +use rustc_middle::mir::{traversal, Body, ConstOperand, Location}; pub struct RequiredConstsVisitor<'a, 'tcx> { required_consts: &'a mut Vec>, } impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { - pub fn new(required_consts: &'a mut Vec>) -> Self { + fn new(required_consts: &'a mut Vec>) -> Self { RequiredConstsVisitor { required_consts } } + + pub fn compute_required_consts(body: &mut Body<'tcx>) { + let mut required_consts = Vec::new(); + let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); + for (bb, bb_data) in traversal::reverse_postorder(&body) { + required_consts_visitor.visit_basic_block_data(bb, bb_data); + } + body.set_required_consts(required_consts); + } } impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index e2fafa3a1a30b..f41f3ef656c51 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -305,7 +305,7 @@ fn new_body<'tcx>( arg_count: usize, span: Span, ) -> Body<'tcx> { - Body::new( + let mut body = Body::new( source, basic_blocks, IndexVec::from_elem_n( @@ -326,7 +326,10 @@ fn new_body<'tcx>( None, // FIXME(compiler-errors): is this correct? None, - ) + ); + // Shims do not directly mention any consts. + body.set_required_consts(Vec::new()); + body } pub struct DropShimElaborator<'a, 'tcx> { @@ -969,13 +972,16 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { }; let source = MirSource::item(ctor_id); - let body = new_body( + let mut body = new_body( source, IndexVec::from_elem_n(start_block, 1), local_decls, sig.inputs().len(), span, ); + // A constructor doesn't mention any other items (and we don't run the usual optimization passes + // so this would otherwise not get filled). + body.set_mentioned_items(Vec::new()); crate::pass_manager::dump_mir_for_phase_change(tcx, &body); diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 99cac67f5b1c1..df2abf6dc9cc4 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1229,7 +1229,7 @@ fn collect_items_of_instance<'tcx>( // Always visit all `required_consts`, so that we evaluate them and abort compilation if any of // them errors. - for const_op in &body.required_consts { + for const_op in body.required_consts() { if let Some(val) = collector.eval_constant(const_op) { collect_const_value(tcx, val, mentioned_items); } @@ -1237,7 +1237,7 @@ fn collect_items_of_instance<'tcx>( // Always gather mentioned items. We try to avoid processing items that we have already added to // `used_items` above. - for item in &body.mentioned_items { + for item in body.mentioned_items() { if !collector.used_mentioned_items.contains(&item.node) { let item_mono = collector.monomorphize(item.node); visit_mentioned_item(tcx, &item_mono, item.span, mentioned_items); From f44958679a59eacf7a8c4356983df042d890fc1d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 31 Jul 2024 16:08:31 +0200 Subject: [PATCH 362/489] Update sysinfo version to 0.31.2 --- Cargo.lock | 87 ++++++++++++++++------ src/bootstrap/Cargo.lock | 111 +++++++++++++++++++++-------- src/bootstrap/Cargo.toml | 2 +- src/bootstrap/src/utils/metrics.rs | 17 +++-- src/tools/opt-dist/Cargo.toml | 2 +- 5 files changed, 158 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a7d7e3f5d7d1..316926e584e23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -771,7 +771,7 @@ dependencies = [ "tracing-subscriber", "unified-diff", "walkdir", - "windows", + "windows 0.52.0", ] [[package]] @@ -1713,7 +1713,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -2436,15 +2436,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3717,7 +3708,7 @@ dependencies = [ "thorin-dwp", "tracing", "wasm-encoder 0.210.0", - "windows", + "windows 0.52.0", ] [[package]] @@ -3774,7 +3765,7 @@ dependencies = [ "tempfile", "thin-vec", "tracing", - "windows", + "windows 0.52.0", ] [[package]] @@ -3835,7 +3826,7 @@ dependencies = [ "shlex", "time", "tracing", - "windows", + "windows 0.52.0", ] [[package]] @@ -3886,7 +3877,7 @@ dependencies = [ "termcolor", "termize", "tracing", - "windows", + "windows 0.52.0", ] [[package]] @@ -4607,7 +4598,7 @@ dependencies = [ "smallvec", "termize", "tracing", - "windows", + "windows 0.52.0", ] [[package]] @@ -5365,16 +5356,13 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.12" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae" +checksum = "d4115055da5f572fff541dd0c4e61b0262977f453cc9fe04be83aba25a89bdab" dependencies = [ - "cfg-if", "core-foundation-sys", "libc", - "ntapi", - "once_cell", - "windows", + "windows 0.57.0", ] [[package]] @@ -6299,7 +6287,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", "windows-targets 0.52.5", ] @@ -6326,12 +6324,55 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.67", +] + [[package]] name = "windows-metadata" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e837f3c3012cfe9e7086302a93f441a7999439be1ad4c530d55d2f6d2921809" +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index de0924c0f4236..60453764d82d3 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -65,7 +65,7 @@ dependencies = [ "termcolor", "toml", "walkdir", - "windows", + "windows 0.52.0", "xz2", ] @@ -378,12 +378,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - [[package]] name = "opener" version = "0.5.2" @@ -549,16 +543,15 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.5" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2" +checksum = "d4115055da5f572fff541dd0c4e61b0262977f453cc9fe04be83aba25a89bdab" dependencies = [ - "cfg-if", "core-foundation-sys", "libc", + "memchr", "ntapi", - "once_cell", - "windows", + "windows 0.57.0", ] [[package]] @@ -655,7 +648,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", + "windows-targets", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", "windows-targets", ] @@ -668,6 +671,49 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -679,13 +725,14 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -694,45 +741,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xattr" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index f723407c3ce31..84262c115b120 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -63,7 +63,7 @@ walkdir = "2.4" xz2 = "0.1" # Dependencies needed by the build-metrics feature -sysinfo = { version = "0.30", default-features = false, optional = true } +sysinfo = { version = "0.31.2", default-features = false, optional = true, features = ["system"] } [target.'cfg(windows)'.dependencies.junction] version = "1.0.0" diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs index bd18eb35c1f2b..e9acb93363e76 100644 --- a/src/bootstrap/src/utils/metrics.rs +++ b/src/bootstrap/src/utils/metrics.rs @@ -13,7 +13,7 @@ use build_helper::metrics::{ JsonInvocation, JsonInvocationSystemStats, JsonNode, JsonRoot, JsonStepSystemStats, Test, TestOutcome, TestSuite, TestSuiteMetadata, }; -use sysinfo::System; +use sysinfo::{CpuRefreshKind, RefreshKind, System}; use crate::core::builder::{Builder, Step}; use crate::utils::helpers::t; @@ -55,7 +55,9 @@ impl BuildMetrics { finished_steps: Vec::new(), running_steps: Vec::new(), - system_info: System::new(), + system_info: System::new_with_specifics( + RefreshKind::new().with_cpu(CpuRefreshKind::everything()), + ), timer_start: None, invocation_timer_start: Instant::now(), invocation_start: SystemTime::now(), @@ -77,7 +79,7 @@ impl BuildMetrics { self.collect_stats(&mut *state); } - state.system_info.refresh_cpu(); + state.system_info.refresh_cpu_usage(); state.timer_start = Some(Instant::now()); state.running_steps.push(StepMetrics { @@ -110,7 +112,7 @@ impl BuildMetrics { state.running_steps.last_mut().unwrap().children.push(step); // Start collecting again for the parent step. - state.system_info.refresh_cpu(); + state.system_info.refresh_cpu_usage(); state.timer_start = Some(Instant::now()); } } @@ -148,7 +150,7 @@ impl BuildMetrics { let elapsed = state.timer_start.unwrap().elapsed(); step.duration_excluding_children_sec += elapsed; - state.system_info.refresh_cpu(); + state.system_info.refresh_cpu_usage(); let cpu = state.system_info.cpus().iter().map(|p| p.cpu_usage()).sum::(); step.cpu_usage_time_sec += cpu as f64 / 100.0 * elapsed.as_secs_f64(); } @@ -159,8 +161,9 @@ impl BuildMetrics { let dest = build.out.join("metrics.json"); - let mut system = System::new(); - system.refresh_cpu(); + let mut system = + System::new_with_specifics(RefreshKind::new().with_cpu(CpuRefreshKind::everything())); + system.refresh_cpu_usage(); system.refresh_memory(); let system_stats = JsonInvocationSystemStats { diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml index 88e8640d56abb..d34f8ad052086 100644 --- a/src/tools/opt-dist/Cargo.toml +++ b/src/tools/opt-dist/Cargo.toml @@ -10,7 +10,7 @@ log = "0.4" anyhow = { version = "1", features = ["backtrace"] } humantime = "2" humansize = "2" -sysinfo = { version = "0.30", default-features = false } +sysinfo = { version = "0.31.2", default-features = false, features = ["disk"] } fs_extra = "1" camino = "1" tar = "0.4" From c8a3cafc0fd995767bd59f2a57a0efa2cf8792cb Mon Sep 17 00:00:00 2001 From: Bryanskiy Date: Thu, 1 Aug 2024 17:44:00 +0300 Subject: [PATCH 363/489] fix dropck documentation for `[T;0]` special-case --- library/core/src/ops/drop.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs index 36ae581e3f723..c6083a121d107 100644 --- a/library/core/src/ops/drop.rs +++ b/library/core/src/ops/drop.rs @@ -171,12 +171,13 @@ /// still be live when `T` gets dropped. The exact details of this analysis are not yet /// stably guaranteed and **subject to change**. Currently, the analysis works as follows: /// - If `T` has no drop glue, then trivially nothing is required to be live. This is the case if -/// neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`] -/// and [`ManuallyDrop`] are considered to never have a destructor, no matter their field type. +/// neither `T` nor any of its (recursive) fields have a destructor (`impl Drop`). [`PhantomData`], +/// arrays of length 0 and [`ManuallyDrop`] are considered to never have a destructor, no matter +/// their field type. /// - If `T` has drop glue, then, for all types `U` that are *owned* by any field of `T`, /// recursively add the types and lifetimes that need to be live when `U` gets dropped. The set of /// owned types is determined by recursively traversing `T`: -/// - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (including arrays of +/// - Recursively descend through `PhantomData`, `Box`, tuples, and arrays (excluding arrays of /// length 0). /// - Stop at reference and raw pointer types as well as function pointers and function items; /// they do not own anything. From b485dd14956ea5d744be38cc5201b8a983be7582 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Fri, 28 Jun 2024 14:20:47 -0400 Subject: [PATCH 364/489] rewrite reproducible-build-2 to rmake --- src/tools/run-make-support/src/fs.rs | 22 +++++++++ .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/reproducible-build-2/Makefile | 27 ----------- tests/run-make/reproducible-build-2/rmake.rs | 45 +++++++++++++++++++ 4 files changed, 67 insertions(+), 28 deletions(-) delete mode 100644 tests/run-make/reproducible-build-2/Makefile create mode 100644 tests/run-make/reproducible-build-2/rmake.rs diff --git a/src/tools/run-make-support/src/fs.rs b/src/tools/run-make-support/src/fs.rs index 0a79616163308..b896168b0a5fe 100644 --- a/src/tools/run-make-support/src/fs.rs +++ b/src/tools/run-make-support/src/fs.rs @@ -83,6 +83,28 @@ pub fn copy, Q: AsRef>(from: P, to: Q) { )); } +#[track_caller] +/// An extension of [`std::fs::copy`] which can copy a directory recursively. +pub fn copy_dir_all, Q: AsRef>(from: P, to: Q) { + create_dir_all(&to); + for entry in read_dir(from) { + let entry = entry.unwrap(); + let ty = entry.file_type().unwrap(); + if ty.is_dir() { + copy_dir_all(entry.path(), to.as_ref().join(entry.file_name())); + } else if ty.is_symlink() { + copy_symlink(entry.path(), to.as_ref().join(entry.file_name())); + } else { + copy(entry.path(), to.as_ref().join(entry.file_name())); + } + } +} + +fn copy_symlink, Q: AsRef>(from: P, to: Q) { + let target_path = fs::read_link(from).unwrap(); + std::os::unix::fs::symlink(target_path, to).unwrap(); +} + /// A wrapper around [`std::fs::File::create`] which includes the file path in the panic message. #[track_caller] pub fn create_file>(path: P) { diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 8747a6265c61e..13230239796ac 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -41,7 +41,6 @@ run-make/raw-dylib-alt-calling-convention/Makefile run-make/raw-dylib-c/Makefile run-make/redundant-libs/Makefile run-make/remap-path-prefix-dwarf/Makefile -run-make/reproducible-build-2/Makefile run-make/reproducible-build/Makefile run-make/rlib-format-packed-bundled-libs/Makefile run-make/simd-ffi/Makefile diff --git a/tests/run-make/reproducible-build-2/Makefile b/tests/run-make/reproducible-build-2/Makefile deleted file mode 100644 index 68fcac8b47f5f..0000000000000 --- a/tests/run-make/reproducible-build-2/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# ignore-musl -# ignore-windows -# Objects are reproducible but their path is not. - -all: \ - fat_lto \ - sysroot - -fat_lto: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - $(RUSTC) reproducible-build.rs -C lto=fat - cp $(TMPDIR)/reproducible-build $(TMPDIR)/reproducible-build-a - $(RUSTC) reproducible-build.rs -C lto=fat - cmp "$(TMPDIR)/reproducible-build-a" "$(TMPDIR)/reproducible-build" || exit 1 - -sysroot: - rm -rf $(TMPDIR) && mkdir $(TMPDIR) - $(RUSTC) reproducible-build-aux.rs - $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(shell $(RUSTC) --print sysroot) --remap-path-prefix=$(shell $(RUSTC) --print sysroot)=/sysroot - cp -R $(shell $(RUSTC) --print sysroot) $(TMPDIR)/sysroot - cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib - $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(TMPDIR)/sysroot --remap-path-prefix=$(TMPDIR)/sysroot=/sysroot - cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 diff --git a/tests/run-make/reproducible-build-2/rmake.rs b/tests/run-make/reproducible-build-2/rmake.rs new file mode 100644 index 0000000000000..6286b60760549 --- /dev/null +++ b/tests/run-make/reproducible-build-2/rmake.rs @@ -0,0 +1,45 @@ +// Builds with fat link-time-optimizations and the --sysroot flag used to be +// non-deterministic - that means, compiling twice with no changes would create +// slightly different outputs. This has been fixed by #63352 and #63505. +// Test 1: Compile with fat-lto twice, check that both compilation outputs are identical. +// Test 2: Compile with sysroot, then change the sysroot path from absolute to relative. +// Outputs should be identical. +// See https://github.com/rust-lang/rust/issues/34902 + +//FIXME(Oneirical): excluded ignore-musl ignore-windows ignore-cross-compile + +use run_make_support::{fs_wrapper, rust_lib_name, rustc}; + +fn main() { + // test 1: fat lto + rustc().input("reproducible-build-aux.rs").run(); + rustc().input("reproducible-build.rs").arg("-Clto=fat").run(); + fs_wrapper::rename("reproducible-build", "reproducible-build-a"); + rustc().input("reproducible-build.rs").arg("-Clto=fat").run(); + assert_eq!(fs_wrapper::read("reproducible-build"), fs_wrapper::read("reproducible-build-a")); + + // test 2: sysroot + let sysroot = rustc().print("sysroot").run().stdout_utf8(); + let sysroot = sysroot.trim(); + + rustc().input("reproducible-build-aux.rs").run(); + rustc() + .input("reproducible-build.rs") + .crate_type("rlib") + .sysroot(&sysroot) + .arg(format!("--remap-path-prefix={sysroot}=/sysroot")) + .run(); + fs_wrapper::copy_dir_all(&sysroot, "sysroot"); + fs_wrapper::rename(rust_lib_name("reproducible_build"), rust_lib_name("foo")); + rustc() + .input("reproducible-build.rs") + .crate_type("rlib") + .sysroot("sysroot") + .arg("--remap-path-prefix=/sysroot=/sysroot") + .run(); + + assert_eq!( + fs_wrapper::read(rust_lib_name("reproducible_build")), + fs_wrapper::read(rust_lib_name("foo")) + ); +} From 94da7b157a5ebcde7ee23f4bd2041307e579891f Mon Sep 17 00:00:00 2001 From: Oneirical Date: Fri, 28 Jun 2024 15:04:06 -0400 Subject: [PATCH 365/489] rewrite stable-symbol-names to rmake --- .../src/external_deps/llvm.rs | 3 +- src/tools/run-make-support/src/fs.rs | 48 ++++++------- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/reproducible-build-2/rmake.rs | 26 +++---- tests/run-make/stable-symbol-names/Makefile | 41 ----------- tests/run-make/stable-symbol-names/rmake.rs | 68 +++++++++++++++++++ 6 files changed, 105 insertions(+), 82 deletions(-) delete mode 100644 tests/run-make/stable-symbol-names/Makefile create mode 100644 tests/run-make/stable-symbol-names/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index 259bb6159461b..bd01275598b9e 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -137,7 +137,8 @@ impl LlvmReadobj { self } - /// Pass `--symbols` to display the symbol. + /// Pass `--symbols` to display the symbol table, including both local + /// and global symbols. pub fn symbols(&mut self) -> &mut Self { self.cmd.arg("--symbols"); self diff --git a/src/tools/run-make-support/src/fs.rs b/src/tools/run-make-support/src/fs.rs index b896168b0a5fe..2c35ba52a629c 100644 --- a/src/tools/run-make-support/src/fs.rs +++ b/src/tools/run-make-support/src/fs.rs @@ -9,11 +9,19 @@ pub fn create_symlink, Q: AsRef>(original: P, link: Q) { if link.as_ref().exists() { std::fs::remove_dir(link.as_ref()).unwrap(); } - std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!( - "failed to create symlink {:?} for {:?}", - link.as_ref().display(), - original.as_ref().display(), - )); + if original.as_ref().is_file() { + std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref()).expect(&format!( + "failed to create symlink {:?} for {:?}", + link.as_ref().display(), + original.as_ref().display(), + )); + } else { + std::os::windows::fs::symlink_dir(original.as_ref(), link.as_ref()).expect(&format!( + "failed to create symlink {:?} for {:?}", + link.as_ref().display(), + original.as_ref().display(), + )); + } } /// Creates a new symlink to a path on the filesystem, adjusting for Windows or Unix. @@ -41,6 +49,8 @@ pub fn copy_dir_all(src: impl AsRef, dst: impl AsRef) { let ty = entry.file_type()?; if ty.is_dir() { copy_dir_all_inner(entry.path(), dst.join(entry.file_name()))?; + } else if ty.is_symlink() { + copy_symlink(entry.path(), dst.join(entry.file_name()))?; } else { std::fs::copy(entry.path(), dst.join(entry.file_name()))?; } @@ -59,6 +69,12 @@ pub fn copy_dir_all(src: impl AsRef, dst: impl AsRef) { } } +fn copy_symlink, Q: AsRef>(from: P, to: Q) -> io::Result<()> { + let target_path = std::fs::read_link(from).unwrap(); + create_symlink(target_path, to); + Ok(()) +} + /// Helper for reading entries in a given directory. pub fn read_dir_entries, F: FnMut(&Path)>(dir: P, mut callback: F) { for entry in read_dir(dir) { @@ -83,28 +99,6 @@ pub fn copy, Q: AsRef>(from: P, to: Q) { )); } -#[track_caller] -/// An extension of [`std::fs::copy`] which can copy a directory recursively. -pub fn copy_dir_all, Q: AsRef>(from: P, to: Q) { - create_dir_all(&to); - for entry in read_dir(from) { - let entry = entry.unwrap(); - let ty = entry.file_type().unwrap(); - if ty.is_dir() { - copy_dir_all(entry.path(), to.as_ref().join(entry.file_name())); - } else if ty.is_symlink() { - copy_symlink(entry.path(), to.as_ref().join(entry.file_name())); - } else { - copy(entry.path(), to.as_ref().join(entry.file_name())); - } - } -} - -fn copy_symlink, Q: AsRef>(from: P, to: Q) { - let target_path = fs::read_link(from).unwrap(); - std::os::unix::fs::symlink(target_path, to).unwrap(); -} - /// A wrapper around [`std::fs::File::create`] which includes the file path in the panic message. #[track_caller] pub fn create_file>(path: P) { diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 13230239796ac..ea50d05e1da45 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -45,7 +45,6 @@ run-make/reproducible-build/Makefile run-make/rlib-format-packed-bundled-libs/Makefile run-make/simd-ffi/Makefile run-make/split-debuginfo/Makefile -run-make/stable-symbol-names/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/symbol-mangling-hashed/Makefile run-make/sysroot-crates-are-unstable/Makefile diff --git a/tests/run-make/reproducible-build-2/rmake.rs b/tests/run-make/reproducible-build-2/rmake.rs index 6286b60760549..c500c4238b088 100644 --- a/tests/run-make/reproducible-build-2/rmake.rs +++ b/tests/run-make/reproducible-build-2/rmake.rs @@ -6,17 +6,22 @@ // Outputs should be identical. // See https://github.com/rust-lang/rust/issues/34902 -//FIXME(Oneirical): excluded ignore-musl ignore-windows ignore-cross-compile +//@ ignore-windows +// Reasons: +// 1. The object files are reproducible, but their paths are not, which causes +// the first assertion in the test to fail. +// 2. When the sysroot gets copied, some symlinks must be re-created, +// which is a privileged action on Windows. -use run_make_support::{fs_wrapper, rust_lib_name, rustc}; +use run_make_support::{bin_name, rfs, rust_lib_name, rustc}; fn main() { // test 1: fat lto rustc().input("reproducible-build-aux.rs").run(); - rustc().input("reproducible-build.rs").arg("-Clto=fat").run(); - fs_wrapper::rename("reproducible-build", "reproducible-build-a"); - rustc().input("reproducible-build.rs").arg("-Clto=fat").run(); - assert_eq!(fs_wrapper::read("reproducible-build"), fs_wrapper::read("reproducible-build-a")); + rustc().input("reproducible-build.rs").arg("-Clto=fat").output("reproducible-build").run(); + rfs::rename("reproducible-build", "reproducible-build-a"); + rustc().input("reproducible-build.rs").arg("-Clto=fat").output("reproducible-build").run(); + assert_eq!(rfs::read("reproducible-build"), rfs::read("reproducible-build-a")); // test 2: sysroot let sysroot = rustc().print("sysroot").run().stdout_utf8(); @@ -29,8 +34,8 @@ fn main() { .sysroot(&sysroot) .arg(format!("--remap-path-prefix={sysroot}=/sysroot")) .run(); - fs_wrapper::copy_dir_all(&sysroot, "sysroot"); - fs_wrapper::rename(rust_lib_name("reproducible_build"), rust_lib_name("foo")); + rfs::copy_dir_all(&sysroot, "sysroot"); + rfs::rename(rust_lib_name("reproducible_build"), rust_lib_name("foo")); rustc() .input("reproducible-build.rs") .crate_type("rlib") @@ -38,8 +43,5 @@ fn main() { .arg("--remap-path-prefix=/sysroot=/sysroot") .run(); - assert_eq!( - fs_wrapper::read(rust_lib_name("reproducible_build")), - fs_wrapper::read(rust_lib_name("foo")) - ); + assert_eq!(rfs::read(rust_lib_name("reproducible_build")), rfs::read(rust_lib_name("foo"))); } diff --git a/tests/run-make/stable-symbol-names/Makefile b/tests/run-make/stable-symbol-names/Makefile deleted file mode 100644 index bbfb8e3888171..0000000000000 --- a/tests/run-make/stable-symbol-names/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -include ../tools.mk - -# The following command will: -# 1. dump the symbols of a library using `nm` -# 2. extract only those lines that we are interested in via `grep` -# 3. from those lines, extract just the symbol name via `sed`, which: -# * always starts with "_ZN" and ends with "E" (`legacy` mangling) -# * always starts with "_R" (`v0` mangling) -# 4. sort those symbol names for deterministic comparison -# 5. write the result into a file - -dump-symbols = nm "$(TMPDIR)/lib$(1).rlib" \ - | grep -E "$(2)" \ - | sed -E "s/.*(_ZN.*E|_R[a-zA-Z0-9_]*).*/\1/" \ - | sort \ - > "$(TMPDIR)/$(1)$(3).nm" - -# This test -# - compiles each of the two crates 2 times and makes sure each time we get -# exactly the same symbol names -# - makes sure that both crates agree on the same symbol names for monomorphic -# functions - -all: - $(RUSTC) stable-symbol-names1.rs - $(call dump-symbols,stable_symbol_names1,generic_|mono_,_v1) - rm $(TMPDIR)/libstable_symbol_names1.rlib - $(RUSTC) stable-symbol-names1.rs - $(call dump-symbols,stable_symbol_names1,generic_|mono_,_v2) - cmp "$(TMPDIR)/stable_symbol_names1_v1.nm" "$(TMPDIR)/stable_symbol_names1_v2.nm" - - $(RUSTC) stable-symbol-names2.rs - $(call dump-symbols,stable_symbol_names2,generic_|mono_,_v1) - rm $(TMPDIR)/libstable_symbol_names2.rlib - $(RUSTC) stable-symbol-names2.rs - $(call dump-symbols,stable_symbol_names2,generic_|mono_,_v2) - cmp "$(TMPDIR)/stable_symbol_names2_v1.nm" "$(TMPDIR)/stable_symbol_names2_v2.nm" - - $(call dump-symbols,stable_symbol_names1,mono_,_cross) - $(call dump-symbols,stable_symbol_names2,mono_,_cross) - cmp "$(TMPDIR)/stable_symbol_names1_cross.nm" "$(TMPDIR)/stable_symbol_names2_cross.nm" diff --git a/tests/run-make/stable-symbol-names/rmake.rs b/tests/run-make/stable-symbol-names/rmake.rs new file mode 100644 index 0000000000000..402f411c7f5e6 --- /dev/null +++ b/tests/run-make/stable-symbol-names/rmake.rs @@ -0,0 +1,68 @@ +// A typo in rustc caused generic symbol names to be non-deterministic - +// that is, it was possible to compile the same file twice with no changes +// and get outputs with different symbol names. +// This test compiles each of the two crates twice, and checks that each output +// contains exactly the same symbol names. +// Additionally, both crates should agree on the same symbol names for monomorphic +// functions. +// See https://github.com/rust-lang/rust/issues/32554 + +use std::collections::HashSet; + +use run_make_support::{llvm_readobj, regex, rfs, rust_lib_name, rustc}; + +static LEGACY_PATTERN: std::sync::OnceLock = std::sync::OnceLock::new(); +static V0_PATTERN: std::sync::OnceLock = std::sync::OnceLock::new(); + +fn main() { + LEGACY_PATTERN.set(regex::Regex::new(r"_ZN.*E").unwrap()).unwrap(); + V0_PATTERN.set(regex::Regex::new(r"_R[a-zA-Z0-9_]*").unwrap()).unwrap(); + // test 1: first file + rustc().input("stable-symbol-names1.rs").run(); + let sym1 = process_symbols("stable_symbol_names1", "generic_|mono_"); + rfs::remove_file(rust_lib_name("stable_symbol_names1")); + rustc().input("stable-symbol-names1.rs").run(); + let sym2 = process_symbols("stable_symbol_names1", "generic_|mono_"); + assert_eq!(sym1, sym2); + + // test 2: second file + rustc().input("stable-symbol-names2.rs").run(); + let sym1 = process_symbols("stable_symbol_names2", "generic_|mono_"); + rfs::remove_file(rust_lib_name("stable_symbol_names2")); + rustc().input("stable-symbol-names2.rs").run(); + let sym2 = process_symbols("stable_symbol_names2", "generic_|mono_"); + assert_eq!(sym1, sym2); + + // test 3: crossed files + let sym1 = process_symbols("stable_symbol_names1", "mono_"); + let sym2 = process_symbols("stable_symbol_names2", "mono_"); + assert_eq!(sym1, sym2); +} + +#[track_caller] +fn process_symbols(path: &str, symbol: &str) -> Vec { + // Dump all symbols. + let out = llvm_readobj().input(rust_lib_name(path)).symbols().run().stdout_utf8(); + // Extract only lines containing `symbol`. + let symbol_regex = regex::Regex::new(symbol).unwrap(); + let out = out.lines().filter(|&line| symbol_regex.find(line).is_some()); + + // HashSet - duplicates should be excluded! + let mut symbols: HashSet = HashSet::new(); + // From those lines, extract just the symbol name via `regex`, which: + // * always starts with "_ZN" and ends with "E" (`legacy` mangling) + // * always starts with "_R" (`v0` mangling) + for line in out { + if let Some(mat) = LEGACY_PATTERN.get().unwrap().find(line) { + symbols.insert(mat.as_str().to_string()); + } + if let Some(mat) = V0_PATTERN.get().unwrap().find(line) { + symbols.insert(mat.as_str().to_string()); + } + } + + let mut symbols: Vec = symbols.into_iter().collect(); + // Sort those symbol names for deterministic comparison. + symbols.sort(); + symbols +} From 45d35ba4fdecb7cbc6e01688c19e12d5f2c9d1d9 Mon Sep 17 00:00:00 2001 From: Konippi Date: Fri, 2 Aug 2024 00:24:29 +0900 Subject: [PATCH 366/489] chore: refactor backtrace formatting --- library/std/src/error.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/library/std/src/error.rs b/library/std/src/error.rs index f5905605e7887..3e17431af45b0 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -500,13 +500,8 @@ where } if self.show_backtrace { - let backtrace = self.backtrace(); - - if let Some(backtrace) = backtrace { - let backtrace = backtrace.to_string(); - - f.write_str("\n\nStack backtrace:\n")?; - f.write_str(backtrace.trim_end())?; + if let Some(backtrace) = self.backtrace() { + write!(f, "\n\nStack backtrace:\n{}", backtrace.to_string().trim_end())?; } } From 52a49d94c7ac119dd9ae365405635f6b1a37a35c Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Fri, 19 Jul 2024 04:44:52 +0000 Subject: [PATCH 367/489] rustdoc: Add test for `impl_trait_in_accos_type` --- .../rustdoc-json/impl-trait-in-assoc-type.rs | 29 +++++++++++++++++++ .../type-alias/impl_trait_in_assoc_type.rs | 17 +++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/rustdoc-json/impl-trait-in-assoc-type.rs create mode 100644 tests/rustdoc/type-alias/impl_trait_in_assoc_type.rs diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs new file mode 100644 index 0000000000000..f02e38ca393de --- /dev/null +++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs @@ -0,0 +1,29 @@ +// ignore-tidy-linelength +#![feature(impl_trait_in_assoc_type)] + +pub struct AlwaysTrue; + +/// impl IntoIterator +impl IntoIterator for AlwaysTrue { + //@ set Item = '$.index[*][?(@.docs=="type Item")].id' + /// type Item + type Item = bool; + + //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[*]' 1 + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.name' '"Iterator"' + //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[*]' 1 + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name' '"Item"' + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.default.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive' '"bool"' + + //@ set IntoIter = '$.index[*][?(@.docs=="type IntoIter")].id' + /// type IntoIter + type IntoIter = impl Iterator; + + //@ set into_iter = '$.index[*][?(@.docs=="fn into_iter")].id' + /// fn into_iter + fn into_iter(self) -> Self::IntoIter { + std::iter::repeat(true) + } +} + +//@ ismany '$.index[*][?(@.docs=="impl IntoIterator")].inner.impl.items[*]' $Item $IntoIter $into_iter diff --git a/tests/rustdoc/type-alias/impl_trait_in_assoc_type.rs b/tests/rustdoc/type-alias/impl_trait_in_assoc_type.rs new file mode 100644 index 0000000000000..2846710cbed7c --- /dev/null +++ b/tests/rustdoc/type-alias/impl_trait_in_assoc_type.rs @@ -0,0 +1,17 @@ +#![feature(impl_trait_in_assoc_type)] + +pub struct AlwaysTrue; + +//@ has impl_trait_in_assoc_type/struct.AlwaysTrue.html + +impl IntoIterator for AlwaysTrue { + type Item = bool; + + //@ has - '//*[@id="associatedtype.IntoIter"]//h4[@class="code-header"]' \ + // 'type IntoIter = impl Iterator' + type IntoIter = impl Iterator; + + fn into_iter(self) -> Self::IntoIter { + std::iter::repeat(true) + } +} From 73ac5e0c6e8e0e35229444caf5461c6c079122b4 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Wed, 3 Jul 2024 14:29:26 +0000 Subject: [PATCH 368/489] rustdoc: Remove OpaqueTy --- src/librustdoc/clean/mod.rs | 9 +++---- src/librustdoc/clean/types.rs | 9 ------- src/librustdoc/fold.rs | 1 - src/librustdoc/formats/cache.rs | 1 - src/librustdoc/formats/item_type.rs | 4 +-- src/librustdoc/html/render/mod.rs | 2 -- src/librustdoc/html/render/print_item.rs | 31 ------------------------ src/librustdoc/json/conversions.rs | 8 ------ src/librustdoc/json/mod.rs | 1 - src/librustdoc/passes/stripper.rs | 3 +-- src/librustdoc/visit.rs | 1 - src/rustdoc-json-types/lib.rs | 10 +------- src/tools/jsondoclint/src/item_kind.rs | 5 ---- src/tools/jsondoclint/src/validator.rs | 12 +++------ 14 files changed, 10 insertions(+), 87 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0dfda83c25dad..324b633e8ea7e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2748,10 +2748,9 @@ fn clean_maybe_renamed_item<'tcx>( type_: clean_ty(ty, cx), kind: ConstantKind::Local { body: body_id, def_id }, })), - ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { - bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), - generics: clean_generics(ty.generics, cx), - }), + // clean_ty changes types which reference an OpaqueTy item to instead be + // an ImplTrait, so it's ok to return nothing here. + ItemKind::OpaqueTy(_) => return vec![], ItemKind::TyAlias(hir_ty, generics) => { *cx.current_type_aliases.entry(def_id).or_insert(0) += 1; let rustdoc_ty = clean_ty(hir_ty, cx); @@ -2834,7 +2833,7 @@ fn clean_maybe_renamed_item<'tcx>( ItemKind::Use(path, kind) => { return clean_use_statement(item, name, path, kind, cx, &mut FxHashSet::default()); } - _ => unreachable!("not yet converted"), + _ => span_bug!(item.span, "not yet converted"), }; vec![generate_item_with_correct_attrs( diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1ec5f38b6ec0f..3f8b9511d6400 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -824,7 +824,6 @@ pub(crate) enum ItemKind { FunctionItem(Box), ModuleItem(Module), TypeAliasItem(Box), - OpaqueTyItem(OpaqueTy), StaticItem(Static), TraitItem(Box), TraitAliasItem(TraitAlias), @@ -882,7 +881,6 @@ impl ItemKind { | ImportItem(_) | FunctionItem(_) | TypeAliasItem(_) - | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(_) | TraitAliasItem(_) @@ -916,7 +914,6 @@ impl ItemKind { | ExternCrateItem { .. } | FunctionItem(_) | TypeAliasItem(_) - | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(_) | TraitAliasItem(_) @@ -2339,12 +2336,6 @@ pub(crate) struct TypeAlias { pub(crate) item_type: Option, } -#[derive(Clone, Debug)] -pub(crate) struct OpaqueTy { - pub(crate) bounds: Vec, - pub(crate) generics: Generics, -} - #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) struct BareFunctionDecl { pub(crate) safety: hir::Safety, diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index beb7686e29c56..bf82c911f290f 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -77,7 +77,6 @@ pub(crate) trait DocFolder: Sized { ExternCrateItem { src: _ } | ImportItem(_) | FunctionItem(_) - | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(..) | TraitAliasItem(_) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 9f284486616a0..5012cddf83a69 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -463,7 +463,6 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { clean::ExternCrateItem { .. } | clean::ImportItem(..) - | clean::OpaqueTyItem(..) | clean::ImplItem(..) | clean::TyMethodItem(..) | clean::MethodItem(..) diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index c860eb8c6964b..3dcef15b552b2 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -51,7 +51,7 @@ pub(crate) enum ItemType { AssocConst = 19, Union = 20, ForeignType = 21, - OpaqueTy = 22, + // OpaqueTy used to be here, but it was removed in #127276 ProcAttribute = 23, ProcDerive = 24, TraitAlias = 25, @@ -84,7 +84,6 @@ impl<'a> From<&'a clean::Item> for ItemType { clean::EnumItem(..) => ItemType::Enum, clean::FunctionItem(..) => ItemType::Function, clean::TypeAliasItem(..) => ItemType::TypeAlias, - clean::OpaqueTyItem(..) => ItemType::OpaqueTy, clean::StaticItem(..) => ItemType::Static, clean::ConstantItem(..) => ItemType::Constant, clean::TraitItem(..) => ItemType::Trait, @@ -191,7 +190,6 @@ impl ItemType { ItemType::AssocConst => "associatedconstant", ItemType::ForeignType => "foreigntype", ItemType::Keyword => "keyword", - ItemType::OpaqueTy => "opaque", ItemType::ProcAttribute => "attr", ItemType::ProcDerive => "derive", ItemType::TraitAlias => "traitalias", diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index b5cc495ce41ef..6961261d7128b 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -376,7 +376,6 @@ impl AllTypes { ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)), ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)), ItemType::TypeAlias => self.type_aliases.insert(ItemEntry::new(new_url, name)), - ItemType::OpaqueTy => self.opaque_tys.insert(ItemEntry::new(new_url, name)), ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)), ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)), ItemType::ProcAttribute => { @@ -2299,7 +2298,6 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection { ItemType::AssocConst => ItemSection::AssociatedConstants, ItemType::ForeignType => ItemSection::ForeignTypes, ItemType::Keyword => ItemSection::Keywords, - ItemType::OpaqueTy => ItemSection::OpaqueTypes, ItemType::ProcAttribute => ItemSection::AttributeMacros, ItemType::ProcDerive => ItemSection::DeriveMacros, ItemType::TraitAlias => ItemSection::TraitAliases, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index eec6df9dd2013..d8b111471b85e 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -202,7 +202,6 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf clean::ConstantItem(..) => "Constant ", clean::ForeignTypeItem => "Foreign Type ", clean::KeywordItem => "Keyword ", - clean::OpaqueTyItem(..) => "Opaque Type ", clean::TraitAliasItem(..) => "Trait Alias ", _ => { // We don't generate pages for any other type. @@ -270,7 +269,6 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf clean::ConstantItem(ci) => item_constant(buf, cx, item, &ci.generics, &ci.type_, &ci.kind), clean::ForeignTypeItem => item_foreign_type(buf, cx, item), clean::KeywordItem => item_keyword(buf, cx, item), - clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e), clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta), _ => { // We don't generate pages for any other type. @@ -1197,35 +1195,6 @@ fn item_trait_alias( .unwrap(); } -fn item_opaque_ty( - w: &mut impl fmt::Write, - cx: &mut Context<'_>, - it: &clean::Item, - t: &clean::OpaqueTy, -) { - wrap_item(w, |w| { - write!( - w, - "{attrs}type {name}{generics}{where_clause} = impl {bounds};", - attrs = render_attributes_in_pre(it, "", cx), - name = it.name.unwrap(), - generics = t.generics.print(cx), - where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), - bounds = bounds(&t.bounds, false, cx), - ) - .unwrap(); - }); - - write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); - - // Render any items associated directly to this alias, as otherwise they - // won't be visible anywhere in the docs. It would be nice to also show - // associated items from the aliased type (see discussion in #32077), but - // we need #14072 to make sense of the generics. - write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) - .unwrap(); -} - fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) { wrap_item(w, |w| { write!( diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index db9dafab9a484..b56244f2d3b6d 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -333,7 +333,6 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ForeignStaticItem(s, _) => ItemEnum::Static(s.into_tcx(tcx)), ForeignTypeItem => ItemEnum::ForeignType, TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), - OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)), // FIXME(generic_const_items): Add support for generic free consts ConstantItem(ci) => { ItemEnum::Constant { type_: ci.type_.into_tcx(tcx), const_: ci.kind.into_tcx(tcx) } @@ -830,12 +829,6 @@ impl FromWithTcx> for TypeAlias { } } -impl FromWithTcx for OpaqueTy { - fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self { - OpaqueTy { bounds: opaque.bounds.into_tcx(tcx), generics: opaque.generics.into_tcx(tcx) } - } -} - impl FromWithTcx for Static { fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self { Static { @@ -867,7 +860,6 @@ impl FromWithTcx for ItemKind { Enum => ItemKind::Enum, Function | TyMethod | Method => ItemKind::Function, TypeAlias => ItemKind::TypeAlias, - OpaqueTy => ItemKind::OpaqueTy, Static => ItemKind::Static, Constant => ItemKind::Constant, Trait => ItemKind::Trait, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 033f01864f149..dd516c4cbd785 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -184,7 +184,6 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { | types::ItemEnum::TraitAlias(_) | types::ItemEnum::Impl(_) | types::ItemEnum::TypeAlias(_) - | types::ItemEnum::OpaqueTy(_) | types::ItemEnum::Constant { .. } | types::ItemEnum::Static(_) | types::ItemEnum::ForeignType diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index d3368186d3ab8..d1e2b9978f7de 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -50,8 +50,7 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { return Some(ret); } // These items can all get re-exported - clean::OpaqueTyItem(..) - | clean::TypeAliasItem(..) + clean::TypeAliasItem(..) | clean::StaticItem(..) | clean::StructItem(..) | clean::EnumItem(..) diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index de836439be957..430bbe991eaaf 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -26,7 +26,6 @@ pub(crate) trait DocVisitor: Sized { | ImportItem(_) | FunctionItem(_) | TypeAliasItem(_) - | OpaqueTyItem(_) | StaticItem(_) | ConstantItem(..) | TraitAliasItem(_) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 841a87fc48a32..a93ac6ccaf1df 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 32; +pub const FORMAT_VERSION: u32 = 33; /// The root of the emitted JSON blob. /// @@ -326,7 +326,6 @@ pub enum ItemKind { Function, /// A type alias declaration, e.g. `type Pig = std::borrow::Cow<'static, str>;` TypeAlias, - OpaqueTy, /// The declaration of a constant, e.g. `const GREETING: &str = "Hi :3";` Constant, /// A `trait` declaration. @@ -414,7 +413,6 @@ pub enum ItemEnum { /// A type alias declaration, e.g. `type Pig = std::borrow::Cow<'static, str>;` TypeAlias(TypeAlias), - OpaqueTy(OpaqueTy), /// The declaration of a constant, e.g. `const GREETING: &str = "Hi :3";` Constant { /// The type of the constant. @@ -1200,12 +1198,6 @@ pub struct TypeAlias { pub generics: Generics, } -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct OpaqueTy { - pub bounds: Vec, - pub generics: Generics, -} - /// A `static` declaration. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Static { diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index 525de03bbce33..7d6ec475badd4 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -13,7 +13,6 @@ pub(crate) enum Kind { Variant, Function, TypeAlias, - OpaqueTy, Constant, Trait, TraitAlias, @@ -55,7 +54,6 @@ impl Kind { // FIXME(adotinthevoid): I'm not sure if these are correct Keyword => false, - OpaqueTy => false, ProcAttribute => false, ProcDerive => false, @@ -99,7 +97,6 @@ impl Kind { Kind::Enum => false, Kind::Variant => false, Kind::TypeAlias => false, - Kind::OpaqueTy => false, Kind::Constant => false, Kind::Trait => false, Kind::TraitAlias => false, @@ -149,7 +146,6 @@ impl Kind { ItemEnum::TraitAlias(_) => TraitAlias, ItemEnum::Impl(_) => Impl, ItemEnum::TypeAlias(_) => TypeAlias, - ItemEnum::OpaqueTy(_) => OpaqueTy, ItemEnum::Constant { .. } => Constant, ItemEnum::Static(_) => Static, ItemEnum::Macro(_) => Macro, @@ -177,7 +173,6 @@ impl Kind { ItemKind::Keyword => Keyword, ItemKind::Macro => Macro, ItemKind::Module => Module, - ItemKind::OpaqueTy => OpaqueTy, ItemKind::Primitive => Primitive, ItemKind::ProcAttribute => ProcAttribute, ItemKind::ProcDerive => ProcDerive, diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 6d790c52174e3..0ffb96bef29ba 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -3,9 +3,9 @@ use std::hash::Hash; use rustdoc_json_types::{ Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs, - GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, - OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, - Type, TypeAlias, TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate, + GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, Path, + Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeAlias, + TypeBinding, TypeBindingKind, Union, Variant, VariantKind, WherePredicate, }; use serde_json::Value; @@ -101,7 +101,6 @@ impl<'a> Validator<'a> { ItemEnum::TraitAlias(x) => self.check_trait_alias(x), ItemEnum::Impl(x) => self.check_impl(x, id), ItemEnum::TypeAlias(x) => self.check_type_alias(x), - ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x), ItemEnum::Constant { type_, const_ } => { self.check_type(type_); self.check_constant(const_); @@ -230,11 +229,6 @@ impl<'a> Validator<'a> { self.check_type(&x.type_); } - fn check_opaque_ty(&mut self, x: &'a OpaqueTy) { - x.bounds.iter().for_each(|b| self.check_generic_bound(b)); - self.check_generics(&x.generics); - } - fn check_constant(&mut self, _x: &'a Constant) { // nop } From 020476296b1aa60f79c2f671c48542afe99cc428 Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Thu, 1 Aug 2024 19:23:18 +0100 Subject: [PATCH 369/489] Share `UnorderedKeyError` with `BTReeMap` for set API --- library/alloc/src/collections/btree/set.rs | 36 +++++----------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 6f23d686bcf8e..0fc892eec6504 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -2,7 +2,6 @@ use crate::vec::Vec; use core::borrow::Borrow; use core::cmp::Ordering::{self, Equal, Greater, Less}; use core::cmp::{max, min}; -use core::error::Error; use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; use core::iter::{FusedIterator, Peekable}; @@ -2177,11 +2176,11 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { /// /// If the inserted element is not greater than the element before the /// cursor (if any), or if it not less than the element after the cursor (if - /// any), then an [`UnorderedError`] is returned since this would + /// any), then an [`UnorderedKeyError`] is returned since this would /// invalidate the [`Ord`] invariant between the elements of the set. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedError> { - self.inner.insert_after(value, SetValZST).map_err(UnorderedError::from_map_error) + pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_after(value, SetValZST) } /// Inserts a new element into the set in the gap that the @@ -2192,11 +2191,11 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { /// /// If the inserted element is not greater than the element before the /// cursor (if any), or if it not less than the element after the cursor (if - /// any), then an [`UnorderedError`] is returned since this would + /// any), then an [`UnorderedKeyError`] is returned since this would /// invalidate the [`Ord`] invariant between the elements of the set. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedError> { - self.inner.insert_before(value, SetValZST).map_err(UnorderedError::from_map_error) + pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_before(value, SetValZST) } /// Removes the next element from the `BTreeSet`. @@ -2218,29 +2217,8 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { } } -/// Error type returned by [`CursorMut::insert_before`] and -/// [`CursorMut::insert_after`] if the element being inserted is not properly -/// ordered with regards to adjacent elements. -#[derive(Clone, PartialEq, Eq, Debug)] #[unstable(feature = "btree_cursors", issue = "107540")] -pub struct UnorderedError {} - -impl UnorderedError { - fn from_map_error(error: super::map::UnorderedKeyError) -> Self { - let super::map::UnorderedKeyError {} = error; - Self {} - } -} - -#[unstable(feature = "btree_cursors", issue = "107540")] -impl fmt::Display for UnorderedError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "value is not properly ordered relative to neighbors") - } -} - -#[unstable(feature = "btree_cursors", issue = "107540")] -impl Error for UnorderedError {} +pub use super::map::UnorderedKeyError; #[cfg(test)] mod tests; From 4560770451a21c3beca5808e362b6fe34c7371ae Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Thu, 1 Aug 2024 19:47:06 +0100 Subject: [PATCH 370/489] Fix some uses of "map" instead of "set" in `BTreeSet` cursor API docs --- library/alloc/src/collections/btree/set.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 0fc892eec6504..47b7e56ddf050 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1194,7 +1194,7 @@ impl BTreeSet { /// gap before the smallest element greater than `x`. /// /// Passing `Bound::Unbounded` will return a cursor pointing to the - /// gap before the smallest element in the map. + /// gap before the smallest element in the set. /// /// # Examples /// @@ -1237,7 +1237,7 @@ impl BTreeSet { /// gap before the smallest element greater than `x`. /// /// Passing `Bound::Unbounded` will return a cursor pointing to the - /// gap before the smallest element in the map. + /// gap before the smallest element in the set. /// /// # Examples /// @@ -1280,7 +1280,7 @@ impl BTreeSet { /// gap after the greatest element smaller than `x`. /// /// Passing `Bound::Unbounded` will return a cursor pointing to the - /// gap after the greatest element in the map. + /// gap after the greatest element in the set. /// /// # Examples /// @@ -1323,7 +1323,7 @@ impl BTreeSet { /// gap after the greatest element smaller than `x`. /// /// Passing `Bound::Unbounded` will return a cursor pointing to the - /// gap after the greatest element in the map. + /// gap after the greatest element in the set. /// /// # Examples /// From cbdc3778667c5bad3f9eee4124000a0ca96e4590 Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Thu, 1 Aug 2024 19:47:28 +0100 Subject: [PATCH 371/489] Introduce `Cursor`/`CursorMut`/`CursorMutKey` thrichotomy for `BTreeSet` like map API --- library/alloc/src/collections/btree/set.rs | 210 +++++++++++++++++++-- 1 file changed, 194 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 47b7e56ddf050..86401714639c0 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1249,25 +1249,25 @@ impl BTreeSet { /// /// let mut set = BTreeSet::from([1, 2, 3, 4]); /// - /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Included(&2)) }; + /// let mut cursor = set.lower_bound_mut(Bound::Included(&2)); /// assert_eq!(cursor.peek_prev(), Some(&mut 1)); /// assert_eq!(cursor.peek_next(), Some(&mut 2)); /// - /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Excluded(&2)) }; + /// let mut cursor = set.lower_bound_mut(Bound::Excluded(&2)); /// assert_eq!(cursor.peek_prev(), Some(&mut 2)); /// assert_eq!(cursor.peek_next(), Some(&mut 3)); /// - /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Unbounded) }; + /// let mut cursor = set.lower_bound_mut(Bound::Unbounded); /// assert_eq!(cursor.peek_prev(), None); /// assert_eq!(cursor.peek_next(), Some(&mut 1)); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] - pub unsafe fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> + pub fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> where T: Borrow + Ord, Q: Ord, { - CursorMut { inner: unsafe { self.map.lower_bound_mut(bound).with_mutable_key() } } + CursorMut { inner: self.map.lower_bound_mut(bound) } } /// Returns a [`Cursor`] pointing at the gap after the greatest element @@ -1353,7 +1353,7 @@ impl BTreeSet { T: Borrow + Ord, Q: Ord, { - CursorMut { inner: unsafe { self.map.upper_bound_mut(bound).with_mutable_key() } } + CursorMut { inner: self.map.upper_bound_mut(bound) } } } @@ -2010,6 +2010,31 @@ impl Debug for Cursor<'_, K> { } } +/// A cursor over a `BTreeSet` with editing operations. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the set during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying map. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always point to a gap between two elements in the set, and can +/// operate on the two immediately adjacent elements. +/// +/// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and [`BTreeSet::upper_bound_mut`] +/// methods. +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global> +{ + inner: super::map::CursorMut<'a, K, SetValZST, A>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for CursorMut<'_, K, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("CursorMut") + } +} + /// A cursor over a `BTreeSet` with editing operations, and which allows /// mutating elements. /// @@ -2021,8 +2046,8 @@ impl Debug for Cursor<'_, K> { /// Cursors always point to a gap between two elements in the set, and can /// operate on the two immediately adjacent elements. /// -/// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and -/// [`BTreeSet::upper_bound_mut`] methods. +/// A `CursorMutKey` is created from a [`CursorMut`] with the +/// [`CursorMut::with_mutable_key`] method. /// /// # Safety /// @@ -2032,15 +2057,18 @@ impl Debug for Cursor<'_, K> { /// * The newly inserted element must be unique in the tree. /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] -pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global> -{ +pub struct CursorMutKey< + 'a, + K: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A = Global, +> { inner: super::map::CursorMutKey<'a, K, SetValZST, A>, } #[unstable(feature = "btree_cursors", issue = "107540")] -impl Debug for CursorMut<'_, K, A> { +impl Debug for CursorMutKey<'_, K, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("CursorMut") + f.write_str("CursorMutKey") } } @@ -2089,7 +2117,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// If the cursor is already at the end of the set then `None` is returned /// and the cursor is not moved. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn next(&mut self) -> Option<&mut T> { + pub fn next(&mut self) -> Option<&T> { self.inner.next().map(|(k, _)| k) } @@ -2099,7 +2127,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// If the cursor is already at the start of the set then `None` is returned /// and the cursor is not moved. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn prev(&mut self) -> Option<&mut T> { + pub fn prev(&mut self) -> Option<&T> { self.inner.prev().map(|(k, _)| k) } @@ -2107,7 +2135,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// /// If the cursor is at the end of the set then `None` is returned. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn peek_next(&mut self) -> Option<&mut T> { + pub fn peek_next(&mut self) -> Option<&T> { self.inner.peek_next().map(|(k, _)| k) } @@ -2115,7 +2143,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// /// If the cursor is at the start of the set then `None` is returned. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn peek_prev(&mut self) -> Option<&mut T> { + pub fn peek_prev(&mut self) -> Option<&T> { self.inner.peek_prev().map(|(k, _)| k) } @@ -2129,6 +2157,70 @@ impl<'a, T, A> CursorMut<'a, T, A> { pub fn as_cursor(&self) -> Cursor<'_, T> { Cursor { inner: self.inner.as_cursor() } } + + /// Converts the cursor into a [`CursorMutKey`], which allows mutating + /// elements in the tree. + /// + /// # Safety + /// + /// Since this cursor allows mutating elements, you must ensure that the + /// `BTreeSet` invariants are maintained. Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn with_mutable_key(self) -> CursorMutKey<'a, T, A> { + CursorMutKey { inner: unsafe { self.inner.with_mutable_key() } } + } +} + +impl<'a, T, A> CursorMutKey<'a, T, A> { + /// Advances the cursor to the next gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the end of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<&mut T> { + self.inner.next().map(|(k, _)| k) + } + + /// Advances the cursor to the previous gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the start of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<&mut T> { + self.inner.prev().map(|(k, _)| k) + } + + /// Returns a reference to the next element without moving the cursor. + /// + /// If the cursor is at the end of the set then `None` is returned + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&mut self) -> Option<&mut T> { + self.inner.peek_next().map(|(k, _)| k) + } + + /// Returns a reference to the previous element without moving the cursor. + /// + /// If the cursor is at the start of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&mut self) -> Option<&mut T> { + self.inner.peek_prev().map(|(k, _)| k) + } + + /// Returns a read-only cursor pointing to the same location as the + /// `CursorMutKey`. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMutKey`, which means it cannot outlive the `CursorMutKey` and that the + /// `CursorMutKey` is frozen for the lifetime of the `Cursor`. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn as_cursor(&self) -> Cursor<'_, T> { + Cursor { inner: self.inner.as_cursor() } + } } impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { @@ -2217,6 +2309,92 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { } } +impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> { + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The key of the newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_after_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_after_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_before_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_before_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_after(value, SetValZST) + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_before(value, SetValZST) + } + + /// Removes the next element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (before the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_next(&mut self) -> Option { + self.inner.remove_next().map(|(k, _)| k) + } + + /// Removes the precending element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (after the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_prev(&mut self) -> Option { + self.inner.remove_prev().map(|(k, _)| k) + } +} + #[unstable(feature = "btree_cursors", issue = "107540")] pub use super::map::UnorderedKeyError; From 8ce8c42e0bf66d32504659cbbe91ad2a0c315891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 22 Jun 2024 04:32:49 +0000 Subject: [PATCH 372/489] Do not underline suggestions for code that is already there When a suggestion part is for already present code, do not highlight it. If after that there are no highlights left, do not show the suggestion at all. Fix clippy lint suggestion incorrectly treated as `span_help`. --- compiler/rustc_errors/src/emitter.rs | 21 +++++++++- compiler/rustc_errors/src/lib.rs | 22 ++++++++--- .../clippy_lints/src/unnecessary_wraps.rs | 4 +- .../ui/unnecessary_literal_unwrap.stderr | 4 +- .../clippy/tests/ui/unnecessary_wraps.stderr | 8 ++-- .../generic_const_exprs/issue-105608.stderr | 4 -- tests/ui/imports/issue-55884-2.stderr | 4 -- tests/ui/lint/wide_pointer_comparisons.stderr | 38 +++++++++---------- tests/ui/privacy/issue-75907.stderr | 2 +- tests/ui/privacy/privacy5.stderr | 20 +++++----- ...ue-42234-unknown-receiver-type.full.stderr | 4 -- ...-turbofish-surrounding-angle-braket.stderr | 2 +- 12 files changed, 75 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 73908e5808569..8963b009c31ec 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1767,7 +1767,10 @@ impl HumanEmitter { debug!(?suggestions); if suggestions.is_empty() { - // Suggestions coming from macros can have malformed spans. This is a heavy handed + // Here we check if there are suggestions that have actual code changes. We sometimes + // suggest the same code that is already there, instead of changing how we produce the + // suggestions and filtering there, we just don't emit the suggestion. + // Suggestions coming from macros can also have malformed spans. This is a heavy handed // approach to avoid ICEs by ignoring the suggestion outright. return Ok(()); } @@ -2046,7 +2049,9 @@ impl HumanEmitter { assert!(underline_start >= 0 && underline_end >= 0); let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { - if let DisplaySuggestion::Underline = show_code_change { + if let DisplaySuggestion::Underline = show_code_change + && is_different(sm, &part.snippet, part.span) + { // If this is a replacement, underline with `~`, if this is an addition // underline with `+`. buffer.putc( @@ -2824,6 +2829,18 @@ impl Style { } } +/// Whether the original and suggested code are the same. +pub fn is_different(sm: &SourceMap, suggested: &str, sp: Span) -> bool { + let found = match sm.span_to_snippet(sp) { + Ok(snippet) => snippet, + Err(e) => { + warn!(error = ?e, "Invalid span {:?}", sp); + return true; + } + }; + found != suggested +} + /// Whether the original and suggested code are visually similar enough to warrant extra wording. pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 09855394cdb2b..ceebcd46a6f7f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -50,7 +50,7 @@ pub use diagnostic_impls::{ IndicateAnonymousLifetime, SingleLabelManySpans, }; pub use emitter::ColorConfig; -use emitter::{is_case_difference, DynEmitter, Emitter}; +use emitter::{is_case_difference, is_different, DynEmitter, Emitter}; use registry::Registry; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; @@ -357,10 +357,16 @@ impl CodeSuggestion { _ => 1, }) .sum(); - line_highlight.push(SubstitutionHighlight { - start: (cur_lo.col.0 as isize + acc) as usize, - end: (cur_lo.col.0 as isize + acc + len) as usize, - }); + if !is_different(sm, &part.snippet, part.span) { + // Account for cases where we are suggesting the same code that's already + // there. This shouldn't happen often, but in some cases for multipart + // suggestions it's much easier to handle it here than in the origin. + } else { + line_highlight.push(SubstitutionHighlight { + start: (cur_lo.col.0 as isize + acc) as usize, + end: (cur_lo.col.0 as isize + acc + len) as usize, + }); + } buf.push_str(&part.snippet); let cur_hi = sm.lookup_char_pos(part.span.hi()); // Account for the difference between the width of the current code and the @@ -392,7 +398,11 @@ impl CodeSuggestion { while buf.ends_with('\n') { buf.pop(); } - Some((buf, substitution.parts, highlights, only_capitalization)) + if highlights.iter().all(|parts| parts.is_empty()) { + None + } else { + Some((buf, substitution.parts, highlights, only_capitalization)) + } }) .collect() } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index e4e7f7d06e706..080efe983c2a8 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -145,7 +145,9 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { ( "this function's return value is unnecessary".to_string(), "remove the return type...".to_string(), - snippet(cx, fn_decl.output.span(), "..").to_string(), + // FIXME: we should instead get the span including the `->` and suggest an + // empty string for this case. + "()".to_string(), "...and then remove returned values", ) } else { diff --git a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr index 15708090361ed..37ee9195fce66 100644 --- a/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_literal_unwrap.stderr @@ -63,7 +63,7 @@ LL | let _val = None::<()>.expect("this always happens"); help: remove the `None` and `expect()` | LL | let _val = panic!("this always happens"); - | ~~~~~~~ ~ + | ~~~~~~~ error: used `unwrap_or_default()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:22:24 @@ -134,7 +134,7 @@ LL | None::<()>.expect("this always happens"); help: remove the `None` and `expect()` | LL | panic!("this always happens"); - | ~~~~~~~ ~ + | ~~~~~~~ error: used `unwrap_or_default()` on `None` value --> tests/ui/unnecessary_literal_unwrap.rs:30:5 diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr index a55a23d449f57..59986d895b30e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_wraps.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_wraps.stderr @@ -118,8 +118,8 @@ LL | | } | help: remove the return type... | -LL | fn issue_6640_1(a: bool, b: bool) -> Option<()> { - | ~~~~~~~~~~ +LL | fn issue_6640_1(a: bool, b: bool) -> () { + | ~~ help: ...and then remove returned values | LL ~ return ; @@ -145,8 +145,8 @@ LL | | } | help: remove the return type... | -LL | fn issue_6640_2(a: bool, b: bool) -> Result<(), i32> { - | ~~~~~~~~~~~~~~~ +LL | fn issue_6640_2(a: bool, b: bool) -> () { + | ~~ help: ...and then remove returned values | LL ~ return ; diff --git a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr index 09b618fb3f050..1c97eaddfe1bb 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-105608.stderr @@ -4,10 +4,6 @@ error[E0282]: type annotations needed LL | Combination::<0>.and::<_>().and::<_>(); | ^^^ cannot infer type of the type parameter `M` declared on the method `and` | -help: consider specifying the generic argument - | -LL | Combination::<0>.and::<_>().and::<_>(); - | ~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-55884-2.stderr b/tests/ui/imports/issue-55884-2.stderr index 8a9d5f2a6d8a6..0d4f01aeafc64 100644 --- a/tests/ui/imports/issue-55884-2.stderr +++ b/tests/ui/imports/issue-55884-2.stderr @@ -24,10 +24,6 @@ note: ...and refers to the struct `ParseOptions` which is defined here | LL | pub struct ParseOptions {} | ^^^^^^^^^^^^^^^^^^^^^^^ you could import this directly -help: import `ParseOptions` through the re-export - | -LL | pub use parser::ParseOptions; - | ~~~~~~~~~~~~~~~~~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr index 81a221c0ee640..7fe382393d7e1 100644 --- a/tests/ui/lint/wide_pointer_comparisons.stderr +++ b/tests/ui/lint/wide_pointer_comparisons.stderr @@ -74,7 +74,7 @@ LL | let _ = PartialEq::eq(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(a, b); - | ~~~~~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~~~~~ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:35:13 @@ -85,7 +85,7 @@ LL | let _ = PartialEq::ne(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(a, b); - | ~~~~~~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~~~~~~ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:37:13 @@ -96,7 +96,7 @@ LL | let _ = a.eq(&b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(a, b); - | ++++++++++++++++++ ~ ~ + | ++++++++++++++++++ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:39:13 @@ -107,7 +107,7 @@ LL | let _ = a.ne(&b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(a, b); - | +++++++++++++++++++ ~ ~ + | +++++++++++++++++++ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:41:13 @@ -283,7 +283,7 @@ LL | let _ = PartialEq::eq(a, b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(*a, *b); - | ~~~~~~~~~~~~~~~~~~~ ~~~ ~ + | ~~~~~~~~~~~~~~~~~~~ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:85:17 @@ -294,7 +294,7 @@ LL | let _ = PartialEq::ne(a, b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(*a, *b); - | ~~~~~~~~~~~~~~~~~~~~ ~~~ ~ + | ~~~~~~~~~~~~~~~~~~~~ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:87:17 @@ -305,7 +305,7 @@ LL | let _ = PartialEq::eq(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(*a, *b); - | ~~~~~~~~~~~~~~~~~~~ ~~~ ~ + | ~~~~~~~~~~~~~~~~~~~ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:89:17 @@ -316,7 +316,7 @@ LL | let _ = PartialEq::ne(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(*a, *b); - | ~~~~~~~~~~~~~~~~~~~~ ~~~ ~ + | ~~~~~~~~~~~~~~~~~~~~ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:91:17 @@ -327,7 +327,7 @@ LL | let _ = a.eq(b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(*a, *b); - | +++++++++++++++++++ ~~~ ~ + | +++++++++++++++++++ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:93:17 @@ -338,7 +338,7 @@ LL | let _ = a.ne(b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(*a, *b); - | ++++++++++++++++++++ ~~~ ~ + | ++++++++++++++++++++ ~~~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:95:17 @@ -519,11 +519,11 @@ LL | let _ = PartialEq::eq(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(a, b); - | ~~~~~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~~~~~ ~ help: use explicit `std::ptr::eq` method to compare metadata and addresses | LL | let _ = std::ptr::eq(a, b); - | ~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:133:17 @@ -534,11 +534,11 @@ LL | let _ = PartialEq::ne(&a, &b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(a, b); - | ~~~~~~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~~~~~~ ~ help: use explicit `std::ptr::eq` method to compare metadata and addresses | LL | let _ = !std::ptr::eq(a, b); - | ~~~~~~~~~~~~~~ ~ ~ + | ~~~~~~~~~~~~~~ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:135:17 @@ -549,11 +549,11 @@ LL | let _ = a.eq(&b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = std::ptr::addr_eq(a, b); - | ++++++++++++++++++ ~ ~ + | ++++++++++++++++++ ~ help: use explicit `std::ptr::eq` method to compare metadata and addresses | LL | let _ = std::ptr::eq(a, b); - | +++++++++++++ ~ ~ + | +++++++++++++ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:137:17 @@ -564,11 +564,11 @@ LL | let _ = a.ne(&b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | let _ = !std::ptr::addr_eq(a, b); - | +++++++++++++++++++ ~ ~ + | +++++++++++++++++++ ~ help: use explicit `std::ptr::eq` method to compare metadata and addresses | LL | let _ = !std::ptr::eq(a, b); - | ++++++++++++++ ~ ~ + | ++++++++++++++ ~ warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:142:9 @@ -594,7 +594,7 @@ LL | cmp!(a, b); help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL | cmp!(std::ptr::addr_eq(a, b)); - | ++++++++++++++++++ ~ + + | ++++++++++++++++++ + warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:159:39 diff --git a/tests/ui/privacy/issue-75907.stderr b/tests/ui/privacy/issue-75907.stderr index f7cb874c2cc0d..3121cc04478a4 100644 --- a/tests/ui/privacy/issue-75907.stderr +++ b/tests/ui/privacy/issue-75907.stderr @@ -14,7 +14,7 @@ LL | let Bar(x, y, Foo(z)) = make_bar(); help: consider making the fields publicly accessible | LL | pub(crate) struct Bar(pub u8, pub u8, pub Foo); - | ~~~ ~~~ +++ + | ~~~ +++ error[E0532]: cannot match against a tuple struct which contains private fields --> $DIR/issue-75907.rs:15:19 diff --git a/tests/ui/privacy/privacy5.stderr b/tests/ui/privacy/privacy5.stderr index 615b0af2762d3..ec3abe9b81629 100644 --- a/tests/ui/privacy/privacy5.stderr +++ b/tests/ui/privacy/privacy5.stderr @@ -53,7 +53,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:56:12 @@ -262,7 +262,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:69:12 @@ -281,7 +281,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:70:12 @@ -300,7 +300,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:71:12 @@ -319,7 +319,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:72:18 @@ -338,7 +338,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:73:18 @@ -357,7 +357,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:74:18 @@ -376,7 +376,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:75:18 @@ -395,7 +395,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:83:17 @@ -452,7 +452,7 @@ LL | pub struct C(pub isize, isize); help: consider making the fields publicly accessible | LL | pub struct C(pub isize, pub isize); - | ~~~ +++ + | +++ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:90:20 diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr index e01e1edab5aa6..6559845c23ec5 100644 --- a/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr +++ b/tests/ui/span/issue-42234-unknown-receiver-type.full.stderr @@ -17,10 +17,6 @@ error[E0282]: type annotations needed LL | .sum::<_>() | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` | -help: consider specifying the generic argument - | -LL | .sum::<_>() - | ~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr index 618ccba0d3d12..dde6060c4334b 100644 --- a/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr +++ b/tests/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr @@ -40,7 +40,7 @@ LL | let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>(); help: surround the type parameters with angle brackets | LL | let _ = vec![1, 2, 3].into_iter().collect::>(); - | + ~ + | + error: aborting due to 4 previous errors From b73077e3d8cc6f5174e0161ea02792c616189f59 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 1 Aug 2024 18:48:48 +0200 Subject: [PATCH 373/489] separate test file for invalid sym operand --- tests/ui/asm/aarch64/type-check-2.rs | 18 ---------- tests/ui/asm/aarch64/type-check-2.stderr | 34 +++++-------------- tests/ui/asm/invalid-sym-operand.rs | 30 +++++++++++++++++ tests/ui/asm/invalid-sym-operand.stderr | 26 +++++++++++++++ tests/ui/asm/type-check-1.rs | 6 ---- tests/ui/asm/type-check-1.stderr | 20 ++++------- tests/ui/asm/x86_64/type-check-2.rs | 20 ----------- tests/ui/asm/x86_64/type-check-2.stderr | 42 +++++------------------- 8 files changed, 80 insertions(+), 116 deletions(-) create mode 100644 tests/ui/asm/invalid-sym-operand.rs create mode 100644 tests/ui/asm/invalid-sym-operand.stderr diff --git a/tests/ui/asm/aarch64/type-check-2.rs b/tests/ui/asm/aarch64/type-check-2.rs index ba68cdd26d94c..46667ae3a6565 100644 --- a/tests/ui/asm/aarch64/type-check-2.rs +++ b/tests/ui/asm/aarch64/type-check-2.rs @@ -15,15 +15,6 @@ fn main() { unsafe { // Inputs must be initialized - // Sym operands must point to a function or static - - const C: i32 = 0; - static S: i32 = 0; - asm!("{}", sym S); - asm!("{}", sym main); - asm!("{}", sym C); - //~^ ERROR invalid `sym` operand - // Register operands must be Copy asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); @@ -65,12 +56,3 @@ fn main() { asm!("{}", in(reg) u); } } - -// Sym operands must point to a function or static - -const C: i32 = 0; -static S: i32 = 0; -global_asm!("{}", sym S); -global_asm!("{}", sym main); -global_asm!("{}", sym C); -//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/aarch64/type-check-2.stderr b/tests/ui/asm/aarch64/type-check-2.stderr index d647f6a9f0635..b7723fc74d4b6 100644 --- a/tests/ui/asm/aarch64/type-check-2.stderr +++ b/tests/ui/asm/aarch64/type-check-2.stderr @@ -1,29 +1,13 @@ -error: invalid `sym` operand - --> $DIR/type-check-2.rs:75:19 - | -LL | global_asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - -error: invalid `sym` operand - --> $DIR/type-check-2.rs:24:20 - | -LL | asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - error: arguments for inline assembly must be copyable - --> $DIR/type-check-2.rs:29:31 + --> $DIR/type-check-2.rs:20:31 | LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `{closure@$DIR/type-check-2.rs:41:28: 41:36}` for inline assembly - --> $DIR/type-check-2.rs:41:28 +error: cannot use value of type `{closure@$DIR/type-check-2.rs:32:28: 32:36}` for inline assembly + --> $DIR/type-check-2.rs:32:28 | LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ @@ -31,7 +15,7 @@ LL | asm!("{}", in(reg) |x: i32| x); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly - --> $DIR/type-check-2.rs:43:28 + --> $DIR/type-check-2.rs:34:28 | LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ @@ -40,7 +24,7 @@ LL | asm!("{}", in(reg) vec![0]); = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use value of type `(i32, i32, i32)` for inline assembly - --> $DIR/type-check-2.rs:45:28 + --> $DIR/type-check-2.rs:36:28 | LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ @@ -48,7 +32,7 @@ LL | asm!("{}", in(reg) (1, 2, 3)); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly - --> $DIR/type-check-2.rs:47:28 + --> $DIR/type-check-2.rs:38:28 | LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ @@ -56,7 +40,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly - --> $DIR/type-check-2.rs:55:31 + --> $DIR/type-check-2.rs:46:31 | LL | asm!("{}", inout(reg) f); | ^ @@ -64,12 +48,12 @@ LL | asm!("{}", inout(reg) f); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly - --> $DIR/type-check-2.rs:58:31 + --> $DIR/type-check-2.rs:49:31 | LL | asm!("{}", inout(reg) r); | ^ | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/asm/invalid-sym-operand.rs b/tests/ui/asm/invalid-sym-operand.rs new file mode 100644 index 0000000000000..25e5fc6f9f6b7 --- /dev/null +++ b/tests/ui/asm/invalid-sym-operand.rs @@ -0,0 +1,30 @@ +use std::arch::{asm, global_asm}; + +fn main() { + unsafe { + // Sym operands must point to a function or static + + let x: u64 = 0; + const C: i32 = 0; + static S: i32 = 0; + asm!("{}", sym S); + asm!("{}", sym main); + asm!("{}", sym C); + //~^ ERROR invalid `sym` operand + asm!("{}", sym x); + //~^ ERROR invalid `sym` operand + } +} + +unsafe fn generic() { + asm!("{}", sym generic::); +} + +// Sym operands must point to a function or static + +const C: i32 = 0; +static S: i32 = 0; +global_asm!("{}", sym S); +global_asm!("{}", sym main); +global_asm!("{}", sym C); +//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/invalid-sym-operand.stderr b/tests/ui/asm/invalid-sym-operand.stderr new file mode 100644 index 0000000000000..a0b97a96d8a51 --- /dev/null +++ b/tests/ui/asm/invalid-sym-operand.stderr @@ -0,0 +1,26 @@ +error: invalid `sym` operand + --> $DIR/invalid-sym-operand.rs:14:24 + | +LL | asm!("{}", sym x); + | ^ is a local variable + | + = help: `sym` operands must refer to either a function or a static + +error: invalid `sym` operand + --> $DIR/invalid-sym-operand.rs:12:20 + | +LL | asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + +error: invalid `sym` operand + --> $DIR/invalid-sym-operand.rs:29:19 + | +LL | global_asm!("{}", sym C); + | ^^^^^ is an `i32` + | + = help: `sym` operands must refer to either a function or a static + +error: aborting due to 3 previous errors + diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs index ad1a391539f1a..2d25c6186e759 100644 --- a/tests/ui/asm/type-check-1.rs +++ b/tests/ui/asm/type-check-1.rs @@ -46,8 +46,6 @@ fn main() { asm!("{}", const const_bar(0)); asm!("{}", const const_bar(x)); //~^ ERROR attempt to use a non-constant value in a constant - asm!("{}", sym x); - //~^ ERROR invalid `sym` operand // Const operands must be integers and must be constants. @@ -64,10 +62,6 @@ fn main() { } } -unsafe fn generic() { - asm!("{}", sym generic::); -} - // Const operands must be integers and must be constants. global_asm!("{}", const 0); diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index bbed571284903..c2fc8d6690dff 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -31,14 +31,6 @@ help: consider using `const` instead of `let` LL | const x: /* Type */ = 0; | ~~~~~ ++++++++++++ -error: invalid `sym` operand - --> $DIR/type-check-1.rs:49:24 - | -LL | asm!("{}", sym x); - | ^ is a local variable - | - = help: `sym` operands must refer to either a function or a static - error: invalid asm output --> $DIR/type-check-1.rs:14:29 | @@ -103,7 +95,7 @@ LL | asm!("{}", inout(reg) v[..]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: invalid type for `const` operand - --> $DIR/type-check-1.rs:57:20 + --> $DIR/type-check-1.rs:55:20 | LL | asm!("{}", const 0f32); | ^^^^^^---- @@ -113,7 +105,7 @@ LL | asm!("{}", const 0f32); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/type-check-1.rs:59:20 + --> $DIR/type-check-1.rs:57:20 | LL | asm!("{}", const 0 as *mut u8); | ^^^^^^------------ @@ -123,7 +115,7 @@ LL | asm!("{}", const 0 as *mut u8); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/type-check-1.rs:62:20 + --> $DIR/type-check-1.rs:60:20 | LL | asm!("{}", const &0); | ^^^^^^-- @@ -133,7 +125,7 @@ LL | asm!("{}", const &0); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/type-check-1.rs:76:19 + --> $DIR/type-check-1.rs:70:19 | LL | global_asm!("{}", const 0f32); | ^^^^^^---- @@ -143,7 +135,7 @@ LL | global_asm!("{}", const 0f32); = help: `const` operands must be of an integer type error: invalid type for `const` operand - --> $DIR/type-check-1.rs:78:19 + --> $DIR/type-check-1.rs:72:19 | LL | global_asm!("{}", const 0 as *mut u8); | ^^^^^^------------ @@ -152,7 +144,7 @@ LL | global_asm!("{}", const 0 as *mut u8); | = help: `const` operands must be of an integer type -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors Some errors have detailed explanations: E0277, E0435. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/asm/x86_64/type-check-2.rs b/tests/ui/asm/x86_64/type-check-2.rs index 4b5d59fdbc785..ff811961462df 100644 --- a/tests/ui/asm/x86_64/type-check-2.rs +++ b/tests/ui/asm/x86_64/type-check-2.rs @@ -27,17 +27,6 @@ fn main() { asm!("{}", out(reg) v[0]); asm!("{}", inout(reg) v[0]); - // Sym operands must point to a function or static - - const C: i32 = 0; - static S: i32 = 0; - asm!("{}", sym S); - asm!("{}", sym main); - asm!("{}", sym C); - //~^ ERROR invalid `sym` operand - asm!("{}", sym x); - //~^ ERROR invalid `sym` operand - // Register operands must be Copy asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); @@ -79,12 +68,3 @@ fn main() { asm!("{}", in(reg) u); } } - -// Sym operands must point to a function or static - -const C: i32 = 0; -static S: i32 = 0; -global_asm!("{}", sym S); -global_asm!("{}", sym main); -global_asm!("{}", sym C); -//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/x86_64/type-check-2.stderr b/tests/ui/asm/x86_64/type-check-2.stderr index e82a7c92664e5..c72e695aefb83 100644 --- a/tests/ui/asm/x86_64/type-check-2.stderr +++ b/tests/ui/asm/x86_64/type-check-2.stderr @@ -1,21 +1,13 @@ -error: invalid `sym` operand - --> $DIR/type-check-2.rs:38:24 - | -LL | asm!("{}", sym x); - | ^ is a local variable - | - = help: `sym` operands must refer to either a function or a static - error: arguments for inline assembly must be copyable - --> $DIR/type-check-2.rs:43:32 + --> $DIR/type-check-2.rs:32:32 | LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `SimdNonCopy` does not implement the Copy trait -error: cannot use value of type `{closure@$DIR/type-check-2.rs:55:28: 55:36}` for inline assembly - --> $DIR/type-check-2.rs:55:28 +error: cannot use value of type `{closure@$DIR/type-check-2.rs:44:28: 44:36}` for inline assembly + --> $DIR/type-check-2.rs:44:28 | LL | asm!("{}", in(reg) |x: i32| x); | ^^^^^^^^^^ @@ -23,7 +15,7 @@ LL | asm!("{}", in(reg) |x: i32| x); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `Vec` for inline assembly - --> $DIR/type-check-2.rs:57:28 + --> $DIR/type-check-2.rs:46:28 | LL | asm!("{}", in(reg) vec![0]); | ^^^^^^^ @@ -32,7 +24,7 @@ LL | asm!("{}", in(reg) vec![0]); = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot use value of type `(i32, i32, i32)` for inline assembly - --> $DIR/type-check-2.rs:59:28 + --> $DIR/type-check-2.rs:48:28 | LL | asm!("{}", in(reg) (1, 2, 3)); | ^^^^^^^^^ @@ -40,7 +32,7 @@ LL | asm!("{}", in(reg) (1, 2, 3)); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly - --> $DIR/type-check-2.rs:61:28 + --> $DIR/type-check-2.rs:50:28 | LL | asm!("{}", in(reg) [1, 2, 3]); | ^^^^^^^^^ @@ -48,7 +40,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `fn() {main}` for inline assembly - --> $DIR/type-check-2.rs:69:31 + --> $DIR/type-check-2.rs:58:31 | LL | asm!("{}", inout(reg) f); | ^ @@ -56,21 +48,13 @@ LL | asm!("{}", inout(reg) f); = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly error: cannot use value of type `&mut i32` for inline assembly - --> $DIR/type-check-2.rs:72:31 + --> $DIR/type-check-2.rs:61:31 | LL | asm!("{}", inout(reg) r); | ^ | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error: invalid `sym` operand - --> $DIR/type-check-2.rs:36:20 - | -LL | asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - error[E0381]: used binding `x` isn't initialized --> $DIR/type-check-2.rs:15:28 | @@ -113,15 +97,7 @@ help: consider changing this to be mutable LL | let mut v: Vec = vec![0, 1, 2]; | +++ -error: invalid `sym` operand - --> $DIR/type-check-2.rs:89:19 - | -LL | global_asm!("{}", sym C); - | ^^^^^ is an `i32` - | - = help: `sym` operands must refer to either a function or a static - -error: aborting due to 13 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0381, E0596. For more information about an error, try `rustc --explain E0381`. From 47e6db542e4a80b6c4b3aa4ab2eb2a991474f24f Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 1 Aug 2024 18:57:59 +0200 Subject: [PATCH 374/489] separate test file for invalid const operand --- tests/ui/asm/invalid-const-operand.rs | 51 +++++++++++++ tests/ui/asm/invalid-const-operand.stderr | 86 ++++++++++++++++++++++ tests/ui/asm/invalid-sym-operand.rs | 18 ++--- tests/ui/asm/invalid-sym-operand.stderr | 14 ++-- tests/ui/asm/type-check-1.rs | 41 ----------- tests/ui/asm/type-check-1.stderr | 88 +---------------------- 6 files changed, 155 insertions(+), 143 deletions(-) create mode 100644 tests/ui/asm/invalid-const-operand.rs create mode 100644 tests/ui/asm/invalid-const-operand.stderr diff --git a/tests/ui/asm/invalid-const-operand.rs b/tests/ui/asm/invalid-const-operand.rs new file mode 100644 index 0000000000000..eff335ff6aaa3 --- /dev/null +++ b/tests/ui/asm/invalid-const-operand.rs @@ -0,0 +1,51 @@ +//@ needs-asm-support +//@ ignore-nvptx64 +//@ ignore-spirv + +#![feature(asm_const)] + +use std::arch::{asm, global_asm}; + +// Const operands must be integers and must be constants. + +global_asm!("{}", const 0); +global_asm!("{}", const 0i32); +global_asm!("{}", const 0i128); +global_asm!("{}", const 0f32); +//~^ ERROR invalid type for `const` operand +global_asm!("{}", const 0 as *mut u8); +//~^ ERROR invalid type for `const` operand + +fn main() { + unsafe { + // Const operands must be integers and must be constants. + + asm!("{}", const 0); + asm!("{}", const 0i32); + asm!("{}", const 0i128); + asm!("{}", const 0f32); + //~^ ERROR invalid type for `const` operand + asm!("{}", const 0 as *mut u8); + //~^ ERROR invalid type for `const` operand + asm!("{}", const &0); + //~^ ERROR invalid type for `const` operand + + // Constants must be... constant + + let x = 0; + const fn const_foo(x: i32) -> i32 { + x + } + const fn const_bar(x: T) -> T { + x + } + asm!("{}", const x); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", const const_foo(0)); + asm!("{}", const const_foo(x)); + //~^ ERROR attempt to use a non-constant value in a constant + asm!("{}", const const_bar(0)); + asm!("{}", const const_bar(x)); + //~^ ERROR attempt to use a non-constant value in a constant + } +} diff --git a/tests/ui/asm/invalid-const-operand.stderr b/tests/ui/asm/invalid-const-operand.stderr new file mode 100644 index 0000000000000..a6d742b53c217 --- /dev/null +++ b/tests/ui/asm/invalid-const-operand.stderr @@ -0,0 +1,86 @@ +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/invalid-const-operand.rs:42:26 + | +LL | asm!("{}", const x); + | ^ non-constant value + | +help: consider using `const` instead of `let` + | +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/invalid-const-operand.rs:45:36 + | +LL | asm!("{}", const const_foo(x)); + | ^ non-constant value + | +help: consider using `const` instead of `let` + | +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ + +error[E0435]: attempt to use a non-constant value in a constant + --> $DIR/invalid-const-operand.rs:48:36 + | +LL | asm!("{}", const const_bar(x)); + | ^ non-constant value + | +help: consider using `const` instead of `let` + | +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:14:19 + | +LL | global_asm!("{}", const 0f32); + | ^^^^^^---- + | | + | is an `f32` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:16:19 + | +LL | global_asm!("{}", const 0 as *mut u8); + | ^^^^^^------------ + | | + | is a `*mut u8` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:26:20 + | +LL | asm!("{}", const 0f32); + | ^^^^^^---- + | | + | is an `f32` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:28:20 + | +LL | asm!("{}", const 0 as *mut u8); + | ^^^^^^------------ + | | + | is a `*mut u8` + | + = help: `const` operands must be of an integer type + +error: invalid type for `const` operand + --> $DIR/invalid-const-operand.rs:30:20 + | +LL | asm!("{}", const &0); + | ^^^^^^-- + | | + | is a `&i32` + | + = help: `const` operands must be of an integer type + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0435`. diff --git a/tests/ui/asm/invalid-sym-operand.rs b/tests/ui/asm/invalid-sym-operand.rs index 25e5fc6f9f6b7..69c4695125c43 100644 --- a/tests/ui/asm/invalid-sym-operand.rs +++ b/tests/ui/asm/invalid-sym-operand.rs @@ -1,5 +1,14 @@ use std::arch::{asm, global_asm}; +// Sym operands must point to a function or static + +const C: i32 = 0; +static S: i32 = 0; +global_asm!("{}", sym S); +global_asm!("{}", sym main); +global_asm!("{}", sym C); +//~^ ERROR invalid `sym` operand + fn main() { unsafe { // Sym operands must point to a function or static @@ -19,12 +28,3 @@ fn main() { unsafe fn generic() { asm!("{}", sym generic::); } - -// Sym operands must point to a function or static - -const C: i32 = 0; -static S: i32 = 0; -global_asm!("{}", sym S); -global_asm!("{}", sym main); -global_asm!("{}", sym C); -//~^ ERROR invalid `sym` operand diff --git a/tests/ui/asm/invalid-sym-operand.stderr b/tests/ui/asm/invalid-sym-operand.stderr index a0b97a96d8a51..8e0676200bb2e 100644 --- a/tests/ui/asm/invalid-sym-operand.stderr +++ b/tests/ui/asm/invalid-sym-operand.stderr @@ -1,5 +1,5 @@ error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:14:24 + --> $DIR/invalid-sym-operand.rs:23:24 | LL | asm!("{}", sym x); | ^ is a local variable @@ -7,18 +7,18 @@ LL | asm!("{}", sym x); = help: `sym` operands must refer to either a function or a static error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:12:20 + --> $DIR/invalid-sym-operand.rs:9:19 | -LL | asm!("{}", sym C); - | ^^^^^ is an `i32` +LL | global_asm!("{}", sym C); + | ^^^^^ is an `i32` | = help: `sym` operands must refer to either a function or a static error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:29:19 + --> $DIR/invalid-sym-operand.rs:21:20 | -LL | global_asm!("{}", sym C); - | ^^^^^ is an `i32` +LL | asm!("{}", sym C); + | ^^^^^ is an `i32` | = help: `sym` operands must refer to either a function or a static diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs index 2d25c6186e759..22669dce280bb 100644 --- a/tests/ui/asm/type-check-1.rs +++ b/tests/ui/asm/type-check-1.rs @@ -28,46 +28,5 @@ fn main() { asm!("{}", inout(reg) v[..]); //~^ ERROR the size for values of type `[u64]` cannot be known at compilation time //~| ERROR cannot use value of type `[u64]` for inline assembly - - // Constants must be... constant - - let x = 0; - const fn const_foo(x: i32) -> i32 { - x - } - const fn const_bar(x: T) -> T { - x - } - asm!("{}", const x); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("{}", const const_foo(0)); - asm!("{}", const const_foo(x)); - //~^ ERROR attempt to use a non-constant value in a constant - asm!("{}", const const_bar(0)); - asm!("{}", const const_bar(x)); - //~^ ERROR attempt to use a non-constant value in a constant - - // Const operands must be integers and must be constants. - - asm!("{}", const 0); - asm!("{}", const 0i32); - asm!("{}", const 0i128); - asm!("{}", const 0f32); - //~^ ERROR invalid type for `const` operand - asm!("{}", const 0 as *mut u8); - //~^ ERROR invalid type for `const` operand - - asm!("{}", const &0); - //~^ ERROR invalid type for `const` operand } } - -// Const operands must be integers and must be constants. - -global_asm!("{}", const 0); -global_asm!("{}", const 0i32); -global_asm!("{}", const 0i128); -global_asm!("{}", const 0f32); -//~^ ERROR invalid type for `const` operand -global_asm!("{}", const 0 as *mut u8); -//~^ ERROR invalid type for `const` operand diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index c2fc8d6690dff..d47e6ae1d2a97 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -1,36 +1,3 @@ -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:41:26 - | -LL | asm!("{}", const x); - | ^ non-constant value - | -help: consider using `const` instead of `let` - | -LL | const x: /* Type */ = 0; - | ~~~~~ ++++++++++++ - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:44:36 - | -LL | asm!("{}", const const_foo(x)); - | ^ non-constant value - | -help: consider using `const` instead of `let` - | -LL | const x: /* Type */ = 0; - | ~~~~~ ++++++++++++ - -error[E0435]: attempt to use a non-constant value in a constant - --> $DIR/type-check-1.rs:47:36 - | -LL | asm!("{}", const const_bar(x)); - | ^ non-constant value - | -help: consider using `const` instead of `let` - | -LL | const x: /* Type */ = 0; - | ~~~~~ ++++++++++++ - error: invalid asm output --> $DIR/type-check-1.rs:14:29 | @@ -94,57 +61,6 @@ LL | asm!("{}", inout(reg) v[..]); | = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:55:20 - | -LL | asm!("{}", const 0f32); - | ^^^^^^---- - | | - | is an `f32` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:57:20 - | -LL | asm!("{}", const 0 as *mut u8); - | ^^^^^^------------ - | | - | is a `*mut u8` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:60:20 - | -LL | asm!("{}", const &0); - | ^^^^^^-- - | | - | is a `&i32` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:70:19 - | -LL | global_asm!("{}", const 0f32); - | ^^^^^^---- - | | - | is an `f32` - | - = help: `const` operands must be of an integer type - -error: invalid type for `const` operand - --> $DIR/type-check-1.rs:72:19 - | -LL | global_asm!("{}", const 0 as *mut u8); - | ^^^^^^------------ - | | - | is a `*mut u8` - | - = help: `const` operands must be of an integer type - -error: aborting due to 16 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0277, E0435. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. From 0bc501e0addf9dec2fe87613c5fdc6180364aceb Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Thu, 1 Aug 2024 21:02:51 +0100 Subject: [PATCH 375/489] Fix mutability in doc tests for `BTreeSet` cursors --- library/alloc/src/collections/btree/set.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 86401714639c0..362e32cc8f46a 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1250,16 +1250,16 @@ impl BTreeSet { /// let mut set = BTreeSet::from([1, 2, 3, 4]); /// /// let mut cursor = set.lower_bound_mut(Bound::Included(&2)); - /// assert_eq!(cursor.peek_prev(), Some(&mut 1)); - /// assert_eq!(cursor.peek_next(), Some(&mut 2)); + /// assert_eq!(cursor.peek_prev(), Some(&1)); + /// assert_eq!(cursor.peek_next(), Some(&2)); /// /// let mut cursor = set.lower_bound_mut(Bound::Excluded(&2)); - /// assert_eq!(cursor.peek_prev(), Some(&mut 2)); - /// assert_eq!(cursor.peek_next(), Some(&mut 3)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); /// /// let mut cursor = set.lower_bound_mut(Bound::Unbounded); /// assert_eq!(cursor.peek_prev(), None); - /// assert_eq!(cursor.peek_next(), Some(&mut 1)); + /// assert_eq!(cursor.peek_next(), Some(&1)); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] pub fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> @@ -1336,15 +1336,15 @@ impl BTreeSet { /// let mut set = BTreeSet::from([1, 2, 3, 4]); /// /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) }; - /// assert_eq!(cursor.peek_prev(), Some(&mut 3)); - /// assert_eq!(cursor.peek_next(), Some(&mut 4)); + /// assert_eq!(cursor.peek_prev(), Some(&3)); + /// assert_eq!(cursor.peek_next(), Some(&4)); /// /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) }; - /// assert_eq!(cursor.peek_prev(), Some(&mut 2)); - /// assert_eq!(cursor.peek_next(), Some(&mut 3)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); /// /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) }; - /// assert_eq!(cursor.peek_prev(), Some(&mut 4)); + /// assert_eq!(cursor.peek_prev(), Some(&4)); /// assert_eq!(cursor.peek_next(), None); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] From 41b017ec9945ce6b514e44b8dd26c9d0c0952c9c Mon Sep 17 00:00:00 2001 From: sayantn Date: Thu, 1 Aug 2024 23:13:51 +0530 Subject: [PATCH 376/489] Add the `sha512`, `sm3` and `sm4` target features Add the feature in `core/lib.rs` --- compiler/rustc_codegen_ssa/src/target_features.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 3 +++ library/core/src/arch.rs | 9 +++++++++ library/core/src/lib.rs | 1 + tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- .../ui/feature-gates/feature-gate-sha512_sm_x86.rs | 6 ++++++ .../feature-gates/feature-gate-sha512_sm_x86.stderr | 13 +++++++++++++ 10 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs create mode 100644 tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 77da4e4caea0f..b52e6259944d7 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -78,6 +78,7 @@ pub fn from_target_feature( Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature, Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature, Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature, + Some(sym::sha512_sm_x86) => rust_features.sha512_sm_x86, Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics, Some(sym::xop_target_feature) => rust_features.xop_target_feature, Some(sym::s390x_target_feature) => rust_features.s390x_target_feature, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 03210085a12c9..86102bbecd04e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -591,6 +591,8 @@ declare_features! ( (incomplete, return_type_notation, "1.70.0", Some(109417)), /// Allows `extern "rust-cold"`. (unstable, rust_cold_cc, "1.63.0", Some(97544)), + /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics + (unstable, sha512_sm_x86, "CURRENT_RUSTC_VERSION", Some(126624)), /// Shortern the tail expression lifetime (unstable, shorter_tail_lifetimes, "1.79.0", Some(123739)), /// Allows the use of SIMD types in functions declared in `extern` blocks. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e8563f50158a5..9977fa7425a3e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1705,6 +1705,7 @@ symbols! { self_in_typedefs, self_struct_ctor, semitransparent, + sha512_sm_x86, shadow_call_stack, shl, shl_assign, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 532507cb18244..e52f2fc06df06 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -238,6 +238,9 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("rdseed", Stable), ("rtm", Unstable(sym::rtm_target_feature)), ("sha", Stable), + ("sha512", Unstable(sym::sha512_sm_x86)), + ("sm3", Unstable(sym::sha512_sm_x86)), + ("sm4", Unstable(sym::sha512_sm_x86)), ("sse", Stable), ("sse2", Stable), ("sse3", Stable), diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 31d6bc36fc8b9..d681bd124fe13 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -4,6 +4,15 @@ #[stable(feature = "simd_arch", since = "1.27.0")] pub use crate::core_arch::arch::*; +#[cfg(bootstrap)] +#[allow(dead_code)] +#[unstable(feature = "sha512_sm_x86", issue = "126624")] +fn dummy() { + // AArch64 also has a target feature named `sm4`, so we need `#![feature(sha512_sm_x86)]` in lib.rs + // But as the bootstrap compiler doesn't know about this feature yet, we need to convert it to a + // library feature until bootstrap gets bumped +} + /// Inline assembly. /// /// Refer to [Rust By Example] for a usage guide and the [reference] for diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0917631e04500..9306581dca93d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -260,6 +260,7 @@ #![feature(powerpc_target_feature)] #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] +#![feature(sha512_sm_x86)] #![feature(sse4a_target_feature)] #![feature(tbm_target_feature)] #![feature(wasm_target_feature)] diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 57cbe173c7896..520cffc4b0268 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 199 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 201 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 00abb5f5e5ca0..d780e04e729a2 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs new file mode 100644 index 0000000000000..176a40ecf5370 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "sha512")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr new file mode 100644 index 0000000000000..da9eea095a332 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-sha512_sm_x86.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `sha512` is currently unstable + --> $DIR/feature-gate-sha512_sm_x86.rs:2:18 + | +LL | #[target_feature(enable = "sha512")] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #126624 for more information + = help: add `#![feature(sha512_sm_x86)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From b72685bcff449a96fddbc3bc476fbe3551d2314f Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Thu, 1 Aug 2024 23:04:56 +0000 Subject: [PATCH 377/489] rustdoc: Remove dead opaque_tys rendering logic --- src/librustdoc/html/render/mod.rs | 10 ---------- src/librustdoc/html/static/js/main.js | 1 - 2 files changed, 11 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6961261d7128b..9617f0d9a1f25 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -332,7 +332,6 @@ struct AllTypes { macros: FxHashSet, functions: FxHashSet, type_aliases: FxHashSet, - opaque_tys: FxHashSet, statics: FxHashSet, constants: FxHashSet, attribute_macros: FxHashSet, @@ -352,7 +351,6 @@ impl AllTypes { macros: new_set(100), functions: new_set(100), type_aliases: new_set(100), - opaque_tys: new_set(100), statics: new_set(100), constants: new_set(100), attribute_macros: new_set(100), @@ -415,9 +413,6 @@ impl AllTypes { if !self.type_aliases.is_empty() { sections.insert(ItemSection::TypeAliases); } - if !self.opaque_tys.is_empty() { - sections.insert(ItemSection::OpaqueTypes); - } if !self.statics.is_empty() { sections.insert(ItemSection::Statics); } @@ -471,7 +466,6 @@ impl AllTypes { print_entries(f, &self.functions, ItemSection::Functions); print_entries(f, &self.type_aliases, ItemSection::TypeAliases); print_entries(f, &self.trait_aliases, ItemSection::TraitAliases); - print_entries(f, &self.opaque_tys, ItemSection::OpaqueTypes); print_entries(f, &self.statics, ItemSection::Statics); print_entries(f, &self.constants, ItemSection::Constants); } @@ -2174,7 +2168,6 @@ pub(crate) enum ItemSection { AssociatedConstants, ForeignTypes, Keywords, - OpaqueTypes, AttributeMacros, DeriveMacros, TraitAliases, @@ -2207,7 +2200,6 @@ impl ItemSection { AssociatedConstants, ForeignTypes, Keywords, - OpaqueTypes, AttributeMacros, DeriveMacros, TraitAliases, @@ -2237,7 +2229,6 @@ impl ItemSection { Self::AssociatedConstants => "associated-consts", Self::ForeignTypes => "foreign-types", Self::Keywords => "keywords", - Self::OpaqueTypes => "opaque-types", Self::AttributeMacros => "attributes", Self::DeriveMacros => "derives", Self::TraitAliases => "trait-aliases", @@ -2267,7 +2258,6 @@ impl ItemSection { Self::AssociatedConstants => "Associated Constants", Self::ForeignTypes => "Foreign Types", Self::Keywords => "Keywords", - Self::OpaqueTypes => "Opaque Types", Self::AttributeMacros => "Attribute Macros", Self::DeriveMacros => "Derive Macros", Self::TraitAliases => "Trait Aliases", diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index e0ea234f9e710..2356ae109bed9 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -568,7 +568,6 @@ function preLoadCss(cssUrl) { //block("associatedconstant", "associated-consts", "Associated Constants"); block("foreigntype", "foreign-types", "Foreign Types"); block("keyword", "keywords", "Keywords"); - block("opaque", "opaque-types", "Opaque Types"); block("attr", "attributes", "Attribute Macros"); block("derive", "derives", "Derive Macros"); block("traitalias", "trait-aliases", "Trait Aliases"); From b2f7e71f0b38bbd0c43177802810ed90af58b93f Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 1 Aug 2024 21:32:12 -0300 Subject: [PATCH 378/489] Dogfood --- library/std/src/lib.rs | 1 + library/std/src/sys/pal/unix/weak.rs | 18 ++---------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6bd9c59a949c2..37ba7e7065d4b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -302,6 +302,7 @@ #![feature(let_chains)] #![feature(link_cfg)] #![feature(linkage)] +#![feature(macro_metavar_expr_concat)] #![feature(min_exhaustive_patterns)] #![feature(min_specialization)] #![feature(must_not_suspend)] diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs index b1b6aae757c51..35762f5a53b5b 100644 --- a/library/std/src/sys/pal/unix/weak.rs +++ b/library/std/src/sys/pal/unix/weak.rs @@ -168,14 +168,7 @@ pub(crate) macro syscall { if let Some(fun) = $name.get() { fun($($arg_name),*) } else { - // This looks like a hack, but concat_idents only accepts idents - // (not paths). - use libc::*; - - syscall( - concat_idents!(SYS_, $name), - $($arg_name),* - ) as $ret + libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret } } ) @@ -185,14 +178,7 @@ pub(crate) macro syscall { pub(crate) macro raw_syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name:$t),*) -> $ret { - // This looks like a hack, but concat_idents only accepts idents - // (not paths). - use libc::*; - - syscall( - concat_idents!(SYS_, $name), - $($arg_name),* - ) as $ret + libc::syscall(libc::${concat(SYS_, $name)}, $($arg_name),*) as $ret } ) } From af79a6396c4175fcdacc18d7448bcde94c3f0363 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 2 Aug 2024 05:16:01 +0200 Subject: [PATCH 379/489] time.rs: remove "Basic usage text" Only one example is given (for each method) --- library/core/src/time.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 179fbabaddeb6..0390bb59a8984 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -617,8 +617,6 @@ impl Duration { /// /// # Examples /// - /// Basic usage: - /// /// ``` /// use std::time::Duration; /// @@ -640,8 +638,6 @@ impl Duration { /// /// # Examples /// - /// Basic usage: - /// /// ``` /// use std::time::Duration; /// @@ -700,8 +696,6 @@ impl Duration { /// /// # Examples /// - /// Basic usage: - /// /// ``` /// use std::time::Duration; /// @@ -758,8 +752,6 @@ impl Duration { /// /// # Examples /// - /// Basic usage: - /// /// ``` /// use std::time::Duration; /// @@ -814,8 +806,6 @@ impl Duration { /// /// # Examples /// - /// Basic usage: - /// /// ``` /// use std::time::Duration; /// From 2f0aaaf2b9fc401708946e60e0f7dabf3c1bf30e Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Thu, 1 Aug 2024 20:43:02 -0700 Subject: [PATCH 380/489] std: Remove has_cpuid The one use of it was guaranteed to be always true. --- library/std/src/lib.rs | 4 ---- library/std/src/sys/pal/uefi/time.rs | 8 -------- 2 files changed, 12 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 6bd9c59a949c2..a760fee42c830 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -269,10 +269,6 @@ #![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] #![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))] -#![cfg_attr( - all(any(target_arch = "x86_64", target_arch = "x86"), target_os = "uefi"), - feature(stdarch_x86_has_cpuid) -)] // // Language features: // tidy-alphabetical-start diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index a97d69f997bf9..495ff2dc930ed 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -175,10 +175,6 @@ pub(crate) mod instant_internal { #[cfg(target_arch = "x86_64")] fn timestamp_rdtsc() -> Option { - if !crate::arch::x86_64::has_cpuid() { - return None; - } - static FREQUENCY: crate::sync::OnceLock = crate::sync::OnceLock::new(); // Get Frequency in Mhz @@ -200,10 +196,6 @@ pub(crate) mod instant_internal { #[cfg(target_arch = "x86")] fn timestamp_rdtsc() -> Option { - if !crate::arch::x86::has_cpuid() { - return None; - } - static FREQUENCY: crate::sync::OnceLock = crate::sync::OnceLock::new(); let freq = FREQUENCY From 7d7c4db474af426bf33a179dea6be0783025b0ca Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 2 Aug 2024 04:56:48 +0000 Subject: [PATCH 381/489] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 105457c3cd3b4..950d2baabe951 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -dba8e2d2c2890a8b9e88cbf4855ac5711337946c +05e692ae025fd4650c601e1e7ab51bdc5e19c35b From 77ca30f1950a062e9eb1caeff790618488058057 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 1 Aug 2024 21:58:34 -0700 Subject: [PATCH 382/489] Implement `UncheckedIterator` directly for `RepeatN` --- library/core/src/iter/sources/repeat_n.rs | 33 +++++++++++++-------- tests/codegen/iter-repeat-n-trivial-drop.rs | 15 +++++++++- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index 8390dab8e543e..4c4ae39f836ca 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -114,19 +114,12 @@ impl Iterator for RepeatN { #[inline] fn next(&mut self) -> Option { - if self.count == 0 { - return None; - } - - self.count -= 1; - Some(if self.count == 0 { - // SAFETY: the check above ensured that the count used to be non-zero, - // so element hasn't been dropped yet, and we just lowered the count to - // zero so it won't be dropped later, and thus it's okay to take it here. - unsafe { ManuallyDrop::take(&mut self.element) } + if self.count > 0 { + // SAFETY: Just checked it's not empty + unsafe { Some(self.next_unchecked()) } } else { - A::clone(&self.element) - }) + None + } } #[inline] @@ -194,4 +187,18 @@ impl FusedIterator for RepeatN {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RepeatN {} #[unstable(feature = "trusted_len_next_unchecked", issue = "37572")] -impl UncheckedIterator for RepeatN {} +impl UncheckedIterator for RepeatN { + #[inline] + unsafe fn next_unchecked(&mut self) -> Self::Item { + // SAFETY: The caller promised the iterator isn't empty + self.count = unsafe { self.count.unchecked_sub(1) }; + if self.count == 0 { + // SAFETY: the check above ensured that the count used to be non-zero, + // so element hasn't been dropped yet, and we just lowered the count to + // zero so it won't be dropped later, and thus it's okay to take it here. + unsafe { ManuallyDrop::take(&mut self.element) } + } else { + A::clone(&self.element) + } + } +} diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs index 31020b77984ba..7de224b92d853 100644 --- a/tests/codegen/iter-repeat-n-trivial-drop.rs +++ b/tests/codegen/iter-repeat-n-trivial-drop.rs @@ -1,8 +1,9 @@ -//@ compile-flags: -O +//@ compile-flags: -C opt-level=3 //@ only-x86_64 #![crate_type = "lib"] #![feature(iter_repeat_n)] +#![feature(array_repeat)] #[derive(Clone)] pub struct NotCopy(u16); @@ -54,3 +55,15 @@ pub fn vec_extend_via_iter_repeat_n() -> Vec { v.extend(std::iter::repeat_n(42_u8, n)); v } + +// Array repeat uses `RepeatN::next_unchecked` internally, +// so also check that the distinction disappears there. + +#[no_mangle] +// CHECK-LABEL: @array_repeat_not_copy +pub unsafe fn array_repeat_not_copy(item: NotCopy) -> [NotCopy; 8] { + // CHECK: insertelement {{.+}} i16 %item + // CHECK: shufflevector <8 x i16> {{.+}} zeroinitializer + // CHECK: store <8 x i16> + std::array::repeat(item) +} From fc260e163adb9d001fe69c1a9578abdb8bb0986d Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 2 Aug 2024 05:05:50 +0000 Subject: [PATCH 383/489] fmt --- src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs | 3 ++- src/tools/miri/src/shims/unix/env.rs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 3f9c991df6af6..fc2b3f9c6ea77 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -673,7 +673,8 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { // attempt to use it for a non-zero-sized access. // Dangling slices are a common case here; it's valid to get their length but with raw // pointer tagging for example all calls to get_unchecked on them are invalid. - if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr(), 0) { + if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr(), 0) + { log_creation(this, Some((alloc_id, base_offset, orig_tag)))?; // Still give it the new provenance, it got retagged after all. return Ok(Some(Provenance::Concrete { alloc_id, tag: new_tag })); diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs index b2861ad50a209..54bf3a3ae8295 100644 --- a/src/tools/miri/src/shims/unix/env.rs +++ b/src/tools/miri/src/shims/unix/env.rs @@ -81,8 +81,10 @@ impl<'tcx> UnixEnvVars<'tcx> { return Ok(None); }; // The offset is used to strip the "{name}=" part of the string. - let var_ptr = var_ptr - .wrapping_offset(Size::from_bytes(u64::try_from(name.len()).unwrap().strict_add(1)), ecx); + let var_ptr = var_ptr.wrapping_offset( + Size::from_bytes(u64::try_from(name.len()).unwrap().strict_add(1)), + ecx, + ); Ok(Some(var_ptr)) } From 36527d691e381403c75bc5e30ad1bfd97de2cf12 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 2 Aug 2024 02:12:29 -0700 Subject: [PATCH 384/489] rustfmt: Remove `has_cpuid` from test --- src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs | 9 --------- src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs | 9 --------- 2 files changed, 18 deletions(-) diff --git a/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs index 9257b8a4be636..b9adc67221aea 100644 --- a/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs +++ b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs @@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool { fn detect_features() -> cache::Initializer { let mut value = cache::Initializer::default(); - // If the x86 CPU does not support the CPUID instruction then it is too - // old to support any of the currently-detectable features. - if !has_cpuid() { - return value; - } - - // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU - // has `cpuid` support. - // 0. EAX = 0: Basic Information: // - EAX returns the "Highest Function Parameter", that is, the maximum // leaf value for subsequent calls of `cpuinfo` in range [0, diff --git a/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs index 2e228aa374527..944b51615f8e5 100644 --- a/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs +++ b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs @@ -34,15 +34,6 @@ pub fn check_for(x: Feature) -> bool { fn detect_features() -> cache::Initializer { let mut value = cache::Initializer::default(); - // If the x86 CPU does not support the CPUID instruction then it is too - // old to support any of the currently-detectable features. - if !has_cpuid() { - return value; - } - - // Calling `__cpuid`/`__cpuid_count` from here on is safe because the CPU - // has `cpuid` support. - // 0. EAX = 0: Basic Information: // - EAX returns the "Highest Function Parameter", that is, the maximum // leaf value for subsequent calls of `cpuinfo` in range [0, From 7742be0095391591c7063465d82f836bdd4787b7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 1 Aug 2024 20:10:19 +0000 Subject: [PATCH 385/489] Handle virtual workspaces in the tidy edition check --- src/tools/tidy/src/edition.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/tools/tidy/src/edition.rs b/src/tools/tidy/src/edition.rs index d658fe13d3627..6a58d58dbde14 100644 --- a/src/tools/tidy/src/edition.rs +++ b/src/tools/tidy/src/edition.rs @@ -4,11 +4,6 @@ use std::path::Path; use crate::walk::{filter_dirs, walk}; -fn is_edition_2021(mut line: &str) -> bool { - line = line.trim(); - line == "edition = \"2021\"" -} - pub fn check(path: &Path, bad: &mut bool) { walk(path, |path, _is_dir| filter_dirs(path), &mut |entry, contents| { let file = entry.path(); @@ -17,8 +12,15 @@ pub fn check(path: &Path, bad: &mut bool) { return; } - let is_2021 = contents.lines().any(is_edition_2021); - if !is_2021 { + let is_2021 = contents.lines().any(|line| line.trim() == "edition = \"2021\""); + + let is_workspace = contents.lines().any(|line| line.trim() == "[workspace]"); + let is_package = contents.lines().any(|line| line.trim() == "[package]"); + assert!(is_workspace || is_package); + + // Check that all packages use the 2021 edition. Virtual workspaces don't allow setting an + // edition, so these shouldn't be checked. + if is_package && !is_2021 { tidy_error!( bad, "{} doesn't have `edition = \"2021\"` on a separate line", From 1f3be75f56bfa7520b86eada306ad66455b4fd6e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 1 Aug 2024 20:09:50 +0000 Subject: [PATCH 386/489] Move the standard library to a separate workspace This ensures that the Cargo.lock packaged for it in the rust-src component is up-to-date, allowing rust-analyzer to run cargo metadata on the standard library even when the rust-src component is stored in a read-only location as is necessary for loading crates.io dependencies of the standard library. This also simplifies tidy's license check for runtime dependencies as it can now look at all entries in library/Cargo.lock without having to filter for just the dependencies of runtime crates. In addition this allows removing an exception in check_runtime_license_exceptions that was necessary due to the compiler enabling a feature on the object crate which pulls in a dependency not allowed for the standard library. While cargo workspaces normally enable dependencies of multiple targets to be reused, for the standard library we do not want this reusing to prevent conflicts between dependencies of the sysroot and of tools that are built using this sysroot. For this reason we already use an unstable cargo feature to ensure that any dependencies which would otherwise be shared get a different -Cmetadata argument as well as using separate build dirs. This doesn't change the situation around vendoring. We already have several cargo workspaces that need to be vendored. Adding another one doesn't change much. There are also no cargo profiles that are shared between the root workspace and the library workspace anyway, so it doesn't add any extra work when changing cargo profiles. --- .gitignore | 1 + Cargo.lock | 304 +----------- Cargo.toml | 37 -- library/Cargo.lock | 489 +++++++++++++++++++ library/Cargo.toml | 44 ++ src/bootstrap/src/core/build_steps/dist.rs | 2 + src/bootstrap/src/core/build_steps/vendor.rs | 1 + src/bootstrap/src/core/metadata.rs | 5 +- src/tools/tidy/src/deps.rs | 104 ++-- 9 files changed, 598 insertions(+), 389 deletions(-) create mode 100644 library/Cargo.lock create mode 100644 library/Cargo.toml diff --git a/.gitignore b/.gitignore index 87d02563ed048..aabec0988a99e 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ build/ /dist/ /unicode-downloads /target +/library/target /src/bootstrap/target /src/tools/x/target # Created by default with `src/ci/docker/run.sh` diff --git a/Cargo.lock b/Cargo.lock index 1a7d7e3f5d7d1..b47a21355db41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,27 +11,11 @@ dependencies = [ "gimli 0.28.1", ] -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "compiler_builtins", - "gimli 0.29.0", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] [[package]] name = "aes" @@ -66,16 +50,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "alloc" -version = "0.0.0" -dependencies = [ - "compiler_builtins", - "core", - "rand", - "rand_xorshift", -] - [[package]] name = "allocator-api2" version = "0.2.18" @@ -256,7 +230,7 @@ version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ - "addr2line 0.21.0", + "addr2line", "cc", "cfg-if", "libc", @@ -455,10 +429,6 @@ name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] [[package]] name = "cfg_aliases" @@ -737,16 +707,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" -[[package]] -name = "compiler_builtins" -version = "0.1.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb58b199190fcfe0846f55a3b545cd6b07a34bdd5930a476ff856f3ebcc5558a" -dependencies = [ - "cc", - "rustc-std-workspace-core", -] - [[package]] name = "compiletest" version = "0.0.0" @@ -787,14 +747,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "core" -version = "0.0.0" -dependencies = [ - "rand", - "rand_xorshift", -] - [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -1134,19 +1086,6 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d" -[[package]] -name = "dlmalloc" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3264b043b8e977326c1ee9e723da2c1f8d09a99df52cacf00b4dbce5ac54414d" -dependencies = [ - "cfg-if", - "compiler_builtins", - "libc", - "rustc-std-workspace-core", - "windows-sys 0.52.0", -] - [[package]] name = "either" version = "1.12.0" @@ -1348,16 +1287,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fortanix-sgx-abi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] - [[package]] name = "fs-err" version = "2.11.0" @@ -1504,8 +1433,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ - "rustc-std-workspace-core", - "rustc-std-workspace-std", "unicode-width", ] @@ -1526,25 +1453,11 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" dependencies = [ - "compiler_builtins", "fallible-iterator", "indexmap", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", "stable_deref_trait", ] -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "gimli" version = "0.31.0" @@ -1606,9 +1519,6 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", "serde", ] @@ -1630,17 +1540,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "hex" version = "0.4.3" @@ -2065,9 +1964,6 @@ name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" -dependencies = [ - "rustc-std-workspace-core", -] [[package]] name = "libdbus-sys" @@ -2299,10 +2195,6 @@ name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] [[package]] name = "memmap2" @@ -2357,9 +2249,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", ] [[package]] @@ -2549,7 +2438,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", ] @@ -2588,14 +2477,11 @@ version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ - "compiler_builtins", "crc32fast", "flate2", "hashbrown", "indexmap", "memchr", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", "ruzstd 0.7.0", "wasmparser 0.214.0", ] @@ -2719,29 +2605,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "panic_abort" -version = "0.0.0" -dependencies = [ - "alloc", - "cfg-if", - "compiler_builtins", - "core", - "libc", -] - -[[package]] -name = "panic_unwind" -version = "0.0.0" -dependencies = [ - "alloc", - "cfg-if", - "compiler_builtins", - "core", - "libc", - "unwind", -] - [[package]] name = "papergrid" version = "0.11.0" @@ -2996,23 +2859,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc_macro" -version = "0.0.0" -dependencies = [ - "core", - "std", -] - -[[package]] -name = "profiler_builtins" -version = "0.0.0" -dependencies = [ - "cc", - "compiler_builtins", - "core", -] - [[package]] name = "psm" version = "0.1.21" @@ -3090,27 +2936,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "4.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] - -[[package]] -name = "r-efi-alloc" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7" -dependencies = [ - "compiler_builtins", - "r-efi", - "rustc-std-workspace-core", -] - [[package]] name = "rand" version = "0.8.5" @@ -3141,15 +2966,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - [[package]] name = "rand_xoshiro" version = "0.6.0" @@ -3361,10 +3177,6 @@ name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", -] [[package]] name = "rustc-hash" @@ -3425,27 +3237,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5c9f15eec8235d7cb775ee6f81891db79b98fd54ba1ad8fae565b88ef1ae4e2" -[[package]] -name = "rustc-std-workspace-alloc" -version = "1.99.0" -dependencies = [ - "alloc", -] - -[[package]] -name = "rustc-std-workspace-core" -version = "1.99.0" -dependencies = [ - "core", -] - -[[package]] -name = "rustc-std-workspace-std" -version = "1.99.0" -dependencies = [ - "std", -] - [[package]] name = "rustc_abi" version = "0.0.0" @@ -5231,46 +5022,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "std" -version = "0.0.0" -dependencies = [ - "addr2line 0.22.0", - "alloc", - "cfg-if", - "compiler_builtins", - "core", - "dlmalloc", - "fortanix-sgx-abi", - "hashbrown", - "hermit-abi 0.4.0", - "libc", - "miniz_oxide", - "object 0.36.2", - "panic_abort", - "panic_unwind", - "profiler_builtins", - "r-efi", - "r-efi-alloc", - "rand", - "rand_xorshift", - "rustc-demangle", - "std_detect", - "unwind", - "wasi", -] - -[[package]] -name = "std_detect" -version = "0.1.5" -dependencies = [ - "cfg-if", - "compiler_builtins", - "libc", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "string_cache" version = "0.8.7" @@ -5377,15 +5128,6 @@ dependencies = [ "windows", ] -[[package]] -name = "sysroot" -version = "0.0.0" -dependencies = [ - "proc_macro", - "std", - "test", -] - [[package]] name = "tabled" version = "0.15.0" @@ -5470,16 +5212,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "test" -version = "0.0.0" -dependencies = [ - "core", - "getopts", - "libc", - "std", -] - [[package]] name = "test-float-parse" version = "0.1.0" @@ -5978,11 +5710,6 @@ name = "unicode-width" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-core", - "rustc-std-workspace-std", -] [[package]] name = "unicode-xid" @@ -6007,28 +5734,6 @@ dependencies = [ "tidy", ] -[[package]] -name = "unwind" -version = "0.0.0" -dependencies = [ - "cfg-if", - "compiler_builtins", - "core", - "libc", - "unwinding", -] - -[[package]] -name = "unwinding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b" -dependencies = [ - "compiler_builtins", - "gimli 0.28.1", - "rustc-std-workspace-core", -] - [[package]] name = "url" version = "2.5.2" @@ -6100,11 +5805,6 @@ name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -dependencies = [ - "compiler_builtins", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] [[package]] name = "wasm-bindgen" diff --git a/Cargo.toml b/Cargo.toml index 178a5ab940889..131feec70abcd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,8 +2,6 @@ resolver = "1" members = [ "compiler/rustc", - "library/std", - "library/sysroot", "src/etc/test-float-parse", "src/rustdoc-json-types", "src/tools/build_helper", @@ -61,23 +59,8 @@ exclude = [ # not all `Cargo.toml` files are available, so we exclude the `x` binary, # so it can be invoked before the current checkout is set up. "src/tools/x", - # stdarch has its own Cargo workspace - "library/stdarch", ] -[profile.release.package.compiler_builtins] -# For compiler-builtins we always use a high number of codegen units. -# The goal here is to place every single intrinsic into its own object -# file to avoid symbol clashes with the system libgcc if possible. Note -# that this number doesn't actually produce this many object files, we -# just don't create more than this number of object files. -# -# It's a bit of a bummer that we have to pass this here, unfortunately. -# Ideally this would be specified through an env var to Cargo so Cargo -# knows how many CGUs are for this specific crate, but for now -# per-crate configuration isn't specifiable in the environment. -codegen-units = 10000 - [profile.release.package.rustc-rayon-core] # The rustc fork of Rayon has deadlock detection code which intermittently # causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227) @@ -85,19 +68,6 @@ codegen-units = 10000 # FIXME: This workaround should be removed once #90227 is fixed. overflow-checks = false -# These dependencies of the standard library implement symbolication for -# backtraces on most platforms. Their debuginfo causes both linking to be slower -# (more data to chew through) and binaries to be larger without really all that -# much benefit. This section turns them all to down to have no debuginfo which -# helps to improve link times a little bit. -[profile.release.package] -addr2line.debug = 0 -adler.debug = 0 -gimli.debug = 0 -miniz_oxide.debug = 0 -object.debug = 0 -rustc-demangle.debug = 0 - # These are very thin wrappers around executing lld with the right binary name. # Basically nothing within them can go wrong without having been explicitly logged anyway. # We ship these in every rustc tarball and even after compression they add up @@ -120,10 +90,3 @@ codegen-units = 1 # FIXME: LTO cannot be enabled for binaries in a workspace # # lto = true - -[patch.crates-io] -# See comments in `library/rustc-std-workspace-core/README.md` for what's going on -# here -rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' } -rustc-std-workspace-alloc = { path = 'library/rustc-std-workspace-alloc' } -rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' } diff --git a/library/Cargo.lock b/library/Cargo.lock new file mode 100644 index 0000000000000..223b61456c267 --- /dev/null +++ b/library/Cargo.lock @@ -0,0 +1,489 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "compiler_builtins", + "gimli 0.29.0", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "alloc" +version = "0.0.0" +dependencies = [ + "compiler_builtins", + "core", + "rand", + "rand_xorshift", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "compiler_builtins" +version = "0.1.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb58b199190fcfe0846f55a3b545cd6b07a34bdd5930a476ff856f3ebcc5558a" +dependencies = [ + "cc", + "rustc-std-workspace-core", +] + +[[package]] +name = "core" +version = "0.0.0" +dependencies = [ + "rand", + "rand_xorshift", +] + +[[package]] +name = "dlmalloc" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3264b043b8e977326c1ee9e723da2c1f8d09a99df52cacf00b4dbce5ac54414d" +dependencies = [ + "cfg-if", + "compiler_builtins", + "libc", + "rustc-std-workspace-core", + "windows-sys", +] + +[[package]] +name = "fortanix-sgx-abi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "rustc-std-workspace-core", + "rustc-std-workspace-std", + "unicode-width", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "allocator-api2", + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +dependencies = [ + "rustc-std-workspace-core", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "object" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" +dependencies = [ + "compiler_builtins", + "memchr", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "panic_abort" +version = "0.0.0" +dependencies = [ + "alloc", + "cfg-if", + "compiler_builtins", + "core", + "libc", +] + +[[package]] +name = "panic_unwind" +version = "0.0.0" +dependencies = [ + "alloc", + "cfg-if", + "compiler_builtins", + "core", + "libc", + "unwind", +] + +[[package]] +name = "proc_macro" +version = "0.0.0" +dependencies = [ + "core", + "std", +] + +[[package]] +name = "profiler_builtins" +version = "0.0.0" +dependencies = [ + "cc", + "compiler_builtins", + "core", +] + +[[package]] +name = "r-efi" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e935efc5854715dfc0a4c9ef18dc69dee0ec3bf9cc3ab740db831c0fdd86a3" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "r-efi-alloc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d6f09fe2b6ad044bc3d2c34ce4979796581afd2f1ebc185837e02421e02fd7" +dependencies = [ + "compiler_builtins", + "r-efi", + "rustc-std-workspace-core", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", +] + +[[package]] +name = "rustc-std-workspace-alloc" +version = "1.99.0" +dependencies = [ + "alloc", +] + +[[package]] +name = "rustc-std-workspace-core" +version = "1.99.0" +dependencies = [ + "core", +] + +[[package]] +name = "rustc-std-workspace-std" +version = "1.99.0" +dependencies = [ + "std", +] + +[[package]] +name = "std" +version = "0.0.0" +dependencies = [ + "addr2line", + "alloc", + "cfg-if", + "compiler_builtins", + "core", + "dlmalloc", + "fortanix-sgx-abi", + "hashbrown", + "hermit-abi", + "libc", + "miniz_oxide", + "object", + "panic_abort", + "panic_unwind", + "profiler_builtins", + "r-efi", + "r-efi-alloc", + "rand", + "rand_xorshift", + "rustc-demangle", + "std_detect", + "unwind", + "wasi", +] + +[[package]] +name = "std_detect" +version = "0.1.5" +dependencies = [ + "cfg-if", + "compiler_builtins", + "libc", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "sysroot" +version = "0.0.0" +dependencies = [ + "proc_macro", + "std", + "test", +] + +[[package]] +name = "test" +version = "0.0.0" +dependencies = [ + "core", + "getopts", + "libc", + "std", +] + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-core", + "rustc-std-workspace-std", +] + +[[package]] +name = "unwind" +version = "0.0.0" +dependencies = [ + "cfg-if", + "compiler_builtins", + "core", + "libc", + "unwinding", +] + +[[package]] +name = "unwinding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a19a21a537f635c16c7576f22d0f2f7d63353c1337ad4ce0d8001c7952a25b" +dependencies = [ + "compiler_builtins", + "gimli 0.28.1", + "rustc-std-workspace-core", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +dependencies = [ + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/library/Cargo.toml b/library/Cargo.toml new file mode 100644 index 0000000000000..c4513b4c127d8 --- /dev/null +++ b/library/Cargo.toml @@ -0,0 +1,44 @@ +[workspace] +resolver = "1" +members = [ + "std", + "sysroot", +] + +exclude = [ + # stdarch has its own Cargo workspace + "stdarch", +] + +[profile.release.package.compiler_builtins] +# For compiler-builtins we always use a high number of codegen units. +# The goal here is to place every single intrinsic into its own object +# file to avoid symbol clashes with the system libgcc if possible. Note +# that this number doesn't actually produce this many object files, we +# just don't create more than this number of object files. +# +# It's a bit of a bummer that we have to pass this here, unfortunately. +# Ideally this would be specified through an env var to Cargo so Cargo +# knows how many CGUs are for this specific crate, but for now +# per-crate configuration isn't specifiable in the environment. +codegen-units = 10000 + +# These dependencies of the standard library implement symbolication for +# backtraces on most platforms. Their debuginfo causes both linking to be slower +# (more data to chew through) and binaries to be larger without really all that +# much benefit. This section turns them all to down to have no debuginfo which +# helps to improve link times a little bit. +[profile.release.package] +addr2line.debug = 0 +adler.debug = 0 +gimli.debug = 0 +miniz_oxide.debug = 0 +object.debug = 0 +rustc-demangle.debug = 0 + +[patch.crates-io] +# See comments in `library/rustc-std-workspace-core/README.md` for what's going on +# here +rustc-std-workspace-core = { path = 'rustc-std-workspace-core' } +rustc-std-workspace-alloc = { path = 'rustc-std-workspace-alloc' } +rustc-std-workspace-std = { path = 'rustc-std-workspace-std' } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 58f86aa996dd1..c14709ffb6324 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1034,6 +1034,8 @@ impl Step for PlainSourceTarball { .arg("--sync") .arg(builder.src.join("./compiler/rustc_codegen_gcc/Cargo.toml")) .arg("--sync") + .arg(builder.src.join("./library/Cargo.toml")) + .arg("--sync") .arg(builder.src.join("./src/bootstrap/Cargo.toml")) .arg("--sync") .arg(builder.src.join("./src/tools/opt-dist/Cargo.toml")) diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index 81770036d71c4..33768465225fe 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -47,6 +47,7 @@ impl Step for Vendor { "src/tools/rust-analyzer/Cargo.toml", "compiler/rustc_codegen_cranelift/Cargo.toml", "compiler/rustc_codegen_gcc/Cargo.toml", + "library/Cargo.toml", "src/bootstrap/Cargo.toml", "src/tools/rustbook/Cargo.toml", ] { diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index 9b4c85e6d34a4..c11230744c395 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -87,5 +87,8 @@ fn workspace_members(build: &Build) -> Vec { }; // Collects `metadata.packages` from all workspaces. - collect_metadata("Cargo.toml") + let mut packages = vec![]; + packages.extend(collect_metadata("Cargo.toml")); + packages.extend(collect_metadata("library/Cargo.toml")); + packages } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index de59d7d89f9ce..e23e931b0eb04 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -54,6 +54,7 @@ type ExceptionList = &'static [(&'static str, &'static str)]; pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>, &[&str])] = &[ // The root workspace has to be first for check_rustfix to work. (".", EXCEPTIONS, Some((&["rustc-main"], PERMITTED_RUSTC_DEPENDENCIES)), &[]), + ("library", EXCEPTIONS_STDLIB, Some((&["sysroot"], PERMITTED_STDLIB_DEPENDENCIES)), &[]), // Outside of the alphabetical section because rustfmt formats it using multiple lines. ( "compiler/rustc_codegen_cranelift", @@ -90,7 +91,6 @@ const EXCEPTIONS: ExceptionList = &[ ("colored", "MPL-2.0"), // rustfmt ("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps) ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations) - ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target. FIXME: this dependency violates the documentation comment above. ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot ("mdbook", "MPL-2.0"), // mdbook ("option-ext", "MPL-2.0"), // cargo-miri (via `directories`) @@ -108,6 +108,17 @@ const EXCEPTIONS: ExceptionList = &[ // tidy-alphabetical-end ]; +/// These are exceptions to Rust's permissive licensing policy, and +/// should be considered bugs. Exceptions are only allowed in Rust +/// tooling. It is _crucial_ that no exception crates be dependencies +/// of the Rust runtime (std/test). +#[rustfmt::skip] +const EXCEPTIONS_STDLIB: ExceptionList = &[ + // tidy-alphabetical-start + ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target. FIXME: this dependency violates the documentation comment above. + // tidy-alphabetical-end +]; + // FIXME uncomment once rust-lang/stdarch#1462 lands /* const EXCEPTIONS_STDARCH: ExceptionList = &[ @@ -228,10 +239,6 @@ const EXCEPTIONS_NON_STANDARD_LICENSE_DEPS: &[&str] = &[ "ring", ]; -/// These are the root crates that are part of the runtime. The licenses for -/// these and all their dependencies *must not* be in the exception list. -const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"]; - const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!()); /// Crates rustc is allowed to depend on. Avoid adding to the list if possible. @@ -240,7 +247,6 @@ const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!()); /// rustc. Please check with the compiler team before adding an entry. const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ // tidy-alphabetical-start - "addr2line", "adler", "ahash", "aho-corasick", @@ -256,7 +262,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "cc", "cfg-if", "cfg_aliases", - "compiler_builtins", "cpufeatures", "crc32fast", "crossbeam-channel", @@ -276,7 +281,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "digest", "displaydoc", "dissimilar", - "dlmalloc", "either", "elsa", "ena", @@ -291,7 +295,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "fluent-langneg", "fluent-syntax", "fnv", - "fortanix-sgx-abi", "generic-array", "getopts", "getrandom", @@ -354,12 +357,9 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "pulldown-cmark-escape", "punycode", "quote", - "r-efi", - "r-efi-alloc", "rand", "rand_chacha", "rand_core", - "rand_xorshift", "rand_xoshiro", "redox_syscall", "regex", @@ -429,7 +429,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "unicode-security", "unicode-width", "unicode-xid", - "unwinding", "valuable", "version_check", "wasi", @@ -463,6 +462,46 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ // tidy-alphabetical-end ]; +const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ + // tidy-alphabetical-start + "addr2line", + "adler", + "allocator-api2", + "cc", + "cfg-if", + "compiler_builtins", + "dlmalloc", + "fortanix-sgx-abi", + "getopts", + "gimli", + "hashbrown", + "hermit-abi", + "libc", + "memchr", + "miniz_oxide", + "object", + "r-efi", + "r-efi-alloc", + "rand", + "rand_core", + "rand_xorshift", + "rustc-demangle", + "unicode-width", + "unwinding", + "wasi", + "windows-sys", + "windows-targets", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", + // tidy-alphabetical-end +]; + const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ // tidy-alphabetical-start "ahash", @@ -556,9 +595,8 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { check_permitted_dependencies(&metadata, workspace, permitted_deps, crates, bad); } - if workspace == "." { - let runtime_ids = compute_runtime_crates(&metadata); - check_runtime_license_exceptions(&metadata, runtime_ids, bad); + if workspace == "library" { + check_runtime_license_exceptions(&metadata, bad); checked_runtime_licenses = true; } } @@ -583,16 +621,8 @@ pub fn has_missing_submodule(root: &Path, submodules: &[&str]) -> bool { /// /// Unlike for tools we don't allow exceptions to the `LICENSES` list for the runtime with the sole /// exception of `fortanix-sgx-abi` which is only used on x86_64-fortanix-unknown-sgx. -fn check_runtime_license_exceptions( - metadata: &Metadata, - runtime_ids: HashSet<&PackageId>, - bad: &mut bool, -) { +fn check_runtime_license_exceptions(metadata: &Metadata, bad: &mut bool) { for pkg in &metadata.packages { - if !runtime_ids.contains(&pkg.id) { - // Only checking dependencies of runtime libraries here. - continue; - } if pkg.source.is_none() { // No need to check local packages. continue; @@ -613,20 +643,6 @@ fn check_runtime_license_exceptions( continue; } - // This exception is due to the fact that the feature set of the - // `object` crate is different between rustc and libstd. In the - // standard library only a conservative set of features are enabled - // which notably does not include the `wasm` feature which pulls in - // this dependency. In the compiler, however, the `wasm` feature is - // enabled. This exception is intended to be here so long as the - // `EXCEPTIONS` above contains `wasmparser`, but once that goes away - // this can be removed. - if pkg.name == "wasmparser" - && pkg.license.as_deref() == Some("Apache-2.0 WITH LLVM-exception") - { - continue; - } - tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id); } } @@ -758,16 +774,6 @@ fn pkg_from_id<'a>(metadata: &'a Metadata, id: &PackageId) -> &'a Package { metadata.packages.iter().find(|p| &p.id == id).unwrap() } -/// Finds all the packages that are in the rust runtime. -fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> { - let mut result = HashSet::new(); - for name in RUNTIME_CRATES { - let id = &pkg_from_name(metadata, name).id; - deps_of(metadata, id, &mut result); - } - result -} - /// Recursively find all dependencies. fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId, result: &mut HashSet<&'a PackageId>) { if !result.insert(pkg_id) { From feeeb5c48ea8cd7a9379091ce3f6f15797cf762f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 2 Aug 2024 11:34:54 +0000 Subject: [PATCH 387/489] Bless tests --- tests/ui/extern/extern-types-field-offset.run.stderr | 2 +- tests/ui/extern/extern-types-size_of_val.align.run.stderr | 2 +- tests/ui/extern/extern-types-size_of_val.size.run.stderr | 2 +- tests/ui/hygiene/panic-location.run.stderr | 2 +- tests/ui/panics/panic-in-cleanup.run.stderr | 2 +- tests/ui/panics/panic-in-ffi.run.stderr | 2 +- tests/ui/process/println-with-broken-pipe.run.stderr | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ui/extern/extern-types-field-offset.run.stderr b/tests/ui/extern/extern-types-field-offset.run.stderr index 1b04b860db5a6..f14073989800b 100644 --- a/tests/ui/extern/extern-types-field-offset.run.stderr +++ b/tests/ui/extern/extern-types-field-offset.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `Opaque` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/extern/extern-types-size_of_val.align.run.stderr b/tests/ui/extern/extern-types-size_of_val.align.run.stderr index 20c4d8785e846..faad1aa13faf6 100644 --- a/tests/ui/extern/extern-types-size_of_val.align.run.stderr +++ b/tests/ui/extern/extern-types-size_of_val.align.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `A` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/extern/extern-types-size_of_val.size.run.stderr b/tests/ui/extern/extern-types-size_of_val.size.run.stderr index 20c4d8785e846..faad1aa13faf6 100644 --- a/tests/ui/extern/extern-types-size_of_val.size.run.stderr +++ b/tests/ui/extern/extern-types-size_of_val.size.run.stderr @@ -1,4 +1,4 @@ -thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: attempted to compute the size or alignment of extern type `A` note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread caused non-unwinding panic. aborting. diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5c1778bc485f9..bfed4cd665030 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:LL:CC: +thread 'main' panicked at alloc/src/raw_vec.rs:LL:CC: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/panics/panic-in-cleanup.run.stderr b/tests/ui/panics/panic-in-cleanup.run.stderr index e7def11b0e948..3417d4bf1a300 100644 --- a/tests/ui/panics/panic-in-cleanup.run.stderr +++ b/tests/ui/panics/panic-in-cleanup.run.stderr @@ -4,6 +4,6 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread 'main' panicked at $DIR/panic-in-cleanup.rs:16:9: BOOM stack backtrace: -thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: panic in a destructor during cleanup thread caused non-unwinding panic. aborting. diff --git a/tests/ui/panics/panic-in-ffi.run.stderr b/tests/ui/panics/panic-in-ffi.run.stderr index 596355399c801..fc70847ad9a3a 100644 --- a/tests/ui/panics/panic-in-ffi.run.stderr +++ b/tests/ui/panics/panic-in-ffi.run.stderr @@ -1,7 +1,7 @@ thread 'main' panicked at $DIR/panic-in-ffi.rs:12:5: Test note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' panicked at library/core/src/panicking.rs:$LINE:$COL: +thread 'main' panicked at core/src/panicking.rs:$LINE:$COL: panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting. diff --git a/tests/ui/process/println-with-broken-pipe.run.stderr b/tests/ui/process/println-with-broken-pipe.run.stderr index a334c0ad20473..f9d138a042414 100644 --- a/tests/ui/process/println-with-broken-pipe.run.stderr +++ b/tests/ui/process/println-with-broken-pipe.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/std/src/io/stdio.rs:LL:CC: +thread 'main' panicked at std/src/io/stdio.rs:LL:CC: failed printing to stdout: Broken pipe (os error 32) note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From c4b741775417771b873432d59c2fe6b78cfb7674 Mon Sep 17 00:00:00 2001 From: primoly <168267431+primoly@users.noreply.github.com> Date: Sun, 28 Jul 2024 14:37:56 +0200 Subject: [PATCH 388/489] Add `miri_start` support --- src/tools/miri/src/bin/miri.rs | 69 ++++++++++++++++--- .../miri/tests/fail/miri_start_wrong_sig.rs | 21 ++++++ .../tests/fail/miri_start_wrong_sig.stderr | 15 ++++ src/tools/miri/tests/fail/no_main.rs | 2 +- src/tools/miri/tests/fail/no_main.stderr | 9 ++- src/tools/miri/tests/pass/miri_start.rs | 19 +++++ src/tools/miri/tests/pass/miri_start.stdout | 1 + 7 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 src/tools/miri/tests/fail/miri_start_wrong_sig.rs create mode 100644 src/tools/miri/tests/fail/miri_start_wrong_sig.stderr create mode 100644 src/tools/miri/tests/pass/miri_start.rs create mode 100644 src/tools/miri/tests/pass/miri_start.stdout diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 25b154a8206c9..2cea8e751177a 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -14,11 +14,14 @@ extern crate tracing; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_hir; +extern crate rustc_hir_analysis; extern crate rustc_interface; extern crate rustc_log; extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; +extern crate rustc_span; +extern crate rustc_target; use std::env::{self, VarError}; use std::num::NonZero; @@ -27,9 +30,12 @@ use std::str::FromStr; use tracing::debug; +use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields}; use rustc_data_structures::sync::Lrc; use rustc_driver::Compilation; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::{self as hir, Node}; +use rustc_hir_analysis::check::check_function_signature; use rustc_interface::interface::Config; use rustc_middle::{ middle::{ @@ -37,14 +43,15 @@ use rustc_middle::{ exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel}, }, query::LocalCrate, - ty::TyCtxt, + traits::{ObligationCause, ObligationCauseCode}, + ty::{self, Ty, TyCtxt}, util::Providers, }; -use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; +use rustc_session::config::{CrateType, EntryFnType, ErrorOutputType, OptLevel}; use rustc_session::search_paths::PathKind; use rustc_session::{CtfeBacktrace, EarlyDiagCtxt}; - -use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields}; +use rustc_span::def_id::DefId; +use rustc_target::spec::abi::Abi; struct MiriCompilerCalls { miri_config: miri::MiriConfig, @@ -82,11 +89,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { tcx.dcx().fatal("miri only makes sense on bin crates"); } - let (entry_def_id, entry_type) = if let Some(entry_def) = tcx.entry_fn(()) { - entry_def - } else { - tcx.dcx().fatal("miri can only run programs that have a main function"); - }; + let (entry_def_id, entry_type) = entry_fn(tcx); let mut config = self.miri_config.clone(); // Add filename to `miri` arguments. @@ -351,6 +354,54 @@ fn jemalloc_magic() { } } +fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, EntryFnType) { + if let Some(entry_def) = tcx.entry_fn(()) { + return entry_def; + } + // Look for a symbol in the local crate named `miri_start`, and threat that as the entry point. + let sym = tcx.exported_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| { + if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None } + }); + if let Some(ExportedSymbol::NonGeneric(id)) = sym { + let start_def_id = id.expect_local(); + let start_span = tcx.def_span(start_def_id); + + let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig( + [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))], + tcx.types.isize, + false, + hir::Safety::Safe, + Abi::Rust, + )); + + let correct_func_sig = check_function_signature( + tcx, + ObligationCause::new(start_span, start_def_id, ObligationCauseCode::Misc), + *id, + expected_sig, + ) + .is_ok(); + + if correct_func_sig { + (*id, EntryFnType::Start) + } else { + tcx.dcx().fatal( + "`miri_start` must have the following signature:\n\ + fn miri_start(argc: isize, argv: *const *const u8) -> isize", + ); + } + } else { + tcx.dcx().fatal("Miri can only run programs that have a main function.\n\ + Alternatively, you can export a `miri_start` function:\n\ + \n\ + #[cfg(miri)]\n\ + #[no_mangle]\n\ + fn miri_start(argc: isize, argv: *const *const u8) -> isize {\ + \n // Call the actual start function that your project implements, based on your target's conventions.\n\ + }"); + } +} + fn main() { #[cfg(any(target_os = "linux", target_os = "macos"))] jemalloc_magic(); diff --git a/src/tools/miri/tests/fail/miri_start_wrong_sig.rs b/src/tools/miri/tests/fail/miri_start_wrong_sig.rs new file mode 100644 index 0000000000000..dac83d817ba49 --- /dev/null +++ b/src/tools/miri/tests/fail/miri_start_wrong_sig.rs @@ -0,0 +1,21 @@ +//@compile-flags: -Cpanic=abort +//@error-in-other-file: `miri_start` must have the following signature: +#![no_main] +#![no_std] + +use core::fmt::Write; + +#[path = "../utils/mod.no_std.rs"] +mod utils; + +#[no_mangle] +fn miri_start() -> isize { + //~^ ERROR: mismatched types + writeln!(utils::MiriStdout, "Hello from miri_start!").unwrap(); + 0 +} + +#[panic_handler] +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/src/tools/miri/tests/fail/miri_start_wrong_sig.stderr b/src/tools/miri/tests/fail/miri_start_wrong_sig.stderr new file mode 100644 index 0000000000000..6217191711658 --- /dev/null +++ b/src/tools/miri/tests/fail/miri_start_wrong_sig.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/miri_start_wrong_sig.rs:LL:CC + | +LL | fn miri_start() -> isize { + | ^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters + | + = note: expected signature `fn(isize, *const *const u8) -> _` + found signature `fn() -> _` + +error: `miri_start` must have the following signature: + fn miri_start(argc: isize, argv: *const *const u8) -> isize + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/tools/miri/tests/fail/no_main.rs b/src/tools/miri/tests/fail/no_main.rs index 01b8c7bd66bf0..4bbd820a636a0 100644 --- a/src/tools/miri/tests/fail/no_main.rs +++ b/src/tools/miri/tests/fail/no_main.rs @@ -1,2 +1,2 @@ -//@error-in-other-file: miri can only run programs that have a main function +//@error-in-other-file: Miri can only run programs that have a main function. #![no_main] diff --git a/src/tools/miri/tests/fail/no_main.stderr b/src/tools/miri/tests/fail/no_main.stderr index 1c4fc88989b21..e9b9e5d65b1d1 100644 --- a/src/tools/miri/tests/fail/no_main.stderr +++ b/src/tools/miri/tests/fail/no_main.stderr @@ -1,4 +1,11 @@ -error: miri can only run programs that have a main function +error: Miri can only run programs that have a main function. + Alternatively, you can export a `miri_start` function: + + #[cfg(miri)] + #[no_mangle] + fn miri_start(argc: isize, argv: *const *const u8) -> isize { + // Call the actual start function that your project implements, based on your target's conventions. + } error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/pass/miri_start.rs b/src/tools/miri/tests/pass/miri_start.rs new file mode 100644 index 0000000000000..756a1f60be151 --- /dev/null +++ b/src/tools/miri/tests/pass/miri_start.rs @@ -0,0 +1,19 @@ +//@compile-flags: -Cpanic=abort +#![no_main] +#![no_std] + +use core::fmt::Write; + +#[path = "../utils/mod.no_std.rs"] +mod utils; + +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { + writeln!(utils::MiriStdout, "Hello from miri_start!").unwrap(); + 0 +} + +#[panic_handler] +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/src/tools/miri/tests/pass/miri_start.stdout b/src/tools/miri/tests/pass/miri_start.stdout new file mode 100644 index 0000000000000..1c9e8489b575c --- /dev/null +++ b/src/tools/miri/tests/pass/miri_start.stdout @@ -0,0 +1 @@ +Hello from miri_start! From 6bb119764b607d40be0a4f246643297f7ea36745 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Aug 2024 14:16:36 +0200 Subject: [PATCH 389/489] docs --- src/tools/miri/README.md | 13 +++++++++++++ src/tools/miri/src/bin/miri.rs | 20 +++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index b1be596c00679..4892f3824d9ec 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -474,6 +474,19 @@ Miri provides some `extern` functions that programs can import to access Miri-specific functionality. They are declared in [/tests/utils/miri\_extern.rs](/tests/utils/miri_extern.rs). +## Entry point for no-std binaries + +Binaries that do not use the standard library are expected to declare a function like this so that +Miri knows where it is supposed to start execution: + +```rust +#[cfg(miri)] +#[no_mangle] +fn miri_start(argc: isize, argv: *const *const u8) -> isize { + // Call the actual start function that your project implements, based on your target's conventions. +} +``` + ## Contributing and getting help If you want to contribute to Miri, great! Please check out our diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 2cea8e751177a..42929bcb2820d 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -358,7 +358,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, EntryFnType) { if let Some(entry_def) = tcx.entry_fn(()) { return entry_def; } - // Look for a symbol in the local crate named `miri_start`, and threat that as the entry point. + // Look for a symbol in the local crate named `miri_start`, and treat that as the entry point. let sym = tcx.exported_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| { if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None } }); @@ -391,14 +391,16 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, EntryFnType) { ); } } else { - tcx.dcx().fatal("Miri can only run programs that have a main function.\n\ - Alternatively, you can export a `miri_start` function:\n\ - \n\ - #[cfg(miri)]\n\ - #[no_mangle]\n\ - fn miri_start(argc: isize, argv: *const *const u8) -> isize {\ - \n // Call the actual start function that your project implements, based on your target's conventions.\n\ - }"); + tcx.dcx().fatal( + "Miri can only run programs that have a main function.\n\ + Alternatively, you can export a `miri_start` function:\n\ + \n\ + #[cfg(miri)]\n\ + #[no_mangle]\n\ + fn miri_start(argc: isize, argv: *const *const u8) -> isize {\ + \n // Call the actual start function that your project implements, based on your target's conventions.\n\ + }" + ); } } From f850e37119eac6489ae6d9983631f2c702a4887f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Aug 2024 09:46:10 -0400 Subject: [PATCH 390/489] Check divergence value first before doing span operations in warn_if_unreachable --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 40d9a2985da06..8c1aa66332fc9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -48,28 +48,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Produces warning on the given node, if the current point in the /// function is unreachable, and there hasn't been another warning. pub(crate) fn warn_if_unreachable(&self, id: HirId, span: Span, kind: &str) { - // If span arose from a desugaring of `if` or `while`, then it is the condition itself, - // which diverges, that we are about to lint on. This gives suboptimal diagnostics. - // Instead, stop here so that the `if`- or `while`-expression's block is linted instead. - if span.is_desugaring(DesugaringKind::CondTemporary) { + let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() else { return; - } + }; - // Don't lint if the result of an async block or async function is `!`. - // This does not affect the unreachable lints *within* the body. - if span.is_desugaring(DesugaringKind::Async) { - return; - } + match span.desugaring_kind() { + // If span arose from a desugaring of `if` or `while`, then it is the condition + // itself, which diverges, that we are about to lint on. This gives suboptimal + // diagnostics. Instead, stop here so that the `if`- or `while`-expression's + // block is linted instead. + Some(DesugaringKind::CondTemporary) => return, - // Don't lint *within* the `.await` operator, since that's all just desugaring junk. - // We only want to lint if there is a subsequent expression after the `.await`. - if span.is_desugaring(DesugaringKind::Await) { - return; - } + // Don't lint if the result of an async block or async function is `!`. + // This does not affect the unreachable lints *within* the body. + Some(DesugaringKind::Async) => return, - let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() else { - return; - }; + // Don't lint *within* the `.await` operator, since that's all just desugaring + // junk. We only want to lint if there is a subsequent expression after the + // `.await` operator. + Some(DesugaringKind::Await) => return, + + _ => {} + } // Don't warn twice. self.diverges.set(Diverges::WarnedAlways); From 8f641b1b953e04eefc0cede84af169088ebc1401 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 18 Jul 2024 12:10:38 -0400 Subject: [PATCH 391/489] rewrite foreign-double-unwind to rmake --- .../src/external_deps/c_build.rs | 27 ++++++++++++ .../run-make-support/src/external_deps/cc.rs | 38 ++++++++++++++++ .../src/external_deps/rustc.rs | 43 +++++++++++++++++++ src/tools/run-make-support/src/lib.rs | 2 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/foreign-double-unwind/Makefile | 12 ------ tests/run-make/foreign-double-unwind/rmake.rs | 21 +++++++++ 7 files changed, 130 insertions(+), 14 deletions(-) delete mode 100644 tests/run-make/foreign-double-unwind/Makefile create mode 100644 tests/run-make/foreign-double-unwind/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index 86c9c08183197..901aede490130 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -1,8 +1,13 @@ use std::path::PathBuf; +<<<<<<< HEAD use super::cygpath::get_windows_path; use crate::artifact_names::{dynamic_lib_name, static_lib_name}; use crate::external_deps::cc::cc; +======= +use crate::artifact_names::static_lib_name; +use crate::external_deps::cc::{cc, cxx}; +>>>>>>> e3cf7e53339 (rewrite foreign-double-unwind to rmake) use crate::external_deps::llvm::llvm_ar; use crate::path_helpers::path; use crate::targets::{is_darwin, is_msvc, is_windows}; @@ -10,6 +15,7 @@ use crate::targets::{is_darwin, is_msvc, is_windows}; // FIXME(Oneirical): These native build functions should take a Path-based generic. /// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name. +/// Built from a C file. #[track_caller] pub fn build_native_static_lib(lib_name: &str) -> PathBuf { let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") }; @@ -58,3 +64,24 @@ pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf { } path(lib_path) } + +/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name. +/// Built from a C++ file. +#[track_caller] +pub fn build_native_static_lib_cxx(lib_name: &str) -> PathBuf { + let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") }; + let src = format!("{lib_name}.cpp"); + let lib_path = static_lib_name(lib_name); + if is_msvc() { + cxx().arg("-EHs").arg("-c").out_exe(&obj_file).input(src).run(); + } else { + cxx().arg("-c").out_exe(&obj_file).input(src).run(); + }; + let obj_file = if is_msvc() { + PathBuf::from(format!("{lib_name}.obj")) + } else { + PathBuf::from(format!("{lib_name}.o")) + }; + llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run(); + path(lib_path) +} diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs index 39ac3efef3948..941a43854a09e 100644 --- a/src/tools/run-make-support/src/external_deps/cc.rs +++ b/src/tools/run-make-support/src/external_deps/cc.rs @@ -214,3 +214,41 @@ pub fn extra_cxx_flags() -> Vec<&'static str> { } } } + +/// `EXTRARSCXXFLAGS` +pub fn extra_rs_cxx_flags() -> Vec<&'static str> { + // Adapted from tools.mk (trimmed): + // + // ```makefile + // ifdef IS_WINDOWS + // ifdef IS_MSVC + // else + // EXTRARSCXXFLAGS := -lstatic:-bundle=stdc++ + // endif + // else + // ifeq ($(UNAME),Darwin) + // EXTRARSCXXFLAGS := -lc++ + // else + // ifeq ($(UNAME),FreeBSD) + // else + // ifeq ($(UNAME),SunOS) + // else + // ifeq ($(UNAME),OpenBSD) + // else + // EXTRARSCXXFLAGS := -lstdc++ + // endif + // endif + // endif + // endif + // endif + // ``` + if is_windows() { + if is_msvc() { vec![] } else { vec!["-lstatic:-bundle=stdc++"] } + } else { + match &uname()[..] { + "Darwin" => vec!["-lc++"], + "FreeBSD" | "SunOS" | "OpenBSD" => vec![], + _ => vec!["-lstdc++"], + } + } +} diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 71d28dd9675fb..cabfbd59c482e 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -5,6 +5,7 @@ use crate::command::Command; use crate::env::env_var; use crate::path_helpers::cwd; use crate::util::set_host_rpath; +use crate::{is_msvc, is_windows, uname}; /// Construct a new `rustc` invocation. This will automatically set the library /// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this. @@ -314,4 +315,46 @@ impl Rustc { self.cmd.arg(format!("-Clinker-flavor={linker_flavor}")); self } + + /// `EXTRARSCXXFLAGS` + pub fn extra_rs_cxx_flags(&mut self) -> &mut Self { + // Adapted from tools.mk (trimmed): + // + // ```makefile + // ifdef IS_WINDOWS + // ifdef IS_MSVC + // else + // EXTRARSCXXFLAGS := -lstatic:-bundle=stdc++ + // endif + // else + // ifeq ($(UNAME),Darwin) + // EXTRARSCXXFLAGS := -lc++ + // else + // ifeq ($(UNAME),FreeBSD) + // else + // ifeq ($(UNAME),SunOS) + // else + // ifeq ($(UNAME),OpenBSD) + // else + // EXTRARSCXXFLAGS := -lstdc++ + // endif + // endif + // endif + // endif + // endif + // ``` + let flag = if is_windows() { + if is_msvc() { None } else { Some("-lstatic:-bundle=stdc++") } + } else { + match &uname()[..] { + "Darwin" => Some("-lc++"), + "FreeBSD" | "SunOS" | "OpenBSD" => None, + _ => Some("-lstdc++"), + } + }; + if let Some(flag) = flag { + self.cmd.arg(flag); + } + self + } } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 97c6bfe86d2bb..63c4c4d88638a 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -44,8 +44,8 @@ pub use wasmparser; pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc}; // These rely on external dependencies. -pub use c_build::{build_native_dynamic_lib, build_native_static_lib}; pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; +pub use c_build::{build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_cxx}; pub use clang::{clang, Clang}; pub use htmldocck::htmldocck; pub use llvm::{ diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a7c8df3e27478..d0824d9730627 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -9,7 +9,6 @@ run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile -run-make/foreign-double-unwind/Makefile run-make/foreign-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile run-make/issue-36710/Makefile diff --git a/tests/run-make/foreign-double-unwind/Makefile b/tests/run-make/foreign-double-unwind/Makefile deleted file mode 100644 index b5e52808d2fc5..0000000000000 --- a/tests/run-make/foreign-double-unwind/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# ignore-cross-compile -# needs-unwind -include ../tools.mk - -all: foo - $(call RUN,foo) | $(CGREP) -v unreachable - -foo: foo.rs $(call NATIVE_STATICLIB,foo) - $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) - -$(TMPDIR)/libfoo.o: foo.cpp - $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/tests/run-make/foreign-double-unwind/rmake.rs b/tests/run-make/foreign-double-unwind/rmake.rs new file mode 100644 index 0000000000000..b2ac8bfbeadf1 --- /dev/null +++ b/tests/run-make/foreign-double-unwind/rmake.rs @@ -0,0 +1,21 @@ +// When using foreign function interface (FFI) with C++, it is possible +// to run into a "double unwind" if either both Rust and C++ run into a panic +// and exception at the same time, or C++ encounters two exceptions. In this case, +// one of the panic unwinds would be leaked and the other would be kept, leading +// to undefined behaviour. After this was fixed in #92911, this test checks that +// the keyword "unreachable" indicative of this bug triggering in this specific context +// does not appear after successfully compiling and executing the program. +// See https://github.com/rust-lang/rust/pull/92911 + +//@ needs-unwind +// Reason: this test exercises panic unwinding +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{build_native_static_lib_cxx, run, rustc}; + +fn main() { + build_native_static_lib_cxx("foo"); + rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run(); + run("foo").assert_stdout_not_contains("unreachable"); +} From 5b44f800f37e0d3093aa5b89c10eb401bbc600eb Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 18 Jul 2024 13:04:45 -0400 Subject: [PATCH 392/489] rewrite and rename issue-36710 to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../foo.cpp | 0 .../foo.rs | 0 .../run-make/cpp-global-destructors/rmake.rs | 27 +++++++++++++++++++ tests/run-make/issue-36710/Makefile | 19 ------------- 5 files changed, 27 insertions(+), 20 deletions(-) rename tests/run-make/{issue-36710 => cpp-global-destructors}/foo.cpp (100%) rename tests/run-make/{issue-36710 => cpp-global-destructors}/foo.rs (100%) create mode 100644 tests/run-make/cpp-global-destructors/rmake.rs delete mode 100644 tests/run-make/issue-36710/Makefile diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index d0824d9730627..2d5f7b9ae9e9e 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -11,7 +11,6 @@ run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile run-make/foreign-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile -run-make/issue-36710/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/issue-88756-default-output/Makefile run-make/jobserver-error/Makefile diff --git a/tests/run-make/issue-36710/foo.cpp b/tests/run-make/cpp-global-destructors/foo.cpp similarity index 100% rename from tests/run-make/issue-36710/foo.cpp rename to tests/run-make/cpp-global-destructors/foo.cpp diff --git a/tests/run-make/issue-36710/foo.rs b/tests/run-make/cpp-global-destructors/foo.rs similarity index 100% rename from tests/run-make/issue-36710/foo.rs rename to tests/run-make/cpp-global-destructors/foo.rs diff --git a/tests/run-make/cpp-global-destructors/rmake.rs b/tests/run-make/cpp-global-destructors/rmake.rs new file mode 100644 index 0000000000000..02928b9de9df3 --- /dev/null +++ b/tests/run-make/cpp-global-destructors/rmake.rs @@ -0,0 +1,27 @@ +// Some start files were missed when originally writing the logic to swap in musl start files. +// This caused #36710. After the fix in #50105, this test checks that linking to C++ code +// with global destructors works. +// See https://github.com/rust-lang/rust/pull/50105 + +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +// FIXME(Oneirical): are these really necessary? This test is supposed to test a musl +// bug... and it ignores musl? This wasn't part of the original test at its creation, which +// had no ignores. + +//# ignore-none no-std is not supported +//# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM +//# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM +//# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` +//# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain +//# (see dist-i586-gnu-i586-i686-musl Dockerfile) +//# ignore-sgx + +use run_make_support::{build_native_static_lib_cxx, run, rustc}; + +fn main() { + build_native_static_lib_cxx("foo"); + rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run(); + run("foo"); +} diff --git a/tests/run-make/issue-36710/Makefile b/tests/run-make/issue-36710/Makefile deleted file mode 100644 index 7b91107a23495..0000000000000 --- a/tests/run-make/issue-36710/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# ignore-cross-compile -# ignore-none no-std is not supported -# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM -# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM -# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` -# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain -# (see dist-i586-gnu-i586-i686-musl Dockerfile) -# ignore-sgx - -include ../tools.mk - -all: foo - $(call RUN,foo) - -foo: foo.rs $(call NATIVE_STATICLIB,foo) - $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) --target $(TARGET) - -$(TMPDIR)/libfoo.o: foo.cpp - $(call COMPILE_OBJ_CXX,$@,$<) From 46b4083e6fa64445d714fff001ce92907980deb1 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 18 Jul 2024 13:12:38 -0400 Subject: [PATCH 393/489] rewrite foreign-exceptions to rmake --- .../src/external_deps/c_build.rs | 5 --- .../run-make-support/src/external_deps/cc.rs | 38 ------------------- .../src/external_deps/rustc.rs | 20 +++++++++- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../run-make/cpp-global-destructors/rmake.rs | 19 +++++----- tests/run-make/foreign-double-unwind/rmake.rs | 4 +- tests/run-make/foreign-exceptions/Makefile | 12 ------ tests/run-make/foreign-exceptions/rmake.rs | 19 ++++++++++ 8 files changed, 48 insertions(+), 70 deletions(-) delete mode 100644 tests/run-make/foreign-exceptions/Makefile create mode 100644 tests/run-make/foreign-exceptions/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index 901aede490130..15e02d04393ce 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -1,13 +1,8 @@ use std::path::PathBuf; -<<<<<<< HEAD use super::cygpath::get_windows_path; use crate::artifact_names::{dynamic_lib_name, static_lib_name}; -use crate::external_deps::cc::cc; -======= -use crate::artifact_names::static_lib_name; use crate::external_deps::cc::{cc, cxx}; ->>>>>>> e3cf7e53339 (rewrite foreign-double-unwind to rmake) use crate::external_deps::llvm::llvm_ar; use crate::path_helpers::path; use crate::targets::{is_darwin, is_msvc, is_windows}; diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs index 941a43854a09e..39ac3efef3948 100644 --- a/src/tools/run-make-support/src/external_deps/cc.rs +++ b/src/tools/run-make-support/src/external_deps/cc.rs @@ -214,41 +214,3 @@ pub fn extra_cxx_flags() -> Vec<&'static str> { } } } - -/// `EXTRARSCXXFLAGS` -pub fn extra_rs_cxx_flags() -> Vec<&'static str> { - // Adapted from tools.mk (trimmed): - // - // ```makefile - // ifdef IS_WINDOWS - // ifdef IS_MSVC - // else - // EXTRARSCXXFLAGS := -lstatic:-bundle=stdc++ - // endif - // else - // ifeq ($(UNAME),Darwin) - // EXTRARSCXXFLAGS := -lc++ - // else - // ifeq ($(UNAME),FreeBSD) - // else - // ifeq ($(UNAME),SunOS) - // else - // ifeq ($(UNAME),OpenBSD) - // else - // EXTRARSCXXFLAGS := -lstdc++ - // endif - // endif - // endif - // endif - // endif - // ``` - if is_windows() { - if is_msvc() { vec![] } else { vec!["-lstatic:-bundle=stdc++"] } - } else { - match &uname()[..] { - "Darwin" => vec!["-lc++"], - "FreeBSD" | "SunOS" | "OpenBSD" => vec![], - _ => vec!["-lstdc++"], - } - } -} diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index cabfbd59c482e..cece58d29566c 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -5,7 +5,7 @@ use crate::command::Command; use crate::env::env_var; use crate::path_helpers::cwd; use crate::util::set_host_rpath; -use crate::{is_msvc, is_windows, uname}; +use crate::{is_darwin, is_msvc, is_windows, uname}; /// Construct a new `rustc` invocation. This will automatically set the library /// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this. @@ -344,10 +344,26 @@ impl Rustc { // endif // ``` let flag = if is_windows() { + // So this is a bit hacky: we can't use the DLL version of libstdc++ because + // it pulls in the DLL version of libgcc, which means that we end up with 2 + // instances of the DW2 unwinding implementation. This is a problem on + // i686-pc-windows-gnu because each module (DLL/EXE) needs to register its + // unwind information with the unwinding implementation, and libstdc++'s + // __cxa_throw won't see the unwinding info we registered with our statically + // linked libgcc. + // + // Now, simply statically linking libstdc++ would fix this problem, except + // that it is compiled with the expectation that pthreads is dynamically + // linked as a DLL and will fail to link with a statically linked libpthread. + // + // So we end up with the following hack: we link use static:-bundle to only + // link the parts of libstdc++ that we actually use, which doesn't include + // the dependency on the pthreads DLL. if is_msvc() { None } else { Some("-lstatic:-bundle=stdc++") } + } else if is_darwin() { + Some("-lc++") } else { match &uname()[..] { - "Darwin" => Some("-lc++"), "FreeBSD" | "SunOS" | "OpenBSD" => None, _ => Some("-lstdc++"), } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2d5f7b9ae9e9e..bd4f54d22da7b 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -9,7 +9,6 @@ run-make/dep-info-spaces/Makefile run-make/dep-info/Makefile run-make/emit-to-stdout/Makefile run-make/extern-fn-reachable/Makefile -run-make/foreign-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile run-make/issue-88756-default-output/Makefile diff --git a/tests/run-make/cpp-global-destructors/rmake.rs b/tests/run-make/cpp-global-destructors/rmake.rs index 02928b9de9df3..9bc5c84e10db5 100644 --- a/tests/run-make/cpp-global-destructors/rmake.rs +++ b/tests/run-make/cpp-global-destructors/rmake.rs @@ -6,17 +6,16 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -// FIXME(Oneirical): are these really necessary? This test is supposed to test a musl -// bug... and it ignores musl? This wasn't part of the original test at its creation, which -// had no ignores. +//@ ignore-none +// Reason: no-std is not supported. +//@ ignore-wasm32 +//@ ignore-wasm64 +// Reason: compiling C++ to WASM may cause problems. -//# ignore-none no-std is not supported -//# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM -//# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM -//# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` -//# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain -//# (see dist-i586-gnu-i586-i686-musl Dockerfile) -//# ignore-sgx +// Neither of these are tested in full CI. +//@ ignore-nvptx64-nvidia-cuda +// Reason: can't find crate "std" +//@ ignore-sgx use run_make_support::{build_native_static_lib_cxx, run, rustc}; diff --git a/tests/run-make/foreign-double-unwind/rmake.rs b/tests/run-make/foreign-double-unwind/rmake.rs index b2ac8bfbeadf1..9bd3b4c0fea5b 100644 --- a/tests/run-make/foreign-double-unwind/rmake.rs +++ b/tests/run-make/foreign-double-unwind/rmake.rs @@ -12,10 +12,10 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed -use run_make_support::{build_native_static_lib_cxx, run, rustc}; +use run_make_support::{build_native_static_lib_cxx, run_fail, rustc}; fn main() { build_native_static_lib_cxx("foo"); rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run(); - run("foo").assert_stdout_not_contains("unreachable"); + run_fail("foo").assert_stdout_not_contains("unreachable"); } diff --git a/tests/run-make/foreign-exceptions/Makefile b/tests/run-make/foreign-exceptions/Makefile deleted file mode 100644 index 56c41b274fb2e..0000000000000 --- a/tests/run-make/foreign-exceptions/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# ignore-cross-compile -# needs-unwind -include ../tools.mk - -all: foo - $(call RUN,foo) - -foo: foo.rs $(call NATIVE_STATICLIB,foo) - $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) - -$(TMPDIR)/libfoo.o: foo.cpp - $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/tests/run-make/foreign-exceptions/rmake.rs b/tests/run-make/foreign-exceptions/rmake.rs new file mode 100644 index 0000000000000..929319f049fe9 --- /dev/null +++ b/tests/run-make/foreign-exceptions/rmake.rs @@ -0,0 +1,19 @@ +// This test was created to check that compilation and execution still works +// after the addition of a new feature, in #65646: the ability to unwind panics +// and exceptions back and forth between Rust and C++. This is a basic smoke test, +// this feature being broken in quiet or subtle ways could still result in this test +// passing. +// See https://github.com/rust-lang/rust/pull/65646 + +//@ needs-unwind +// Reason: this test exercises panic unwinding +//@ ignore-cross-compile +// Reason: the compiled binary is executed + +use run_make_support::{build_native_static_lib_cxx, run, rustc}; + +fn main() { + build_native_static_lib_cxx("foo"); + rustc().input("foo.rs").arg("-lfoo").extra_rs_cxx_flags().run(); + run("foo"); +} From 6264d2eba9d5b237a5c5c9a9527fbda54d751203 Mon Sep 17 00:00:00 2001 From: binarycat Date: Sat, 27 Jul 2024 15:15:02 -0400 Subject: [PATCH 394/489] bootstrap: fix bug preventing the use of custom targets the bug was caused by two factors: 1. only checking the RUST_TARGET_PATH form, not the full filepath form 2. indirectly trying to use the Debug presentation to get the file path --- src/bootstrap/src/core/config/config.rs | 5 +++++ src/bootstrap/src/core/sanity.rs | 12 +++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 1343e257efe08..776e2c5cb17d7 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -512,6 +512,11 @@ impl TargetSelection { pub fn is_windows(&self) -> bool { self.contains("windows") } + + /// Path to the file defining the custom target, if any. + pub fn filepath(&self) -> Option<&Path> { + self.file.as_ref().map(Path::new) + } } impl fmt::Display for TargetSelection { diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 45f4090ef2285..c42d4c56c3816 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -260,7 +260,9 @@ than building it. if !has_target { // This might also be a custom target, so check the target file that could have been specified by the user. - if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") { + if target.filepath().is_some_and(|p| p.exists()) { + has_target = true; + } else if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") { let mut target_filename = OsString::from(&target_str); // Target filename ends with `.json`. target_filename.push(".json"); @@ -275,8 +277,12 @@ than building it. if !has_target { panic!( - "No such target exists in the target list, - specify a correct location of the JSON specification file for custom targets!" + "No such target exists in the target list,\n\ + make sure to correctly specify the location \ + of the JSON specification file \ + for custom targets!\n\ + Use BOOTSTRAP_SKIP_TARGET_SANITY=1 to \ + bypass this check." ); } } From c27fa5c3329d4f7fce200043c3117bc1a548f025 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 15:37:45 -0400 Subject: [PATCH 395/489] rewrite rustdoc-default-output to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../run-make/issue-88756-default-output/Makefile | 4 ---- .../issue-88756-default-output/README.md | 1 - tests/run-make/issue-88756-default-output/x.rs | 1 - .../output-default.stdout | 0 tests/run-make/rustdoc-default-output/rmake.rs | 16 ++++++++++++++++ 6 files changed, 16 insertions(+), 7 deletions(-) delete mode 100644 tests/run-make/issue-88756-default-output/Makefile delete mode 100644 tests/run-make/issue-88756-default-output/README.md delete mode 100644 tests/run-make/issue-88756-default-output/x.rs rename tests/run-make/{issue-88756-default-output => rustdoc-default-output}/output-default.stdout (100%) create mode 100644 tests/run-make/rustdoc-default-output/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index dc4db13902da9..d8eb5667ab894 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -19,7 +19,6 @@ run-make/issue-36710/Makefile run-make/issue-47551/Makefile run-make/issue-69368/Makefile run-make/issue-84395-lto-embed-bitcode/Makefile -run-make/issue-88756-default-output/Makefile run-make/jobserver-error/Makefile run-make/libs-through-symlinks/Makefile run-make/libtest-json/Makefile diff --git a/tests/run-make/issue-88756-default-output/Makefile b/tests/run-make/issue-88756-default-output/Makefile deleted file mode 100644 index d1c3d0fe08249..0000000000000 --- a/tests/run-make/issue-88756-default-output/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -include ../tools.mk - -all: - $(BARE_RUSTDOC) 2>&1 | sed -E 's@/nightly/|/beta/|/stable/|/1\.[0-9]+\.[0-9]+/@/$$CHANNEL/@g' | diff - output-default.stdout diff --git a/tests/run-make/issue-88756-default-output/README.md b/tests/run-make/issue-88756-default-output/README.md deleted file mode 100644 index 8cbfac4f7d2f1..0000000000000 --- a/tests/run-make/issue-88756-default-output/README.md +++ /dev/null @@ -1 +0,0 @@ -This is a test to verify that the default behavior of `rustdoc` is printing out help output instead of erroring out (#88756). diff --git a/tests/run-make/issue-88756-default-output/x.rs b/tests/run-make/issue-88756-default-output/x.rs deleted file mode 100644 index 5df7576133a68..0000000000000 --- a/tests/run-make/issue-88756-default-output/x.rs +++ /dev/null @@ -1 +0,0 @@ -// nothing to see here diff --git a/tests/run-make/issue-88756-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout similarity index 100% rename from tests/run-make/issue-88756-default-output/output-default.stdout rename to tests/run-make/rustdoc-default-output/output-default.stdout diff --git a/tests/run-make/rustdoc-default-output/rmake.rs b/tests/run-make/rustdoc-default-output/rmake.rs new file mode 100644 index 0000000000000..06720445a35ce --- /dev/null +++ b/tests/run-make/rustdoc-default-output/rmake.rs @@ -0,0 +1,16 @@ +// Calling rustdoc with no arguments, which should bring up a help menu, used to +// cause an error as rustdoc expects an input file. Fixed in #98331, this test +// ensures the output of rustdoc's help menu is as expected. +// See https://github.com/rust-lang/rust/issues/88756 + +use run_make_support::{bare_rustdoc, diff}; + +fn main() { + let out = bare_rustdoc().run().stdout_utf8(); + diff() + .expected_file("output-default.stdout") + .actual_text("actual", out) + // replace the channel type in the URL with $CHANNEL + .normalize(r"nightly/|beta/|stable/|1\.[0-9]+\.[0-9]+/", "$$CHANNEL/") + .run(); +} From c0d9357a4cc2bd41b0f31b997ad6131aaac98d67 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 13:06:06 -0400 Subject: [PATCH 396/489] rewrite cross-lang-lto-clang to rmake --- src/tools/run-make-support/src/command.rs | 7 +++ .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/cross-lang-lto-clang/Makefile | 25 -------- tests/run-make/cross-lang-lto-clang/rmake.rs | 61 +++++++++++++++++++ 4 files changed, 68 insertions(+), 26 deletions(-) delete mode 100644 tests/run-make/cross-lang-lto-clang/Makefile create mode 100644 tests/run-make/cross-lang-lto-clang/rmake.rs diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index a0b96e25a0cba..6582c3c7e8e60 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -258,6 +258,13 @@ impl CompletedProcess { self } + /// Checks that `stderr` does not contain the regex pattern `unexpected`. + #[track_caller] + pub fn assert_stderr_not_contains_regex>(&self, unexpected: S) -> &Self { + assert_not_contains_regex(&self.stdout_utf8(), unexpected); + self + } + #[track_caller] pub fn assert_exit_code(&self, code: i32) -> &Self { assert!(self.output.status.code() == Some(code)); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a7c8df3e27478..b04f472e5bf01 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,7 +1,6 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile run-make/cdylib-dylib-linkage/Makefile -run-make/cross-lang-lto-clang/Makefile run-make/cross-lang-lto-pgo-smoketest/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile run-make/dep-info-doesnt-run-much/Makefile diff --git a/tests/run-make/cross-lang-lto-clang/Makefile b/tests/run-make/cross-lang-lto-clang/Makefile deleted file mode 100644 index acf49c8f5c85d..0000000000000 --- a/tests/run-make/cross-lang-lto-clang/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# needs-force-clang-based-tests - -# This test makes sure that cross-language inlining actually works by checking -# the generated machine code. - -include ../tools.mk - -all: cpp-executable rust-executable - -cpp-executable: - $(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs - $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3 - # Make sure we don't find a call instruction to the function we expect to - # always be inlined. - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined" - # As a sanity check, make sure we do find a call instruction to a - # non-inlined function - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined" - -rust-executable: - $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2 - (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) - $(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined" - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined" diff --git a/tests/run-make/cross-lang-lto-clang/rmake.rs b/tests/run-make/cross-lang-lto-clang/rmake.rs new file mode 100644 index 0000000000000..114b2d355793f --- /dev/null +++ b/tests/run-make/cross-lang-lto-clang/rmake.rs @@ -0,0 +1,61 @@ +// This test checks that cross-language inlining actually works by checking +// the generated machine code. +// See https://github.com/rust-lang/rust/pull/57514 + +//@ needs-force-clang-based-tests +// FIXME(#126180): This test doesn't actually run anywhere, because the only +// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. + +use run_make_support::{clang, env_var, llvm_ar, llvm_objdump, rustc, static_lib_name}; + +fn main() { + rustc() + .linker_plugin_lto("on") + .output(static_lib_name("rustlib-xlto")) + .opt_level("2") + .codegen_units(1) + .input("rustlib.rs") + .run(); + clang() + .lto("thin") + .use_ld("lld") + .arg("-lrustlib-xlto") + .out_exe("cmain") + .input("cmain.c") + .arg("-O3") + .run(); + // Make sure we don't find a call instruction to the function we expect to + // always be inlined. + llvm_objdump() + .arg("-d") + .input("cmain") + .run() + .assert_stdout_not_contains_regex("call.*rust_always_inlined"); + // As a sanity check, make sure we do find a call instruction to a + // non-inlined function + llvm_objdump() + .arg("-d") + .input("cmain") + .run() + .assert_stdout_contains_regex("call.*rust_never_inlined"); + clang().input("clib.c").lto("thin").arg("-c").out_exe("clib.o").arg("-O2").run(); + llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run(); + rustc() + .linker_plugin_lto("on") + .opt_level("2") + .linker(&env_var("CLANG")) + .link_arg("-fuse-ld=lld") + .input("main.rs") + .output("rsmain") + .run(); + llvm_objdump() + .arg("-d") + .input("rsmain") + .run() + .assert_stdout_not_contains_regex("call.*c_always_inlined"); + llvm_objdump() + .arg("-d") + .input("rsmain") + .run() + .assert_stdout_contains_regex("call.*c_never_inlined"); +} From 560e86d753b79b0ba63e470aabb84049439b3793 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 29 Jul 2024 14:08:43 -0400 Subject: [PATCH 397/489] rewrite cross-lang-lto-pgo-smoketest to rmake --- .../src/external_deps/clang.rs | 5 +- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/cross-lang-lto-clang/_Makefile | 29 +++++ .../{Makefile => _Makefile} | 4 + .../cross-lang-lto-pgo-smoketest/rmake.rs | 111 ++++++++++++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 tests/run-make/cross-lang-lto-clang/_Makefile rename tests/run-make/cross-lang-lto-pgo-smoketest/{Makefile => _Makefile} (94%) create mode 100644 tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs diff --git a/src/tools/run-make-support/src/external_deps/clang.rs b/src/tools/run-make-support/src/external_deps/clang.rs index 2b0712541cd5f..2d110c6825e05 100644 --- a/src/tools/run-make-support/src/external_deps/clang.rs +++ b/src/tools/run-make-support/src/external_deps/clang.rs @@ -1,7 +1,7 @@ use std::path::Path; use crate::command::Command; -use crate::{bin_name, env_var}; +use crate::{bin_name, cwd, env_var}; /// Construct a new `clang` invocation. `clang` is not always available for all targets. #[track_caller] @@ -23,7 +23,8 @@ impl Clang { #[track_caller] pub fn new() -> Self { let clang = env_var("CLANG"); - let cmd = Command::new(clang); + let mut cmd = Command::new(clang); + cmd.arg("-L").arg(cwd()); Self { cmd } } diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index b04f472e5bf01..46fe73ee5ae4a 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,7 +1,6 @@ run-make/branch-protection-check-IBT/Makefile run-make/cat-and-grep-sanity-check/Makefile run-make/cdylib-dylib-linkage/Makefile -run-make/cross-lang-lto-pgo-smoketest/Makefile run-make/cross-lang-lto-upstream-rlibs/Makefile run-make/dep-info-doesnt-run-much/Makefile run-make/dep-info-spaces/Makefile diff --git a/tests/run-make/cross-lang-lto-clang/_Makefile b/tests/run-make/cross-lang-lto-clang/_Makefile new file mode 100644 index 0000000000000..b039328b0f9e8 --- /dev/null +++ b/tests/run-make/cross-lang-lto-clang/_Makefile @@ -0,0 +1,29 @@ +# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180, +# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this +# Makefile. + +# needs-force-clang-based-tests + +# This test makes sure that cross-language inlining actually works by checking +# the generated machine code. + +include ../tools.mk + +all: cpp-executable rust-executable + +cpp-executable: + $(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs + $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3 + # Make sure we don't find a call instruction to the function we expect to + # always be inlined. + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined" + # As a sanity check, make sure we do find a call instruction to a + # non-inlined function + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined" + +rust-executable: + $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2 + (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) + $(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined" + "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined" diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile b/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile similarity index 94% rename from tests/run-make/cross-lang-lto-pgo-smoketest/Makefile rename to tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile index 738e23f9c6614..737f066b4da03 100644 --- a/tests/run-make/cross-lang-lto-pgo-smoketest/Makefile +++ b/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile @@ -1,3 +1,7 @@ +# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180, +# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this +# Makefile. + # needs-force-clang-based-tests # FIXME(#126180): This test doesn't actually run anywhere, because the only diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs b/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs new file mode 100644 index 0000000000000..e4d8879607fd8 --- /dev/null +++ b/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs @@ -0,0 +1,111 @@ +// This test makes sure that cross-language inlining can be used in conjunction +// with profile-guided optimization. The test only tests that the whole workflow +// can be executed without anything crashing. It does not test whether PGO or +// xLTO have any specific effect on the generated code. +// See https://github.com/rust-lang/rust/pull/61036 + +//@ needs-force-clang-based-tests +// FIXME(#126180): This test doesn't actually run anywhere, because the only +// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. + +//FIXME(Oneirical): There was a strange workaround for MSVC on this test +// which added -C panic=abort to every RUSTC call. It was justified as follows: +// LLVM doesn't support instrumenting binaries that use SEH: +// https://bugs.llvm.org/show_bug.cgi?id=41279 +// Things work fine with -Cpanic=abort though. + +use run_make_support::{ + clang, env_var, has_extension, has_prefix, llvm_ar, llvm_profdata, rfs, run, rustc, + shallow_find_files, static_lib_name, +}; + +fn main() { + rustc() + .linker_plugin_lto("on") + .output(static_lib_name("rustlib-xlto")) + .opt_level("3") + .codegen_units(1) + .input("rustlib.rs") + .arg("-Cprofile-generate=cpp-profdata") + .run(); + clang() + .lto("thin") + .arg("-fprofile-generate=cpp-profdata") + .use_ld("lld") + .arg("-lrustlib-xlto") + .out_exe("cmain") + .input("cmain.c") + .arg("-O3") + .run(); + run("cmain"); + // Postprocess the profiling data so it can be used by the compiler + let profraw_files = shallow_find_files("cpp-profdata", |path| { + has_prefix(path, "default") && has_extension(path, "profraw") + }); + let profraw_file = profraw_files.get(0).unwrap(); + llvm_profdata().merge().output("cpp-profdata/merged.profdata").input(profraw_file).run(); + rustc() + .linker_plugin_lto("on") + .profile_use("cpp-profdata/merged.profdata") + .output(static_lib_name("rustlib-xlto")) + .opt_level("3") + .codegen_units(1) + .input("rustlib.rs") + .run(); + clang() + .lto("thin") + .arg("-fprofile-use=cpp-profdata/merged.profdata") + .use_ld("lld") + .arg("-lrustlib-xlto") + .out_exe("cmain") + .input("cmain.c") + .arg("-O3") + .run(); + + clang() + .input("clib.c") + .arg("-fprofile-generate=rs-profdata") + .lto("thin") + .arg("-c") + .out_exe("clib.o") + .arg("-O3") + .run(); + llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run(); + rustc() + .linker_plugin_lto("on") + .opt_level("3") + .codegen_units(1) + .arg("-Cprofile-generate=rs-profdata") + .linker(&env_var("CLANG")) + .link_arg("-fuse-ld=lld") + .input("main.rs") + .output("rsmain") + .run(); + run("rsmain"); + // Postprocess the profiling data so it can be used by the compiler + let profraw_files = shallow_find_files("rs-profdata", |path| { + has_prefix(path, "default") && has_extension(path, "profraw") + }); + let profraw_file = profraw_files.get(0).unwrap(); + llvm_profdata().merge().output("rs-profdata/merged.profdata").input(profraw_file).run(); + clang() + .input("clib.c") + .arg("-fprofile-use=rs-profdata/merged.profdata") + .arg("-c") + .lto("thin") + .out_exe("clib.o") + .arg("-O3") + .run(); + rfs::remove_file(static_lib_name("xyz")); + llvm_ar().obj_to_ar().output_input(static_lib_name("xyz"), "clib.o").run(); + rustc() + .linker_plugin_lto("on") + .opt_level("3") + .codegen_units(1) + .arg("-Cprofile-use=rs-profdata/merged.profdata") + .linker(&env_var("CLANG")) + .link_arg("-fuse-ld=lld") + .input("main.rs") + .output("rsmain") + .run(); +} From 290a260721591338e7acbd207c0c96283b5ec0fb Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 1 Aug 2024 11:51:31 -0400 Subject: [PATCH 398/489] run cross-lang-lto-pgo-smoketest in CI by renaming it --- src/tools/run-make-support/src/command.rs | 7 -- .../src/external_deps/llvm.rs | 6 ++ tests/run-make/cross-lang-lto-clang/_Makefile | 29 ------ tests/run-make/cross-lang-lto-clang/rmake.rs | 13 +-- .../clib.c | 0 .../cmain.c | 0 .../main.rs | 0 .../rmake.rs | 17 +++- .../rustlib.rs | 0 .../cross-lang-lto-pgo-smoketest/_Makefile | 94 ------------------- .../cross-lang-lto-riscv-abi/rmake.rs | 7 +- tests/run-make/wasm-override-linker/rmake.rs | 4 + 12 files changed, 35 insertions(+), 142 deletions(-) delete mode 100644 tests/run-make/cross-lang-lto-clang/_Makefile rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/clib.c (100%) rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/cmain.c (100%) rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/main.rs (100%) rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/rmake.rs (85%) rename tests/run-make/{cross-lang-lto-pgo-smoketest => cross-lang-lto-pgo-smoketest-clang}/rustlib.rs (100%) delete mode 100644 tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index 6582c3c7e8e60..a0b96e25a0cba 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -258,13 +258,6 @@ impl CompletedProcess { self } - /// Checks that `stderr` does not contain the regex pattern `unexpected`. - #[track_caller] - pub fn assert_stderr_not_contains_regex>(&self, unexpected: S) -> &Self { - assert_not_contains_regex(&self.stdout_utf8(), unexpected); - self - } - #[track_caller] pub fn assert_exit_code(&self, code: i32) -> &Self { assert!(self.output.status.code() == Some(code)); diff --git a/src/tools/run-make-support/src/external_deps/llvm.rs b/src/tools/run-make-support/src/external_deps/llvm.rs index c06cefa91a924..56021cec269b1 100644 --- a/src/tools/run-make-support/src/external_deps/llvm.rs +++ b/src/tools/run-make-support/src/external_deps/llvm.rs @@ -246,6 +246,12 @@ impl LlvmObjdump { self.cmd.arg(path.as_ref()); self } + + /// Disassemble all executable sections found in the input files. + pub fn disassemble(&mut self) -> &mut Self { + self.cmd.arg("-d"); + self + } } impl LlvmAr { diff --git a/tests/run-make/cross-lang-lto-clang/_Makefile b/tests/run-make/cross-lang-lto-clang/_Makefile deleted file mode 100644 index b039328b0f9e8..0000000000000 --- a/tests/run-make/cross-lang-lto-clang/_Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180, -# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this -# Makefile. - -# needs-force-clang-based-tests - -# This test makes sure that cross-language inlining actually works by checking -# the generated machine code. - -include ../tools.mk - -all: cpp-executable rust-executable - -cpp-executable: - $(RUSTC) -Clinker-plugin-lto=on -o $(TMPDIR)/librustlib-xlto.a -Copt-level=2 -Ccodegen-units=1 ./rustlib.rs - $(CLANG) -flto=thin -fuse-ld=lld -L $(TMPDIR) -lrustlib-xlto -o $(TMPDIR)/cmain ./cmain.c -O3 - # Make sure we don't find a call instruction to the function we expect to - # always be inlined. - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -v -e "call.*rust_always_inlined" - # As a sanity check, make sure we do find a call instruction to a - # non-inlined function - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/cmain | $(CGREP) -e "call.*rust_never_inlined" - -rust-executable: - $(CLANG) ./clib.c -flto=thin -c -o $(TMPDIR)/clib.o -O2 - (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) - $(RUSTC) -Clinker-plugin-lto=on -L$(TMPDIR) -Copt-level=2 -Clinker=$(CLANG) -Clink-arg=-fuse-ld=lld ./main.rs -o $(TMPDIR)/rsmain - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -e "call.*c_never_inlined" - "$(LLVM_BIN_DIR)"/llvm-objdump -d $(TMPDIR)/rsmain | $(CGREP) -v -e "call.*c_always_inlined" diff --git a/tests/run-make/cross-lang-lto-clang/rmake.rs b/tests/run-make/cross-lang-lto-clang/rmake.rs index 114b2d355793f..1b15a54aacb02 100644 --- a/tests/run-make/cross-lang-lto-clang/rmake.rs +++ b/tests/run-make/cross-lang-lto-clang/rmake.rs @@ -3,8 +3,9 @@ // See https://github.com/rust-lang/rust/pull/57514 //@ needs-force-clang-based-tests -// FIXME(#126180): This test doesn't actually run anywhere, because the only -// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. +// NOTE(#126180): This test only runs on `x86_64-gnu-debug`, because that CI job sets +// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their +// name. use run_make_support::{clang, env_var, llvm_ar, llvm_objdump, rustc, static_lib_name}; @@ -27,14 +28,14 @@ fn main() { // Make sure we don't find a call instruction to the function we expect to // always be inlined. llvm_objdump() - .arg("-d") + .disassemble() .input("cmain") .run() .assert_stdout_not_contains_regex("call.*rust_always_inlined"); // As a sanity check, make sure we do find a call instruction to a // non-inlined function llvm_objdump() - .arg("-d") + .disassemble() .input("cmain") .run() .assert_stdout_contains_regex("call.*rust_never_inlined"); @@ -49,12 +50,12 @@ fn main() { .output("rsmain") .run(); llvm_objdump() - .arg("-d") + .disassemble() .input("rsmain") .run() .assert_stdout_not_contains_regex("call.*c_always_inlined"); llvm_objdump() - .arg("-d") + .disassemble() .input("rsmain") .run() .assert_stdout_contains_regex("call.*c_never_inlined"); diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/clib.c b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/clib.c similarity index 100% rename from tests/run-make/cross-lang-lto-pgo-smoketest/clib.c rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/clib.c diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/cmain.c b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/cmain.c similarity index 100% rename from tests/run-make/cross-lang-lto-pgo-smoketest/cmain.c rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/cmain.c diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/main.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/main.rs similarity index 100% rename from tests/run-make/cross-lang-lto-pgo-smoketest/main.rs rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/main.rs diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs similarity index 85% rename from tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs index e4d8879607fd8..03c9af4bb8982 100644 --- a/tests/run-make/cross-lang-lto-pgo-smoketest/rmake.rs +++ b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rmake.rs @@ -5,14 +5,23 @@ // See https://github.com/rust-lang/rust/pull/61036 //@ needs-force-clang-based-tests -// FIXME(#126180): This test doesn't actually run anywhere, because the only -// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. +// NOTE(#126180): This test would only run on `x86_64-gnu-debug`, because that CI job sets +// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their +// name. + +//@ needs-profiler-support +// FIXME(Oneirical): Except that due to the reliance on llvm-profdata, this test +// never runs, because `x86_64-gnu-debug` does not have the `profiler_builtins` crate. //FIXME(Oneirical): There was a strange workaround for MSVC on this test // which added -C panic=abort to every RUSTC call. It was justified as follows: -// LLVM doesn't support instrumenting binaries that use SEH: + +// "LLVM doesn't support instrumenting binaries that use SEH: // https://bugs.llvm.org/show_bug.cgi?id=41279 -// Things work fine with -Cpanic=abort though. +// Things work fine with -Cpanic=abort though." + +// This isn't very pertinent, however, as the test does not get run on any +// MSVC platforms. use run_make_support::{ clang, env_var, has_extension, has_prefix, llvm_ar, llvm_profdata, rfs, run, rustc, diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs b/tests/run-make/cross-lang-lto-pgo-smoketest-clang/rustlib.rs similarity index 100% rename from tests/run-make/cross-lang-lto-pgo-smoketest/rustlib.rs rename to tests/run-make/cross-lang-lto-pgo-smoketest-clang/rustlib.rs diff --git a/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile b/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile deleted file mode 100644 index 737f066b4da03..0000000000000 --- a/tests/run-make/cross-lang-lto-pgo-smoketest/_Makefile +++ /dev/null @@ -1,94 +0,0 @@ -# FIXME(Oneirical): This is already implemented as an rmake.rs file, but due to #126180, -# the rmake.rs is not ran on CI. Once the rmake test has been proven to work, remove this -# Makefile. - -# needs-force-clang-based-tests - -# FIXME(#126180): This test doesn't actually run anywhere, because the only -# CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. - -# This test makes sure that cross-language inlining can be used in conjunction -# with profile-guided optimization. The test only tests that the whole workflow -# can be executed without anything crashing. It does not test whether PGO or -# xLTO have any specific effect on the generated code. - -include ../tools.mk - -COMMON_FLAGS=-Copt-level=3 -Ccodegen-units=1 - -# LLVM doesn't support instrumenting binaries that use SEH: -# https://bugs.llvm.org/show_bug.cgi?id=41279 -# -# Things work fine with -Cpanic=abort though. -ifdef IS_MSVC -COMMON_FLAGS+= -Cpanic=abort -endif - -all: cpp-executable rust-executable - -cpp-executable: - $(RUSTC) -Clinker-plugin-lto=on \ - -Cprofile-generate="$(TMPDIR)"/cpp-profdata \ - -o "$(TMPDIR)"/librustlib-xlto.a \ - $(COMMON_FLAGS) \ - ./rustlib.rs - $(CLANG) -flto=thin \ - -fprofile-generate="$(TMPDIR)"/cpp-profdata \ - -fuse-ld=lld \ - -L "$(TMPDIR)" \ - -lrustlib-xlto \ - -o "$(TMPDIR)"/cmain \ - -O3 \ - ./cmain.c - $(TMPDIR)/cmain - # Postprocess the profiling data so it can be used by the compiler - "$(LLVM_BIN_DIR)"/llvm-profdata merge \ - -o "$(TMPDIR)"/cpp-profdata/merged.profdata \ - "$(TMPDIR)"/cpp-profdata/default_*.profraw - $(RUSTC) -Clinker-plugin-lto=on \ - -Cprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \ - -o "$(TMPDIR)"/librustlib-xlto.a \ - $(COMMON_FLAGS) \ - ./rustlib.rs - $(CLANG) -flto=thin \ - -fprofile-use="$(TMPDIR)"/cpp-profdata/merged.profdata \ - -fuse-ld=lld \ - -L "$(TMPDIR)" \ - -lrustlib-xlto \ - -o "$(TMPDIR)"/cmain \ - -O3 \ - ./cmain.c - -rust-executable: - exit - $(CLANG) ./clib.c -fprofile-generate="$(TMPDIR)"/rs-profdata -flto=thin -c -o $(TMPDIR)/clib.o -O3 - (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) - $(RUSTC) -Clinker-plugin-lto=on \ - -Cprofile-generate="$(TMPDIR)"/rs-profdata \ - -L$(TMPDIR) \ - $(COMMON_FLAGS) \ - -Clinker=$(CLANG) \ - -Clink-arg=-fuse-ld=lld \ - -o $(TMPDIR)/rsmain \ - ./main.rs - $(TMPDIR)/rsmain - # Postprocess the profiling data so it can be used by the compiler - "$(LLVM_BIN_DIR)"/llvm-profdata merge \ - -o "$(TMPDIR)"/rs-profdata/merged.profdata \ - "$(TMPDIR)"/rs-profdata/default_*.profraw - $(CLANG) ./clib.c \ - -fprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \ - -flto=thin \ - -c \ - -o $(TMPDIR)/clib.o \ - -O3 - rm "$(TMPDIR)"/libxyz.a - (cd $(TMPDIR); $(AR) crus ./libxyz.a ./clib.o) - $(RUSTC) -Clinker-plugin-lto=on \ - -Cprofile-use="$(TMPDIR)"/rs-profdata/merged.profdata \ - -L$(TMPDIR) \ - $(COMMON_FLAGS) \ - -Clinker=$(CLANG) \ - -Clink-arg=-fuse-ld=lld \ - -o $(TMPDIR)/rsmain \ - ./main.rs diff --git a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs index 391759ec5f662..92573353a741b 100644 --- a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs +++ b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs @@ -3,8 +3,11 @@ //@ needs-force-clang-based-tests //@ needs-llvm-components riscv -// FIXME(#126180): This test doesn't actually run anywhere, because the only -// CI job that sets RUSTBUILD_FORCE_CLANG_BASED_TESTS runs very few tests. +//@ needs-force-clang-based-tests +// FIXME(#126180): This test can only run on `x86_64-gnu-debug`, because that CI job sets +// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their +// name. +// However, this test does not run at all as its name does not contain "clang". use std::path::PathBuf; use std::process::{Command, Output}; diff --git a/tests/run-make/wasm-override-linker/rmake.rs b/tests/run-make/wasm-override-linker/rmake.rs index 01bc08e990159..b04edc18eef34 100644 --- a/tests/run-make/wasm-override-linker/rmake.rs +++ b/tests/run-make/wasm-override-linker/rmake.rs @@ -2,6 +2,10 @@ // $ RUSTBUILD_FORCE_CLANG_BASED_TESTS=1 ./x.py test tests/run-make/wasm-override-linker/ //@ needs-force-clang-based-tests +// FIXME(#126180): This test can only run on `x86_64-gnu-debug`, because that CI job sets +// RUSTBUILD_FORCE_CLANG_BASED_TESTS and only runs tests which contain "clang" in their +// name. +// However, this test does not run at all as its name does not contain "clang". use run_make_support::{env_var, rustc, target}; From 84e261e5cb47f637b1d94f03fc65b80c8f45add4 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 2 Aug 2024 12:16:52 -0400 Subject: [PATCH 399/489] chore: use shorthand initializer --- compiler/rustc_builtin_macros/src/alloc_error_handler.rs | 2 +- compiler/rustc_query_system/src/query/job.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index 09d892768b464..1df2812e0c887 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -80,7 +80,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span let params = thin_vec![cx.param(span, size, ty_usize.clone()), cx.param(span, align, ty_usize)]; let decl = cx.fn_decl(params, never); let header = FnHeader { safety: Safety::Unsafe(span), ..FnHeader::default() }; - let sig = FnSig { decl, header, span: span }; + let sig = FnSig { decl, header, span }; let body = Some(cx.block_expr(call)); let kind = ItemKind::Fn(Box::new(Fn { diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 761d6acdbaeb9..ca3efc11201e1 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -588,7 +588,7 @@ pub fn report_cycle<'a>( cycle_stack, stack_bottom: stack[0].query.description.to_owned(), alias, - cycle_usage: cycle_usage, + cycle_usage, stack_count, note_span: (), }; From eb726a50e65387c348ba56f2416fc3c0b649f95e Mon Sep 17 00:00:00 2001 From: Folkert Date: Fri, 2 Aug 2024 20:45:14 +0200 Subject: [PATCH 400/489] add `needs-asm-support` to invalid-sym-operand --- tests/ui/asm/invalid-sym-operand.rs | 4 ++++ tests/ui/asm/invalid-sym-operand.stderr | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/ui/asm/invalid-sym-operand.rs b/tests/ui/asm/invalid-sym-operand.rs index 69c4695125c43..2129c20b9681d 100644 --- a/tests/ui/asm/invalid-sym-operand.rs +++ b/tests/ui/asm/invalid-sym-operand.rs @@ -1,3 +1,7 @@ +//@ needs-asm-support +//@ ignore-nvptx64 +//@ ignore-spirv + use std::arch::{asm, global_asm}; // Sym operands must point to a function or static diff --git a/tests/ui/asm/invalid-sym-operand.stderr b/tests/ui/asm/invalid-sym-operand.stderr index 8e0676200bb2e..f0e6a17c25f6b 100644 --- a/tests/ui/asm/invalid-sym-operand.stderr +++ b/tests/ui/asm/invalid-sym-operand.stderr @@ -1,5 +1,5 @@ error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:23:24 + --> $DIR/invalid-sym-operand.rs:27:24 | LL | asm!("{}", sym x); | ^ is a local variable @@ -7,7 +7,7 @@ LL | asm!("{}", sym x); = help: `sym` operands must refer to either a function or a static error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:9:19 + --> $DIR/invalid-sym-operand.rs:13:19 | LL | global_asm!("{}", sym C); | ^^^^^ is an `i32` @@ -15,7 +15,7 @@ LL | global_asm!("{}", sym C); = help: `sym` operands must refer to either a function or a static error: invalid `sym` operand - --> $DIR/invalid-sym-operand.rs:21:20 + --> $DIR/invalid-sym-operand.rs:25:20 | LL | asm!("{}", sym C); | ^^^^^ is an `i32` From 05111c90beecb35f58d0e7e335b0994bc08e8534 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 2 Aug 2024 20:36:03 -0400 Subject: [PATCH 401/489] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 257b72b8adfb1..fa646583675d7 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 257b72b8adfb1f2aa9916cefca67285c21666276 +Subproject commit fa646583675d7c140482bd906145c71b7fb4fc2b From 7dd5ad282c4aab165236c8ba9404929d7dd337ac Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 1 Aug 2024 22:54:22 -0700 Subject: [PATCH 402/489] rustdoc: Extract helper function to add item to search index --- src/librustdoc/formats/cache.rs | 272 ++++++++++++++++---------------- 1 file changed, 135 insertions(+), 137 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 9f284486616a0..8c0ed6cddf064 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } // Index this method for searching later on. - if let Some(s) = item.name.or_else(|| { + if let Some(name) = item.name.or_else(|| { if item.is_stripped() { None } else if let clean::ImportItem(ref i) = *item.kind @@ -271,142 +271,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { None } }) { - let (parent, is_inherent_impl_item) = match *item.kind { - clean::StrippedItem(..) => ((None, None), false), - clean::AssocConstItem(..) | clean::AssocTypeItem(..) - if self - .cache - .parent_stack - .last() - .is_some_and(|parent| parent.is_trait_impl()) => - { - // skip associated items in trait impls - ((None, None), false) - } - clean::TyMethodItem(..) - | clean::TyAssocConstItem(..) - | clean::TyAssocTypeItem(..) - | clean::StructFieldItem(..) - | clean::VariantItem(..) => ( - ( - Some( - self.cache - .parent_stack - .last() - .expect("parent_stack is empty") - .item_id() - .expect_def_id(), - ), - Some(&self.cache.stack[..self.cache.stack.len() - 1]), - ), - false, - ), - clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { - if self.cache.parent_stack.is_empty() { - ((None, None), false) - } else { - let last = self.cache.parent_stack.last().expect("parent_stack is empty 2"); - let did = match &*last { - ParentStackItem::Impl { - // impl Trait for &T { fn method(self); } - // - // When generating a function index with the above shape, we want it - // associated with `T`, not with the primitive reference type. It should - // show up as `T::method`, rather than `reference::method`, in the search - // results page. - for_: clean::Type::BorrowedRef { type_, .. }, - .. - } => type_.def_id(&self.cache), - ParentStackItem::Impl { for_, .. } => for_.def_id(&self.cache), - ParentStackItem::Type(item_id) => item_id.as_def_id(), - }; - let path = did - .and_then(|did| self.cache.paths.get(&did)) - // The current stack not necessarily has correlation - // for where the type was defined. On the other - // hand, `paths` always has the right - // information if present. - .map(|(fqp, _)| &fqp[..fqp.len() - 1]); - ((did, path), true) - } - } - _ => ((None, Some(&*self.cache.stack)), false), - }; - - match parent { - (parent, Some(path)) if is_inherent_impl_item || !self.cache.stripped_mod => { - debug_assert!(!item.is_stripped()); - - // A crate has a module at its root, containing all items, - // which should not be indexed. The crate-item itself is - // inserted later on when serializing the search-index. - if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root()) - && let ty = item.type_() - && (ty != ItemType::StructField - || u16::from_str_radix(s.as_str(), 10).is_err()) - { - let desc = - short_markdown_summary(&item.doc_value(), &item.link_names(self.cache)); - // For searching purposes, a re-export is a duplicate if: - // - // - It's either an inline, or a true re-export - // - It's got the same name - // - Both of them have the same exact path - let defid = (match &*item.kind { - &clean::ItemKind::ImportItem(ref import) => import.source.did, - _ => None, - }) - .or_else(|| item.item_id.as_def_id()); - // In case this is a field from a tuple struct, we don't add it into - // the search index because its name is something like "0", which is - // not useful for rustdoc search. - self.cache.search_index.push(IndexItem { - ty, - defid, - name: s, - path: join_with_double_colon(path), - desc, - parent, - parent_idx: None, - exact_path: None, - impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = - self.cache.parent_stack.last() - { - item_id.as_def_id() - } else { - None - }, - search_type: get_function_type_for_search( - &item, - self.tcx, - clean_impl_generics(self.cache.parent_stack.last()).as_ref(), - parent, - self.cache, - ), - aliases: item.attrs.get_doc_aliases(), - deprecation: item.deprecation(self.tcx), - }); - } - } - (Some(parent), None) if is_inherent_impl_item => { - // We have a parent, but we don't know where they're - // defined yet. Wait for later to index this item. - let impl_generics = clean_impl_generics(self.cache.parent_stack.last()); - self.cache.orphan_impl_items.push(OrphanImplItem { - parent, - item: item.clone(), - impl_generics, - impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = - self.cache.parent_stack.last() - { - item_id.as_def_id() - } else { - None - }, - }); - } - _ => {} - } + add_item_to_search_index(self.tcx, &mut self.cache, &item, name) } // Keep track of the fully qualified path for this item. @@ -573,6 +438,139 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } } +fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) { + let (parent, is_inherent_impl_item) = match *item.kind { + clean::StrippedItem(..) => ((None, None), false), + clean::AssocConstItem(..) | clean::AssocTypeItem(..) + if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) => + { + // skip associated items in trait impls + ((None, None), false) + } + clean::TyMethodItem(..) + | clean::TyAssocConstItem(..) + | clean::TyAssocTypeItem(..) + | clean::StructFieldItem(..) + | clean::VariantItem(..) => ( + ( + Some( + cache + .parent_stack + .last() + .expect("parent_stack is empty") + .item_id() + .expect_def_id(), + ), + Some(&cache.stack[..cache.stack.len() - 1]), + ), + false, + ), + clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { + if cache.parent_stack.is_empty() { + ((None, None), false) + } else { + let last = cache.parent_stack.last().expect("parent_stack is empty 2"); + let did = match &*last { + ParentStackItem::Impl { + // impl Trait for &T { fn method(self); } + // + // When generating a function index with the above shape, we want it + // associated with `T`, not with the primitive reference type. It should + // show up as `T::method`, rather than `reference::method`, in the search + // results page. + for_: clean::Type::BorrowedRef { type_, .. }, + .. + } => type_.def_id(&cache), + ParentStackItem::Impl { for_, .. } => for_.def_id(&cache), + ParentStackItem::Type(item_id) => item_id.as_def_id(), + }; + let path = did + .and_then(|did| cache.paths.get(&did)) + // The current stack not necessarily has correlation + // for where the type was defined. On the other + // hand, `paths` always has the right + // information if present. + .map(|(fqp, _)| &fqp[..fqp.len() - 1]); + ((did, path), true) + } + } + _ => ((None, Some(&*cache.stack)), false), + }; + + match parent { + (parent, Some(path)) if is_inherent_impl_item || !cache.stripped_mod => { + debug_assert!(!item.is_stripped()); + + // A crate has a module at its root, containing all items, + // which should not be indexed. The crate-item itself is + // inserted later on when serializing the search-index. + if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root()) + && let ty = item.type_() + && (ty != ItemType::StructField || u16::from_str_radix(name.as_str(), 10).is_err()) + { + let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache)); + // For searching purposes, a re-export is a duplicate if: + // + // - It's either an inline, or a true re-export + // - It's got the same name + // - Both of them have the same exact path + let defid = (match &*item.kind { + &clean::ItemKind::ImportItem(ref import) => import.source.did, + _ => None, + }) + .or_else(|| item.item_id.as_def_id()); + // In case this is a field from a tuple struct, we don't add it into + // the search index because its name is something like "0", which is + // not useful for rustdoc search. + cache.search_index.push(IndexItem { + ty, + defid, + name, + path: join_with_double_colon(path), + desc, + parent, + parent_idx: None, + exact_path: None, + impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = + cache.parent_stack.last() + { + item_id.as_def_id() + } else { + None + }, + search_type: get_function_type_for_search( + &item, + tcx, + clean_impl_generics(cache.parent_stack.last()).as_ref(), + parent, + cache, + ), + aliases: item.attrs.get_doc_aliases(), + deprecation: item.deprecation(tcx), + }); + } + } + (Some(parent), None) if is_inherent_impl_item => { + // We have a parent, but we don't know where they're + // defined yet. Wait for later to index this item. + let impl_generics = clean_impl_generics(cache.parent_stack.last()); + cache.orphan_impl_items.push(OrphanImplItem { + parent, + item: item.clone(), + impl_generics, + impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = + cache.parent_stack.last() + { + item_id.as_def_id() + } else { + None + }, + }); + } + _ => {} + } +} + pub(crate) struct OrphanImplItem { pub(crate) parent: DefId, pub(crate) impl_id: Option, From 2721e97c5d9a4e5a001461e499a751e81e10df4c Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 1 Aug 2024 23:20:20 -0700 Subject: [PATCH 403/489] rustdoc: Clarify construction of name for search index --- src/librustdoc/formats/cache.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 8c0ed6cddf064..13b91f483ebf6 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -260,17 +260,20 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } // Index this method for searching later on. - if let Some(name) = item.name.or_else(|| { - if item.is_stripped() { - None - } else if let clean::ImportItem(ref i) = *item.kind - && let clean::ImportKind::Simple(s) = i.kind - { - Some(s) - } else { - None - } - }) { + let search_name = if !item.is_stripped() { + item.name.or_else(|| { + if let clean::ImportItem(ref i) = *item.kind + && let clean::ImportKind::Simple(s) = i.kind + { + Some(s) + } else { + None + } + }) + } else { + None + }; + if let Some(name) = search_name { add_item_to_search_index(self.tcx, &mut self.cache, &item, name) } From 4e2084769b8e6de0dd43453315b7466305e9d312 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Thu, 1 Aug 2024 23:33:42 -0700 Subject: [PATCH 404/489] rustdoc: Simplify some search index code --- src/librustdoc/clean/types.rs | 20 +++++------ src/librustdoc/formats/cache.rs | 60 +++++++++++++++------------------ 2 files changed, 36 insertions(+), 44 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1ec5f38b6ec0f..cf01ffb2e7586 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1680,13 +1680,16 @@ impl Type { } } - fn inner_def_id(&self, cache: Option<&Cache>) -> Option { + /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s. + /// + /// [clean]: crate::clean + pub(crate) fn def_id(&self, cache: &Cache) -> Option { let t: PrimitiveType = match *self { Type::Path { ref path } => return Some(path.def_id()), DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()), - Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), + Primitive(p) => return cache.primitive_locations.get(&p).cloned(), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, - BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), + BorrowedRef { ref type_, .. } => return type_.def_id(cache), Tuple(ref tys) => { if tys.is_empty() { PrimitiveType::Unit @@ -1699,17 +1702,10 @@ impl Type { Array(..) => PrimitiveType::Array, Type::Pat(..) => PrimitiveType::Pat, RawPointer(..) => PrimitiveType::RawPointer, - QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache), + QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache), Generic(_) | Infer | ImplTrait(_) => return None, }; - cache.and_then(|c| Primitive(t).def_id(c)) - } - - /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s. - /// - /// [clean]: crate::clean - pub(crate) fn def_id(&self, cache: &Cache) -> Option { - self.inner_def_id(Some(cache)) + Primitive(t).def_id(cache) } } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 13b91f483ebf6..0788543d89af7 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -442,13 +442,13 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) { - let (parent, is_inherent_impl_item) = match *item.kind { - clean::StrippedItem(..) => ((None, None), false), + let (parent, is_impl_child) = match *item.kind { + clean::StrippedItem(..) => return, clean::AssocConstItem(..) | clean::AssocTypeItem(..) if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) => { // skip associated items in trait impls - ((None, None), false) + return; } clean::TyMethodItem(..) | clean::TyAssocConstItem(..) @@ -469,39 +469,35 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It false, ), clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { - if cache.parent_stack.is_empty() { - ((None, None), false) - } else { - let last = cache.parent_stack.last().expect("parent_stack is empty 2"); - let did = match &*last { - ParentStackItem::Impl { - // impl Trait for &T { fn method(self); } - // - // When generating a function index with the above shape, we want it - // associated with `T`, not with the primitive reference type. It should - // show up as `T::method`, rather than `reference::method`, in the search - // results page. - for_: clean::Type::BorrowedRef { type_, .. }, - .. - } => type_.def_id(&cache), - ParentStackItem::Impl { for_, .. } => for_.def_id(&cache), - ParentStackItem::Type(item_id) => item_id.as_def_id(), - }; - let path = did - .and_then(|did| cache.paths.get(&did)) - // The current stack not necessarily has correlation - // for where the type was defined. On the other - // hand, `paths` always has the right - // information if present. - .map(|(fqp, _)| &fqp[..fqp.len() - 1]); - ((did, path), true) - } + let last = cache.parent_stack.last().expect("parent_stack is empty 2"); + let did = match &*last { + ParentStackItem::Impl { + // impl Trait for &T { fn method(self); } + // + // When generating a function index with the above shape, we want it + // associated with `T`, not with the primitive reference type. It should + // show up as `T::method`, rather than `reference::method`, in the search + // results page. + for_: clean::Type::BorrowedRef { type_, .. }, + .. + } => type_.def_id(&cache), + ParentStackItem::Impl { for_, .. } => for_.def_id(&cache), + ParentStackItem::Type(item_id) => item_id.as_def_id(), + }; + let path = did + .and_then(|did| cache.paths.get(&did)) + // The current stack not necessarily has correlation + // for where the type was defined. On the other + // hand, `paths` always has the right + // information if present. + .map(|(fqp, _)| &fqp[..fqp.len() - 1]); + ((did, path), true) } _ => ((None, Some(&*cache.stack)), false), }; match parent { - (parent, Some(path)) if is_inherent_impl_item || !cache.stripped_mod => { + (parent, Some(path)) if is_impl_child || !cache.stripped_mod => { debug_assert!(!item.is_stripped()); // A crate has a module at its root, containing all items, @@ -553,7 +549,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It }); } } - (Some(parent), None) if is_inherent_impl_item => { + (Some(parent), None) if is_impl_child => { // We have a parent, but we don't know where they're // defined yet. Wait for later to index this item. let impl_generics = clean_impl_generics(cache.parent_stack.last()); From 015aa8d0fba2247da33967a93fad9a2bea16037f Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 2 Aug 2024 12:58:59 -0700 Subject: [PATCH 405/489] Restructure a confusing `match` --- src/librustdoc/formats/cache.rs | 124 ++++++++++++++++---------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 0788543d89af7..5c18cebb96573 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -442,7 +442,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) { - let (parent, is_impl_child) = match *item.kind { + let ((parent_did, parent_path), is_impl_child) = match *item.kind { clean::StrippedItem(..) => return, clean::AssocConstItem(..) | clean::AssocTypeItem(..) if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) => @@ -496,67 +496,59 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It _ => ((None, Some(&*cache.stack)), false), }; - match parent { - (parent, Some(path)) if is_impl_child || !cache.stripped_mod => { - debug_assert!(!item.is_stripped()); - - // A crate has a module at its root, containing all items, - // which should not be indexed. The crate-item itself is - // inserted later on when serializing the search-index. - if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root()) - && let ty = item.type_() - && (ty != ItemType::StructField || u16::from_str_radix(name.as_str(), 10).is_err()) + if let Some(parent_did) = parent_did + && parent_path.is_none() + && is_impl_child + { + // We have a parent, but we don't know where they're + // defined yet. Wait for later to index this item. + let impl_generics = clean_impl_generics(cache.parent_stack.last()); + cache.orphan_impl_items.push(OrphanImplItem { + parent: parent_did, + item: item.clone(), + impl_generics, + impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() { - let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache)); - // For searching purposes, a re-export is a duplicate if: - // - // - It's either an inline, or a true re-export - // - It's got the same name - // - Both of them have the same exact path - let defid = (match &*item.kind { - &clean::ItemKind::ImportItem(ref import) => import.source.did, - _ => None, - }) - .or_else(|| item.item_id.as_def_id()); - // In case this is a field from a tuple struct, we don't add it into - // the search index because its name is something like "0", which is - // not useful for rustdoc search. - cache.search_index.push(IndexItem { - ty, - defid, - name, - path: join_with_double_colon(path), - desc, - parent, - parent_idx: None, - exact_path: None, - impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = - cache.parent_stack.last() - { - item_id.as_def_id() - } else { - None - }, - search_type: get_function_type_for_search( - &item, - tcx, - clean_impl_generics(cache.parent_stack.last()).as_ref(), - parent, - cache, - ), - aliases: item.attrs.get_doc_aliases(), - deprecation: item.deprecation(tcx), - }); - } - } - (Some(parent), None) if is_impl_child => { - // We have a parent, but we don't know where they're - // defined yet. Wait for later to index this item. - let impl_generics = clean_impl_generics(cache.parent_stack.last()); - cache.orphan_impl_items.push(OrphanImplItem { - parent, - item: item.clone(), - impl_generics, + item_id.as_def_id() + } else { + None + }, + }); + } else if let Some(path) = parent_path + && (is_impl_child || !cache.stripped_mod) + { + debug_assert!(!item.is_stripped()); + + // A crate has a module at its root, containing all items, + // which should not be indexed. The crate-item itself is + // inserted later on when serializing the search-index. + if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root()) + && let ty = item.type_() + && (ty != ItemType::StructField || u16::from_str_radix(name.as_str(), 10).is_err()) + { + let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache)); + // For searching purposes, a re-export is a duplicate if: + // + // - It's either an inline, or a true re-export + // - It's got the same name + // - Both of them have the same exact path + let defid = (match &*item.kind { + &clean::ItemKind::ImportItem(ref import) => import.source.did, + _ => None, + }) + .or_else(|| item.item_id.as_def_id()); + // In case this is a field from a tuple struct, we don't add it into + // the search index because its name is something like "0", which is + // not useful for rustdoc search. + cache.search_index.push(IndexItem { + ty, + defid, + name, + path: join_with_double_colon(path), + desc, + parent: parent_did, + parent_idx: None, + exact_path: None, impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() { @@ -564,9 +556,17 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It } else { None }, + search_type: get_function_type_for_search( + &item, + tcx, + clean_impl_generics(cache.parent_stack.last()).as_ref(), + parent_did, + cache, + ), + aliases: item.attrs.get_doc_aliases(), + deprecation: item.deprecation(tcx), }); } - _ => {} } } From 08f4d54ea91b1092161e9bb77b5b6aa3f9d48714 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 2 Aug 2024 14:01:38 -0700 Subject: [PATCH 406/489] Extract local variables --- src/librustdoc/formats/cache.rs | 63 +++++++++++++++++---------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 5c18cebb96573..effdce54015aa 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -503,17 +503,15 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It // We have a parent, but we don't know where they're // defined yet. Wait for later to index this item. let impl_generics = clean_impl_generics(cache.parent_stack.last()); - cache.orphan_impl_items.push(OrphanImplItem { - parent: parent_did, - item: item.clone(), - impl_generics, - impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() - { - item_id.as_def_id() - } else { - None - }, - }); + let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() + { + item_id.as_def_id() + } else { + None + }; + let orphan_item = + OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id }; + cache.orphan_impl_items.push(orphan_item); } else if let Some(path) = parent_path && (is_impl_child || !cache.stripped_mod) { @@ -540,32 +538,37 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It // In case this is a field from a tuple struct, we don't add it into // the search index because its name is something like "0", which is // not useful for rustdoc search. - cache.search_index.push(IndexItem { + let path = join_with_double_colon(path); + let impl_id = + if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() { + item_id.as_def_id() + } else { + None + }; + let search_type = get_function_type_for_search( + &item, + tcx, + clean_impl_generics(cache.parent_stack.last()).as_ref(), + parent_did, + cache, + ); + let aliases = item.attrs.get_doc_aliases(); + let deprecation = item.deprecation(tcx); + let index_item = IndexItem { ty, defid, name, - path: join_with_double_colon(path), + path, desc, parent: parent_did, parent_idx: None, exact_path: None, - impl_id: if let Some(ParentStackItem::Impl { item_id, .. }) = - cache.parent_stack.last() - { - item_id.as_def_id() - } else { - None - }, - search_type: get_function_type_for_search( - &item, - tcx, - clean_impl_generics(cache.parent_stack.last()).as_ref(), - parent_did, - cache, - ), - aliases: item.attrs.get_doc_aliases(), - deprecation: item.deprecation(tcx), - }); + impl_id, + search_type, + aliases, + deprecation, + }; + cache.search_index.push(index_item); } } } From 220c2d8c9bc07d0a7b81104edb14f892e0a5f0aa Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Fri, 2 Aug 2024 14:48:36 -0700 Subject: [PATCH 407/489] Restructure `add_item_to_search_index` to eliminate code paths Many of the code paths it handled were actually impossible. In other cases, the various checks and transformations were spread around in such a way that it was hard to tell what was going on. --- src/librustdoc/formats/cache.rs | 213 +++++++++++++++----------------- 1 file changed, 103 insertions(+), 110 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index effdce54015aa..d2d0f5a4380b6 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -442,7 +442,9 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { } fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::Item, name: Symbol) { - let ((parent_did, parent_path), is_impl_child) = match *item.kind { + // Item has a name, so it must also have a DefId (can't be an impl, let alone a blanket or auto impl). + let item_def_id = item.item_id.as_def_id().unwrap(); + let (parent_did, parent_path) = match *item.kind { clean::StrippedItem(..) => return, clean::AssocConstItem(..) | clean::AssocTypeItem(..) if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) => @@ -454,123 +456,114 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It | clean::TyAssocConstItem(..) | clean::TyAssocTypeItem(..) | clean::StructFieldItem(..) - | clean::VariantItem(..) => ( - ( - Some( - cache - .parent_stack - .last() - .expect("parent_stack is empty") - .item_id() - .expect_def_id(), - ), - Some(&cache.stack[..cache.stack.len() - 1]), - ), - false, - ), + | clean::VariantItem(..) => { + // Don't index if containing module is stripped (i.e., private), + // or if item is tuple struct/variant field (name is a number -> not useful for search). + if cache.stripped_mod + || item.type_() == ItemType::StructField + && name.as_str().chars().all(|c| c.is_digit(10)) + { + return; + } + let parent_did = + cache.parent_stack.last().expect("parent_stack is empty").item_id().expect_def_id(); + let parent_path = &cache.stack[..cache.stack.len() - 1]; + (Some(parent_did), parent_path) + } clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { let last = cache.parent_stack.last().expect("parent_stack is empty 2"); - let did = match &*last { - ParentStackItem::Impl { - // impl Trait for &T { fn method(self); } - // - // When generating a function index with the above shape, we want it - // associated with `T`, not with the primitive reference type. It should - // show up as `T::method`, rather than `reference::method`, in the search - // results page. - for_: clean::Type::BorrowedRef { type_, .. }, - .. - } => type_.def_id(&cache), + let parent_did = match &*last { + // impl Trait for &T { fn method(self); } + // + // When generating a function index with the above shape, we want it + // associated with `T`, not with the primitive reference type. It should + // show up as `T::method`, rather than `reference::method`, in the search + // results page. + ParentStackItem::Impl { for_: clean::Type::BorrowedRef { type_, .. }, .. } => { + type_.def_id(&cache) + } ParentStackItem::Impl { for_, .. } => for_.def_id(&cache), ParentStackItem::Type(item_id) => item_id.as_def_id(), }; - let path = did - .and_then(|did| cache.paths.get(&did)) - // The current stack not necessarily has correlation - // for where the type was defined. On the other - // hand, `paths` always has the right - // information if present. - .map(|(fqp, _)| &fqp[..fqp.len() - 1]); - ((did, path), true) + let Some(parent_did) = parent_did else { return }; + // The current stack not necessarily has correlation + // for where the type was defined. On the other + // hand, `paths` always has the right + // information if present. + match cache.paths.get(&parent_did) { + Some((fqp, _)) => (Some(parent_did), &fqp[..fqp.len() - 1]), + None => { + handle_orphan_impl_child(cache, item, parent_did); + return; + } + } + } + _ => { + // Don't index if item is crate root, which is inserted later on when serializing the index. + if item_def_id.is_crate_root() { + return; + } + (None, &*cache.stack) } - _ => ((None, Some(&*cache.stack)), false), }; - if let Some(parent_did) = parent_did - && parent_path.is_none() - && is_impl_child - { - // We have a parent, but we don't know where they're - // defined yet. Wait for later to index this item. - let impl_generics = clean_impl_generics(cache.parent_stack.last()); - let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() - { - item_id.as_def_id() - } else { - None - }; - let orphan_item = - OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id }; - cache.orphan_impl_items.push(orphan_item); - } else if let Some(path) = parent_path - && (is_impl_child || !cache.stripped_mod) - { - debug_assert!(!item.is_stripped()); - - // A crate has a module at its root, containing all items, - // which should not be indexed. The crate-item itself is - // inserted later on when serializing the search-index. - if item.item_id.as_def_id().is_some_and(|idx| !idx.is_crate_root()) - && let ty = item.type_() - && (ty != ItemType::StructField || u16::from_str_radix(name.as_str(), 10).is_err()) - { - let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache)); - // For searching purposes, a re-export is a duplicate if: - // - // - It's either an inline, or a true re-export - // - It's got the same name - // - Both of them have the same exact path - let defid = (match &*item.kind { - &clean::ItemKind::ImportItem(ref import) => import.source.did, - _ => None, - }) - .or_else(|| item.item_id.as_def_id()); - // In case this is a field from a tuple struct, we don't add it into - // the search index because its name is something like "0", which is - // not useful for rustdoc search. - let path = join_with_double_colon(path); - let impl_id = - if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() { - item_id.as_def_id() - } else { - None - }; - let search_type = get_function_type_for_search( - &item, - tcx, - clean_impl_generics(cache.parent_stack.last()).as_ref(), - parent_did, - cache, - ); - let aliases = item.attrs.get_doc_aliases(); - let deprecation = item.deprecation(tcx); - let index_item = IndexItem { - ty, - defid, - name, - path, - desc, - parent: parent_did, - parent_idx: None, - exact_path: None, - impl_id, - search_type, - aliases, - deprecation, - }; - cache.search_index.push(index_item); - } - } + debug_assert!(!item.is_stripped()); + + let desc = short_markdown_summary(&item.doc_value(), &item.link_names(cache)); + // For searching purposes, a re-export is a duplicate if: + // + // - It's either an inline, or a true re-export + // - It's got the same name + // - Both of them have the same exact path + let defid = match &*item.kind { + clean::ItemKind::ImportItem(import) => import.source.did.unwrap_or(item_def_id), + _ => item_def_id, + }; + let path = join_with_double_colon(parent_path); + let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() { + item_id.as_def_id() + } else { + None + }; + let search_type = get_function_type_for_search( + &item, + tcx, + clean_impl_generics(cache.parent_stack.last()).as_ref(), + parent_did, + cache, + ); + let aliases = item.attrs.get_doc_aliases(); + let deprecation = item.deprecation(tcx); + let index_item = IndexItem { + ty: item.type_(), + defid: Some(defid), + name, + path, + desc, + parent: parent_did, + parent_idx: None, + exact_path: None, + impl_id, + search_type, + aliases, + deprecation, + }; + cache.search_index.push(index_item); +} + +/// We have a parent, but we don't know where they're +/// defined yet. Wait for later to index this item. +/// See [`Cache::orphan_impl_items`]. +fn handle_orphan_impl_child(cache: &mut Cache, item: &clean::Item, parent_did: DefId) { + let impl_generics = clean_impl_generics(cache.parent_stack.last()); + let impl_id = if let Some(ParentStackItem::Impl { item_id, .. }) = cache.parent_stack.last() { + item_id.as_def_id() + } else { + None + }; + let orphan_item = + OrphanImplItem { parent: parent_did, item: item.clone(), impl_generics, impl_id }; + cache.orphan_impl_items.push(orphan_item); } pub(crate) struct OrphanImplItem { From a798e0f4883997907e6a1ffa484071c0ceb2ba85 Mon Sep 17 00:00:00 2001 From: Konippi Date: Fri, 2 Aug 2024 23:58:05 +0900 Subject: [PATCH 408/489] chore: refactor backtrace style in panic --- library/std/src/panic.rs | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 2ca9256715cd8..4c496ade81cda 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -463,11 +463,10 @@ static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0); /// environment variable; see the details in [`get_backtrace_style`]. #[unstable(feature = "panic_backtrace_config", issue = "93346")] pub fn set_backtrace_style(style: BacktraceStyle) { - if !cfg!(feature = "backtrace") { - // If the `backtrace` feature of this crate isn't enabled, skip setting. - return; + if cfg!(feature = "backtrace") { + // If the `backtrace` feature of this crate is enabled, set the backtrace style. + SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release); } - SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release); } /// Checks whether the standard library's panic hook will capture and print a @@ -503,21 +502,13 @@ pub fn get_backtrace_style() -> Option { return Some(style); } - let format = crate::env::var_os("RUST_BACKTRACE") - .map(|x| { - if &x == "0" { - BacktraceStyle::Off - } else if &x == "full" { - BacktraceStyle::Full - } else { - BacktraceStyle::Short - } - }) - .unwrap_or(if crate::sys::FULL_BACKTRACE_DEFAULT { - BacktraceStyle::Full - } else { - BacktraceStyle::Off - }); + let format = match crate::env::var_os("RUST_BACKTRACE") { + Some(x) if &x == "0" => BacktraceStyle::Off, + Some(x) if &x == "full" => BacktraceStyle::Full, + Some(_) => BacktraceStyle::Short, + None if crate::sys::FULL_BACKTRACE_DEFAULT => BacktraceStyle::Full, + None => BacktraceStyle::Off, + }; set_backtrace_style(format); Some(format) } From ed010dd32c55c2add60dc4baff837b281cf81be8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 31 Jul 2024 15:56:09 +0000 Subject: [PATCH 409/489] Assert that all attributes are actually checked via `CheckAttrVisitor` and aren't accidentally usable on completely unrelated HIR nodes Co-authored-by: Jieyou Xu --- compiler/rustc_feature/src/builtin_attrs.rs | 8 +-- compiler/rustc_passes/messages.ftl | 4 ++ compiler/rustc_passes/src/check_attr.rs | 66 ++++++++++++++++++++- compiler/rustc_passes/src/errors.rs | 7 +++ 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index ef03a25bc164b..72ea55d5999a2 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -703,21 +703,21 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, allocator_internals, experimental!(needs_allocator), ), gated!( - panic_runtime, Normal, template!(Word), WarnFollowing, + panic_runtime, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No, experimental!(panic_runtime) ), gated!( - needs_panic_runtime, Normal, template!(Word), WarnFollowing, + needs_panic_runtime, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No, experimental!(needs_panic_runtime) ), gated!( - compiler_builtins, Normal, template!(Word), WarnFollowing, + compiler_builtins, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No, "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ which contains compiler-rt intrinsics and will never be stable", ), gated!( - profiler_runtime, Normal, template!(Word), WarnFollowing, + profiler_runtime, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No, "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ which contains the profiler runtime and will never be stable", diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 1747307a1b2c5..59c9d1e49f5b3 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -100,6 +100,10 @@ passes_continue_labeled_block = .label = labeled blocks cannot be `continue`'d .block_label = labeled block the `continue` points to +passes_coroutine_on_non_closure = + attribute should be applied to closures + .label = not a closure + passes_coverage_not_fn_or_closure = attribute should be applied to a function definition or closure .label = not a function or closure diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 86b18570f376b..755f67b3f4fe0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -20,13 +20,13 @@ use rustc_hir::{ TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID, }; use rustc_macros::LintDiagnostic; -use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, @@ -239,7 +239,59 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - _ => {} + [sym::coroutine] => { + self.check_coroutine(attr, target); + } + [ + // ok + sym::allow + | sym::expect + | sym::warn + | sym::deny + | sym::forbid + | sym::cfg + // need to be fixed + | sym::cfi_encoding // FIXME(cfi_encoding) + | sym::may_dangle // FIXME(dropck_eyepatch) + | sym::pointee // FIXME(derive_smart_pointer) + | sym::linkage // FIXME(linkage) + | sym::no_sanitize // FIXME(no_sanitize) + | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) + | sym::used // handled elsewhere to restrict to static items + | sym::repr // handled elsewhere to restrict to type decls items + | sym::instruction_set // broken on stable!!! + | sym::windows_subsystem // broken on stable!!! + | sym::patchable_function_entry // FIXME(patchable_function_entry) + | sym::deprecated_safe // FIXME(deprecated_safe) + // internal + | sym::prelude_import + | sym::panic_handler + | sym::allow_internal_unsafe + | sym::fundamental + | sym::lang + | sym::needs_allocator + | sym::default_lib_allocator + | sym::start + | sym::custom_mir, + ] => {} + [name, ..] => { + match BUILTIN_ATTRIBUTE_MAP.get(name) { + // checked below + Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} + Some(_) => { + // FIXME: differentiate between unstable and internal attributes just like we do with features instead + // of just accepting `rustc_` attributes by name. That should allow trimming the above list, too. + if !name.as_str().starts_with("rustc_") { + span_bug!( + attr.span, + "builtin attribute {name:?} not handled by `CheckAttrVisitor`" + ) + } + } + None => (), + } + } + [] => unreachable!(), } let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); @@ -376,6 +428,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks that `#[optimize(..)]` is applied to a function/closure/method, /// or to an impl block or module. + // FIXME(#128488): this should probably be elevated to an error? fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) { match target { Target::Fn @@ -2279,6 +2332,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.abort.set(true); } } + + fn check_coroutine(&self, attr: &Attribute, target: Target) { + match target { + Target::Closure => return, + _ => { + self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr.span }); + } + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c4f3c8a0d6cf3..36dfc40e7628b 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -636,6 +636,13 @@ pub struct Confusables { pub attr_span: Span, } +#[derive(Diagnostic)] +#[diag(passes_coroutine_on_non_closure)] +pub struct CoroutineOnNonClosure { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_empty_confusables)] pub(crate) struct EmptyConfusables { From 33cb33441de5086e5daa2d951619c279fc394681 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 1 Aug 2024 10:03:10 +0000 Subject: [PATCH 410/489] Add test for `coroutine` attribute --- tests/ui/coroutine/invalid_attr_usage.rs | 11 +++++++++++ tests/ui/coroutine/invalid_attr_usage.stderr | 14 ++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/ui/coroutine/invalid_attr_usage.rs create mode 100644 tests/ui/coroutine/invalid_attr_usage.stderr diff --git a/tests/ui/coroutine/invalid_attr_usage.rs b/tests/ui/coroutine/invalid_attr_usage.rs new file mode 100644 index 0000000000000..995a3aa3100fc --- /dev/null +++ b/tests/ui/coroutine/invalid_attr_usage.rs @@ -0,0 +1,11 @@ +//! The `coroutine` attribute is only allowed on closures. + +#![feature(coroutines)] + +#[coroutine] +//~^ ERROR: attribute should be applied to closures +struct Foo; + +#[coroutine] +//~^ ERROR: attribute should be applied to closures +fn main() {} diff --git a/tests/ui/coroutine/invalid_attr_usage.stderr b/tests/ui/coroutine/invalid_attr_usage.stderr new file mode 100644 index 0000000000000..316a0117e5d41 --- /dev/null +++ b/tests/ui/coroutine/invalid_attr_usage.stderr @@ -0,0 +1,14 @@ +error: attribute should be applied to closures + --> $DIR/invalid_attr_usage.rs:5:1 + | +LL | #[coroutine] + | ^^^^^^^^^^^^ + +error: attribute should be applied to closures + --> $DIR/invalid_attr_usage.rs:9:1 + | +LL | #[coroutine] + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 8b9d7b1489ddd90a69820b6b4f146a79351e850d Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 4 Jul 2024 12:43:37 +0800 Subject: [PATCH 411/489] Simplify match based on the cast result of `IntToInt`. --- Cargo.lock | 1 + compiler/rustc_mir_transform/Cargo.toml | 1 + .../rustc_mir_transform/src/match_branches.rs | 141 +++-- ...h_i128_u128.MatchBranchSimplification.diff | 61 +- ...atch_i16_i8.MatchBranchSimplification.diff | 37 -- ...atch_i8_i16.MatchBranchSimplification.diff | 37 -- ..._i16_failed.MatchBranchSimplification.diff | 37 -- ...sext_i8_i16.MatchBranchSimplification.diff | 52 ++ ..._i16_failed.MatchBranchSimplification.diff | 47 ++ ...sext_i8_u16.MatchBranchSimplification.diff | 52 ++ ..._u16_failed.MatchBranchSimplification.diff | 47 ++ ...runc_i16_i8.MatchBranchSimplification.diff | 77 +++ ...6_i8_failed.MatchBranchSimplification.diff | 72 +++ ...runc_i16_u8.MatchBranchSimplification.diff | 77 +++ ...6_u8_failed.MatchBranchSimplification.diff | 72 +++ ...runc_u16_i8.MatchBranchSimplification.diff | 67 ++ ...6_i8_failed.MatchBranchSimplification.diff | 62 ++ ...runc_u16_u8.MatchBranchSimplification.diff | 67 ++ ...6_u8_failed.MatchBranchSimplification.diff | 62 ++ ...atch_u8_i16.MatchBranchSimplification.diff | 32 - ...ch_u8_i16_2.MatchBranchSimplification.diff | 26 - ..._i16_failed.MatchBranchSimplification.diff | 32 - ...16_fallback.MatchBranchSimplification.diff | 31 - ...match_u8_i8.MatchBranchSimplification.diff | 47 ++ ...tch_u8_i8_2.MatchBranchSimplification.diff | 80 +++ ...i8_2_failed.MatchBranchSimplification.diff | 74 +++ ...8_i8_failed.MatchBranchSimplification.diff | 42 ++ ...ailed_len_1.MatchBranchSimplification.diff | 42 ++ ...ailed_len_2.MatchBranchSimplification.diff | 42 ++ ...i8_fallback.MatchBranchSimplification.diff | 38 ++ ...atch_u8_u16.MatchBranchSimplification.diff | 37 -- ...ch_u8_u16_2.MatchBranchSimplification.diff | 37 -- ...zext_u8_i16.MatchBranchSimplification.diff | 47 ++ ..._i16_failed.MatchBranchSimplification.diff | 42 ++ ...zext_u8_u16.MatchBranchSimplification.diff | 47 ++ ..._u16_failed.MatchBranchSimplification.diff | 42 ++ tests/mir-opt/matches_reduce_branches.rs | 579 +++++++++++++++--- ...stive_match.MatchBranchSimplification.diff | 41 +- ...ve_match_i8.MatchBranchSimplification.diff | 41 +- tests/mir-opt/matches_u8.rs | 1 + 40 files changed, 1937 insertions(+), 532 deletions(-) delete mode 100644 tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff delete mode 100644 tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff create mode 100644 tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff diff --git a/Cargo.lock b/Cargo.lock index 316926e584e23..0b5aa7db3190c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4346,6 +4346,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", + "rustc_type_ir", "smallvec", "tracing", ] diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index f864a13a31bbc..07ca51a67aefb 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -25,6 +25,7 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } +rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index df4f3ccb9b5b8..68000fe0ef889 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -3,8 +3,10 @@ use std::iter; use rustc_index::IndexSlice; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::*; +use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt}; -use rustc_target::abi::Size; +use rustc_target::abi::Integer; +use rustc_type_ir::TyKind::*; use super::simplify::simplify_cfg; @@ -264,33 +266,56 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf { } } +/// Check if the cast constant using `IntToInt` is equal to the target constant. +fn can_cast( + tcx: TyCtxt<'_>, + src_val: impl Into, + src_layout: TyAndLayout<'_>, + cast_ty: Ty<'_>, + target_scalar: ScalarInt, +) -> bool { + let from_scalar = ScalarInt::try_from_uint(src_val.into(), src_layout.size).unwrap(); + let v = match src_layout.ty.kind() { + Uint(_) => from_scalar.to_uint(src_layout.size), + Int(_) => from_scalar.to_int(src_layout.size) as u128, + _ => unreachable!("invalid int"), + }; + let size = match *cast_ty.kind() { + Int(t) => Integer::from_int_ty(&tcx, t).size(), + Uint(t) => Integer::from_uint_ty(&tcx, t).size(), + _ => unreachable!("invalid int"), + }; + let v = size.truncate(v); + let cast_scalar = ScalarInt::try_from_uint(v, size).unwrap(); + cast_scalar == target_scalar +} + #[derive(Default)] struct SimplifyToExp { - transfrom_types: Vec, + transfrom_kinds: Vec, } #[derive(Clone, Copy)] -enum CompareType<'tcx, 'a> { +enum ExpectedTransformKind<'tcx, 'a> { /// Identical statements. Same(&'a StatementKind<'tcx>), /// Assignment statements have the same value. - Eq(&'a Place<'tcx>, Ty<'tcx>, ScalarInt), + SameByEq { place: &'a Place<'tcx>, ty: Ty<'tcx>, scalar: ScalarInt }, /// Enum variant comparison type. - Discr { place: &'a Place<'tcx>, ty: Ty<'tcx>, is_signed: bool }, + Cast { place: &'a Place<'tcx>, ty: Ty<'tcx> }, } -enum TransfromType { +enum TransfromKind { Same, - Eq, - Discr, + Cast, } -impl From> for TransfromType { - fn from(compare_type: CompareType<'_, '_>) -> Self { +impl From> for TransfromKind { + fn from(compare_type: ExpectedTransformKind<'_, '_>) -> Self { match compare_type { - CompareType::Same(_) => TransfromType::Same, - CompareType::Eq(_, _, _) => TransfromType::Eq, - CompareType::Discr { .. } => TransfromType::Discr, + ExpectedTransformKind::Same(_) => TransfromKind::Same, + ExpectedTransformKind::SameByEq { .. } => TransfromKind::Same, + ExpectedTransformKind::Cast { .. } => TransfromKind::Cast, } } } @@ -354,7 +379,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } let mut target_iter = targets.iter(); - let (first_val, first_target) = target_iter.next().unwrap(); + let (first_case_val, first_target) = target_iter.next().unwrap(); let first_terminator_kind = &bbs[first_target].terminator().kind; // Check that destinations are identical, and if not, then don't optimize this block if !targets @@ -364,24 +389,20 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { return None; } - let discr_size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size; + let discr_layout = tcx.layout_of(param_env.and(discr_ty)).unwrap(); let first_stmts = &bbs[first_target].statements; - let (second_val, second_target) = target_iter.next().unwrap(); + let (second_case_val, second_target) = target_iter.next().unwrap(); let second_stmts = &bbs[second_target].statements; if first_stmts.len() != second_stmts.len() { return None; } - fn int_equal(l: ScalarInt, r: impl Into, size: Size) -> bool { - l.to_bits_unchecked() == ScalarInt::try_from_uint(r, size).unwrap().to_bits_unchecked() - } - // We first compare the two branches, and then the other branches need to fulfill the same conditions. - let mut compare_types = Vec::new(); + let mut expected_transform_kinds = Vec::new(); for (f, s) in iter::zip(first_stmts, second_stmts) { let compare_type = match (&f.kind, &s.kind) { // If two statements are exactly the same, we can optimize. - (f_s, s_s) if f_s == s_s => CompareType::Same(f_s), + (f_s, s_s) if f_s == s_s => ExpectedTransformKind::Same(f_s), // If two statements are assignments with the match values to the same place, we can optimize. ( @@ -395,22 +416,29 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { f_c.const_.try_eval_scalar_int(tcx, param_env), s_c.const_.try_eval_scalar_int(tcx, param_env), ) { - (Some(f), Some(s)) if f == s => CompareType::Eq(lhs_f, f_c.const_.ty(), f), - // Enum variants can also be simplified to an assignment statement if their values are equal. - // We need to consider both unsigned and signed scenarios here. + (Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq { + place: lhs_f, + ty: f_c.const_.ty(), + scalar: f, + }, + // Enum variants can also be simplified to an assignment statement, + // if we can use `IntToInt` cast to get an equal value. (Some(f), Some(s)) - if ((f_c.const_.ty().is_signed() || discr_ty.is_signed()) - && int_equal(f, first_val, discr_size) - && int_equal(s, second_val, discr_size)) - || (Some(f) == ScalarInt::try_from_uint(first_val, f.size()) - && Some(s) - == ScalarInt::try_from_uint(second_val, s.size())) => + if (can_cast( + tcx, + first_case_val, + discr_layout, + f_c.const_.ty(), + f, + ) && can_cast( + tcx, + second_case_val, + discr_layout, + f_c.const_.ty(), + s, + )) => { - CompareType::Discr { - place: lhs_f, - ty: f_c.const_.ty(), - is_signed: f_c.const_.ty().is_signed() || discr_ty.is_signed(), - } + ExpectedTransformKind::Cast { place: lhs_f, ty: f_c.const_.ty() } } _ => { return None; @@ -421,47 +449,36 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { // Otherwise we cannot optimize. Try another block. _ => return None, }; - compare_types.push(compare_type); + expected_transform_kinds.push(compare_type); } // All remaining BBs need to fulfill the same pattern as the two BBs from the previous step. for (other_val, other_target) in target_iter { let other_stmts = &bbs[other_target].statements; - if compare_types.len() != other_stmts.len() { + if expected_transform_kinds.len() != other_stmts.len() { return None; } - for (f, s) in iter::zip(&compare_types, other_stmts) { + for (f, s) in iter::zip(&expected_transform_kinds, other_stmts) { match (*f, &s.kind) { - (CompareType::Same(f_s), s_s) if f_s == s_s => {} + (ExpectedTransformKind::Same(f_s), s_s) if f_s == s_s => {} ( - CompareType::Eq(lhs_f, f_ty, val), + ExpectedTransformKind::SameByEq { place: lhs_f, ty: f_ty, scalar }, StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty - && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(val) => {} + && s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {} ( - CompareType::Discr { place: lhs_f, ty: f_ty, is_signed }, + ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty }, StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), - ) if lhs_f == lhs_s && s_c.const_.ty() == f_ty => { - let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) else { - return None; - }; - if is_signed - && s_c.const_.ty().is_signed() - && int_equal(f, other_val, discr_size) - { - continue; - } - if Some(f) == ScalarInt::try_from_uint(other_val, f.size()) { - continue; - } - return None; - } + ) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env) + && lhs_f == lhs_s + && s_c.const_.ty() == f_ty + && can_cast(tcx, other_val, discr_layout, f_ty, f) => {} _ => return None, } } } - self.transfrom_types = compare_types.into_iter().map(|c| c.into()).collect(); + self.transfrom_kinds = expected_transform_kinds.into_iter().map(|c| c.into()).collect(); Some(()) } @@ -479,13 +496,13 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp { let (_, first) = targets.iter().next().unwrap(); let first = &bbs[first]; - for (t, s) in iter::zip(&self.transfrom_types, &first.statements) { + for (t, s) in iter::zip(&self.transfrom_kinds, &first.statements) { match (t, &s.kind) { - (TransfromType::Same, _) | (TransfromType::Eq, _) => { + (TransfromKind::Same, _) => { patch.add_statement(parent_end, s.kind.clone()); } ( - TransfromType::Discr, + TransfromKind::Cast, StatementKind::Assign(box (lhs, Rvalue::Use(Operand::Constant(f_c)))), ) => { let operand = Operand::Copy(Place::from(discr_local)); diff --git a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff index dc50ae9547255..fc34ce7125ec2 100644 --- a/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff @@ -5,37 +5,42 @@ debug i => _1; let mut _0: u128; let mut _2: i128; ++ let mut _3: i128; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [1: bb5, 2: bb4, 3: bb3, 340282366920938463463374607431768211455: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const core::num::::MAX; - goto -> bb6; - } - - bb3: { - _0 = const 3_u128; - goto -> bb6; - } - - bb4: { - _0 = const 2_u128; - goto -> bb6; - } - - bb5: { - _0 = const 1_u128; - goto -> bb6; - } - - bb6: { +- switchInt(move _2) -> [1: bb5, 2: bb4, 3: bb3, 340282366920938463463374607431768211455: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const core::num::::MAX; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const 3_u128; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const 2_u128; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 1_u128; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u128 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff deleted file mode 100644 index 3514914b8ecb0..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_i16_i8` before MatchBranchSimplification -+ // MIR for `match_i16_i8` after MatchBranchSimplification - - fn match_i16_i8(_1: EnumAi16) -> i8 { - debug i => _1; - let mut _0: i8; - let mut _2: i16; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [65535: bb4, 2: bb3, 65533: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const -3_i8; - goto -> bb5; - } - - bb3: { - _0 = const 2_i8; - goto -> bb5; - } - - bb4: { - _0 = const -1_i8; - goto -> bb5; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff deleted file mode 100644 index ff4255ec8cc97..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_i8_i16` before MatchBranchSimplification -+ // MIR for `match_i8_i16` after MatchBranchSimplification - - fn match_i8_i16(_1: EnumAi8) -> i16 { - debug i => _1; - let mut _0: i16; - let mut _2: i8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [255: bb4, 2: bb3, 253: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const -3_i16; - goto -> bb5; - } - - bb3: { - _0 = const 2_i16; - goto -> bb5; - } - - bb4: { - _0 = const -1_i16; - goto -> bb5; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff deleted file mode 100644 index 022039ecee629..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_i8_i16_failed` before MatchBranchSimplification -+ // MIR for `match_i8_i16_failed` after MatchBranchSimplification - - fn match_i8_i16_failed(_1: EnumAi8) -> i16 { - debug i => _1; - let mut _0: i16; - let mut _2: i8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [255: bb4, 2: bb3, 253: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 3_i16; - goto -> bb5; - } - - bb3: { - _0 = const 2_i16; - goto -> bb5; - } - - bb4: { - _0 = const -1_i16; - goto -> bb5; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..7f8c2ab8d3748 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff @@ -0,0 +1,52 @@ +- // MIR for `match_sext_i8_i16` before MatchBranchSimplification ++ // MIR for `match_sext_i8_i16` after MatchBranchSimplification + + fn match_sext_i8_i16(_1: EnumAi8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: i8; ++ let mut _3: i8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 127_i16; +- goto -> bb7; +- } +- +- bb3: { +- _0 = const 1_i16; +- goto -> bb7; +- } +- +- bb4: { +- _0 = const 0_i16; +- goto -> bb7; +- } +- +- bb5: { +- _0 = const -1_i16; +- goto -> bb7; +- } +- +- bb6: { +- _0 = const -128_i16; +- goto -> bb7; +- } +- +- bb7: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i16 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..94ec22932222b --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_sext_i8_i16_failed` before MatchBranchSimplification ++ // MIR for `match_sext_i8_i16_failed` after MatchBranchSimplification + + fn match_sext_i8_i16_failed(_1: EnumAi8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: i8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 127_i16; + goto -> bb7; + } + + bb3: { + _0 = const 1_i16; + goto -> bb7; + } + + bb4: { + _0 = const 0_i16; + goto -> bb7; + } + + bb5: { + _0 = const 255_i16; + goto -> bb7; + } + + bb6: { + _0 = const -128_i16; + goto -> bb7; + } + + bb7: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..86d0d0ba6cf57 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff @@ -0,0 +1,52 @@ +- // MIR for `match_sext_i8_u16` before MatchBranchSimplification ++ // MIR for `match_sext_i8_u16` after MatchBranchSimplification + + fn match_sext_i8_u16(_1: EnumAi8) -> u16 { + debug i => _1; + let mut _0: u16; + let mut _2: i8; ++ let mut _3: i8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 127_u16; +- goto -> bb7; +- } +- +- bb3: { +- _0 = const 1_u16; +- goto -> bb7; +- } +- +- bb4: { +- _0 = const 0_u16; +- goto -> bb7; +- } +- +- bb5: { +- _0 = const u16::MAX; +- goto -> bb7; +- } +- +- bb6: { +- _0 = const 65408_u16; +- goto -> bb7; +- } +- +- bb7: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u16 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..281f373bf879a --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_sext_i8_u16_failed` before MatchBranchSimplification ++ // MIR for `match_sext_i8_u16_failed` after MatchBranchSimplification + + fn match_sext_i8_u16_failed(_1: EnumAi8) -> u16 { + debug i => _1; + let mut _0: u16; + let mut _2: i8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [128: bb6, 255: bb5, 0: bb4, 1: bb3, 127: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 127_u16; + goto -> bb7; + } + + bb3: { + _0 = const 1_u16; + goto -> bb7; + } + + bb4: { + _0 = const 0_u16; + goto -> bb7; + } + + bb5: { + _0 = const 255_u16; + goto -> bb7; + } + + bb6: { + _0 = const 65408_u16; + goto -> bb7; + } + + bb7: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..d3d27be207019 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff @@ -0,0 +1,77 @@ +- // MIR for `match_trunc_i16_i8` before MatchBranchSimplification ++ // MIR for `match_trunc_i16_i8` after MatchBranchSimplification + + fn match_trunc_i16_i8(_1: EnumAi16) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: i16; ++ let mut _3: i16; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const i8::MAX; +- goto -> bb12; +- } +- +- bb3: { +- _0 = const 1_i8; +- goto -> bb12; +- } +- +- bb4: { +- _0 = const 0_i8; +- goto -> bb12; +- } +- +- bb5: { +- _0 = const -1_i8; +- goto -> bb12; +- } +- +- bb6: { +- _0 = const i8::MIN; +- goto -> bb12; +- } +- +- bb7: { +- _0 = const i8::MAX; +- goto -> bb12; +- } +- +- bb8: { +- _0 = const 1_i8; +- goto -> bb12; +- } +- +- bb9: { +- _0 = const 0_i8; +- goto -> bb12; +- } +- +- bb10: { +- _0 = const -1_i8; +- goto -> bb12; +- } +- +- bb11: { +- _0 = const i8::MIN; +- goto -> bb12; +- } +- +- bb12: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..7f663baefba5d --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff @@ -0,0 +1,72 @@ +- // MIR for `match_trunc_i16_i8_failed` before MatchBranchSimplification ++ // MIR for `match_trunc_i16_i8_failed` after MatchBranchSimplification + + fn match_trunc_i16_i8_failed(_1: EnumAi16) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: i16; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const -127_i8; + goto -> bb12; + } + + bb3: { + _0 = const 1_i8; + goto -> bb12; + } + + bb4: { + _0 = const 0_i8; + goto -> bb12; + } + + bb5: { + _0 = const -1_i8; + goto -> bb12; + } + + bb6: { + _0 = const i8::MIN; + goto -> bb12; + } + + bb7: { + _0 = const i8::MAX; + goto -> bb12; + } + + bb8: { + _0 = const 1_i8; + goto -> bb12; + } + + bb9: { + _0 = const 0_i8; + goto -> bb12; + } + + bb10: { + _0 = const -1_i8; + goto -> bb12; + } + + bb11: { + _0 = const i8::MIN; + goto -> bb12; + } + + bb12: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..5fe899148ebc5 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff @@ -0,0 +1,77 @@ +- // MIR for `match_trunc_i16_u8` before MatchBranchSimplification ++ // MIR for `match_trunc_i16_u8` after MatchBranchSimplification + + fn match_trunc_i16_u8(_1: EnumAi16) -> u8 { + debug i => _1; + let mut _0: u8; + let mut _2: i16; ++ let mut _3: i16; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 127_u8; +- goto -> bb12; +- } +- +- bb3: { +- _0 = const 1_u8; +- goto -> bb12; +- } +- +- bb4: { +- _0 = const 0_u8; +- goto -> bb12; +- } +- +- bb5: { +- _0 = const u8::MAX; +- goto -> bb12; +- } +- +- bb6: { +- _0 = const 128_u8; +- goto -> bb12; +- } +- +- bb7: { +- _0 = const 127_u8; +- goto -> bb12; +- } +- +- bb8: { +- _0 = const 1_u8; +- goto -> bb12; +- } +- +- bb9: { +- _0 = const 0_u8; +- goto -> bb12; +- } +- +- bb10: { +- _0 = const u8::MAX; +- goto -> bb12; +- } +- +- bb11: { +- _0 = const 128_u8; +- goto -> bb12; +- } +- +- bb12: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..1c0ffb30c5b5b --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff @@ -0,0 +1,72 @@ +- // MIR for `match_trunc_i16_u8_failed` before MatchBranchSimplification ++ // MIR for `match_trunc_i16_u8_failed` after MatchBranchSimplification + + fn match_trunc_i16_u8_failed(_1: EnumAi16) -> u8 { + debug i => _1; + let mut _0: u8; + let mut _2: i16; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [128: bb11, 255: bb10, 0: bb9, 1: bb8, 127: bb7, 65408: bb6, 65535: bb5, 65280: bb4, 65281: bb3, 65407: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const -127_i8 as u8 (IntToInt); + goto -> bb12; + } + + bb3: { + _0 = const 1_u8; + goto -> bb12; + } + + bb4: { + _0 = const 0_u8; + goto -> bb12; + } + + bb5: { + _0 = const u8::MAX; + goto -> bb12; + } + + bb6: { + _0 = const 128_u8; + goto -> bb12; + } + + bb7: { + _0 = const 127_u8; + goto -> bb12; + } + + bb8: { + _0 = const 1_u8; + goto -> bb12; + } + + bb9: { + _0 = const 0_u8; + goto -> bb12; + } + + bb10: { + _0 = const u8::MAX; + goto -> bb12; + } + + bb11: { + _0 = const 128_u8; + goto -> bb12; + } + + bb12: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..85f97a13cac94 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff @@ -0,0 +1,67 @@ +- // MIR for `match_trunc_u16_i8` before MatchBranchSimplification ++ // MIR for `match_trunc_u16_i8` after MatchBranchSimplification + + fn match_trunc_u16_i8(_1: EnumAu16) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u16; ++ let mut _3: u16; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const -1_i8; +- goto -> bb10; +- } +- +- bb3: { +- _0 = const i8::MIN; +- goto -> bb10; +- } +- +- bb4: { +- _0 = const i8::MAX; +- goto -> bb10; +- } +- +- bb5: { +- _0 = const 0_i8; +- goto -> bb10; +- } +- +- bb6: { +- _0 = const -1_i8; +- goto -> bb10; +- } +- +- bb7: { +- _0 = const i8::MIN; +- goto -> bb10; +- } +- +- bb8: { +- _0 = const i8::MAX; +- goto -> bb10; +- } +- +- bb9: { +- _0 = const 0_i8; +- goto -> bb10; +- } +- +- bb10: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..cf6c86a71ad95 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff @@ -0,0 +1,62 @@ +- // MIR for `match_trunc_u16_i8_failed` before MatchBranchSimplification ++ // MIR for `match_trunc_u16_i8_failed` after MatchBranchSimplification + + fn match_trunc_u16_i8_failed(_1: EnumAu16) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u16; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 1_i8; + goto -> bb10; + } + + bb3: { + _0 = const i8::MIN; + goto -> bb10; + } + + bb4: { + _0 = const i8::MAX; + goto -> bb10; + } + + bb5: { + _0 = const 0_i8; + goto -> bb10; + } + + bb6: { + _0 = const -1_i8; + goto -> bb10; + } + + bb7: { + _0 = const i8::MIN; + goto -> bb10; + } + + bb8: { + _0 = const i8::MAX; + goto -> bb10; + } + + bb9: { + _0 = const 0_i8; + goto -> bb10; + } + + bb10: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..768d838eaa6fc --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff @@ -0,0 +1,67 @@ +- // MIR for `match_trunc_u16_u8` before MatchBranchSimplification ++ // MIR for `match_trunc_u16_u8` after MatchBranchSimplification + + fn match_trunc_u16_u8(_1: EnumAu16) -> u8 { + debug i => _1; + let mut _0: u8; + let mut _2: u16; ++ let mut _3: u16; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const u8::MAX; +- goto -> bb10; +- } +- +- bb3: { +- _0 = const 128_u8; +- goto -> bb10; +- } +- +- bb4: { +- _0 = const 127_u8; +- goto -> bb10; +- } +- +- bb5: { +- _0 = const 0_u8; +- goto -> bb10; +- } +- +- bb6: { +- _0 = const u8::MAX; +- goto -> bb10; +- } +- +- bb7: { +- _0 = const 128_u8; +- goto -> bb10; +- } +- +- bb8: { +- _0 = const 127_u8; +- goto -> bb10; +- } +- +- bb9: { +- _0 = const 0_u8; +- goto -> bb10; +- } +- +- bb10: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..109e97bb578af --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff @@ -0,0 +1,62 @@ +- // MIR for `match_trunc_u16_u8_failed` before MatchBranchSimplification ++ // MIR for `match_trunc_u16_u8_failed` after MatchBranchSimplification + + fn match_trunc_u16_u8_failed(_1: EnumAu16) -> u8 { + debug i => _1; + let mut _0: u8; + let mut _2: u16; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb9, 127: bb8, 128: bb7, 255: bb6, 65280: bb5, 65407: bb4, 65408: bb3, 65535: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 127_u8; + goto -> bb10; + } + + bb3: { + _0 = const 128_u8; + goto -> bb10; + } + + bb4: { + _0 = const 127_u8; + goto -> bb10; + } + + bb5: { + _0 = const 0_u8; + goto -> bb10; + } + + bb6: { + _0 = const u8::MAX; + goto -> bb10; + } + + bb7: { + _0 = const 128_u8; + goto -> bb10; + } + + bb8: { + _0 = const 127_u8; + goto -> bb10; + } + + bb9: { + _0 = const 0_u8; + goto -> bb10; + } + + bb10: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff deleted file mode 100644 index 72ad60956ab78..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff +++ /dev/null @@ -1,32 +0,0 @@ -- // MIR for `match_u8_i16` before MatchBranchSimplification -+ // MIR for `match_u8_i16` after MatchBranchSimplification - - fn match_u8_i16(_1: EnumAu8) -> i16 { - debug i => _1; - let mut _0: i16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 2_i16; - goto -> bb4; - } - - bb3: { - _0 = const 1_i16; - goto -> bb4; - } - - bb4: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff deleted file mode 100644 index 3333cd765a891..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff +++ /dev/null @@ -1,26 +0,0 @@ -- // MIR for `match_u8_i16_2` before MatchBranchSimplification -+ // MIR for `match_u8_i16_2` after MatchBranchSimplification - - fn match_u8_i16_2(_1: EnumAu8) -> i16 { - let mut _0: i16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(_2) -> [1: bb3, 2: bb1, otherwise: bb2]; - } - - bb1: { - _0 = const 2_i16; - goto -> bb3; - } - - bb2: { - unreachable; - } - - bb3: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff deleted file mode 100644 index 6da19e46dab7f..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff +++ /dev/null @@ -1,32 +0,0 @@ -- // MIR for `match_u8_i16_failed` before MatchBranchSimplification -+ // MIR for `match_u8_i16_failed` after MatchBranchSimplification - - fn match_u8_i16_failed(_1: EnumAu8) -> i16 { - debug i => _1; - let mut _0: i16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 3_i16; - goto -> bb4; - } - - bb3: { - _0 = const 1_i16; - goto -> bb4; - } - - bb4: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff deleted file mode 100644 index 5690f17f24f65..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff +++ /dev/null @@ -1,31 +0,0 @@ -- // MIR for `match_u8_i16_fallback` before MatchBranchSimplification -+ // MIR for `match_u8_i16_fallback` after MatchBranchSimplification - - fn match_u8_i16_fallback(_1: u8) -> i16 { - debug i => _1; - let mut _0: i16; - - bb0: { - switchInt(_1) -> [1: bb3, 2: bb2, otherwise: bb1]; - } - - bb1: { - _0 = const 3_i16; - goto -> bb4; - } - - bb2: { - _0 = const 2_i16; - goto -> bb4; - } - - bb3: { - _0 = const 1_i16; - goto -> bb4; - } - - bb4: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..d63eed7c019a4 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_u8_i8` before MatchBranchSimplification ++ // MIR for `match_u8_i8` after MatchBranchSimplification + + fn match_u8_i8(_1: EnumAu8) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u8; ++ let mut _3: u8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const -1_i8; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const i8::MIN; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const i8::MAX; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 0_i8; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..98dee1835a827 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff @@ -0,0 +1,80 @@ +- // MIR for `match_u8_i8_2` before MatchBranchSimplification ++ // MIR for `match_u8_i8_2` after MatchBranchSimplification + + fn match_u8_i8_2(_1: EnumAu8) -> (i8, i8) { + debug i => _1; + let mut _0: (i8, i8); + let _2: i8; + let _4: (); + let mut _5: u8; + let mut _6: i8; + let mut _7: i8; ++ let mut _8: u8; + scope 1 { + debug a => _2; + let _3: i8; + scope 2 { + debug b => _3; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _5 = discriminant(_1); +- switchInt(move _5) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _2 = const -1_i8; +- _3 = const -1_i8; ++ StorageLive(_8); ++ _8 = move _5; ++ _2 = _8 as i8 (IntToInt); ++ _3 = _8 as i8 (IntToInt); + _4 = (); +- goto -> bb6; +- } +- +- bb3: { +- _2 = const i8::MIN; +- _3 = const i8::MIN; +- _4 = (); +- goto -> bb6; +- } +- +- bb4: { +- _2 = const i8::MAX; +- _3 = const i8::MAX; +- _4 = (); +- goto -> bb6; +- } +- +- bb5: { +- _2 = const 0_i8; +- _3 = const 0_i8; +- _4 = (); +- goto -> bb6; +- } +- +- bb6: { ++ StorageDead(_8); + StorageDead(_4); + StorageLive(_6); + _6 = _2; + StorageLive(_7); + _7 = _3; + _0 = (move _6, move _7); + StorageDead(_7); + StorageDead(_6); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..901dda5861775 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff @@ -0,0 +1,74 @@ +- // MIR for `match_u8_i8_2_failed` before MatchBranchSimplification ++ // MIR for `match_u8_i8_2_failed` after MatchBranchSimplification + + fn match_u8_i8_2_failed(_1: EnumAu8) -> (i8, i8) { + debug i => _1; + let mut _0: (i8, i8); + let _2: i8; + let _4: (); + let mut _5: u8; + let mut _6: i8; + let mut _7: i8; + scope 1 { + debug a => _2; + let _3: i8; + scope 2 { + debug b => _3; + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _5 = discriminant(_1); + switchInt(move _5) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _2 = const -1_i8; + _3 = const 1_i8; + _4 = (); + goto -> bb6; + } + + bb3: { + _2 = const i8::MIN; + _3 = const i8::MIN; + _4 = (); + goto -> bb6; + } + + bb4: { + _2 = const i8::MAX; + _3 = const i8::MAX; + _4 = (); + goto -> bb6; + } + + bb5: { + _2 = const 0_i8; + _3 = const 0_i8; + _4 = (); + goto -> bb6; + } + + bb6: { + StorageDead(_4); + StorageLive(_6); + _6 = _2; + StorageLive(_7); + _7 = _3; + _0 = (move _6, move _7); + StorageDead(_7); + StorageDead(_6); + StorageDead(_3); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..ac96be5531270 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_u8_i8_failed` before MatchBranchSimplification ++ // MIR for `match_u8_i8_failed` after MatchBranchSimplification + + fn match_u8_i8_failed(_1: EnumAu8) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 1_i8; + goto -> bb6; + } + + bb3: { + _0 = const i8::MIN; + goto -> bb6; + } + + bb4: { + _0 = const i8::MAX; + goto -> bb6; + } + + bb5: { + _0 = const 0_i8; + goto -> bb6; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..9ebf2cf27cbf7 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_u8_i8_failed_len_1` before MatchBranchSimplification ++ // MIR for `match_u8_i8_failed_len_1` after MatchBranchSimplification + + fn match_u8_i8_failed_len_1(_1: EnumAu8) -> i8 { + let mut _0: i8; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(_2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5]; + } + + bb1: { + _0 = const 0_i8; + goto -> bb6; + } + + bb2: { + _0 = const i8::MAX; + _0 = const i8::MAX; + goto -> bb6; + } + + bb3: { + _0 = const i8::MIN; + goto -> bb6; + } + + bb4: { + _0 = const -1_i8; + goto -> bb6; + } + + bb5: { + unreachable; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..554856777eb6e --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_u8_i8_failed_len_2` before MatchBranchSimplification ++ // MIR for `match_u8_i8_failed_len_2` after MatchBranchSimplification + + fn match_u8_i8_failed_len_2(_1: EnumAu8) -> i8 { + let mut _0: i8; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(_2) -> [0: bb1, 127: bb2, 128: bb3, 255: bb4, otherwise: bb5]; + } + + bb1: { + _0 = const 0_i8; + goto -> bb6; + } + + bb2: { + _0 = const i8::MAX; + goto -> bb6; + } + + bb3: { + _0 = const i8::MIN; + goto -> bb6; + } + + bb4: { + _0 = const -1_i8; + _0 = const -1_i8; + goto -> bb6; + } + + bb5: { + unreachable; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..356655021f7f2 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff @@ -0,0 +1,38 @@ +- // MIR for `match_u8_i8_fallback` before MatchBranchSimplification ++ // MIR for `match_u8_i8_fallback` after MatchBranchSimplification + + fn match_u8_i8_fallback(_1: EnumAu8) -> i8 { + debug i => _1; + let mut _0: i8; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb4, 127: bb3, 128: bb2, otherwise: bb1]; + } + + bb1: { + _0 = const -1_i8; + goto -> bb5; + } + + bb2: { + _0 = const i8::MIN; + goto -> bb5; + } + + bb3: { + _0 = const i8::MAX; + goto -> bb5; + } + + bb4: { + _0 = const 0_i8; + goto -> bb5; + } + + bb5: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff deleted file mode 100644 index dc9c1c2b97f1f..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_u8_u16` before MatchBranchSimplification -+ // MIR for `match_u8_u16` after MatchBranchSimplification - - fn match_u8_u16(_1: EnumBu8) -> u16 { - debug i => _1; - let mut _0: u16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(move _2) -> [1: bb4, 2: bb3, 5: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 5_u16; - goto -> bb5; - } - - bb3: { - _0 = const 2_u16; - goto -> bb5; - } - - bb4: { - _0 = const 1_u16; - goto -> bb5; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff deleted file mode 100644 index b47de6a52b77f..0000000000000 --- a/tests/mir-opt/matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff +++ /dev/null @@ -1,37 +0,0 @@ -- // MIR for `match_u8_u16_2` before MatchBranchSimplification -+ // MIR for `match_u8_u16_2` after MatchBranchSimplification - - fn match_u8_u16_2(_1: EnumBu8) -> i16 { - let mut _0: i16; - let mut _2: u8; - - bb0: { - _2 = discriminant(_1); - switchInt(_2) -> [1: bb1, 2: bb2, 5: bb3, otherwise: bb4]; - } - - bb1: { - _0 = const 1_i16; - goto -> bb5; - } - - bb2: { - _0 = const 2_i16; - goto -> bb5; - } - - bb3: { - _0 = const 5_i16; - _0 = const 5_i16; - goto -> bb5; - } - - bb4: { - unreachable; - } - - bb5: { - return; - } - } - diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..e00a604fe25da --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_zext_u8_i16` before MatchBranchSimplification ++ // MIR for `match_zext_u8_i16` after MatchBranchSimplification + + fn match_zext_u8_i16(_1: EnumAu8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: u8; ++ let mut _3: u8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 255_i16; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const 128_i16; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const 127_i16; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 0_i16; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i16 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..a19cd796c275d --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_zext_u8_i16_failed` before MatchBranchSimplification ++ // MIR for `match_zext_u8_i16_failed` after MatchBranchSimplification + + fn match_zext_u8_i16_failed(_1: EnumAu8) -> i16 { + debug i => _1; + let mut _0: i16; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 255_i16; + goto -> bb6; + } + + bb3: { + _0 = const 128_i16; + goto -> bb6; + } + + bb4: { + _0 = const -127_i16; + goto -> bb6; + } + + bb5: { + _0 = const 0_i16; + goto -> bb6; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..befb9118907b4 --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff @@ -0,0 +1,47 @@ +- // MIR for `match_zext_u8_u16` before MatchBranchSimplification ++ // MIR for `match_zext_u8_u16` after MatchBranchSimplification + + fn match_zext_u8_u16(_1: EnumAu8) -> u16 { + debug i => _1; + let mut _0: u16; + let mut _2: u8; ++ let mut _3: u8; + + bb0: { + _2 = discriminant(_1); +- switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 255_u16; +- goto -> bb6; +- } +- +- bb3: { +- _0 = const 128_u16; +- goto -> bb6; +- } +- +- bb4: { +- _0 = const 127_u16; +- goto -> bb6; +- } +- +- bb5: { +- _0 = const 0_u16; +- goto -> bb6; +- } +- +- bb6: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u16 (IntToInt); ++ StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..f781f88449d1d --- /dev/null +++ b/tests/mir-opt/matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff @@ -0,0 +1,42 @@ +- // MIR for `match_zext_u8_u16_failed` before MatchBranchSimplification ++ // MIR for `match_zext_u8_u16_failed` after MatchBranchSimplification + + fn match_zext_u8_u16_failed(_1: EnumAu8) -> u16 { + debug i => _1; + let mut _0: u16; + let mut _2: u8; + + bb0: { + _2 = discriminant(_1); + switchInt(move _2) -> [0: bb5, 127: bb4, 128: bb3, 255: bb2, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + _0 = const 255_u16; + goto -> bb6; + } + + bb3: { + _0 = const 128_u16; + goto -> bb6; + } + + bb4: { + _0 = const 65407_u16; + goto -> bb6; + } + + bb5: { + _0 = const 0_u16; + goto -> bb6; + } + + bb6: { + return; + } + } + diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs index 176d68bcd4019..9328c616127a8 100644 --- a/tests/mir-opt/matches_reduce_branches.rs +++ b/tests/mir-opt/matches_reduce_branches.rs @@ -1,8 +1,10 @@ //@ test-mir-pass: MatchBranchSimplification +//@ compile-flags: -Zunsound-mir-opts #![feature(repr128)] #![feature(core_intrinsics)] #![feature(custom_mir)] +#![allow(non_camel_case_types)] use std::intrinsics::mir::*; @@ -12,6 +14,7 @@ fn foo(bar: Option<()>) { // CHECK: = Eq( // CHECK: switchInt // CHECK-NOT: switchInt + // CHECK: return if matches!(bar, None) { () } @@ -23,6 +26,7 @@ fn bar(i: i32) -> (bool, bool, bool, bool) { // CHECK: = Ne( // CHECK: = Eq( // CHECK-NOT: switchInt + // CHECK: return let a; let b; let c; @@ -52,6 +56,7 @@ fn bar(i: i32) -> (bool, bool, bool, bool) { fn match_nested_if() -> bool { // CHECK-LABEL: fn match_nested_if( // CHECK-NOT: switchInt + // CHECK: return let val = match () { () if if if if true { true } else { false } { true } else { false } { true @@ -66,42 +71,170 @@ fn match_nested_if() -> bool { val } +// # Fold switchInt into IntToInt. +// To simplify writing and checking these test cases, I use the first character of +// each case to distinguish the sign of the number: +// 'u' for unsigned, '_' for negative, and 'o' for non-negative. +// Followed by a decimal number, and add the corresponding radix representation. +// For example, o127_0x7f represents 127i8, and _1_0xff represents -1i8. + +// ## Cast but without numeric conversion. + #[repr(u8)] enum EnumAu8 { - A = 1, - B = 2, + u0_0x00 = 0, + u127_0x7f = 127, + u128_0x80 = 128, + u255_0xff = 255, +} + +#[repr(i8)] +enum EnumAi8 { + _128_0x80 = -128, + _1_0xff = -1, + o0_0x00 = 0, + o1_0x01 = 1, + o127_0x7f = 127, } -// EMIT_MIR matches_reduce_branches.match_u8_i16.MatchBranchSimplification.diff -fn match_u8_i16(i: EnumAu8) -> i16 { - // CHECK-LABEL: fn match_u8_i16( +// EMIT_MIR matches_reduce_branches.match_u8_i8.MatchBranchSimplification.diff +fn match_u8_i8(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8( + // CHECK-NOT: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 127, + EnumAu8::u128_0x80 => -128, + EnumAu8::u255_0xff => -1, + } +} + +// EMIT_MIR matches_reduce_branches.match_u8_i8_failed.MatchBranchSimplification.diff +fn match_u8_i8_failed(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8_failed( // CHECK: switchInt + // CHECK: return match i { - EnumAu8::A => 1, - EnumAu8::B => 2, + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 127, + EnumAu8::u128_0x80 => -128, + EnumAu8::u255_0xff => 1, // failed } } -// EMIT_MIR matches_reduce_branches.match_u8_i16_2.MatchBranchSimplification.diff +// EMIT_MIR matches_reduce_branches.match_u8_i8_2.MatchBranchSimplification.diff +fn match_u8_i8_2(i: EnumAu8) -> (i8, i8) { + // CHECK-LABEL: fn match_u8_i8_2( + // CHECK-NOT: switchInt + // CHECK: IntToInt + // CHECK: IntToInt + // CHECK: return + let a: i8; + let b: i8; + match i { + EnumAu8::u0_0x00 => { + a = 0; + b = 0; + () + } + EnumAu8::u127_0x7f => { + a = 127; + b = 127; + () + } + EnumAu8::u128_0x80 => { + a = -128; + b = -128; + () + } + EnumAu8::u255_0xff => { + a = -1; + b = -1; + () + } + }; + (a, b) +} + +// EMIT_MIR matches_reduce_branches.match_u8_i8_2_failed.MatchBranchSimplification.diff +fn match_u8_i8_2_failed(i: EnumAu8) -> (i8, i8) { + // CHECK-LABEL: fn match_u8_i8_2_failed( + // CHECK: switchInt + // CHECK: return + let a: i8; + let b: i8; + match i { + EnumAu8::u0_0x00 => { + a = 0; + b = 0; + () + } + EnumAu8::u127_0x7f => { + a = 127; + b = 127; + () + } + EnumAu8::u128_0x80 => { + a = -128; + b = -128; + () + } + EnumAu8::u255_0xff => { + a = -1; + b = 1; // failed + () + } + }; + (a, b) +} + +// EMIT_MIR matches_reduce_branches.match_u8_i8_fallback.MatchBranchSimplification.diff +fn match_u8_i8_fallback(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8_fallback( + // CHECK: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 127, + EnumAu8::u128_0x80 => -128, + _ => -1, + } +} + +// EMIT_MIR matches_reduce_branches.match_u8_i8_failed_len_1.MatchBranchSimplification.diff // Check for different instruction lengths #[custom_mir(dialect = "built")] -fn match_u8_i16_2(i: EnumAu8) -> i16 { - // CHECK-LABEL: fn match_u8_i16_2( +fn match_u8_i8_failed_len_1(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8_failed_len_1( // CHECK: switchInt + // CHECK: return mir! { { let a = Discriminant(i); match a { - 1 => bb1, - 2 => bb2, + 0 => bb1, + 127 => bb2, + 128 => bb3, + 255 => bb4, _ => unreachable_bb, } } bb1 = { + RET = 0; Goto(ret) } bb2 = { - RET = 2; + RET = 127; + RET = 127; + Goto(ret) + } + bb3 = { + RET = -128; + Goto(ret) + } + bb4 = { + RET = -1; Goto(ret) } unreachable_bb = { @@ -113,72 +246,39 @@ fn match_u8_i16_2(i: EnumAu8) -> i16 { } } -// EMIT_MIR matches_reduce_branches.match_u8_i16_failed.MatchBranchSimplification.diff -fn match_u8_i16_failed(i: EnumAu8) -> i16 { - // CHECK-LABEL: fn match_u8_i16_failed( - // CHECK: switchInt - match i { - EnumAu8::A => 1, - EnumAu8::B => 3, - } -} - -// EMIT_MIR matches_reduce_branches.match_u8_i16_fallback.MatchBranchSimplification.diff -fn match_u8_i16_fallback(i: u8) -> i16 { - // CHECK-LABEL: fn match_u8_i16_fallback( - // CHECK: switchInt - match i { - 1 => 1, - 2 => 2, - _ => 3, - } -} - -#[repr(u8)] -enum EnumBu8 { - A = 1, - B = 2, - C = 5, -} - -// EMIT_MIR matches_reduce_branches.match_u8_u16.MatchBranchSimplification.diff -fn match_u8_u16(i: EnumBu8) -> u16 { - // CHECK-LABEL: fn match_u8_u16( - // CHECK: switchInt - match i { - EnumBu8::A => 1, - EnumBu8::B => 2, - EnumBu8::C => 5, - } -} - -// EMIT_MIR matches_reduce_branches.match_u8_u16_2.MatchBranchSimplification.diff +// EMIT_MIR matches_reduce_branches.match_u8_i8_failed_len_2.MatchBranchSimplification.diff // Check for different instruction lengths #[custom_mir(dialect = "built")] -fn match_u8_u16_2(i: EnumBu8) -> i16 { - // CHECK-LABEL: fn match_u8_u16_2( +fn match_u8_i8_failed_len_2(i: EnumAu8) -> i8 { + // CHECK-LABEL: fn match_u8_i8_failed_len_2( // CHECK: switchInt + // CHECK: return mir! { { let a = Discriminant(i); match a { - 1 => bb1, - 2 => bb2, - 5 => bb5, + 0 => bb1, + 127 => bb2, + 128 => bb3, + 255 => bb4, _ => unreachable_bb, } } bb1 = { - RET = 1; + RET = 0; Goto(ret) } bb2 = { - RET = 2; + RET = 127; Goto(ret) } - bb5 = { - RET = 5; - RET = 5; + bb3 = { + RET = -128; + Goto(ret) + } + bb4 = { + RET = -1; + RET = -1; Goto(ret) } unreachable_bb = { @@ -190,50 +290,309 @@ fn match_u8_u16_2(i: EnumBu8) -> i16 { } } -#[repr(i8)] -enum EnumAi8 { - A = -1, - B = 2, - C = -3, +// ## Cast with sext. + +// EMIT_MIR matches_reduce_branches.match_sext_i8_i16.MatchBranchSimplification.diff +fn match_sext_i8_i16(i: EnumAi8) -> i16 { + // CHECK-LABEL: fn match_sext_i8_i16( + // CHECK-NOT: switchInt + // CHECK: return + match i { + EnumAi8::_128_0x80 => -128, + EnumAi8::_1_0xff => -1, + EnumAi8::o0_0x00 => 0, + EnumAi8::o1_0x01 => 1, + EnumAi8::o127_0x7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_sext_i8_i16_failed.MatchBranchSimplification.diff +// Converting `-1i8` to `255i16` is zext. +fn match_sext_i8_i16_failed(i: EnumAi8) -> i16 { + // CHECK-LABEL: fn match_sext_i8_i16_failed( + // CHECK: switchInt + // CHECK: return + match i { + EnumAi8::_128_0x80 => -128, + EnumAi8::_1_0xff => 255, // failed + EnumAi8::o0_0x00 => 0, + EnumAi8::o1_0x01 => 1, + EnumAi8::o127_0x7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_sext_i8_u16.MatchBranchSimplification.diff +fn match_sext_i8_u16(i: EnumAi8) -> u16 { + // CHECK-LABEL: fn match_sext_i8_u16( + // CHECK-NOT: switchInt + // CHECK: return + match i { + EnumAi8::_128_0x80 => 0xff80, + EnumAi8::_1_0xff => 0xffff, + EnumAi8::o0_0x00 => 0, + EnumAi8::o1_0x01 => 1, + EnumAi8::o127_0x7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_sext_i8_u16_failed.MatchBranchSimplification.diff +// Converting `-1i8` to `255u16` is zext. +fn match_sext_i8_u16_failed(i: EnumAi8) -> u16 { + // CHECK-LABEL: fn match_sext_i8_u16_failed( + // CHECK: switchInt + // CHECK: return + match i { + EnumAi8::_128_0x80 => 0xff80, + EnumAi8::_1_0xff => 0x00ff, // failed + EnumAi8::o0_0x00 => 0, + EnumAi8::o1_0x01 => 1, + EnumAi8::o127_0x7f => 127, + } +} + +// ## Cast with zext. + +// EMIT_MIR matches_reduce_branches.match_zext_u8_u16.MatchBranchSimplification.diff +fn match_zext_u8_u16(i: EnumAu8) -> u16 { + // CHECK-LABEL: fn match_zext_u8_u16( + // CHECK-NOT: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 0x7f, + EnumAu8::u128_0x80 => 128, + EnumAu8::u255_0xff => 255, + } } -// EMIT_MIR matches_reduce_branches.match_i8_i16.MatchBranchSimplification.diff -fn match_i8_i16(i: EnumAi8) -> i16 { - // CHECK-LABEL: fn match_i8_i16( +// EMIT_MIR matches_reduce_branches.match_zext_u8_u16_failed.MatchBranchSimplification.diff +fn match_zext_u8_u16_failed(i: EnumAu8) -> u16 { + // CHECK-LABEL: fn match_zext_u8_u16_failed( // CHECK: switchInt + // CHECK: return + match i { + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 0xff7f, // failed + EnumAu8::u128_0x80 => 128, + EnumAu8::u255_0xff => 255, + } +} + +// EMIT_MIR matches_reduce_branches.match_zext_u8_i16.MatchBranchSimplification.diff +fn match_zext_u8_i16(i: EnumAu8) -> i16 { + // CHECK-LABEL: fn match_zext_u8_i16( + // CHECK-NOT: switchInt + // CHECK: return match i { - EnumAi8::A => -1, - EnumAi8::B => 2, - EnumAi8::C => -3, + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => 127, + EnumAu8::u128_0x80 => 128, + EnumAu8::u255_0xff => 255, } } -// EMIT_MIR matches_reduce_branches.match_i8_i16_failed.MatchBranchSimplification.diff -fn match_i8_i16_failed(i: EnumAi8) -> i16 { - // CHECK-LABEL: fn match_i8_i16_failed( +// EMIT_MIR matches_reduce_branches.match_zext_u8_i16_failed.MatchBranchSimplification.diff +fn match_zext_u8_i16_failed(i: EnumAu8) -> i16 { + // CHECK-LABEL: fn match_zext_u8_i16_failed( // CHECK: switchInt + // CHECK: return match i { - EnumAi8::A => -1, - EnumAi8::B => 2, - EnumAi8::C => 3, + EnumAu8::u0_0x00 => 0, + EnumAu8::u127_0x7f => -127, // failed + EnumAu8::u128_0x80 => 128, + EnumAu8::u255_0xff => 255, } } +// ## Cast with trunc. + +#[repr(u16)] +enum EnumAu16 { + // 0x00nn + u0_0x0000 = 0, + u127_0x007f = 127, + u128_0x0080 = 128, + u255_0x00ff = 255, + // 0xffnn + u65280_0xff00 = 65280, + u65407_0xff7f = 65407, + u65408_0xff80 = 65408, + u65535_0xffff = 65535, +} + #[repr(i16)] enum EnumAi16 { - A = -1, - B = 2, - C = -3, + // 0x00nn + o128_0x0080 = 128, + o255_0x00ff = 255, + o0_0x0000 = 0, + o1_0x0001 = 1, + o127_0x007f = 127, + // 0xffnn + _128_0xff80 = -128, + _1_0xffff = -1, + o0_0xff00 = -256, + o1_0xff01 = -255, + o127_0xff7f = -129, } -// EMIT_MIR matches_reduce_branches.match_i16_i8.MatchBranchSimplification.diff -fn match_i16_i8(i: EnumAi16) -> i8 { - // CHECK-LABEL: fn match_i16_i8( +// EMIT_MIR matches_reduce_branches.match_trunc_i16_i8.MatchBranchSimplification.diff +fn match_trunc_i16_i8(i: EnumAi16) -> i8 { + // CHECK-LABEL: fn match_trunc_i16_i8( + // CHECK-NOT: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAi16::o128_0x0080 => -128, + EnumAi16::o255_0x00ff => -1, + EnumAi16::o0_0x0000 => 0, + EnumAi16::o1_0x0001 => 1, + EnumAi16::o127_0x007f => 127, + // 0xffnn + EnumAi16::_128_0xff80 => -128, + EnumAi16::_1_0xffff => -1, + EnumAi16::o0_0xff00 => 0, + EnumAi16::o1_0xff01 => 1, + EnumAi16::o127_0xff7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_i16_i8_failed.MatchBranchSimplification.diff +fn match_trunc_i16_i8_failed(i: EnumAi16) -> i8 { + // CHECK-LABEL: fn match_trunc_i16_i8_failed( // CHECK: switchInt + // CHECK: return match i { - EnumAi16::A => -1, - EnumAi16::B => 2, - EnumAi16::C => -3, + // 0x00nn + EnumAi16::o128_0x0080 => -128, + EnumAi16::o255_0x00ff => -1, + EnumAi16::o0_0x0000 => 0, + EnumAi16::o1_0x0001 => 1, + EnumAi16::o127_0x007f => 127, + // 0xffnn + EnumAi16::_128_0xff80 => -128, + EnumAi16::_1_0xffff => -1, + EnumAi16::o0_0xff00 => 0, + EnumAi16::o1_0xff01 => 1, + EnumAi16::o127_0xff7f => -127, // failed + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_i16_u8.MatchBranchSimplification.diff +fn match_trunc_i16_u8(i: EnumAi16) -> u8 { + // CHECK-LABEL: fn match_trunc_i16_u8( + // CHECK-NOT: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAi16::o128_0x0080 => 128, + EnumAi16::o255_0x00ff => 255, + EnumAi16::o0_0x0000 => 0, + EnumAi16::o1_0x0001 => 1, + EnumAi16::o127_0x007f => 127, + // 0xffnn + EnumAi16::_128_0xff80 => 128, + EnumAi16::_1_0xffff => 255, + EnumAi16::o0_0xff00 => 0, + EnumAi16::o1_0xff01 => 1, + EnumAi16::o127_0xff7f => 127, + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_i16_u8_failed.MatchBranchSimplification.diff +fn match_trunc_i16_u8_failed(i: EnumAi16) -> u8 { + // CHECK-LABEL: fn match_trunc_i16_u8_failed( + // CHECK: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAi16::o128_0x0080 => 128, + EnumAi16::o255_0x00ff => 255, + EnumAi16::o0_0x0000 => 0, + EnumAi16::o1_0x0001 => 1, + EnumAi16::o127_0x007f => 127, + // 0xffnn + EnumAi16::_128_0xff80 => 128, + EnumAi16::_1_0xffff => 255, + EnumAi16::o0_0xff00 => 0, + EnumAi16::o1_0xff01 => 1, + EnumAi16::o127_0xff7f => -127i8 as u8, // failed + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_u16_u8.MatchBranchSimplification.diff +fn match_trunc_u16_u8(i: EnumAu16) -> u8 { + // CHECK-LABEL: fn match_trunc_u16_u8( + // CHECK-NOT: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAu16::u0_0x0000 => 0, + EnumAu16::u127_0x007f => 127, + EnumAu16::u128_0x0080 => 128, + EnumAu16::u255_0x00ff => 255, + // 0xffnn + EnumAu16::u65280_0xff00 => 0, + EnumAu16::u65407_0xff7f => 127, + EnumAu16::u65408_0xff80 => 128, + EnumAu16::u65535_0xffff => 255, + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_u16_u8_failed.MatchBranchSimplification.diff +fn match_trunc_u16_u8_failed(i: EnumAu16) -> u8 { + // CHECK-LABEL: fn match_trunc_u16_u8_failed( + // CHECK: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAu16::u0_0x0000 => 0, + EnumAu16::u127_0x007f => 127, + EnumAu16::u128_0x0080 => 128, + EnumAu16::u255_0x00ff => 255, + // 0xffnn + EnumAu16::u65280_0xff00 => 0, + EnumAu16::u65407_0xff7f => 127, + EnumAu16::u65408_0xff80 => 128, + EnumAu16::u65535_0xffff => 127, // failed + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_u16_i8.MatchBranchSimplification.diff +fn match_trunc_u16_i8(i: EnumAu16) -> i8 { + // CHECK-LABEL: fn match_trunc_u16_i8( + // CHECK-NOT: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAu16::u0_0x0000 => 0, + EnumAu16::u127_0x007f => 127, + EnumAu16::u128_0x0080 => -128, + EnumAu16::u255_0x00ff => -1, + // 0xffnn + EnumAu16::u65280_0xff00 => 0, + EnumAu16::u65407_0xff7f => 127, + EnumAu16::u65408_0xff80 => -128, + EnumAu16::u65535_0xffff => -1, + } +} + +// EMIT_MIR matches_reduce_branches.match_trunc_u16_i8_failed.MatchBranchSimplification.diff +fn match_trunc_u16_i8_failed(i: EnumAu16) -> i8 { + // CHECK-LABEL: fn match_trunc_u16_i8_failed( + // CHECK: switchInt + // CHECK: return + match i { + // 0x00nn + EnumAu16::u0_0x0000 => 0, + EnumAu16::u127_0x007f => 127, + EnumAu16::u128_0x0080 => -128, + EnumAu16::u255_0x00ff => -1, + // 0xffnn + EnumAu16::u65280_0xff00 => 0, + EnumAu16::u65407_0xff7f => 127, + EnumAu16::u65408_0xff80 => -128, + EnumAu16::u65535_0xffff => 1, } } @@ -248,7 +607,8 @@ enum EnumAi128 { // EMIT_MIR matches_reduce_branches.match_i128_u128.MatchBranchSimplification.diff fn match_i128_u128(i: EnumAi128) -> u128 { // CHECK-LABEL: fn match_i128_u128( - // CHECK: switchInt + // CHECK-NOT: switchInt + // CHECK: return match i { EnumAi128::A => 1, EnumAi128::B => 2, @@ -262,15 +622,34 @@ fn main() { let _ = foo(Some(())); let _ = bar(0); let _ = match_nested_if(); - let _ = match_u8_i16(EnumAu8::A); - let _ = match_u8_i16_2(EnumAu8::A); - let _ = match_u8_i16_failed(EnumAu8::A); - let _ = match_u8_i16_fallback(1); - let _ = match_u8_u16(EnumBu8::A); - let _ = match_u8_u16_2(EnumBu8::A); - let _ = match_i8_i16(EnumAi8::A); - let _ = match_i8_i16_failed(EnumAi8::A); - let _ = match_i8_i16(EnumAi8::A); - let _ = match_i16_i8(EnumAi16::A); + + let _: i8 = match_u8_i8(EnumAu8::u0_0x00); + let _: i8 = match_u8_i8_failed(EnumAu8::u0_0x00); + let _: (i8, i8) = match_u8_i8_2(EnumAu8::u0_0x00); + let _: (i8, i8) = match_u8_i8_2_failed(EnumAu8::u0_0x00); + let _: i8 = match_u8_i8_fallback(EnumAu8::u0_0x00); + let _: i8 = match_u8_i8_failed_len_1(EnumAu8::u0_0x00); + let _: i8 = match_u8_i8_failed_len_2(EnumAu8::u0_0x00); + + let _: i16 = match_sext_i8_i16(EnumAi8::o0_0x00); + let _: i16 = match_sext_i8_i16_failed(EnumAi8::o0_0x00); + let _: u16 = match_sext_i8_u16(EnumAi8::o0_0x00); + let _: u16 = match_sext_i8_u16_failed(EnumAi8::o0_0x00); + + let _: u16 = match_zext_u8_u16(EnumAu8::u0_0x00); + let _: u16 = match_zext_u8_u16_failed(EnumAu8::u0_0x00); + let _: i16 = match_zext_u8_i16(EnumAu8::u0_0x00); + let _: i16 = match_zext_u8_i16_failed(EnumAu8::u0_0x00); + + let _: i8 = match_trunc_i16_i8(EnumAi16::o0_0x0000); + let _: i8 = match_trunc_i16_i8_failed(EnumAi16::o0_0x0000); + let _: u8 = match_trunc_i16_u8(EnumAi16::o0_0x0000); + let _: u8 = match_trunc_i16_u8_failed(EnumAi16::o0_0x0000); + + let _: i8 = match_trunc_u16_i8(EnumAu16::u0_0x0000); + let _: i8 = match_trunc_u16_i8_failed(EnumAu16::u0_0x0000); + let _: u8 = match_trunc_u16_u8(EnumAu16::u0_0x0000); + let _: u8 = match_trunc_u16_u8_failed(EnumAu16::u0_0x0000); + let _ = match_i128_u128(EnumAi128::A); } diff --git a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff index 157f9c98353e7..11a18f58e3a1f 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff @@ -5,27 +5,32 @@ debug e => _1; let mut _0: u8; let mut _2: isize; ++ let mut _3: isize; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 1_u8; - goto -> bb4; - } - - bb3: { - _0 = const 0_u8; - goto -> bb4; - } - - bb4: { +- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 1_u8; +- goto -> bb4; +- } +- +- bb3: { +- _0 = const 0_u8; +- goto -> bb4; +- } +- +- bb4: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as u8 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff index 19083771fd954..809badc41ba71 100644 --- a/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff +++ b/tests/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff @@ -5,27 +5,32 @@ debug e => _1; let mut _0: i8; let mut _2: isize; ++ let mut _3: isize; bb0: { _2 = discriminant(_1); - switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; - } - - bb1: { - unreachable; - } - - bb2: { - _0 = const 1_i8; - goto -> bb4; - } - - bb3: { - _0 = const 0_i8; - goto -> bb4; - } - - bb4: { +- switchInt(move _2) -> [0: bb3, 1: bb2, otherwise: bb1]; +- } +- +- bb1: { +- unreachable; +- } +- +- bb2: { +- _0 = const 1_i8; +- goto -> bb4; +- } +- +- bb3: { +- _0 = const 0_i8; +- goto -> bb4; +- } +- +- bb4: { ++ StorageLive(_3); ++ _3 = move _2; ++ _0 = _3 as i8 (IntToInt); ++ StorageDead(_3); return; } } diff --git a/tests/mir-opt/matches_u8.rs b/tests/mir-opt/matches_u8.rs index 86d6462567428..89deead461ee8 100644 --- a/tests/mir-opt/matches_u8.rs +++ b/tests/mir-opt/matches_u8.rs @@ -1,5 +1,6 @@ // skip-filecheck //@ test-mir-pass: MatchBranchSimplification +//@ compile-flags: -Zunsound-mir-opts // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff From 1f9d9603c05a1fb56825b4fc54ea28aa04485024 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 31 Jul 2024 07:58:39 +0800 Subject: [PATCH 412/489] Re-enable SimplifyToExp in match_branches. --- compiler/rustc_mir_transform/src/match_branches.rs | 5 +---- tests/mir-opt/matches_reduce_branches.rs | 1 - tests/mir-opt/matches_u8.rs | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 68000fe0ef889..47758b56f8c90 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -44,10 +44,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { should_cleanup = true; continue; } - // unsound: https://github.com/rust-lang/rust/issues/124150 - if tcx.sess.opts.unstable_opts.unsound_mir_opts - && SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() - { + if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() { should_cleanup = true; continue; } diff --git a/tests/mir-opt/matches_reduce_branches.rs b/tests/mir-opt/matches_reduce_branches.rs index 9328c616127a8..6787e5816a309 100644 --- a/tests/mir-opt/matches_reduce_branches.rs +++ b/tests/mir-opt/matches_reduce_branches.rs @@ -1,5 +1,4 @@ //@ test-mir-pass: MatchBranchSimplification -//@ compile-flags: -Zunsound-mir-opts #![feature(repr128)] #![feature(core_intrinsics)] diff --git a/tests/mir-opt/matches_u8.rs b/tests/mir-opt/matches_u8.rs index 89deead461ee8..86d6462567428 100644 --- a/tests/mir-opt/matches_u8.rs +++ b/tests/mir-opt/matches_u8.rs @@ -1,6 +1,5 @@ // skip-filecheck //@ test-mir-pass: MatchBranchSimplification -//@ compile-flags: -Zunsound-mir-opts // EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff // EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff From b0beb64830b082c78ea5f0b3d69ef2fa880728c4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Aug 2024 22:10:13 -0400 Subject: [PATCH 413/489] Use ParamEnv::reveal_all in CFI --- .../src/cfi/typeid/itanium_cxx_abi/mod.rs | 5 ++- tests/ui/sanitizer/cfi-can-reveal-opaques.rs | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/ui/sanitizer/cfi-can-reveal-opaques.rs diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs index ac664c53f4454..cb15c67b895b8 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_target::abi::call::{Conv, FnAbi, PassMode}; use tracing::instrument; @@ -112,11 +112,12 @@ pub fn typeid_for_instance<'tcx>( instance: Instance<'tcx>, options: TypeIdOptions, ) -> String { + assert!(!instance.has_non_region_param(), "{instance:#?} must be fully monomorphic"); let transform_ty_options = TransformTyOptions::from_bits(options.bits()) .unwrap_or_else(|| bug!("typeid_for_instance: invalid option(s) `{:?}`", options.bits())); let instance = transform_instance(tcx, instance, transform_ty_options); let fn_abi = tcx - .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty()))) + .fn_abi_of_instance(ty::ParamEnv::reveal_all().and((instance, ty::List::empty()))) .unwrap_or_else(|error| { bug!("typeid_for_instance: couldn't get fn_abi of instance {instance:?}: {error:?}") }); diff --git a/tests/ui/sanitizer/cfi-can-reveal-opaques.rs b/tests/ui/sanitizer/cfi-can-reveal-opaques.rs new file mode 100644 index 0000000000000..55988a62a8cdf --- /dev/null +++ b/tests/ui/sanitizer/cfi-can-reveal-opaques.rs @@ -0,0 +1,44 @@ +//@ needs-sanitizer-cfi +//@ compile-flags: -Ccodegen-units=1 -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi +//@ no-prefer-dynamic +//@ only-x86_64-unknown-linux-gnu +//@ build-pass + +// See comment below for why this test exists. + +trait Tr { + type Projection; +} + +impl Tr for F +where + F: Fn() -> U +{ + type Projection = U; +} + +fn test, U>(b: B) -> B::Projection +{ + todo!() +} + +fn main() { + fn rpit_fn() -> impl Sized {} + + // When CFI runs, it tries to compute the signature of the call. This + // ends up giving us a signature of: + // `fn test::() -> >::Projection`, + // where `rpit_fn` is the ZST FnDef for the function. However, we were + // previously using a Reveal::UserFacing param-env. This means that the + // `>::Projection` return type is impossible to normalize, + // since it would require proving `rpit_fn: Fn() -> ()`, but we cannot + // prove that the `impl Sized` opaque is `()` with a user-facing param-env. + // This leads to a normalization error, and then an ICE. + // + // Side-note: + // So why is the second generic of `test` "`()`", and not the + // `impl Sized` since we inferred it from the return type of `rpit_fn` + // during typeck? Well, that's because we're using the generics from the + // terminator of the MIR, which has had the RevealAll pass performed on it. + let _ = test(rpit_fn); +} From 6aab319def5d2861a2ba87c002d453d4ae8df38e Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 3 Aug 2024 05:03:34 +0000 Subject: [PATCH 414/489] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 950d2baabe951..f03fe70aa2149 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -05e692ae025fd4650c601e1e7ab51bdc5e19c35b +1df0458781d6fd753a68c4cdc4de5313b1635dbd From 5ce554f4ecaffe1161eaecc9111a06da3a95cc12 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 3 Aug 2024 09:31:21 +0300 Subject: [PATCH 415/489] allow setting `link-shared` and `static-libstdcpp` with CI LLVM These options also affect `compiler/rustc_llvm` builds. They should be configurable even when using CI LLVM. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 1343e257efe08..39a17754c4f6b 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1840,6 +1840,23 @@ impl Config { config.llvm_from_ci = config.parse_download_ci_llvm(download_ci_llvm, asserts); if config.llvm_from_ci { + let warn = |option: &str| { + println!( + "WARNING: `{option}` will only be used on `compiler/rustc_llvm` build, not for the LLVM build." + ); + println!( + "HELP: To use `{option}` for LLVM builds, set `download-ci-llvm` option to false." + ); + }; + + if static_libstdcpp.is_some() { + warn("static-libstdcpp"); + } + + if link_shared.is_some() { + warn("link-shared"); + } + // None of the LLVM options, except assertions, are supported // when using downloaded LLVM. We could just ignore these but // that's potentially confusing, so force them to not be @@ -1849,9 +1866,6 @@ impl Config { check_ci_llvm!(optimize_toml); check_ci_llvm!(thin_lto); check_ci_llvm!(release_debuginfo); - // CI-built LLVM can be either dynamic or static. We won't know until we download it. - check_ci_llvm!(link_shared); - check_ci_llvm!(static_libstdcpp); check_ci_llvm!(targets); check_ci_llvm!(experimental_targets); check_ci_llvm!(clang_cl); From 21c02517c31e90ec1c001f3997abcea2caa36f0c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Aug 2024 10:29:52 +0200 Subject: [PATCH 416/489] Miri: add a flag to do recursive validity checking --- .../src/const_eval/eval_queries.rs | 2 +- .../rustc_const_eval/src/interpret/machine.rs | 7 + .../rustc_const_eval/src/interpret/memory.rs | 5 +- .../rustc_const_eval/src/interpret/place.rs | 15 +- .../src/interpret/validity.rs | 176 +++++++++++------- .../src/util/check_validity_requirement.rs | 2 +- src/tools/miri/README.md | 2 + src/tools/miri/src/bin/miri.rs | 6 +- src/tools/miri/src/eval.rs | 16 +- src/tools/miri/src/intrinsics/mod.rs | 2 +- src/tools/miri/src/lib.rs | 1 + src/tools/miri/src/machine.rs | 36 ++-- .../validity/recursive-validity-ref-bool.rs | 8 + .../recursive-validity-ref-bool.stderr | 15 ++ 14 files changed, 186 insertions(+), 107 deletions(-) create mode 100644 src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.rs create mode 100644 src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index ba4b80d102697..6d5bca5731331 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -396,7 +396,7 @@ fn const_validate_mplace<'tcx>( let alloc_id = mplace.ptr().provenance.unwrap().alloc_id(); let mut ref_tracking = RefTracking::new(mplace.clone()); let mut inner = false; - while let Some((mplace, path)) = ref_tracking.todo.pop() { + while let Some((mplace, path)) = ref_tracking.next() { let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) { _ if cid.promoted.is_some() => CtfeValidationMode::Promoted, Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static` diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 4620b15d8d985..bdce8253b2e76 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -165,6 +165,13 @@ pub trait Machine<'tcx>: Sized { /// Whether to enforce the validity invariant for a specific layout. fn enforce_validity(ecx: &InterpCx<'tcx, Self>, layout: TyAndLayout<'tcx>) -> bool; + /// Whether to enforce the validity invariant *recursively*. + fn enforce_validity_recursively( + _ecx: &InterpCx<'tcx, Self>, + _layout: TyAndLayout<'tcx>, + ) -> bool { + false + } /// Whether function calls should be [ABI](CallAbi)-checked. fn enforce_abi(_ecx: &InterpCx<'tcx, Self>) -> bool { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index b71e6ed8d2b65..2e5d0ae773654 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1006,8 +1006,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }) } - /// Runs the close in "validation" mode, which means the machine's memory read hooks will be + /// Runs the closure in "validation" mode, which means the machine's memory read hooks will be /// suppressed. Needless to say, this must only be set with great care! Cannot be nested. + /// + /// We do this so Miri's allocation access tracking does not show the validation + /// reads as spurious accesses. pub(super) fn run_for_validation(&self, f: impl FnOnce() -> R) -> R { // This deliberately uses `==` on `bool` to follow the pattern // `assert!(val.replace(new) == old)`. diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 242f36363a58e..470a62026b943 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -572,7 +572,10 @@ where if M::enforce_validity(self, dest.layout()) { // Data got changed, better make sure it matches the type! - self.validate_operand(&dest.to_op(self)?)?; + self.validate_operand( + &dest.to_op(self)?, + M::enforce_validity_recursively(self, dest.layout()), + )?; } Ok(()) @@ -811,7 +814,10 @@ where // Generally for transmutation, data must be valid both at the old and new type. // But if the types are the same, the 2nd validation below suffices. if src.layout().ty != dest.layout().ty && M::enforce_validity(self, src.layout()) { - self.validate_operand(&src.to_op(self)?)?; + self.validate_operand( + &src.to_op(self)?, + M::enforce_validity_recursively(self, src.layout()), + )?; } // Do the actual copy. @@ -819,7 +825,10 @@ where if validate_dest && M::enforce_validity(self, dest.layout()) { // Data got changed, better make sure it matches the type! - self.validate_operand(&dest.to_op(self)?)?; + self.validate_operand( + &dest.to_op(self)?, + M::enforce_validity_recursively(self, dest.layout()), + )?; } Ok(()) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index c8d59c5648da0..460f5448634b5 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -155,8 +155,8 @@ impl CtfeValidationMode { /// State for tracking recursive validation of references pub struct RefTracking { - pub seen: FxHashSet, - pub todo: Vec<(T, PATH)>, + seen: FxHashSet, + todo: Vec<(T, PATH)>, } impl RefTracking { @@ -169,8 +169,11 @@ impl RefTracking ref_tracking_for_consts.seen.insert(op); ref_tracking_for_consts } + pub fn next(&mut self) -> Option<(T, PATH)> { + self.todo.pop() + } - pub fn track(&mut self, op: T, path: impl FnOnce() -> PATH) { + fn track(&mut self, op: T, path: impl FnOnce() -> PATH) { if self.seen.insert(op.clone()) { trace!("Recursing below ptr {:#?}", op); let path = path(); @@ -435,88 +438,96 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if self.ecx.scalar_may_be_null(Scalar::from_maybe_pointer(place.ptr(), self.ecx))? { throw_validation_failure!(self.path, NullPtr { ptr_kind }) } - // Do not allow pointers to uninhabited types. + // Do not allow references to uninhabited types. if place.layout.abi.is_uninhabited() { let ty = place.layout.ty; throw_validation_failure!(self.path, PtrToUninhabited { ptr_kind, ty }) } // Recursive checking if let Some(ref_tracking) = self.ref_tracking.as_deref_mut() { - // Determine whether this pointer expects to be pointing to something mutable. - let ptr_expected_mutbl = match ptr_kind { - PointerKind::Box => Mutability::Mut, - PointerKind::Ref(mutbl) => { - // We do not take into account interior mutability here since we cannot know if - // there really is an `UnsafeCell` inside `Option` -- so we check - // that in the recursive descent behind this reference (controlled by - // `allow_immutable_unsafe_cell`). - mutbl - } - }; // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. - if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr(), 0) { + if let Some(ctfe_mode) = self.ctfe_mode { let mut skip_recursive_check = false; - if let Some(GlobalAlloc::Static(did)) = self.ecx.tcx.try_get_global_alloc(alloc_id) + // CTFE imposes restrictions on what references can point to. + if let Ok((alloc_id, _offset, _prov)) = + self.ecx.ptr_try_get_alloc_id(place.ptr(), 0) { - let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { bug!() }; - // Special handling for pointers to statics (irrespective of their type). - assert!(!self.ecx.tcx.is_thread_local_static(did)); - assert!(self.ecx.tcx.is_static(did)); - // Mode-specific checks - match self.ctfe_mode { - Some( - CtfeValidationMode::Static { .. } | CtfeValidationMode::Promoted { .. }, - ) => { - // We skip recursively checking other statics. These statics must be sound by - // themselves, and the only way to get broken statics here is by using - // unsafe code. - // The reasons we don't check other statics is twofold. For one, in all - // sound cases, the static was already validated on its own, and second, we - // trigger cycle errors if we try to compute the value of the other static - // and that static refers back to us (potentially through a promoted). - // This could miss some UB, but that's fine. - // We still walk nested allocations, as they are fundamentally part of this validation run. - // This means we will also recurse into nested statics of *other* - // statics, even though we do not recurse into other statics directly. - // That's somewhat inconsistent but harmless. - skip_recursive_check = !nested; - } - Some(CtfeValidationMode::Const { .. }) => { - // We can't recursively validate `extern static`, so we better reject them. - if self.ecx.tcx.is_foreign_item(did) { - throw_validation_failure!(self.path, ConstRefToExtern); + if let Some(GlobalAlloc::Static(did)) = + self.ecx.tcx.try_get_global_alloc(alloc_id) + { + let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { + bug!() + }; + // Special handling for pointers to statics (irrespective of their type). + assert!(!self.ecx.tcx.is_thread_local_static(did)); + assert!(self.ecx.tcx.is_static(did)); + // Mode-specific checks + match ctfe_mode { + CtfeValidationMode::Static { .. } + | CtfeValidationMode::Promoted { .. } => { + // We skip recursively checking other statics. These statics must be sound by + // themselves, and the only way to get broken statics here is by using + // unsafe code. + // The reasons we don't check other statics is twofold. For one, in all + // sound cases, the static was already validated on its own, and second, we + // trigger cycle errors if we try to compute the value of the other static + // and that static refers back to us (potentially through a promoted). + // This could miss some UB, but that's fine. + // We still walk nested allocations, as they are fundamentally part of this validation run. + // This means we will also recurse into nested statics of *other* + // statics, even though we do not recurse into other statics directly. + // That's somewhat inconsistent but harmless. + skip_recursive_check = !nested; + } + CtfeValidationMode::Const { .. } => { + // We can't recursively validate `extern static`, so we better reject them. + if self.ecx.tcx.is_foreign_item(did) { + throw_validation_failure!(self.path, ConstRefToExtern); + } } } - None => {} } - } - // Dangling and Mutability check. - let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id); - if alloc_kind == AllocKind::Dead { - // This can happen for zero-sized references. We can't have *any* references to non-existing - // allocations though, interning rejects them all as the rest of rustc isn't happy with them... - // so we throw an error, even though this isn't really UB. - // A potential future alternative would be to resurrect this as a zero-sized allocation - // (which codegen will then compile to an aligned dummy pointer anyway). - throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); - } - // If this allocation has size zero, there is no actual mutability here. - if size != Size::ZERO { - let alloc_actual_mutbl = mutability(self.ecx, alloc_id); - // Mutable pointer to immutable memory is no good. - if ptr_expected_mutbl == Mutability::Mut - && alloc_actual_mutbl == Mutability::Not - { - throw_validation_failure!(self.path, MutableRefToImmutable); + // Dangling and Mutability check. + let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id); + if alloc_kind == AllocKind::Dead { + // This can happen for zero-sized references. We can't have *any* references to + // non-existing allocations in const-eval though, interning rejects them all as + // the rest of rustc isn't happy with them... so we throw an error, even though + // this isn't really UB. + // A potential future alternative would be to resurrect this as a zero-sized allocation + // (which codegen will then compile to an aligned dummy pointer anyway). + throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); } - // In a const, everything must be completely immutable. - if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) { + // If this allocation has size zero, there is no actual mutability here. + if size != Size::ZERO { + // Determine whether this pointer expects to be pointing to something mutable. + let ptr_expected_mutbl = match ptr_kind { + PointerKind::Box => Mutability::Mut, + PointerKind::Ref(mutbl) => { + // We do not take into account interior mutability here since we cannot know if + // there really is an `UnsafeCell` inside `Option` -- so we check + // that in the recursive descent behind this reference (controlled by + // `allow_immutable_unsafe_cell`). + mutbl + } + }; + // Determine what it actually points to. + let alloc_actual_mutbl = mutability(self.ecx, alloc_id); + // Mutable pointer to immutable memory is no good. if ptr_expected_mutbl == Mutability::Mut - || alloc_actual_mutbl == Mutability::Mut + && alloc_actual_mutbl == Mutability::Not { - throw_validation_failure!(self.path, ConstRefToMutable); + throw_validation_failure!(self.path, MutableRefToImmutable); + } + // In a const, everything must be completely immutable. + if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) { + if ptr_expected_mutbl == Mutability::Mut + || alloc_actual_mutbl == Mutability::Mut + { + throw_validation_failure!(self.path, ConstRefToMutable); + } } } } @@ -524,6 +535,15 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if skip_recursive_check { return Ok(()); } + } else { + // This is not CTFE, so it's Miri with recursive checking. + // FIXME: we do *not* check behind boxes, since creating a new box first creates it uninitialized + // and then puts the value in there, so briefly we have a box with uninit contents. + // FIXME: should we also skip `UnsafeCell` behind shared references? Currently that is not + // needed since validation reads bypass Stacked Borrows and data race checks. + if matches!(ptr_kind, PointerKind::Box) { + return Ok(()); + } } let path = &self.path; ref_tracking.track(place, || { @@ -1072,11 +1092,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// `op` is assumed to cover valid memory if it is an indirect operand. /// It will error if the bits at the destination do not match the ones described by the layout. #[inline(always)] - pub fn validate_operand(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> { + pub fn validate_operand( + &self, + op: &OpTy<'tcx, M::Provenance>, + recursive: bool, + ) -> InterpResult<'tcx> { // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's // still correct to not use `ctfe_mode`: that mode is for validation of the final constant - // value, it rules out things like `UnsafeCell` in awkward places. It also can make checking - // recurse through references which, for now, we don't want here, either. - self.validate_operand_internal(op, vec![], None, None) + // value, it rules out things like `UnsafeCell` in awkward places. + if !recursive { + return self.validate_operand_internal(op, vec![], None, None); + } + // Do a recursive check. + let mut ref_tracking = RefTracking::empty(); + self.validate_operand_internal(op, vec![], Some(&mut ref_tracking), None)?; + while let Some((mplace, path)) = ref_tracking.todo.pop() { + self.validate_operand_internal(&mplace.into(), path, Some(&mut ref_tracking), None)?; + } + Ok(()) } } diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index daf57285ebe6d..4b6b1e453b82e 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -67,7 +67,7 @@ fn might_permit_raw_init_strict<'tcx>( // This does *not* actually check that references are dereferenceable, but since all types that // require dereferenceability also require non-null, we don't actually get any false negatives // due to this. - Ok(cx.validate_operand(&ot).is_ok()) + Ok(cx.validate_operand(&ot, /*recursive*/ false).is_ok()) } /// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index b1be596c00679..ff0f162822c45 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -398,6 +398,8 @@ to Miri failing to detect cases of undefined behavior in a program. application instead of raising an error within the context of Miri (and halting execution). Note that code might not expect these operations to ever panic, so this flag can lead to strange (mis)behavior. +* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking + recurse below references. * `-Zmiri-retag-fields[=]` controls when Stacked Borrows retagging recurses into fields. `all` means it always recurses (the default, and equivalent to `-Zmiri-retag-fields` without an explicit value), `none` means it never recurses, `scalar` means it only recurses for diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 25b154a8206c9..4b3c97e248f41 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -44,7 +44,7 @@ use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; use rustc_session::search_paths::PathKind; use rustc_session::{CtfeBacktrace, EarlyDiagCtxt}; -use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields}; +use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields, ValidationMode}; struct MiriCompilerCalls { miri_config: miri::MiriConfig, @@ -421,7 +421,9 @@ fn main() { } else if arg == "--" { after_dashdash = true; } else if arg == "-Zmiri-disable-validation" { - miri_config.validate = false; + miri_config.validation = ValidationMode::No; + } else if arg == "-Zmiri-recursive-validation" { + miri_config.validation = ValidationMode::Deep; } else if arg == "-Zmiri-disable-stacked-borrows" { miri_config.borrow_tracker = None; } else if arg == "-Zmiri-tree-borrows" { diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 2184a4426c8dc..53e877517089c 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -68,7 +68,7 @@ pub enum IsolatedOp { Allow, } -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum BacktraceStyle { /// Prints a terser backtrace which ideally only contains relevant information. Short, @@ -78,6 +78,16 @@ pub enum BacktraceStyle { Off, } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum ValidationMode { + /// Do not perform any kind of validation. + No, + /// Validate the interior of the value, but not things behind references. + Shallow, + /// Fully recursively validate references. + Deep, +} + /// Configuration needed to spawn a Miri instance. #[derive(Clone)] pub struct MiriConfig { @@ -85,7 +95,7 @@ pub struct MiriConfig { /// (This is still subject to isolation as well as `forwarded_env_vars`.) pub env: Vec<(OsString, OsString)>, /// Determine if validity checking is enabled. - pub validate: bool, + pub validation: ValidationMode, /// Determines if Stacked Borrows or Tree Borrows is enabled. pub borrow_tracker: Option, /// Whether `core::ptr::Unique` receives special treatment. @@ -162,7 +172,7 @@ impl Default for MiriConfig { fn default() -> MiriConfig { MiriConfig { env: vec![], - validate: true, + validation: ValidationMode::Shallow, borrow_tracker: Some(BorrowTrackerMethod::StackedBorrows), unique_is_unique: false, check_alignment: AlignmentCheck::Int, diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 9cd776c937101..d60119e75f16d 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -153,7 +153,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Would not be considered UB, or the other way around (`is_val_statically_known(0)`). "is_val_statically_known" => { let [arg] = check_arg_count(args)?; - this.validate_operand(arg)?; + this.validate_operand(arg, /*recursive*/ false)?; let branch: bool = this.machine.rng.get_mut().gen(); this.write_scalar(Scalar::from_bool(branch), dest)?; } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 24909f21eb2b3..2b3ae6df5de8a 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -142,6 +142,7 @@ pub use crate::diagnostics::{ }; pub use crate::eval::{ create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith, + ValidationMode, }; pub use crate::helpers::{AccessKind, EvalContextExt as _}; pub use crate::machine::{ diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 5f4aa9d2f5d21..fec345c8de1da 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -187,7 +187,11 @@ impl fmt::Display for MiriMemoryKind { pub type MemoryKind = interpret::MemoryKind; /// Pointer provenance. -#[derive(Clone, Copy)] +// This needs to be `Eq`+`Hash` because the `Machine` trait needs that because validity checking +// *might* be recursive and then it has to track which places have already been visited. +// These implementations are a bit questionable, and it means we may check the same place multiple +// times with different provenance, but that is in general not wrong. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum Provenance { /// For pointers with concrete provenance. we exactly know which allocation they are attached to /// and what their borrow tag is. @@ -215,24 +219,6 @@ pub enum Provenance { Wildcard, } -// This needs to be `Eq`+`Hash` because the `Machine` trait needs that because validity checking -// *might* be recursive and then it has to track which places have already been visited. -// However, comparing provenance is meaningless, since `Wildcard` might be any provenance -- and of -// course we don't actually do recursive checking. -// We could change `RefTracking` to strip provenance for its `seen` set but that type is generic so that is quite annoying. -// Instead owe add the required instances but make them panic. -impl PartialEq for Provenance { - fn eq(&self, _other: &Self) -> bool { - panic!("Provenance must not be compared") - } -} -impl Eq for Provenance {} -impl std::hash::Hash for Provenance { - fn hash(&self, _state: &mut H) { - panic!("Provenance must not be hashed") - } -} - /// The "extra" information a pointer has over a regular AllocId. #[derive(Copy, Clone, PartialEq)] pub enum ProvenanceExtra { @@ -460,7 +446,7 @@ pub struct MiriMachine<'tcx> { pub(crate) isolated_op: IsolatedOp, /// Whether to enforce the validity invariant. - pub(crate) validate: bool, + pub(crate) validation: ValidationMode, /// The table of file descriptors. pub(crate) fds: shims::FdTable, @@ -659,7 +645,7 @@ impl<'tcx> MiriMachine<'tcx> { cmd_line: None, tls: TlsData::default(), isolated_op: config.isolated_op, - validate: config.validate, + validation: config.validation, fds: shims::FdTable::init(config.mute_stdout_stderr), dirs: Default::default(), layouts, @@ -801,7 +787,7 @@ impl VisitProvenance for MiriMachine<'_> { fds, tcx: _, isolated_op: _, - validate: _, + validation: _, clock: _, layouts: _, static_roots: _, @@ -943,7 +929,11 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { #[inline(always)] fn enforce_validity(ecx: &MiriInterpCx<'tcx>, _layout: TyAndLayout<'tcx>) -> bool { - ecx.machine.validate + ecx.machine.validation != ValidationMode::No + } + #[inline(always)] + fn enforce_validity_recursively(ecx: &InterpCx<'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool { + ecx.machine.validation == ValidationMode::Deep } #[inline(always)] diff --git a/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.rs b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.rs new file mode 100644 index 0000000000000..17b81f29cfe9a --- /dev/null +++ b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.rs @@ -0,0 +1,8 @@ +//@compile-flags: -Zmiri-recursive-validation + +fn main() { + let x = 3u8; + let xref = &x; + let xref_wrong_type: &bool = unsafe { std::mem::transmute(xref) }; //~ERROR: encountered 0x03, but expected a boolean + let _val = *xref_wrong_type; +} diff --git a/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr new file mode 100644 index 0000000000000..2b2fa9b8a206d --- /dev/null +++ b/src/tools/miri/tests/fail/validity/recursive-validity-ref-bool.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value at .: encountered 0x03, but expected a boolean + --> $DIR/recursive-validity-ref-bool.rs:LL:CC + | +LL | let xref_wrong_type: &bool = unsafe { std::mem::transmute(xref) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered 0x03, but expected a boolean + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/recursive-validity-ref-bool.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 35977b47cc80e54af8e8559231945bada6fe1c01 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 29 Jul 2024 22:17:25 +0300 Subject: [PATCH 417/489] linker: Pass fewer search directories to the linker --- compiler/rustc_codegen_ssa/src/back/link.rs | 94 ++++++++++++--------- compiler/rustc_session/src/filesearch.rs | 5 ++ 2 files changed, 61 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7d457526380d9..93ddd1ef04412 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2065,17 +2065,57 @@ fn add_local_crate_metadata_objects( } /// Add sysroot and other globally set directories to the directory search list. -fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) { - // The default library location, we need this to find the runtime. - // The location of crates will be determined as needed. - let lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); - cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); +fn add_library_search_dirs( + cmd: &mut dyn Linker, + sess: &Session, + self_contained_components: LinkSelfContainedComponents, + apple_sdk_root: Option<&Path>, +) { + if !sess.opts.unstable_opts.link_native_libraries { + return; + } - // Special directory with libraries used only in self-contained linkage mode - if self_contained { - let lib_path = sess.target_filesearch(PathKind::All).get_self_contained_lib_path(); + // Library search paths explicitly supplied by user (`-L` on the command line). + for search_path in sess.target_filesearch(PathKind::Native).cli_search_paths() { + cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)); + } + for search_path in sess.target_filesearch(PathKind::Framework).cli_search_paths() { + // Contrary to the `-L` docs only framework-specific paths are considered here. + if search_path.kind != PathKind::All { + cmd.framework_path(&search_path.dir); + } + } + + // The toolchain ships some native library components and self-contained linking was enabled. + // Add the self-contained library directory to search paths. + if self_contained_components.intersects( + LinkSelfContainedComponents::LIBC + | LinkSelfContainedComponents::UNWIND + | LinkSelfContainedComponents::MINGW, + ) { + let lib_path = sess.target_filesearch(PathKind::Native).get_self_contained_lib_path(); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); } + + // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot + // library directory instead of the self-contained directories. + // The targets here should be in sync with `copy_third_party_objects` in bootstrap. + // FIXME: implement `-Clink-self-contained=+/-unwind`, move the shipped libunwind + // to self-contained directory, and stop adding this search path. + if sess.target.vendor == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia" + { + let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path(); + cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); + } + + // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks + // we must have the support library stubs in the library search path (#121430). + if let Some(sdk_root) = apple_sdk_root + && sess.target.llvm_target.contains("macabi") + { + cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib")); + cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks")); + } } /// Add options making relocation sections in the produced ELF files read-only @@ -2367,7 +2407,7 @@ fn add_order_independent_options( // Take care of the flavors and CLI options requesting the `lld` linker. add_lld_args(cmd, sess, flavor, self_contained_components); - add_apple_sdk(cmd, sess, flavor); + let apple_sdk_root = add_apple_sdk(cmd, sess, flavor); add_link_script(cmd, sess, tmpdir, crate_type); @@ -2423,7 +2463,7 @@ fn add_order_independent_options( cmd.linker_plugin_lto(); - add_library_search_dirs(cmd, sess, self_contained_components.are_any_components_enabled()); + add_library_search_dirs(cmd, sess, self_contained_components, apple_sdk_root.as_deref()); cmd.output_filename(out_filename); @@ -2637,19 +2677,6 @@ fn add_local_native_libraries( tmpdir: &Path, link_output_kind: LinkOutputKind, ) { - if sess.opts.unstable_opts.link_native_libraries { - // User-supplied library search paths (-L on the command line). These are the same paths - // used to find Rust crates, so some of them may have been added already by the previous - // crate linking code. This only allows them to be found at compile time so it is still - // entirely up to outside forces to make sure that library can be found at runtime. - for search_path in sess.target_filesearch(PathKind::All).search_paths() { - match search_path.kind { - PathKind::Framework => cmd.framework_path(&search_path.dir), - _ => cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)), - } - } - } - // All static and dynamic native library dependencies are linked to the local crate. let link_static = true; let link_dynamic = true; @@ -2944,7 +2971,7 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool } } -fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { +fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option { let arch = &sess.target.arch; let os = &sess.target.os; let llvm_target = &sess.target.llvm_target; @@ -2952,11 +2979,11 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos") || !matches!(flavor, LinkerFlavor::Darwin(..)) { - return; + return None; } if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) { - return; + return None; } let sdk_name = match (arch.as_ref(), os.as_ref()) { @@ -2980,14 +3007,14 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { (_, "macos") => "macosx", _ => { sess.dcx().emit_err(errors::UnsupportedArch { arch, os }); - return; + return None; } }; let sdk_root = match get_apple_sdk_root(sdk_name) { Ok(s) => s, Err(e) => { sess.dcx().emit_err(e); - return; + return None; } }; @@ -3007,16 +3034,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { _ => unreachable!(), } - if llvm_target.contains("macabi") { - // Mac Catalyst uses the macOS SDK, but to link to iOS-specific - // frameworks, we must have the support library stubs in the library - // search path. - - // The flags are called `-L` and `-F` both in Clang, ld64 and ldd. - let sdk_root = Path::new(&sdk_root); - cmd.include_path(&sdk_root.join("System/iOSSupport/usr/lib")); - cmd.framework_path(&sdk_root.join("System/iOSSupport/System/Library/Frameworks")); - } + Some(sdk_root.into()) } fn get_apple_sdk_root(sdk_name: &str) -> Result> { diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 0c3ec36fed5a7..63ca5fefd9faf 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -19,6 +19,11 @@ pub struct FileSearch<'a> { } impl<'a> FileSearch<'a> { + pub fn cli_search_paths(&self) -> impl Iterator { + let kind = self.kind; + self.cli_search_paths.iter().filter(move |sp| sp.kind.matches(kind)) + } + pub fn search_paths(&self) -> impl Iterator { let kind = self.kind; self.cli_search_paths From 1f873f9cf1e6307d1f0bee85f7a866f9531b8a98 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 3 Aug 2024 14:18:55 +0300 Subject: [PATCH 418/489] Fix linking to sanitizers on Apple targets --- compiler/rustc_codegen_ssa/src/back/link.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 93ddd1ef04412..653895380bebc 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2099,10 +2099,14 @@ fn add_library_search_dirs( // Toolchains for some targets may ship `libunwind.a`, but place it into the main sysroot // library directory instead of the self-contained directories. + // Sanitizer libraries have the same issue and are also linked by name on Apple targets. // The targets here should be in sync with `copy_third_party_objects` in bootstrap. - // FIXME: implement `-Clink-self-contained=+/-unwind`, move the shipped libunwind - // to self-contained directory, and stop adding this search path. - if sess.target.vendor == "fortanix" || sess.target.os == "linux" || sess.target.os == "fuchsia" + // FIXME: implement `-Clink-self-contained=+/-unwind,+/-sanitizers`, move the shipped libunwind + // and sanitizers to self-contained directory, and stop adding this search path. + if sess.target.vendor == "fortanix" + || sess.target.os == "linux" + || sess.target.os == "fuchsia" + || sess.target.is_like_osx && !sess.opts.unstable_opts.sanitizer.is_empty() { let lib_path = sess.target_filesearch(PathKind::Native).get_lib_path(); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); From 361ab1af0c74820ff74cd48dd7817c308da62642 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:28:57 -0400 Subject: [PATCH 419/489] Revert "Rollup merge of #128104 - mu001999-contrib:fix/128053, r=petrochenkov" This reverts commit 91b18a058c4661f82e420b633dc0a3e1ccd14b88, reversing changes made to 9aedec9313dc8ecf9bdcb5f09c4eb0ad8b9a4875. --- compiler/rustc_passes/src/dead.rs | 36 +++++++++---------- ...lone-debug-dead-code-in-the-same-struct.rs | 4 +-- ...-debug-dead-code-in-the-same-struct.stderr | 16 ++------- .../dead-code/unconstructible-pub-struct.rs | 35 ------------------ .../unconstructible-pub-struct.stderr | 14 -------- 5 files changed, 22 insertions(+), 83 deletions(-) delete mode 100644 tests/ui/lint/dead-code/unconstructible-pub-struct.rs delete mode 100644 tests/ui/lint/dead-code/unconstructible-pub-struct.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 8a931fc4158e3..3b1a796130c43 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -73,26 +73,24 @@ fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> { } fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool { - let adt_def = tcx.adt_def(id); - - // skip types contain fields of unit and never type, - // it's usually intentional to make the type not constructible - let not_require_constructor = adt_def.all_fields().any(|field| { + // treat PhantomData and positional ZST as public, + // we don't want to lint types which only have them, + // cause it's a common way to use such types to check things like well-formedness + tcx.adt_def(id).all_fields().all(|field| { let field_type = tcx.type_of(field.did).instantiate_identity(); - field_type.is_unit() || field_type.is_never() - }); - - not_require_constructor - || adt_def.all_fields().all(|field| { - let field_type = tcx.type_of(field.did).instantiate_identity(); - // skip fields of PhantomData, - // cause it's a common way to check things like well-formedness - if field_type.is_phantom_data() { - return true; - } - - field.vis.is_public() - }) + if field_type.is_phantom_data() { + return true; + } + let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit()); + if is_positional + && tcx + .layout_of(tcx.param_env(field.did).and(field_type)) + .map_or(true, |layout| layout.is_zst()) + { + return true; + } + field.vis.is_public() + }) } /// check struct and its fields are public or not, diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs index 6ab1fb7b039bd..885dacc727af6 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs @@ -1,9 +1,9 @@ #![forbid(dead_code)] #[derive(Debug)] -pub struct Whatever { +pub struct Whatever { //~ ERROR struct `Whatever` is never constructed pub field0: (), - field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read + field1: (), field2: (), field3: (), field4: (), diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr index e9b757b6bae72..e10d28ad03a4e 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr @@ -1,19 +1,9 @@ -error: fields `field1`, `field2`, `field3`, and `field4` are never read - --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5 +error: struct `Whatever` is never constructed + --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12 | LL | pub struct Whatever { - | -------- fields in this struct -LL | pub field0: (), -LL | field1: (), - | ^^^^^^ -LL | field2: (), - | ^^^^^^ -LL | field3: (), - | ^^^^^^ -LL | field4: (), - | ^^^^^^ + | ^^^^^^^^ | - = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis note: the lint level is defined here --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11 | diff --git a/tests/ui/lint/dead-code/unconstructible-pub-struct.rs b/tests/ui/lint/dead-code/unconstructible-pub-struct.rs deleted file mode 100644 index 2202cbb673098..0000000000000 --- a/tests/ui/lint/dead-code/unconstructible-pub-struct.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![feature(never_type)] -#![deny(dead_code)] - -pub struct T1(!); -pub struct T2(()); -pub struct T3(std::marker::PhantomData); - -pub struct T4 { - _x: !, -} - -pub struct T5 { - _x: !, - _y: X, -} - -pub struct T6 { - _x: (), -} - -pub struct T7 { - _x: (), - _y: X, -} - -pub struct T8 { - _x: std::marker::PhantomData, -} - -pub struct T9 { //~ ERROR struct `T9` is never constructed - _x: std::marker::PhantomData, - _y: i32, -} - -fn main() {} diff --git a/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr b/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr deleted file mode 100644 index a3dde042bbe15..0000000000000 --- a/tests/ui/lint/dead-code/unconstructible-pub-struct.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: struct `T9` is never constructed - --> $DIR/unconstructible-pub-struct.rs:30:12 - | -LL | pub struct T9 { - | ^^ - | -note: the lint level is defined here - --> $DIR/unconstructible-pub-struct.rs:2:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: aborting due to 1 previous error - From c6b6c1270a25ee05c4e1f6a9daaf48ef60317f2c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:28:58 -0400 Subject: [PATCH 420/489] Revert "Rollup merge of #127017 - mu001999-contrib:dead/enhance, r=pnkfelix" This reverts commit a70dc297a899b76793a14c5705f6ec78fd7a57a7, reversing changes made to ceae37188b9f1be527bb16c9d657a161be7dbbe3. --- compiler/rustc_passes/src/dead.rs | 32 +++++-------- .../dead-code/unused-impl-for-non-adts.rs | 45 ------------------- .../dead-code/unused-impl-for-non-adts.stderr | 20 --------- 3 files changed, 10 insertions(+), 87 deletions(-) delete mode 100644 tests/ui/lint/dead-code/unused-impl-for-non-adts.rs delete mode 100644 tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 3b1a796130c43..9c475c9fbf462 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -55,24 +55,7 @@ impl Publicness { } } -fn adt_of<'tcx>(ty: &hir::Ty<'tcx>) -> Option<(LocalDefId, DefKind)> { - match ty.kind { - TyKind::Path(hir::QPath::Resolved(_, path)) => { - if let Res::Def(def_kind, def_id) = path.res - && let Some(local_def_id) = def_id.as_local() - { - Some((local_def_id, def_kind)) - } else { - None - } - } - TyKind::Slice(ty) | TyKind::Array(ty, _) => adt_of(ty), - TyKind::Ptr(ty) | TyKind::Ref(_, ty) => adt_of(ty.ty), - _ => None, - } -} - -fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool { +fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool { // treat PhantomData and positional ZST as public, // we don't want to lint types which only have them, // cause it's a common way to use such types to check things like well-formedness @@ -97,7 +80,10 @@ fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: LocalDefId) -> bool { /// for enum and union, just check they are public, /// and doesn't solve types like &T for now, just skip them fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness { - if let Some((def_id, def_kind)) = adt_of(ty) { + if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind + && let Res::Def(def_kind, def_id) = path.res + && def_id.is_local() + { return match def_kind { DefKind::Enum | DefKind::Union => { let ty_is_public = tcx.visibility(def_id).is_public(); @@ -580,8 +566,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId, impl_item_id: LocalDefId) -> bool { - if let Some((local_def_id, def_kind)) = - adt_of(self.tcx.hir().item(impl_id).expect_impl().self_ty) + if let TyKind::Path(hir::QPath::Resolved(_, path)) = + self.tcx.hir().item(impl_id).expect_impl().self_ty.kind + && let Res::Def(def_kind, def_id) = path.res + && let Some(local_def_id) = def_id.as_local() && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) { if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id @@ -928,7 +916,7 @@ fn create_and_seed_worklist( match tcx.def_kind(id) { DefKind::Impl { .. } => false, DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), - DefKind::Struct => struct_all_fields_are_public(tcx, id) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), + DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), _ => true }) .map(|id| (id, ComesFromAllowExpect::No)) diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs b/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs deleted file mode 100644 index 46065dcee81e0..0000000000000 --- a/tests/ui/lint/dead-code/unused-impl-for-non-adts.rs +++ /dev/null @@ -1,45 +0,0 @@ -#![deny(dead_code)] - -struct Foo; //~ ERROR struct `Foo` is never constructed - -trait Trait { //~ ERROR trait `Trait` is never used - fn foo(&self) {} -} - -impl Trait for Foo {} - -impl Trait for [Foo] {} -impl Trait for [Foo; N] {} - -impl Trait for *const Foo {} -impl Trait for *mut Foo {} - -impl Trait for &Foo {} -impl Trait for &&Foo {} -impl Trait for &mut Foo {} - -impl Trait for [&Foo] {} -impl Trait for &[Foo] {} -impl Trait for &*const Foo {} - -pub trait Trait2 { - fn foo(&self) {} -} - -impl Trait2 for Foo {} - -impl Trait2 for [Foo] {} -impl Trait2 for [Foo; N] {} - -impl Trait2 for *const Foo {} -impl Trait2 for *mut Foo {} - -impl Trait2 for &Foo {} -impl Trait2 for &&Foo {} -impl Trait2 for &mut Foo {} - -impl Trait2 for [&Foo] {} -impl Trait2 for &[Foo] {} -impl Trait2 for &*const Foo {} - -fn main() {} diff --git a/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr b/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr deleted file mode 100644 index e61fc403e810d..0000000000000 --- a/tests/ui/lint/dead-code/unused-impl-for-non-adts.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: struct `Foo` is never constructed - --> $DIR/unused-impl-for-non-adts.rs:3:8 - | -LL | struct Foo; - | ^^^ - | -note: the lint level is defined here - --> $DIR/unused-impl-for-non-adts.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: trait `Trait` is never used - --> $DIR/unused-impl-for-non-adts.rs:5:7 - | -LL | trait Trait { - | ^^^^^ - -error: aborting due to 2 previous errors - From 5f5b4ee12859e9ba54a862a07c02be272be27d50 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:28:59 -0400 Subject: [PATCH 421/489] Revert "Rollup merge of #127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix" This reverts commit 31fe9628cf830a08e7194a446f66c668aaea86e9, reversing changes made to f20307851ead9fbbb9fa88bbffb3258a069230a6. --- compiler/rustc_passes/src/dead.rs | 40 +++++++++++++------ library/core/src/default.rs | 1 + tests/ui-fulldeps/deriving-global.rs | 3 -- tests/ui-fulldeps/deriving-hygiene.rs | 1 - .../ui/const-generics/issues/issue-86535-2.rs | 1 - tests/ui/const-generics/issues/issue-86535.rs | 1 - .../impl-trait/extra-impl-in-trait-impl.fixed | 2 - .../ui/impl-trait/extra-impl-in-trait-impl.rs | 2 - .../extra-impl-in-trait-impl.stderr | 8 ++-- tests/ui/lint/dead-code/issue-59003.rs | 2 +- .../lint-unused-adt-appeared-in-pattern.rs | 37 ----------------- ...lint-unused-adt-appeared-in-pattern.stderr | 20 ---------- .../not-lint-used-adt-appeared-in-pattern.rs | 32 --------------- ...sed-adt-impl-pub-trait-with-assoc-const.rs | 36 ++++++----------- ...adt-impl-pub-trait-with-assoc-const.stderr | 24 ++--------- .../dead-code/unused-struct-derive-default.rs | 1 - .../unused-struct-derive-default.stderr | 1 + tests/ui/parser/issues/issue-105366.fixed | 1 - tests/ui/parser/issues/issue-105366.rs | 1 - tests/ui/parser/issues/issue-105366.stderr | 2 +- 20 files changed, 52 insertions(+), 164 deletions(-) delete mode 100644 tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs delete mode 100644 tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr delete mode 100644 tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 9c475c9fbf462..78fbcc1f40623 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -278,10 +278,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { pats: &[hir::PatField<'_>], ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { - ty::Adt(adt, _) => { - self.check_def_id(adt.did()); - adt.variant_of_res(res) - } + ty::Adt(adt, _) => adt.variant_of_res(res), _ => span_bug!(lhs.span, "non-ADT in struct pattern"), }; for pat in pats { @@ -301,10 +298,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { dotdot: hir::DotDotPos, ) { let variant = match self.typeck_results().node_type(lhs.hir_id).kind() { - ty::Adt(adt, _) => { - self.check_def_id(adt.did()); - adt.variant_of_res(res) - } + ty::Adt(adt, _) => adt.variant_of_res(res), _ => { self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern"); return; @@ -409,6 +403,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return false; } + // don't ignore impls for Enums and pub Structs whose methods don't have self receiver, + // cause external crate may call such methods to construct values of these types + if let Some(local_impl_of) = impl_of.as_local() + && let Some(local_def_id) = def_id.as_local() + && let Some(fn_sig) = + self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id)) + && matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None) + && let TyKind::Path(hir::QPath::Resolved(_, path)) = + self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind + && let Res::Def(def_kind, did) = path.res + { + match def_kind { + // for example, #[derive(Default)] pub struct T(i32); + // external crate can call T::default() to construct T, + // so that don't ignore impl Default for pub Enum and Structs + DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => { + return false; + } + // don't ignore impl Default for Enums, + // cause we don't know which variant is constructed + DefKind::Enum => return false, + _ => (), + }; + } + if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) && self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads) { @@ -672,9 +691,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.handle_field_pattern_match(pat, res, fields); } PatKind::Path(ref qpath) => { - if let ty::Adt(adt, _) = self.typeck_results().node_type(pat.hir_id).kind() { - self.check_def_id(adt.did()); - } let res = self.typeck_results().qpath_res(qpath, pat.hir_id); self.handle_res(res); } @@ -830,7 +846,7 @@ fn check_item<'tcx>( // mark the method live if the self_ty is public, // or the method is public and may construct self if tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || (ty_is_public && may_construct_self)) + && (ty_and_all_fields_are_public || may_construct_self) { // if the impl item is public, // and the ty may be constructed or can be constructed in foreign crates, diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 4524b352ec817..5cacedcb241a5 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -103,6 +103,7 @@ use crate::ascii::Char as AsciiChar; /// ``` #[cfg_attr(not(test), rustc_diagnostic_item = "Default")] #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)] pub trait Default: Sized { /// Returns the "default value" for a type. /// diff --git a/tests/ui-fulldeps/deriving-global.rs b/tests/ui-fulldeps/deriving-global.rs index 0ba149c9ad654..7783010be441d 100644 --- a/tests/ui-fulldeps/deriving-global.rs +++ b/tests/ui-fulldeps/deriving-global.rs @@ -17,21 +17,18 @@ mod submod { // if any of these are implemented without global calls for any // function calls, then being in a submodule will (correctly) // cause errors about unrecognised module `std` (or `extra`) - #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] enum A { A1(usize), A2(isize), } - #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct B { x: usize, y: isize, } - #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct C(usize, isize); } diff --git a/tests/ui-fulldeps/deriving-hygiene.rs b/tests/ui-fulldeps/deriving-hygiene.rs index f948d6ac544e5..a3a6f9e022ebb 100644 --- a/tests/ui-fulldeps/deriving-hygiene.rs +++ b/tests/ui-fulldeps/deriving-hygiene.rs @@ -20,7 +20,6 @@ pub const s: u8 = 1; pub const state: u8 = 1; pub const cmp: u8 = 1; -#[allow(dead_code)] #[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Decodable, Encodable, Hash)] struct Foo {} diff --git a/tests/ui/const-generics/issues/issue-86535-2.rs b/tests/ui/const-generics/issues/issue-86535-2.rs index ab68c6b78df34..8d064f3eeb1b7 100644 --- a/tests/ui/const-generics/issues/issue-86535-2.rs +++ b/tests/ui/const-generics/issues/issue-86535-2.rs @@ -9,7 +9,6 @@ pub trait Foo { [(); Self::ASSOC_C]:; } -#[allow(dead_code)] struct Bar; impl Foo for Bar { const ASSOC_C: usize = 3; diff --git a/tests/ui/const-generics/issues/issue-86535.rs b/tests/ui/const-generics/issues/issue-86535.rs index 9aaf7ddc9e86e..62454f4a388a0 100644 --- a/tests/ui/const-generics/issues/issue-86535.rs +++ b/tests/ui/const-generics/issues/issue-86535.rs @@ -2,7 +2,6 @@ #![feature(adt_const_params, unsized_const_params, generic_const_exprs)] #![allow(incomplete_features, unused_variables)] -#[allow(dead_code)] struct F; impl X for F<{ S }> { const W: usize = 3; diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed index 3c4499f017337..886fc1d005802 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.fixed @@ -1,8 +1,6 @@ //@ run-rustfix -#[allow(dead_code)] struct S(T); -#[allow(dead_code)] struct S2; impl Default for S { diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs index ac0783295242e..f3271993867cb 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.rs +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.rs @@ -1,8 +1,6 @@ //@ run-rustfix -#[allow(dead_code)] struct S(T); -#[allow(dead_code)] struct S2; impl impl Default for S { diff --git a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr index 91c7da5a04fb4..5aafc8b64d4ff 100644 --- a/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr +++ b/tests/ui/impl-trait/extra-impl-in-trait-impl.stderr @@ -1,23 +1,23 @@ error: unexpected `impl` keyword - --> $DIR/extra-impl-in-trait-impl.rs:8:18 + --> $DIR/extra-impl-in-trait-impl.rs:6:18 | LL | impl impl Default for S { | ^^^^^ help: remove the extra `impl` | note: this is parsed as an `impl Trait` type, but a trait is expected at this position - --> $DIR/extra-impl-in-trait-impl.rs:8:18 + --> $DIR/extra-impl-in-trait-impl.rs:6:18 | LL | impl impl Default for S { | ^^^^^^^^^^^^ error: unexpected `impl` keyword - --> $DIR/extra-impl-in-trait-impl.rs:14:6 + --> $DIR/extra-impl-in-trait-impl.rs:12:6 | LL | impl impl Default for S2 { | ^^^^^ help: remove the extra `impl` | note: this is parsed as an `impl Trait` type, but a trait is expected at this position - --> $DIR/extra-impl-in-trait-impl.rs:14:6 + --> $DIR/extra-impl-in-trait-impl.rs:12:6 | LL | impl impl Default for S2 { | ^^^^^^^^^^^^ diff --git a/tests/ui/lint/dead-code/issue-59003.rs b/tests/ui/lint/dead-code/issue-59003.rs index 319cf2db1495f..e3dcaca577889 100644 --- a/tests/ui/lint/dead-code/issue-59003.rs +++ b/tests/ui/lint/dead-code/issue-59003.rs @@ -4,8 +4,8 @@ #![deny(dead_code)] -#[allow(dead_code)] struct Foo { + #[allow(dead_code)] inner: u32, } diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs deleted file mode 100644 index 25777438456b6..0000000000000 --- a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![deny(dead_code)] - -struct Foo(u8); //~ ERROR struct `Foo` is never constructed - -enum Bar { //~ ERROR enum `Bar` is never used - Var1(u8), - Var2(u8), -} - -pub trait Tr1 { - fn f1() -> Self; -} - -impl Tr1 for Foo { - fn f1() -> Foo { - let f = Foo(0); - let Foo(tag) = f; - Foo(tag) - } -} - -impl Tr1 for Bar { - fn f1() -> Bar { - let b = Bar::Var1(0); - let b = if let Bar::Var1(_) = b { - Bar::Var1(0) - } else { - Bar::Var2(0) - }; - match b { - Bar::Var1(_) => Bar::Var2(0), - Bar::Var2(_) => Bar::Var1(0), - } - } -} - -fn main() {} diff --git a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr b/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr deleted file mode 100644 index 7c1a4b4597755..0000000000000 --- a/tests/ui/lint/dead-code/lint-unused-adt-appeared-in-pattern.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: struct `Foo` is never constructed - --> $DIR/lint-unused-adt-appeared-in-pattern.rs:3:8 - | -LL | struct Foo(u8); - | ^^^ - | -note: the lint level is defined here - --> $DIR/lint-unused-adt-appeared-in-pattern.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: enum `Bar` is never used - --> $DIR/lint-unused-adt-appeared-in-pattern.rs:5:6 - | -LL | enum Bar { - | ^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs b/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs deleted file mode 100644 index 43a2e43190433..0000000000000 --- a/tests/ui/lint/dead-code/not-lint-used-adt-appeared-in-pattern.rs +++ /dev/null @@ -1,32 +0,0 @@ -//@ check-pass - -#![deny(dead_code)] - -#[repr(u8)] -#[derive(Copy, Clone, Debug)] -pub enum RecordField { - Target = 1, - Level, - Module, - File, - Line, - NumArgs, -} - -unsafe trait Pod {} - -#[repr(transparent)] -struct RecordFieldWrapper(RecordField); - -unsafe impl Pod for RecordFieldWrapper {} - -fn try_read(buf: &[u8]) -> T { - unsafe { std::ptr::read_unaligned(buf.as_ptr() as *const T) } -} - -pub fn foo(buf: &[u8]) -> RecordField { - let RecordFieldWrapper(tag) = try_read(buf); - tag -} - -fn main() {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs index 658cc3d6c613a..bf2fc243e8194 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs @@ -1,9 +1,8 @@ #![deny(dead_code)] struct T1; //~ ERROR struct `T1` is never constructed -struct T2; //~ ERROR struct `T2` is never constructed -pub struct T3(i32); //~ ERROR struct `T3` is never constructed -pub struct T4(i32); //~ ERROR field `0` is never read +pub struct T2(i32); //~ ERROR struct `T2` is never constructed +struct T3; trait Trait1 { //~ ERROR trait `Trait1` is never used const UNUSED: i32; @@ -12,13 +11,13 @@ trait Trait1 { //~ ERROR trait `Trait1` is never used } pub trait Trait2 { - const MAY_USED: i32; - fn may_used(&self) {} + const USED: i32; + fn used(&self) {} } pub trait Trait3 { - const MAY_USED: i32; - fn may_used() -> Self; + const USED: i32; + fn construct_self() -> Self; } impl Trait1 for T1 { @@ -31,34 +30,23 @@ impl Trait1 for T1 { impl Trait1 for T2 { const UNUSED: i32 = 0; fn construct_self() -> Self { - Self + T2(0) } } impl Trait2 for T1 { - const MAY_USED: i32 = 0; + const USED: i32 = 0; } impl Trait2 for T2 { - const MAY_USED: i32 = 0; -} - -impl Trait2 for T3 { - const MAY_USED: i32 = 0; + const USED: i32 = 0; } -impl Trait3 for T2 { - const MAY_USED: i32 = 0; - fn may_used() -> Self { +impl Trait3 for T3 { + const USED: i32 = 0; + fn construct_self() -> Self { Self } } -impl Trait3 for T4 { - const MAY_USED: i32 = 0; - fn may_used() -> Self { - T4(0) - } -} - fn main() {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr index 08c7a5cb4b062..174096d939883 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr @@ -11,32 +11,16 @@ LL | #![deny(dead_code)] | ^^^^^^^^^ error: struct `T2` is never constructed - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:8 + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:12 | -LL | struct T2; - | ^^ - -error: struct `T3` is never constructed - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:5:12 - | -LL | pub struct T3(i32); +LL | pub struct T2(i32); | ^^ -error: field `0` is never read - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:6:15 - | -LL | pub struct T4(i32); - | -- ^^^ - | | - | field in this struct - | - = help: consider removing this field - error: trait `Trait1` is never used - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:8:7 + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7 | LL | trait Trait1 { | ^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.rs b/tests/ui/lint/dead-code/unused-struct-derive-default.rs index f20b7cb66ee51..330ad32dd5709 100644 --- a/tests/ui/lint/dead-code/unused-struct-derive-default.rs +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.rs @@ -22,5 +22,4 @@ pub struct T2 { fn main() { let _x: Used = Default::default(); - let _e: E = Default::default(); } diff --git a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr index 7422f9a39f312..bbb0bd7be7064 100644 --- a/tests/ui/lint/dead-code/unused-struct-derive-default.stderr +++ b/tests/ui/lint/dead-code/unused-struct-derive-default.stderr @@ -4,6 +4,7 @@ error: struct `T` is never constructed LL | struct T; | ^ | + = note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis note: the lint level is defined here --> $DIR/unused-struct-derive-default.rs:1:9 | diff --git a/tests/ui/parser/issues/issue-105366.fixed b/tests/ui/parser/issues/issue-105366.fixed index 95419dc07f2cc..7157b647524dd 100644 --- a/tests/ui/parser/issues/issue-105366.fixed +++ b/tests/ui/parser/issues/issue-105366.fixed @@ -1,6 +1,5 @@ //@ run-rustfix -#[allow(dead_code)] struct Foo; impl From for Foo { diff --git a/tests/ui/parser/issues/issue-105366.rs b/tests/ui/parser/issues/issue-105366.rs index 3278b73799125..dc3cb8b343d32 100644 --- a/tests/ui/parser/issues/issue-105366.rs +++ b/tests/ui/parser/issues/issue-105366.rs @@ -1,6 +1,5 @@ //@ run-rustfix -#[allow(dead_code)] struct Foo; fn From for Foo { diff --git a/tests/ui/parser/issues/issue-105366.stderr b/tests/ui/parser/issues/issue-105366.stderr index 195305a2ec889..18c04dfaf2088 100644 --- a/tests/ui/parser/issues/issue-105366.stderr +++ b/tests/ui/parser/issues/issue-105366.stderr @@ -1,5 +1,5 @@ error: you might have meant to write `impl` instead of `fn` - --> $DIR/issue-105366.rs:6:1 + --> $DIR/issue-105366.rs:5:1 | LL | fn From for Foo { | ^^ From 22da61624590a413c98df5087ff4454fcc618dbf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:29:01 -0400 Subject: [PATCH 422/489] Revert "Rollup merge of #126618 - mu001999-contrib:dead/enhance, r=pnkfelix" This reverts commit 2724aeaaeb127a8073e39461caacbe21a128ce7b, reversing changes made to d929a42a664c026167800801b26d734db925314f. --- compiler/rustc_passes/src/dead.rs | 41 ++++++++----------- .../ui/const-generics/cross_crate_complex.rs | 1 - .../missing-bounds.fixed | 4 -- .../missing-bounds.rs | 4 -- .../missing-bounds.stderr | 18 ++++---- .../dead-code/unused-trait-with-assoc-ty.rs | 11 ----- .../unused-trait-with-assoc-ty.stderr | 20 --------- tests/ui/pattern/issue-22546.rs | 2 +- tests/ui/pattern/issue-22546.stderr | 10 +++++ 9 files changed, 36 insertions(+), 75 deletions(-) delete mode 100644 tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs delete mode 100644 tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr create mode 100644 tests/ui/pattern/issue-22546.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 78fbcc1f40623..d4ce9b02473b0 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -156,10 +156,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_res(&mut self, res: Res) { match res { - Res::Def( - DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias, - def_id, - ) => { + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => { self.check_def_id(def_id); } _ if self.in_pat => {} @@ -470,7 +467,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_item(self, item) } hir::ItemKind::ForeignMod { .. } => {} - hir::ItemKind::Trait(_, _, _, _, trait_item_refs) => { + hir::ItemKind::Trait(..) => { for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) { if let Some(local_def_id) = impl_def_id.as_local() && let ItemKind::Impl(impl_ref) = @@ -483,12 +480,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_path(self, impl_ref.of_trait.unwrap().path); } } - // mark assoc ty live if the trait is live - for trait_item in trait_item_refs { - if let hir::AssocItemKind::Type = trait_item.kind { - self.check_def_id(trait_item.id.owner_id.to_def_id()); - } - } + intravisit::walk_item(self, item) } _ => intravisit::walk_item(self, item), @@ -505,8 +497,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && let ItemKind::Impl(impl_ref) = self.tcx.hir().expect_item(local_impl_id).kind { - if !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) - .ty_and_all_fields_are_public + if !matches!(trait_item.kind, hir::TraitItemKind::Type(..)) + && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) + .ty_and_all_fields_are_public { // skip impl-items of non pure pub ty, // cause we don't know the ty is constructed or not, @@ -845,8 +838,9 @@ fn check_item<'tcx>( // for trait impl blocks, // mark the method live if the self_ty is public, // or the method is public and may construct self - if tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || may_construct_self) + if of_trait && matches!(tcx.def_kind(local_def_id), DefKind::AssocTy) + || tcx.visibility(local_def_id).is_public() + && (ty_and_all_fields_are_public || may_construct_self) { // if the impl item is public, // and the ty may be constructed or can be constructed in foreign crates, @@ -883,13 +877,10 @@ fn check_trait_item( worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, id: hir::TraitItemId, ) { - use hir::TraitItemKind::{Const, Fn, Type}; - if matches!( - tcx.def_kind(id.owner_id), - DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn - ) { + use hir::TraitItemKind::{Const, Fn}; + if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { let trait_item = tcx.hir().trait_item(id); - if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..)) + if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..)) && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) { @@ -931,7 +922,7 @@ fn create_and_seed_worklist( // checks impls, impl-items and pub structs with all public fields later match tcx.def_kind(id) { DefKind::Impl { .. } => false, - DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), + DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), _ => true }) @@ -1218,7 +1209,6 @@ impl<'tcx> DeadVisitor<'tcx> { } match self.tcx.def_kind(def_id) { DefKind::AssocConst - | DefKind::AssocTy | DefKind::AssocFn | DefKind::Fn | DefKind::Static { .. } @@ -1260,14 +1250,15 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) { for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { - // We have diagnosed unused assocs in traits + // We have diagnosed unused assoc consts and fns in traits if matches!(def_kind, DefKind::Impl { of_trait: true }) - && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn) + && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocFn) // skip unused public inherent methods, // cause we have diagnosed unconstructed struct || matches!(def_kind, DefKind::Impl { of_trait: false }) && tcx.visibility(def_id).is_public() && ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public + || def_kind == DefKind::Trait && tcx.def_kind(def_id) == DefKind::AssocTy { continue; } diff --git a/tests/ui/const-generics/cross_crate_complex.rs b/tests/ui/const-generics/cross_crate_complex.rs index b44d889f5e99e..d13b69aa0cfb4 100644 --- a/tests/ui/const-generics/cross_crate_complex.rs +++ b/tests/ui/const-generics/cross_crate_complex.rs @@ -11,7 +11,6 @@ async fn foo() { async_in_foo(async_out_foo::<4>().await).await; } -#[allow(dead_code)] struct Faz; impl Foo for Faz {} diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed index ff69016d8626d..703d3c1e0fb17 100644 --- a/tests/ui/generic-associated-types/missing-bounds.fixed +++ b/tests/ui/generic-associated-types/missing-bounds.fixed @@ -2,7 +2,6 @@ use std::ops::Add; -#[allow(dead_code)] struct A(B); impl Add for A where B: Add { @@ -13,7 +12,6 @@ impl Add for A where B: Add { } } -#[allow(dead_code)] struct C(B); impl> Add for C { @@ -24,7 +22,6 @@ impl> Add for C { } } -#[allow(dead_code)] struct D(B); impl> Add for D { @@ -35,7 +32,6 @@ impl> Add for D { } } -#[allow(dead_code)] struct E(B); impl> Add for E where B: Add { diff --git a/tests/ui/generic-associated-types/missing-bounds.rs b/tests/ui/generic-associated-types/missing-bounds.rs index 1f83356c2fa6b..f40b422887311 100644 --- a/tests/ui/generic-associated-types/missing-bounds.rs +++ b/tests/ui/generic-associated-types/missing-bounds.rs @@ -2,7 +2,6 @@ use std::ops::Add; -#[allow(dead_code)] struct A(B); impl Add for A where B: Add { @@ -13,7 +12,6 @@ impl Add for A where B: Add { } } -#[allow(dead_code)] struct C(B); impl Add for C { @@ -24,7 +22,6 @@ impl Add for C { } } -#[allow(dead_code)] struct D(B); impl Add for D { @@ -35,7 +32,6 @@ impl Add for D { } } -#[allow(dead_code)] struct E(B); impl Add for E where ::Output = B { diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 0f0dc24c06c0f..1d7d80d1b0768 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -1,5 +1,5 @@ error: equality constraints are not yet supported in `where` clauses - --> $DIR/missing-bounds.rs:41:33 + --> $DIR/missing-bounds.rs:37:33 | LL | impl Add for E where ::Output = B { | ^^^^^^^^^^^^^^^^^^^^^^ not supported @@ -11,7 +11,7 @@ LL | impl Add for E where B: Add { | ~~~~~~~~~~~~~~~~~~ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:12:11 + --> $DIR/missing-bounds.rs:11:11 | LL | impl Add for A where B: Add { | - expected this type parameter @@ -24,14 +24,14 @@ LL | A(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` help: the type constructed contains `::Output` due to the type of the argument passed - --> $DIR/missing-bounds.rs:12:9 + --> $DIR/missing-bounds.rs:11:9 | LL | A(self.0 + rhs.0) | ^^--------------^ | | | this argument influences the type of `A` note: tuple struct defined here - --> $DIR/missing-bounds.rs:6:8 + --> $DIR/missing-bounds.rs:5:8 | LL | struct A(B); | ^ @@ -41,7 +41,7 @@ LL | impl Add for A where B: Add { | ++++++++++++ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:23:14 + --> $DIR/missing-bounds.rs:21:14 | LL | impl Add for C { | - expected this type parameter @@ -54,7 +54,7 @@ LL | Self(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` note: tuple struct defined here - --> $DIR/missing-bounds.rs:17:8 + --> $DIR/missing-bounds.rs:15:8 | LL | struct C(B); | ^ @@ -64,7 +64,7 @@ LL | impl> Add for C { | ++++++++++++ error[E0369]: cannot add `B` to `B` - --> $DIR/missing-bounds.rs:34:21 + --> $DIR/missing-bounds.rs:31:21 | LL | Self(self.0 + rhs.0) | ------ ^ ----- B @@ -77,7 +77,7 @@ LL | impl> Add for D { | +++++++++++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:46:14 + --> $DIR/missing-bounds.rs:42:14 | LL | impl Add for E where ::Output = B { | - expected this type parameter @@ -90,7 +90,7 @@ LL | Self(self.0 + rhs.0) = note: expected type parameter `B` found associated type `::Output` note: tuple struct defined here - --> $DIR/missing-bounds.rs:39:8 + --> $DIR/missing-bounds.rs:35:8 | LL | struct E(B); | ^ diff --git a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs deleted file mode 100644 index e8116d83ebf1c..0000000000000 --- a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![deny(dead_code)] - -struct T1; //~ ERROR struct `T1` is never constructed - -trait Foo { type Unused; } //~ ERROR trait `Foo` is never used -impl Foo for T1 { type Unused = Self; } - -pub trait Bar { type Used; } -impl Bar for T1 { type Used = Self; } - -fn main() {} diff --git a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr b/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr deleted file mode 100644 index ab73c64063431..0000000000000 --- a/tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: struct `T1` is never constructed - --> $DIR/unused-trait-with-assoc-ty.rs:3:8 - | -LL | struct T1; - | ^^ - | -note: the lint level is defined here - --> $DIR/unused-trait-with-assoc-ty.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: trait `Foo` is never used - --> $DIR/unused-trait-with-assoc-ty.rs:5:7 - | -LL | trait Foo { type Unused; } - | ^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/pattern/issue-22546.rs b/tests/ui/pattern/issue-22546.rs index d5c5b68be78d7..fd1d5fb6c4775 100644 --- a/tests/ui/pattern/issue-22546.rs +++ b/tests/ui/pattern/issue-22546.rs @@ -15,7 +15,7 @@ impl Foo { } } -trait Tr { +trait Tr { //~ WARN trait `Tr` is never used type U; } diff --git a/tests/ui/pattern/issue-22546.stderr b/tests/ui/pattern/issue-22546.stderr new file mode 100644 index 0000000000000..e067a95e4226c --- /dev/null +++ b/tests/ui/pattern/issue-22546.stderr @@ -0,0 +1,10 @@ +warning: trait `Tr` is never used + --> $DIR/issue-22546.rs:18:7 + | +LL | trait Tr { + | ^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + From d29818c9f552d6941bc00770e7aa1e2768e02e07 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:29:02 -0400 Subject: [PATCH 423/489] Revert "Rollup merge of #126315 - mu001999-contrib:fix/126289, r=petrochenkov" This reverts commit 977c5fd419ade52467f7de79d5bfc25c0c893275, reversing changes made to 24c94f0e4f5aa333c665fbbba423172c30176624. --- compiler/rustc_passes/src/dead.rs | 2 +- .../allow-unconstructed-pub-struct.rs | 33 ------------------- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d4ce9b02473b0..90f436a6fc1ae 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -923,7 +923,7 @@ fn create_and_seed_worklist( match tcx.def_kind(id) { DefKind::Impl { .. } => false, DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), - DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), + DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()), _ => true }) .map(|id| (id, ComesFromAllowExpect::No)) diff --git a/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs b/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs deleted file mode 100644 index 8cd1524045b15..0000000000000 --- a/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs +++ /dev/null @@ -1,33 +0,0 @@ -//@ check-pass - -mod ffi { - use super::*; - - extern "C" { - pub fn DomPromise_AddRef(promise: *const Promise); - pub fn DomPromise_Release(promise: *const Promise); - } -} - -#[repr(C)] -#[allow(unused)] -pub struct Promise { - private: [u8; 0], - __nosync: ::std::marker::PhantomData<::std::rc::Rc>, -} - -pub unsafe trait RefCounted { - unsafe fn addref(&self); - unsafe fn release(&self); -} - -unsafe impl RefCounted for Promise { - unsafe fn addref(&self) { - ffi::DomPromise_AddRef(self) - } - unsafe fn release(&self) { - ffi::DomPromise_Release(self) - } -} - -fn main() {} From ac56007ea7ba6f5bdf9c018f6561617fc5626e3d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:29:20 -0400 Subject: [PATCH 424/489] Revert "Rollup merge of #125572 - mu001999-contrib:dead/enhance, r=pnkfelix" This reverts commit 13314df21b0bb0cdd02c6760581d1b9f1052fa7e, reversing changes made to 6e534c73c35f569492ed5fb5f349075d58ed8b7e. --- compiler/rustc_passes/src/dead.rs | 121 ++++-------------- .../item-collection/generic-impl.rs | 10 +- .../item-collection/overloaded-operators.rs | 24 ++-- tests/ui/coherence/re-rebalance-coherence.rs | 1 - .../defaults/repr-c-issue-82792.rs | 1 - .../generic_const_exprs/associated-consts.rs | 3 +- .../transparent-maybeunit-array-wrapper.rs | 1 - ...lone-debug-dead-code-in-the-same-struct.rs | 4 +- ...-debug-dead-code-in-the-same-struct.stderr | 16 ++- tests/ui/issues/issue-5708.rs | 1 - tests/ui/lint/dead-code/lint-dead-code-1.rs | 5 +- .../ui/lint/dead-code/lint-dead-code-1.stderr | 26 +--- tests/ui/lint/dead-code/unused-assoc-const.rs | 20 --- .../lint/dead-code/unused-assoc-const.stderr | 16 --- tests/ui/lint/dead-code/unused-pub-struct.rs | 48 ------- .../lint/dead-code/unused-pub-struct.stderr | 14 -- ...re-clause-before-tuple-struct-body-0.fixed | 3 +- ...where-clause-before-tuple-struct-body-0.rs | 3 +- ...e-clause-before-tuple-struct-body-0.stderr | 10 +- tests/ui/pub/pub-ident-struct-4.fixed | 3 +- tests/ui/pub/pub-ident-struct-4.rs | 3 +- tests/ui/pub/pub-ident-struct-4.stderr | 8 +- tests/ui/regions/regions-issue-21422.rs | 1 - .../structs-enums/newtype-struct-with-dtor.rs | 2 - .../ui/structs-enums/uninstantiable-struct.rs | 3 +- .../ui/suggestions/derive-clone-for-eq.fixed | 1 - tests/ui/suggestions/derive-clone-for-eq.rs | 1 - .../ui/suggestions/derive-clone-for-eq.stderr | 4 +- .../ui/suggestions/option-content-move.fixed | 2 - tests/ui/suggestions/option-content-move.rs | 2 - .../ui/suggestions/option-content-move.stderr | 4 +- tests/ui/traits/object/generics.rs | 1 - 32 files changed, 89 insertions(+), 273 deletions(-) delete mode 100644 tests/ui/lint/dead-code/unused-assoc-const.rs delete mode 100644 tests/ui/lint/dead-code/unused-assoc-const.stderr delete mode 100644 tests/ui/lint/dead-code/unused-pub-struct.rs delete mode 100644 tests/ui/lint/dead-code/unused-pub-struct.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 90f436a6fc1ae..7ae5c9040042c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -17,7 +17,7 @@ use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, AssocItemContainer, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; @@ -44,63 +44,16 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { ) } -struct Publicness { - ty_is_public: bool, - ty_and_all_fields_are_public: bool, -} - -impl Publicness { - fn new(ty_is_public: bool, ty_and_all_fields_are_public: bool) -> Self { - Self { ty_is_public, ty_and_all_fields_are_public } - } -} - -fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool { - // treat PhantomData and positional ZST as public, - // we don't want to lint types which only have them, - // cause it's a common way to use such types to check things like well-formedness - tcx.adt_def(id).all_fields().all(|field| { - let field_type = tcx.type_of(field.did).instantiate_identity(); - if field_type.is_phantom_data() { - return true; - } - let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit()); - if is_positional - && tcx - .layout_of(tcx.param_env(field.did).and(field_type)) - .map_or(true, |layout| layout.is_zst()) - { - return true; - } - field.vis.is_public() - }) -} - -/// check struct and its fields are public or not, -/// for enum and union, just check they are public, -/// and doesn't solve types like &T for now, just skip them -fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness { +fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool { if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && let Res::Def(def_kind, def_id) = path.res && def_id.is_local() + && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) { - return match def_kind { - DefKind::Enum | DefKind::Union => { - let ty_is_public = tcx.visibility(def_id).is_public(); - Publicness::new(ty_is_public, ty_is_public) - } - DefKind::Struct => { - let ty_is_public = tcx.visibility(def_id).is_public(); - Publicness::new( - ty_is_public, - ty_is_public && struct_all_fields_are_public(tcx, def_id), - ) - } - _ => Publicness::new(true, true), - }; + tcx.visibility(def_id).is_public() + } else { + true } - - Publicness::new(true, true) } /// Determine if a work from the worklist is coming from a `#[allow]` @@ -499,11 +452,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { { if !matches!(trait_item.kind, hir::TraitItemKind::Type(..)) && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty) - .ty_and_all_fields_are_public { - // skip impl-items of non pure pub ty, - // cause we don't know the ty is constructed or not, - // check these later in `solve_rest_impl_items` + // skip methods of private ty, + // they would be solved in `solve_rest_impl_items` continue; } @@ -584,21 +535,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && let Some(local_def_id) = def_id.as_local() && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union) { + if self.tcx.visibility(impl_item_id).is_public() { + // for the public method, we don't know the trait item is used or not, + // so we mark the method live if the self is used + return self.live_symbols.contains(&local_def_id); + } + if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id && let Some(local_id) = trait_item_id.as_local() { - // for the local impl item, we can know the trait item is used or not, + // for the private method, we can know the trait item is used or not, // so we mark the method live if the self is used and the trait item is used - self.live_symbols.contains(&local_id) && self.live_symbols.contains(&local_def_id) - } else { - // for the foreign method and inherent pub method, - // we don't know the trait item or the method is used or not, - // so we mark the method live if the self is used - self.live_symbols.contains(&local_def_id) + return self.live_symbols.contains(&local_id) + && self.live_symbols.contains(&local_def_id); } - } else { - false } + false } } @@ -820,9 +772,7 @@ fn check_item<'tcx>( .iter() .filter_map(|def_id| def_id.as_local()); - let self_ty = tcx.hir().item(id).expect_impl().self_ty; - let Publicness { ty_is_public, ty_and_all_fields_are_public } = - ty_ref_to_pub_struct(tcx, self_ty); + let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty); // And we access the Map here to get HirId from LocalDefId for local_def_id in local_def_ids { @@ -838,20 +788,18 @@ fn check_item<'tcx>( // for trait impl blocks, // mark the method live if the self_ty is public, // or the method is public and may construct self - if of_trait && matches!(tcx.def_kind(local_def_id), DefKind::AssocTy) - || tcx.visibility(local_def_id).is_public() - && (ty_and_all_fields_are_public || may_construct_self) + if of_trait + && (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn) + || tcx.visibility(local_def_id).is_public() + && (ty_is_pub || may_construct_self)) { - // if the impl item is public, - // and the ty may be constructed or can be constructed in foreign crates, - // mark the impl item live worklist.push((local_def_id, ComesFromAllowExpect::No)); } else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, local_def_id) { worklist.push((local_def_id, comes_from_allow)); - } else if of_trait || tcx.visibility(local_def_id).is_public() && ty_is_public { - // private impl items of traits || public impl items not constructs self + } else if of_trait { + // private method || public method not constructs self unsolved_impl_items.push((id, local_def_id)); } } @@ -918,14 +866,6 @@ fn create_and_seed_worklist( effective_vis .is_public_at_level(Level::Reachable) .then_some(id) - .filter(|&id| - // checks impls, impl-items and pub structs with all public fields later - match tcx.def_kind(id) { - DefKind::Impl { .. } => false, - DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), - DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()), - _ => true - }) .map(|id| (id, ComesFromAllowExpect::No)) }) // Seed entry point @@ -1250,15 +1190,10 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) { for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { - // We have diagnosed unused assoc consts and fns in traits + // We have diagnosed unused methods in traits if matches!(def_kind, DefKind::Impl { of_trait: true }) - && matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocFn) - // skip unused public inherent methods, - // cause we have diagnosed unconstructed struct - || matches!(def_kind, DefKind::Impl { of_trait: false }) - && tcx.visibility(def_id).is_public() - && ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public - || def_kind == DefKind::Trait && tcx.def_kind(def_id) == DefKind::AssocTy + && tcx.def_kind(def_id) == DefKind::AssocFn + || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn { continue; } diff --git a/tests/codegen-units/item-collection/generic-impl.rs b/tests/codegen-units/item-collection/generic-impl.rs index b4cd99272b152..23d09e0d8af3e 100644 --- a/tests/codegen-units/item-collection/generic-impl.rs +++ b/tests/codegen-units/item-collection/generic-impl.rs @@ -22,16 +22,16 @@ impl Struct { } } -pub struct _LifeTimeOnly<'a> { +pub struct LifeTimeOnly<'a> { _a: &'a u32, } -impl<'a> _LifeTimeOnly<'a> { - //~ MONO_ITEM fn _LifeTimeOnly::<'_>::foo +impl<'a> LifeTimeOnly<'a> { + //~ MONO_ITEM fn LifeTimeOnly::<'_>::foo pub fn foo(&self) {} - //~ MONO_ITEM fn _LifeTimeOnly::<'_>::bar + //~ MONO_ITEM fn LifeTimeOnly::<'_>::bar pub fn bar(&'a self) {} - //~ MONO_ITEM fn _LifeTimeOnly::<'_>::baz + //~ MONO_ITEM fn LifeTimeOnly::<'_>::baz pub fn baz<'b>(&'b self) {} pub fn non_instantiated(&self) {} diff --git a/tests/codegen-units/item-collection/overloaded-operators.rs b/tests/codegen-units/item-collection/overloaded-operators.rs index e00e22dbab996..69b55695d3d30 100644 --- a/tests/codegen-units/item-collection/overloaded-operators.rs +++ b/tests/codegen-units/item-collection/overloaded-operators.rs @@ -5,44 +5,44 @@ use std::ops::{Add, Deref, Index, IndexMut}; -pub struct _Indexable { +pub struct Indexable { data: [u8; 3], } -impl Index for _Indexable { +impl Index for Indexable { type Output = u8; - //~ MONO_ITEM fn <_Indexable as std::ops::Index>::index + //~ MONO_ITEM fn >::index fn index(&self, index: usize) -> &Self::Output { if index >= 3 { &self.data[0] } else { &self.data[index] } } } -impl IndexMut for _Indexable { - //~ MONO_ITEM fn <_Indexable as std::ops::IndexMut>::index_mut +impl IndexMut for Indexable { + //~ MONO_ITEM fn >::index_mut fn index_mut(&mut self, index: usize) -> &mut Self::Output { if index >= 3 { &mut self.data[0] } else { &mut self.data[index] } } } -//~ MONO_ITEM fn <_Equatable as std::cmp::PartialEq>::eq -//~ MONO_ITEM fn <_Equatable as std::cmp::PartialEq>::ne +//~ MONO_ITEM fn ::eq +//~ MONO_ITEM fn ::ne #[derive(PartialEq)] -pub struct _Equatable(u32); +pub struct Equatable(u32); -impl Add for _Equatable { +impl Add for Equatable { type Output = u32; - //~ MONO_ITEM fn <_Equatable as std::ops::Add>::add + //~ MONO_ITEM fn >::add fn add(self, rhs: u32) -> u32 { self.0 + rhs } } -impl Deref for _Equatable { +impl Deref for Equatable { type Target = u32; - //~ MONO_ITEM fn <_Equatable as std::ops::Deref>::deref + //~ MONO_ITEM fn ::deref fn deref(&self) -> &Self::Target { &self.0 } diff --git a/tests/ui/coherence/re-rebalance-coherence.rs b/tests/ui/coherence/re-rebalance-coherence.rs index 5383a634617f4..9c176d5b1b12b 100644 --- a/tests/ui/coherence/re-rebalance-coherence.rs +++ b/tests/ui/coherence/re-rebalance-coherence.rs @@ -4,7 +4,6 @@ extern crate re_rebalance_coherence_lib as lib; use lib::*; -#[allow(dead_code)] struct Oracle; impl Backend for Oracle {} impl<'a, T:'a, Tab> QueryFragment for BatchInsert<'a, T, Tab> {} diff --git a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs index 4bf2fa761eae8..c23187598bceb 100644 --- a/tests/ui/const-generics/defaults/repr-c-issue-82792.rs +++ b/tests/ui/const-generics/defaults/repr-c-issue-82792.rs @@ -2,7 +2,6 @@ //@ run-pass -#[allow(dead_code)] #[repr(C)] pub struct Loaf { head: [T; N], diff --git a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs index 50a6102c605a9..5d2198f50ad92 100644 --- a/tests/ui/const-generics/generic_const_exprs/associated-consts.rs +++ b/tests/ui/const-generics/generic_const_exprs/associated-consts.rs @@ -16,8 +16,7 @@ impl BlockCipher for BarCipher { const BLOCK_SIZE: usize = 32; } -#[allow(dead_code)] -pub struct Block(C); +pub struct Block(#[allow(dead_code)] C); pub fn test() where diff --git a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs index 35c41ae461520..419d605d0c875 100644 --- a/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs +++ b/tests/ui/const-generics/transparent-maybeunit-array-wrapper.rs @@ -6,7 +6,6 @@ use std::mem::MaybeUninit; -#[allow(dead_code)] #[repr(transparent)] pub struct MaybeUninitWrapper(MaybeUninit<[u64; N]>); diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs index 885dacc727af6..6ab1fb7b039bd 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.rs @@ -1,9 +1,9 @@ #![forbid(dead_code)] #[derive(Debug)] -pub struct Whatever { //~ ERROR struct `Whatever` is never constructed +pub struct Whatever { pub field0: (), - field1: (), + field1: (), //~ ERROR fields `field1`, `field2`, `field3`, and `field4` are never read field2: (), field3: (), field4: (), diff --git a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr index e10d28ad03a4e..e9b757b6bae72 100644 --- a/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr +++ b/tests/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr @@ -1,9 +1,19 @@ -error: struct `Whatever` is never constructed - --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:4:12 +error: fields `field1`, `field2`, `field3`, and `field4` are never read + --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:6:5 | LL | pub struct Whatever { - | ^^^^^^^^ + | -------- fields in this struct +LL | pub field0: (), +LL | field1: (), + | ^^^^^^ +LL | field2: (), + | ^^^^^^ +LL | field3: (), + | ^^^^^^ +LL | field4: (), + | ^^^^^^ | + = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis note: the lint level is defined here --> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11 | diff --git a/tests/ui/issues/issue-5708.rs b/tests/ui/issues/issue-5708.rs index 89ea9fbdcd8fe..ce9ef78ffcd9c 100644 --- a/tests/ui/issues/issue-5708.rs +++ b/tests/ui/issues/issue-5708.rs @@ -44,7 +44,6 @@ pub trait MyTrait { fn dummy(&self, t: T) -> T { panic!() } } -#[allow(dead_code)] pub struct MyContainer<'a, T:'a> { foos: Vec<&'a (dyn MyTrait+'a)> , } diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.rs b/tests/ui/lint/dead-code/lint-dead-code-1.rs index 3386dfa47470f..ddcafedf7bc5f 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-1.rs +++ b/tests/ui/lint/dead-code/lint-dead-code-1.rs @@ -46,10 +46,11 @@ struct SemiUsedStruct; impl SemiUsedStruct { fn la_la_la() {} } -struct StructUsedAsField; //~ ERROR struct `StructUsedAsField` is never constructed +struct StructUsedAsField; pub struct StructUsedInEnum; struct StructUsedInGeneric; -pub struct PubStruct2 { //~ ERROR struct `PubStruct2` is never constructed +pub struct PubStruct2 { + #[allow(dead_code)] struct_used_as_field: *const StructUsedAsField } diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.stderr b/tests/ui/lint/dead-code/lint-dead-code-1.stderr index b0163df8855cd..eb728b5b93055 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/tests/ui/lint/dead-code/lint-dead-code-1.stderr @@ -22,26 +22,14 @@ error: struct `PrivStruct` is never constructed LL | struct PrivStruct; | ^^^^^^^^^^ -error: struct `StructUsedAsField` is never constructed - --> $DIR/lint-dead-code-1.rs:49:8 - | -LL | struct StructUsedAsField; - | ^^^^^^^^^^^^^^^^^ - -error: struct `PubStruct2` is never constructed - --> $DIR/lint-dead-code-1.rs:52:12 - | -LL | pub struct PubStruct2 { - | ^^^^^^^^^^ - error: enum `priv_enum` is never used - --> $DIR/lint-dead-code-1.rs:63:6 + --> $DIR/lint-dead-code-1.rs:64:6 | LL | enum priv_enum { foo2, bar2 } | ^^^^^^^^^ error: variant `bar3` is never constructed - --> $DIR/lint-dead-code-1.rs:66:5 + --> $DIR/lint-dead-code-1.rs:67:5 | LL | enum used_enum { | --------- variant in this enum @@ -50,25 +38,25 @@ LL | bar3 | ^^^^ error: function `priv_fn` is never used - --> $DIR/lint-dead-code-1.rs:87:4 + --> $DIR/lint-dead-code-1.rs:88:4 | LL | fn priv_fn() { | ^^^^^^^ error: function `foo` is never used - --> $DIR/lint-dead-code-1.rs:92:4 + --> $DIR/lint-dead-code-1.rs:93:4 | LL | fn foo() { | ^^^ error: function `bar` is never used - --> $DIR/lint-dead-code-1.rs:97:4 + --> $DIR/lint-dead-code-1.rs:98:4 | LL | fn bar() { | ^^^ error: function `baz` is never used - --> $DIR/lint-dead-code-1.rs:101:4 + --> $DIR/lint-dead-code-1.rs:102:4 | LL | fn baz() -> impl Copy { | ^^^ @@ -79,5 +67,5 @@ error: struct `Bar` is never constructed LL | pub struct Bar; | ^^^ -error: aborting due to 12 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui/lint/dead-code/unused-assoc-const.rs b/tests/ui/lint/dead-code/unused-assoc-const.rs deleted file mode 100644 index 36e8315ad3605..0000000000000 --- a/tests/ui/lint/dead-code/unused-assoc-const.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![deny(dead_code)] - -trait Trait { - const UNUSED_CONST: i32; //~ ERROR associated constant `UNUSED_CONST` is never used - const USED_CONST: i32; - - fn foo(&self) {} -} - -pub struct T(()); - -impl Trait for T { - const UNUSED_CONST: i32 = 0; - const USED_CONST: i32 = 1; -} - -fn main() { - T(()).foo(); - T::USED_CONST; -} diff --git a/tests/ui/lint/dead-code/unused-assoc-const.stderr b/tests/ui/lint/dead-code/unused-assoc-const.stderr deleted file mode 100644 index 78296d706638b..0000000000000 --- a/tests/ui/lint/dead-code/unused-assoc-const.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: associated constant `UNUSED_CONST` is never used - --> $DIR/unused-assoc-const.rs:4:11 - | -LL | trait Trait { - | ----- associated constant in this trait -LL | const UNUSED_CONST: i32; - | ^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/unused-assoc-const.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/lint/dead-code/unused-pub-struct.rs b/tests/ui/lint/dead-code/unused-pub-struct.rs deleted file mode 100644 index aaf4dd612de4d..0000000000000 --- a/tests/ui/lint/dead-code/unused-pub-struct.rs +++ /dev/null @@ -1,48 +0,0 @@ -#![deny(dead_code)] - -pub struct NotLint1(()); -pub struct NotLint2(std::marker::PhantomData); - -pub struct NeverConstructed(i32); //~ ERROR struct `NeverConstructed` is never constructed - -impl NeverConstructed { - pub fn not_construct_self(&self) {} -} - -impl Clone for NeverConstructed { - fn clone(&self) -> NeverConstructed { - NeverConstructed(0) - } -} - -pub trait Trait { - fn not_construct_self(&self); -} - -impl Trait for NeverConstructed { - fn not_construct_self(&self) { - self.0; - } -} - -pub struct Constructed(i32); - -impl Constructed { - pub fn construct_self() -> Self { - Constructed(0) - } -} - -impl Clone for Constructed { - fn clone(&self) -> Constructed { - Constructed(0) - } -} - -impl Trait for Constructed { - fn not_construct_self(&self) { - self.0; - } -} - -fn main() {} diff --git a/tests/ui/lint/dead-code/unused-pub-struct.stderr b/tests/ui/lint/dead-code/unused-pub-struct.stderr deleted file mode 100644 index 3667ddb97bd3e..0000000000000 --- a/tests/ui/lint/dead-code/unused-pub-struct.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: struct `NeverConstructed` is never constructed - --> $DIR/unused-pub-struct.rs:6:12 - | -LL | pub struct NeverConstructed(i32); - | ^^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/unused-pub-struct.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed index e9c89807fa566..a851300a9828e 100644 --- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed +++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.fixed @@ -1,8 +1,7 @@ // Regression test for issues #100790 and #106439. //@ run-rustfix -#[allow(dead_code)] -pub struct Example(usize) +pub struct Example(#[allow(dead_code)] usize) where (): Sized; //~^^^ ERROR where clauses are not allowed before tuple struct bodies diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs index 3bd0f51ec2cbe..10f435859f15a 100644 --- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs +++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.rs @@ -1,11 +1,10 @@ // Regression test for issues #100790 and #106439. //@ run-rustfix -#[allow(dead_code)] pub struct Example where (): Sized, -(usize); +(#[allow(dead_code)] usize); //~^^^ ERROR where clauses are not allowed before tuple struct bodies struct _Demo diff --git a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr index 77eafa6bea336..ddbf237e8662b 100644 --- a/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr +++ b/tests/ui/parser/recover/recover-where-clause-before-tuple-struct-body-0.stderr @@ -1,23 +1,23 @@ error: where clauses are not allowed before tuple struct bodies - --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:6:1 + --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:5:1 | LL | pub struct Example | ------- while parsing this tuple struct LL | / where LL | | (): Sized, | |______________^ unexpected where clause -LL | (usize); - | ------- the struct body +LL | (#[allow(dead_code)] usize); + | --------------------------- the struct body | help: move the body before the where clause | -LL ~ pub struct Example(usize) +LL ~ pub struct Example(#[allow(dead_code)] usize) LL | where LL ~ (): Sized; | error: where clauses are not allowed before tuple struct bodies - --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:12:1 + --> $DIR/recover-where-clause-before-tuple-struct-body-0.rs:11:1 | LL | struct _Demo | ----- while parsing this tuple struct diff --git a/tests/ui/pub/pub-ident-struct-4.fixed b/tests/ui/pub/pub-ident-struct-4.fixed index a62ece43eced3..5fedbb7243749 100644 --- a/tests/ui/pub/pub-ident-struct-4.fixed +++ b/tests/ui/pub/pub-ident-struct-4.fixed @@ -1,7 +1,6 @@ //@ run-rustfix -#[allow(dead_code)] -pub struct T(String); +pub struct T(#[allow(dead_code)] String); //~^ ERROR missing `struct` for struct definition fn main() {} diff --git a/tests/ui/pub/pub-ident-struct-4.rs b/tests/ui/pub/pub-ident-struct-4.rs index 0d56a31beaf1c..5c721c25a7815 100644 --- a/tests/ui/pub/pub-ident-struct-4.rs +++ b/tests/ui/pub/pub-ident-struct-4.rs @@ -1,7 +1,6 @@ //@ run-rustfix -#[allow(dead_code)] -pub T(String); +pub T(#[allow(dead_code)] String); //~^ ERROR missing `struct` for struct definition fn main() {} diff --git a/tests/ui/pub/pub-ident-struct-4.stderr b/tests/ui/pub/pub-ident-struct-4.stderr index d3072464e05cd..e04fff1ebf4a9 100644 --- a/tests/ui/pub/pub-ident-struct-4.stderr +++ b/tests/ui/pub/pub-ident-struct-4.stderr @@ -1,12 +1,12 @@ error: missing `struct` for struct definition - --> $DIR/pub-ident-struct-4.rs:4:1 + --> $DIR/pub-ident-struct-4.rs:3:4 | -LL | pub T(String); - | ^^^^^ +LL | pub T(#[allow(dead_code)] String); + | ^ | help: add `struct` here to parse `T` as a struct | -LL | pub struct T(String); +LL | pub struct T(#[allow(dead_code)] String); | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-issue-21422.rs b/tests/ui/regions/regions-issue-21422.rs index 67852a6f5de0d..54beed9b3ac2b 100644 --- a/tests/ui/regions/regions-issue-21422.rs +++ b/tests/ui/regions/regions-issue-21422.rs @@ -5,7 +5,6 @@ //@ pretty-expanded FIXME #23616 -#[allow(dead_code)] pub struct P<'a> { _ptr: *const &'a u8, } diff --git a/tests/ui/structs-enums/newtype-struct-with-dtor.rs b/tests/ui/structs-enums/newtype-struct-with-dtor.rs index 16439a7fedd3e..19672e41c9a30 100644 --- a/tests/ui/structs-enums/newtype-struct-with-dtor.rs +++ b/tests/ui/structs-enums/newtype-struct-with-dtor.rs @@ -3,10 +3,8 @@ #![allow(unused_variables)] //@ pretty-expanded FIXME #23616 -#[allow(dead_code)] pub struct Fd(u32); -#[allow(dead_code)] fn foo(a: u32) {} impl Drop for Fd { diff --git a/tests/ui/structs-enums/uninstantiable-struct.rs b/tests/ui/structs-enums/uninstantiable-struct.rs index 1074dbcd6e6b5..97bc7d8414e7f 100644 --- a/tests/ui/structs-enums/uninstantiable-struct.rs +++ b/tests/ui/structs-enums/uninstantiable-struct.rs @@ -1,5 +1,4 @@ //@ run-pass -#[allow(dead_code)] -pub struct Z(&'static Z); +pub struct Z(#[allow(dead_code)] &'static Z); pub fn main() {} diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed index cf800c6e47d87..4dc362f947875 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.fixed +++ b/tests/ui/suggestions/derive-clone-for-eq.fixed @@ -1,7 +1,6 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[allow(dead_code)] #[derive(Clone, Eq)] //~ ERROR [E0277] pub struct Struct(T); diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs index 84736426bac0d..b3635000f1658 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.rs +++ b/tests/ui/suggestions/derive-clone-for-eq.rs @@ -1,7 +1,6 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[allow(dead_code)] #[derive(Clone, Eq)] //~ ERROR [E0277] pub struct Struct(T); diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index 54670fbffcfb9..6fae6e1316df0 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/derive-clone-for-eq.rs:5:17 + --> $DIR/derive-clone-for-eq.rs:4:17 | LL | #[derive(Clone, Eq)] | ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct: PartialEq` | note: required for `Struct` to implement `PartialEq` - --> $DIR/derive-clone-for-eq.rs:8:19 + --> $DIR/derive-clone-for-eq.rs:7:19 | LL | impl PartialEq for Struct | ----- ^^^^^^^^^^^^ ^^^^^^^^^ diff --git a/tests/ui/suggestions/option-content-move.fixed b/tests/ui/suggestions/option-content-move.fixed index ef07d55871e7e..4a5a9483c20c8 100644 --- a/tests/ui/suggestions/option-content-move.fixed +++ b/tests/ui/suggestions/option-content-move.fixed @@ -1,5 +1,4 @@ //@ run-rustfix -#[allow(dead_code)] pub struct LipogramCorpora { selections: Vec<(char, Option)>, } @@ -18,7 +17,6 @@ impl LipogramCorpora { } } -#[allow(dead_code)] pub struct LipogramCorpora2 { selections: Vec<(char, Result)>, } diff --git a/tests/ui/suggestions/option-content-move.rs b/tests/ui/suggestions/option-content-move.rs index 5be6358fd6a57..90d05c7439970 100644 --- a/tests/ui/suggestions/option-content-move.rs +++ b/tests/ui/suggestions/option-content-move.rs @@ -1,5 +1,4 @@ //@ run-rustfix -#[allow(dead_code)] pub struct LipogramCorpora { selections: Vec<(char, Option)>, } @@ -18,7 +17,6 @@ impl LipogramCorpora { } } -#[allow(dead_code)] pub struct LipogramCorpora2 { selections: Vec<(char, Result)>, } diff --git a/tests/ui/suggestions/option-content-move.stderr b/tests/ui/suggestions/option-content-move.stderr index b4ec5b180d210..a382a04344aeb 100644 --- a/tests/ui/suggestions/option-content-move.stderr +++ b/tests/ui/suggestions/option-content-move.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `selection.1` which is behind a shared reference - --> $DIR/option-content-move.rs:11:20 + --> $DIR/option-content-move.rs:10:20 | LL | if selection.1.unwrap().contains(selection.0) { | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call @@ -19,7 +19,7 @@ LL | if selection.1.clone().unwrap().contains(selection.0) { | ++++++++ error[E0507]: cannot move out of `selection.1` which is behind a shared reference - --> $DIR/option-content-move.rs:30:20 + --> $DIR/option-content-move.rs:28:20 | LL | if selection.1.unwrap().contains(selection.0) { | ^^^^^^^^^^^ -------- `selection.1` moved due to this method call diff --git a/tests/ui/traits/object/generics.rs b/tests/ui/traits/object/generics.rs index 0ae562c0d30a0..462b0bc5bb77f 100644 --- a/tests/ui/traits/object/generics.rs +++ b/tests/ui/traits/object/generics.rs @@ -7,7 +7,6 @@ pub trait Trait2 { fn doit(&self) -> A; } -#[allow(dead_code)] pub struct Impl { m1: marker::PhantomData<(A1,A2,A3)>, /* From cbd27db9a996661792bbbd1dde7ac476eded8340 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:16:33 -0400 Subject: [PATCH 425/489] Suppress new false-negatives that were masked by dead code analysis changes --- library/std/src/sys/pal/unix/pipe.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index 8762af614f17e..f0ebc767badad 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -47,6 +47,8 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { } impl AnonPipe { + #[allow(dead_code)] + // FIXME: This function seems legitimately unused. pub fn try_clone(&self) -> io::Result { self.0.duplicate().map(Self) } @@ -85,6 +87,8 @@ impl AnonPipe { self.0.is_write_vectored() } + #[allow(dead_code)] + // FIXME: This function seems legitimately unused. pub fn as_file_desc(&self) -> &FileDesc { &self.0 } From a57b8b91dbcb1cc3768c0a2a2a0c4971ed01b2f0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Jul 2024 12:23:41 -0400 Subject: [PATCH 426/489] Bless test fallout --- tests/ui-fulldeps/deriving-global.rs | 3 +++ tests/ui-fulldeps/deriving-hygiene.rs | 1 + .../unused-adt-impl-pub-trait-with-assoc-const.rs | 2 +- .../unused-adt-impl-pub-trait-with-assoc-const.stderr | 10 +++++++--- tests/ui/pub/pub-ident-struct-4.stderr | 4 ++-- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/ui-fulldeps/deriving-global.rs b/tests/ui-fulldeps/deriving-global.rs index 7783010be441d..0ba149c9ad654 100644 --- a/tests/ui-fulldeps/deriving-global.rs +++ b/tests/ui-fulldeps/deriving-global.rs @@ -17,18 +17,21 @@ mod submod { // if any of these are implemented without global calls for any // function calls, then being in a submodule will (correctly) // cause errors about unrecognised module `std` (or `extra`) + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] enum A { A1(usize), A2(isize), } + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct B { x: usize, y: isize, } + #[allow(dead_code)] #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)] struct C(usize, isize); } diff --git a/tests/ui-fulldeps/deriving-hygiene.rs b/tests/ui-fulldeps/deriving-hygiene.rs index a3a6f9e022ebb..f948d6ac544e5 100644 --- a/tests/ui-fulldeps/deriving-hygiene.rs +++ b/tests/ui-fulldeps/deriving-hygiene.rs @@ -20,6 +20,7 @@ pub const s: u8 = 1; pub const state: u8 = 1; pub const cmp: u8 = 1; +#[allow(dead_code)] #[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Decodable, Encodable, Hash)] struct Foo {} diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs index bf2fc243e8194..5b755d62a0598 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.rs @@ -1,7 +1,7 @@ #![deny(dead_code)] struct T1; //~ ERROR struct `T1` is never constructed -pub struct T2(i32); //~ ERROR struct `T2` is never constructed +pub struct T2(i32); //~ ERROR field `0` is never read struct T3; trait Trait1 { //~ ERROR trait `Trait1` is never used diff --git a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr index 174096d939883..2441a3f868dc2 100644 --- a/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr +++ b/tests/ui/lint/dead-code/unused-adt-impl-pub-trait-with-assoc-const.stderr @@ -10,11 +10,15 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: struct `T2` is never constructed - --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:12 +error: field `0` is never read + --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:4:15 | LL | pub struct T2(i32); - | ^^ + | -- ^^^ + | | + | field in this struct + | + = help: consider removing this field error: trait `Trait1` is never used --> $DIR/unused-adt-impl-pub-trait-with-assoc-const.rs:7:7 diff --git a/tests/ui/pub/pub-ident-struct-4.stderr b/tests/ui/pub/pub-ident-struct-4.stderr index e04fff1ebf4a9..04965a1a73720 100644 --- a/tests/ui/pub/pub-ident-struct-4.stderr +++ b/tests/ui/pub/pub-ident-struct-4.stderr @@ -1,8 +1,8 @@ error: missing `struct` for struct definition - --> $DIR/pub-ident-struct-4.rs:3:4 + --> $DIR/pub-ident-struct-4.rs:3:1 | LL | pub T(#[allow(dead_code)] String); - | ^ + | ^^^^^ | help: add `struct` here to parse `T` as a struct | From 106cf7bec2019aa92912e1df1f4d045f6435bc9a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 3 Aug 2024 07:57:23 -0400 Subject: [PATCH 427/489] Remove another false-negative hidden by dead code changes --- src/bootstrap/src/core/build_steps/check.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 8b71300cf85e7..7f7faf077d047 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -31,10 +31,6 @@ pub struct Std { } impl Std { - pub fn new(target: TargetSelection) -> Self { - Self::new_with_build_kind(target, None) - } - pub fn new_with_build_kind(target: TargetSelection, kind: Option) -> Self { Self { target, crates: vec![], override_build_kind: kind } } From b564b70d1cb3678108f9045e8fcf2627270d544b Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 12:26:50 +0000 Subject: [PATCH 428/489] Update run-make/used to use `any_symbol_contains` --- tests/run-make/used/rmake.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs index 56ef5c6b9cc0c..eb5d026feda1f 100644 --- a/tests/run-make/used/rmake.rs +++ b/tests/run-make/used/rmake.rs @@ -4,12 +4,11 @@ // It comes from #39987 which implements this RFC for the #[used] attribute: // https://rust-lang.github.io/rfcs/2386-used.html -//@ ignore-msvc - -use run_make_support::{cmd, rustc}; +use run_make_support::rustc; +use run_make_support::symbols::any_symbol_contains; fn main() { rustc().opt_level("3").emit("obj").input("used.rs").run(); - - cmd("nm").arg("used.o").run().assert_stdout_contains("FOO"); + assert!(any_symbol_contains("used.o", &["FOO"])); + assert!(!any_symbol_contains("used.o", &["BAR"])); } From eb451464a7557f2d8115183a92e6a300d20d75e5 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 13:01:34 +0000 Subject: [PATCH 429/489] Remove BAR for run-make/used.rs --- tests/run-make/used/rmake.rs | 1 - tests/run-make/used/used.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs index eb5d026feda1f..39f36b2eea8f6 100644 --- a/tests/run-make/used/rmake.rs +++ b/tests/run-make/used/rmake.rs @@ -10,5 +10,4 @@ use run_make_support::symbols::any_symbol_contains; fn main() { rustc().opt_level("3").emit("obj").input("used.rs").run(); assert!(any_symbol_contains("used.o", &["FOO"])); - assert!(!any_symbol_contains("used.o", &["BAR"])); } diff --git a/tests/run-make/used/used.rs b/tests/run-make/used/used.rs index dca0a5e1167a8..133f8121a8e91 100644 --- a/tests/run-make/used/used.rs +++ b/tests/run-make/used/used.rs @@ -2,5 +2,3 @@ #[used] static FOO: u32 = 0; - -static BAR: u32 = 0; From a3a09b488fde8fbe66c2be44491cdb87201d32a2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 3 Aug 2024 00:14:45 +0200 Subject: [PATCH 430/489] Simplify `body` usage in rustdoc --- src/librustdoc/html/static/js/main.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index e0ea234f9e710..ee771a40595ab 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1115,8 +1115,7 @@ function preLoadCss(cssUrl) { wrapper.style.left = 0; wrapper.style.right = "auto"; wrapper.style.visibility = "hidden"; - const body = document.getElementsByTagName("body")[0]; - body.appendChild(wrapper); + document.body.appendChild(wrapper); const wrapperPos = wrapper.getBoundingClientRect(); // offset so that the arrow points at the center of the "(i)" const finalPos = pos.left + window.scrollX - wrapperPos.width + 24; @@ -1235,8 +1234,7 @@ function preLoadCss(cssUrl) { } window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE = false; } - const body = document.getElementsByTagName("body")[0]; - body.removeChild(window.CURRENT_TOOLTIP_ELEMENT); + document.body.removeChild(window.CURRENT_TOOLTIP_ELEMENT); clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT); window.CURRENT_TOOLTIP_ELEMENT = null; } @@ -1833,7 +1831,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm let elem = event.target; while (!hasClass(elem, "example-wrap")) { elem = elem.parentElement; - if (elem.tagName === "body" || hasClass(elem, "docblock")) { + if (elem === document.body || hasClass(elem, "docblock")) { return null; } } From c2523c954360b5e96fcbbac554573c87d3cf6dcc Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 14:56:16 +0000 Subject: [PATCH 431/489] Use object in run-make/symbols-visibility --- tests/run-make/symbol-visibility/rmake.rs | 76 ++++++++++------------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs index b37ff44f4ead6..488b0886ed7de 100644 --- a/tests/run-make/symbol-visibility/rmake.rs +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -4,12 +4,8 @@ // are exported, and that generics are only shown if explicitely requested. // See https://github.com/rust-lang/rust/issues/37530 -//@ ignore-windows-msvc - -//FIXME(Oneirical): This currently uses llvm-nm for symbol detection. However, -// the custom Rust-based solution of #128314 may prove to be an interesting alternative. - -use run_make_support::{bin_name, dynamic_lib_name, is_darwin, is_windows, llvm_nm, regex, rustc}; +use run_make_support::object::read::Object; +use run_make_support::{bin_name, dynamic_lib_name, is_msvc, object, regex, rfs, rustc}; fn main() { let cdylib_name = dynamic_lib_name("a_cdylib"); @@ -64,16 +60,15 @@ fn main() { ); // FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 - // if is_windows() { - // // Check that an executable does not export any dynamic symbols - // symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib") - //, false); - // symbols_check( - // &exe_name, - // SymbolCheckType::StrSymbol("public_rust_function_from_exe"), - // false, - // ); - // } + if is_msvc() { + // Check that an executable does not export any dynamic symbols + symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), false); + symbols_check( + &exe_name, + SymbolCheckType::StrSymbol("public_rust_function_from_exe"), + false, + ); + } // Check the combined case, where we generate a cdylib and an rlib in the same // compilation session: @@ -131,44 +126,37 @@ fn main() { ); // FIXME(nbdd0121): This is broken in MinGW, see https://github.com/rust-lang/rust/pull/95604#issuecomment-1101564032 - // if is_windows() { - // // Check that an executable does not export any dynamic symbols - // symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib") - //, false); - // symbols_check( - // &exe_name, - // SymbolCheckType::StrSymbol("public_rust_function_from_exe"), - // false, - // ); - // } + if is_msvc() { + // Check that an executable does not export any dynamic symbols + symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), false); + symbols_check( + &exe_name, + SymbolCheckType::StrSymbol("public_rust_function_from_exe"), + false, + ); + } } #[track_caller] fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) { - let mut nm = llvm_nm(); - if is_windows() { - nm.arg("--extern-only"); - } else if is_darwin() { - nm.arg("--extern-only").arg("--defined-only"); - } else { - nm.arg("--dynamic"); + let binary_data = rfs::read(path); + let file = object::File::parse(&*binary_data).unwrap(); + let mut found: u64 = 0; + for export in file.exports().unwrap() { + let name = std::str::from_utf8(export.name()).unwrap(); + if has_symbol(name, symbol_check_type) { + found += 1; + } } - let out = nm.input(path).run().stdout_utf8(); - assert_eq!( - out.lines() - .filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type)) - .count() - == 1, - exists_once - ); + assert_eq!(found, exists_once as u64); } -fn has_symbol(line: &str, symbol_check_type: SymbolCheckType) -> bool { +fn has_symbol(name: &str, symbol_check_type: SymbolCheckType) -> bool { if let SymbolCheckType::StrSymbol(expected) = symbol_check_type { - line.contains(expected) + !name.contains("__imp_") && name.contains(expected) } else { let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap(); - regex.is_match(line) + regex.is_match(name) } } From 36a805939e6e9d4bdff03c28bc1ad9dbd36bdb95 Mon Sep 17 00:00:00 2001 From: Christopher Swenson Date: Sat, 3 Aug 2024 08:49:38 -0700 Subject: [PATCH 432/489] Remove unnecessary constants from flt2dec dragon The "dragon" `flt2dec` algorithm uses multi-precision multiplication by (sometimes large) powers of 10. It has precomputed some values to help with these calculations. BUT: * There is no need to store powers of 10 and 2 * powers of 10: it is trivial to compute the second from the first. * We can save a chunk of memory by storing powers of 5 instead of powers of 10 for the large powers (and just shifting by 2 as appropriate). * This also slightly speeds up the routines (by ~1-3%) since the intermediate products are smaller and the shift is cheap. In this PR, we remove the unnecessary constants and do the necessary adjustments. Relevant benchmarks before (on my Threadripper 3970X, x86_64-unknown-linux-gnu): ``` num::flt2dec::bench_big_shortest 137.92/iter +/- 2.24 num::flt2dec::strategy::dragon::bench_big_exact_12 2135.28/iter +/- 38.90 num::flt2dec::strategy::dragon::bench_big_exact_3 904.95/iter +/- 10.58 num::flt2dec::strategy::dragon::bench_big_exact_inf 47230.33/iter +/- 320.84 num::flt2dec::strategy::dragon::bench_big_shortest 3915.05/iter +/- 51.37 ``` and after: ``` num::flt2dec::bench_big_shortest 137.40/iter +/- 2.03 num::flt2dec::strategy::dragon::bench_big_exact_12 2101.10/iter +/- 25.63 num::flt2dec::strategy::dragon::bench_big_exact_3 873.86/iter +/- 4.20 num::flt2dec::strategy::dragon::bench_big_exact_inf 47468.19/iter +/- 374.45 num::flt2dec::strategy::dragon::bench_big_shortest 3877.01/iter +/- 45.74 ``` --- .../core/src/num/flt2dec/strategy/dragon.rs | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/library/core/src/num/flt2dec/strategy/dragon.rs b/library/core/src/num/flt2dec/strategy/dragon.rs index 751edd3c79383..f8db6370653ab 100644 --- a/library/core/src/num/flt2dec/strategy/dragon.rs +++ b/library/core/src/num/flt2dec/strategy/dragon.rs @@ -12,48 +12,51 @@ use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS}; static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; -static TWOPOW10: [Digit; 10] = - [2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000]; - -// precalculated arrays of `Digit`s for 10^(2^n) -static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2]; -static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee]; -static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03]; -static POW10TO128: [Digit; 14] = [ - 0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, - 0xa6337f19, 0xe91f2603, 0x24e, +// precalculated arrays of `Digit`s for 5^(2^n). +static POW5TO16: [Digit; 2] = [0x86f26fc1, 0x23]; +static POW5TO32: [Digit; 3] = [0x85acef81, 0x2d6d415b, 0x4ee]; +static POW5TO64: [Digit; 5] = [0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03]; +static POW5TO128: [Digit; 10] = [ + 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, 0xa6337f19, + 0xe91f2603, 0x24e, ]; -static POW10TO256: [Digit; 27] = [ - 0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, - 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, - 0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7, +static POW5TO256: [Digit; 19] = [ + 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, 0x26b2716e, + 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, + 0xf46eeddc, 0x5fdcefce, 0x553f7, ]; #[doc(hidden)] pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big { debug_assert!(n < 512); + // Save ourself the left shift for the smallest cases. + if n < 8 { + return x.mul_small(POW10[n & 7]); + } + // Multiply by the powers of 5 and shift the 2s in at the end. + // This keeps the intermediate products smaller and faster. if n & 7 != 0 { - x.mul_small(POW10[n & 7]); + x.mul_small(POW10[n & 7] >> (n & 7)); } if n & 8 != 0 { - x.mul_small(POW10[8]); + x.mul_small(POW10[8] >> 8); } if n & 16 != 0 { - x.mul_digits(&POW10TO16); + x.mul_digits(&POW5TO16); } if n & 32 != 0 { - x.mul_digits(&POW10TO32); + x.mul_digits(&POW5TO32); } if n & 64 != 0 { - x.mul_digits(&POW10TO64); + x.mul_digits(&POW5TO64); } if n & 128 != 0 { - x.mul_digits(&POW10TO128); + x.mul_digits(&POW5TO128); } if n & 256 != 0 { - x.mul_digits(&POW10TO256); + x.mul_digits(&POW5TO256); } - x + x.mul_pow2(n) } fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big { @@ -62,7 +65,7 @@ fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big { x.div_rem_small(POW10[largest]); n -= largest; } - x.div_rem_small(TWOPOW10[n]); + x.div_rem_small(POW10[n] << 1); x } From f28d1570912c37fad69439bac7fce40d46e8ef3a Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 16:04:37 +0000 Subject: [PATCH 433/489] Update rmake.rs --- tests/run-make/symbol-visibility/rmake.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs index 488b0886ed7de..997eaf793d261 100644 --- a/tests/run-make/symbol-visibility/rmake.rs +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -144,7 +144,7 @@ fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bo let mut found: u64 = 0; for export in file.exports().unwrap() { let name = std::str::from_utf8(export.name()).unwrap(); - if has_symbol(name, symbol_check_type) { + if !name.contains("__imp_") && has_symbol(name, symbol_check_type) { found += 1; } } @@ -153,7 +153,7 @@ fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bo fn has_symbol(name: &str, symbol_check_type: SymbolCheckType) -> bool { if let SymbolCheckType::StrSymbol(expected) = symbol_check_type { - !name.contains("__imp_") && name.contains(expected) + name.contains(expected) } else { let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap(); regex.is_match(name) From 8497800abde9214041e11f35efdbfa437f761001 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 1 Aug 2024 15:41:17 +0000 Subject: [PATCH 434/489] Add test for updating enum discriminant through pointer --- .../issue-122600-ptr-discriminant-update.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/codegen/issues/issue-122600-ptr-discriminant-update.rs diff --git a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs new file mode 100644 index 0000000000000..4b520a6206951 --- /dev/null +++ b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -O +//@ min-llvm-version: 19 + +#![crate_type = "lib"] + +pub enum State { + A([u8; 753]), + B([u8; 753]), +} + +// CHECK-LABEL: @update +#[no_mangle] +pub unsafe fn update(s: *mut State) { + // CHECK-NEXT: start: + // CHECK-NEXT: store i8 + // CHECK-NEXT: ret + let State::A(v) = s.read() else { std::hint::unreachable_unchecked() }; + s.write(State::B(v)); +} From eb2de64aa1cb0d3eded99458566e8eee8333a751 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 3 Aug 2024 12:30:38 -0700 Subject: [PATCH 435/489] rustdoc: make the hover trail for doc anchors a bit bigger https://rust-lang.zulipchat.com/#narrow/stream/266220-t-rustdoc/topic/Weird.20markdown.20heading.20rendering.3F --- src/librustdoc/html/static/css/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index f4e231327a8c2..02a6bb8f5487a 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -930,7 +930,7 @@ a.doc-anchor { left: -17px; /* We add this padding so that when the cursor moves from the heading's text to the anchor, the anchor doesn't disappear. */ - padding-right: 5px; + padding-right: 10px; /* And this padding is used to make the anchor larger and easier to click on. */ padding-left: 3px; } From 2cde11f2d145d031b26fe22a3e7d2e278bc0e6ba Mon Sep 17 00:00:00 2001 From: sayantn Date: Sun, 4 Aug 2024 02:32:03 +0530 Subject: [PATCH 436/489] Chore: add `x86_amx_intrinsics` feature flag to `core/lib.rs` and remove `issue-120720-reduce-nan.rs` --- library/core/src/lib.rs | 1 + tests/codegen/simd/issue-120720-reduce-nan.rs | 21 ------------------- 2 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 tests/codegen/simd/issue-120720-reduce-nan.rs diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 9306581dca93d..e74900ff7471b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -264,6 +264,7 @@ #![feature(sse4a_target_feature)] #![feature(tbm_target_feature)] #![feature(wasm_target_feature)] +#![feature(x86_amx_intrinsics)] // tidy-alphabetical-end // allow using `core::` in intra-doc links diff --git a/tests/codegen/simd/issue-120720-reduce-nan.rs b/tests/codegen/simd/issue-120720-reduce-nan.rs deleted file mode 100644 index 13af0bb076e6a..0000000000000 --- a/tests/codegen/simd/issue-120720-reduce-nan.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ compile-flags: -C opt-level=3 -C target-cpu=cannonlake -//@ only-x86_64 - -// In a previous implementation, _mm512_reduce_add_pd did the reduction with all fast-math flags -// enabled, making it UB to reduce a vector containing a NaN. - -#![crate_type = "lib"] -#![feature(stdarch_x86_avx512, avx512_target_feature)] -use std::arch::x86_64::*; - -// CHECK-LABEL: @demo( -#[no_mangle] -#[target_feature(enable = "avx512f")] // Function-level target feature mismatches inhibit inlining -pub unsafe fn demo() -> bool { - // CHECK: %0 = tail call reassoc double @llvm.vector.reduce.fadd.v8f64( - // CHECK: %_0.i = fcmp uno double %0, 0.000000e+00 - // CHECK: ret i1 %_0.i - let res = - unsafe { _mm512_reduce_add_pd(_mm512_set_pd(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, f64::NAN)) }; - res.is_nan() -} From b94a9c1b123026463fd6e1c71c74d9308cdf4f26 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 22:08:39 +0000 Subject: [PATCH 437/489] Remove skipping symbols with the `__imp_` prefix --- tests/run-make/symbol-visibility/rmake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/symbol-visibility/rmake.rs b/tests/run-make/symbol-visibility/rmake.rs index 997eaf793d261..f84e63ef74e8d 100644 --- a/tests/run-make/symbol-visibility/rmake.rs +++ b/tests/run-make/symbol-visibility/rmake.rs @@ -144,7 +144,7 @@ fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bo let mut found: u64 = 0; for export in file.exports().unwrap() { let name = std::str::from_utf8(export.name()).unwrap(); - if !name.contains("__imp_") && has_symbol(name, symbol_check_type) { + if has_symbol(name, symbol_check_type) { found += 1; } } From 01bda01e3374d73e98806f8e27cbb7f6ceb9ad98 Mon Sep 17 00:00:00 2001 From: sayantn Date: Sun, 4 Aug 2024 03:07:12 +0530 Subject: [PATCH 438/489] Update stdarch --- library/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch b/library/stdarch index df3618d9f3516..47b929ddc521a 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit df3618d9f35165f4bc548114e511c49c29e1fd9b +Subproject commit 47b929ddc521a78b0f699ba8d5c274d28593448a From de26ad1a2a30a65d74b9bf433fc805e261c6ed53 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 26 Feb 2024 13:13:43 +0000 Subject: [PATCH 439/489] Promote riscv64gc-unknown-linux-musl to tier 2 --- .../docker/host-x86_64/dist-various-2/Dockerfile | 14 ++++++++++++-- src/tools/build-manifest/src/main.rs | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 2621e9a603185..1b98d54169338 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -24,7 +24,8 @@ RUN apt-get update && apt-get build-dep -y clang llvm && apt-get install -y --no # Needed for apt-key to work: dirmngr \ gpg-agent \ - g++-9-arm-linux-gnueabi + g++-9-arm-linux-gnueabi \ + g++-11-riscv64-linux-gnu RUN apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys 74DA7924C5513486 RUN add-apt-repository -y 'deb https://apt.dilos.org/dilos dilos2 main' @@ -73,6 +74,10 @@ RUN env \ CC=arm-linux-gnueabi-gcc-9 CFLAGS="-march=armv7-a" \ CXX=arm-linux-gnueabi-g++-9 CXXFLAGS="-march=armv7-a" \ bash musl.sh armv7 && \ + env \ + CC=riscv64-linux-gnu-gcc-11 \ + CXX=riscv64-linux-gnu-g++-11 \ + bash musl.sh riscv64gc && \ rm -rf /build/* WORKDIR /tmp @@ -125,6 +130,7 @@ ENV TARGETS=$TARGETS,x86_64-unknown-none ENV TARGETS=$TARGETS,aarch64-unknown-uefi ENV TARGETS=$TARGETS,i686-unknown-uefi ENV TARGETS=$TARGETS,x86_64-unknown-uefi +ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-musl # As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211 # we need asm in the search path for gcc-9 (for gnux32) but not in the search path of the @@ -132,7 +138,11 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi # Luckily one of the folders is /usr/local/include so symlink /usr/include/x86_64-linux-gnu/asm there RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm +# musl-gcc can't find libgcc_s.so.1 since it doesn't use the standard search paths. +RUN ln -s /usr/riscv64-linux-gnu/lib/libgcc_s.so.1 /usr/lib/gcc-cross/riscv64-linux-gnu/11/ + ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-llvm-bitcode-linker --disable-docs \ - --musl-root-armv7=/musl-armv7 + --musl-root-armv7=/musl-armv7 \ + --musl-root-riscv64gc=/musl-riscv64gc ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index ff475b9571b87..2b263f848e89e 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -141,6 +141,7 @@ static TARGETS: &[&str] = &[ "riscv64gc-unknown-hermit", "riscv64gc-unknown-none-elf", "riscv64gc-unknown-linux-gnu", + "riscv64gc-unknown-linux-musl", "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", From a937a3b5a164d267202c2226995d717651991f92 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 22 Jun 2024 16:42:05 +0200 Subject: [PATCH 440/489] Make riscv64gc-unknown-linux-musl dynamically linked by default --- .../src/spec/targets/riscv64gc_unknown_linux_musl.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs index 3e575fdd528de..8b40132986867 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs @@ -21,6 +21,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), + crt_static_default: false, ..base::linux_musl::opts() }, } From 9963a6c400f7c5aa762e0b5419df756432f2e83b Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 22 Jun 2024 17:04:00 +0200 Subject: [PATCH 441/489] Add platform support document for riscv64gc-unknown-linux-musl --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 +- .../riscv64gc-unknown-linux-musl.md | 47 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index d5141591b97e4..467fd6f43e48f 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -66,6 +66,7 @@ - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) - [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md) - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md) + - [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md) - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f3b49a65aad28..7fd1808a1f026 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -98,6 +98,7 @@ target | notes `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17) `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17) [`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29) +[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3) `s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17) `x86_64-unknown-freebsd` | 64-bit FreeBSD `x86_64-unknown-illumos` | illumos @@ -354,7 +355,6 @@ target | std | host | notes [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit `riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia -`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.3) [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 [`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md new file mode 100644 index 0000000000000..5b3dc68303803 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md @@ -0,0 +1,47 @@ +# riscv64gc-unknown-linux-musl + +**Tier: 2** + +Target for RISC-V Linux programs using musl libc. + +## Target maintainers + +- [@Amanieu](https://github.com/Amanieu) +- [@kraj](https://github.com/kraj) + +## Requirements + +Building the target itself requires a RISC-V compiler that is supported by `cc-rs`. + +## Building the target + +The target can be built by enabling it for a `rustc` build. + +```toml +[build] +target = ["riscv64gc-unknown-linux-musl"] +``` + +Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`: + +```toml +[target.riscv64gc-unknown-linux-musl] +cc = "riscv64-linux-gnu-gcc" +cxx = "riscv64-linux-gnu-g++" +ar = "riscv64-linux-gnu-ar" +linker = "riscv64-linux-gnu-gcc" +``` + +## Building Rust programs + +This target are distributed through `rustup`, and otherwise require no +special configuration. + +## Cross-compilation + +This target can be cross-compiled from any host. + +## Testing + +This target can be tested as normal with `x.py` on a RISC-V host or via QEMU +emulation. From cb7c596681c3c5718c7fd0fbe15c487cd36c65c3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 4 Aug 2024 01:08:10 +0200 Subject: [PATCH 442/489] Update rinja version to 0.3.0 --- Cargo.lock | 15 +++++++++------ src/librustdoc/Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b5aa7db3190c..13b8eaea06804 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3282,20 +3282,22 @@ dependencies = [ [[package]] name = "rinja" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d47a46d7729e891c8accf260e9daa02ae6d570aa2a94fb1fb27eb5364a2323" +checksum = "6d3762e3740cdbf2fd2be465cc2c26d643ad17353cc2e0223d211c1b096118bd" dependencies = [ + "itoa", "rinja_derive", ] [[package]] name = "rinja_derive" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44dae9afe59d58ed8d988d67d1945f3638125d2fd2104058399382e11bd3ea2a" +checksum = "fd01fd8e15e7d19c8b8052c1d428325131e02ff1633cdcf695190c2e56ab682c" dependencies = [ "basic-toml", + "memchr", "mime", "mime_guess", "once_map", @@ -3308,10 +3310,11 @@ dependencies = [ [[package]] name = "rinja_parser" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1771c78cd5d3b1646ef8d8f2ed100db936e8b291d3cc06e92a339ff346858c" +checksum = "a2f6bf7cef118c6de21206edf0b3f19f5ede60006be674a58ca21b6e003a1b57" dependencies = [ + "memchr", "nom", ] diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index dfd7414652fa7..b3fccbf6456e0 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -8,7 +8,7 @@ path = "lib.rs" [dependencies] arrayvec = { version = "0.7", default-features = false } -rinja = { version = "0.2", default-features = false, features = ["config"] } +rinja = { version = "0.3", default-features = false, features = ["config"] } base64 = "0.21.7" itertools = "0.12" indexmap = "2" From 3a41a11a8f8af11867c0401027235215cac643ca Mon Sep 17 00:00:00 2001 From: Jerry Wang Date: Wed, 17 Jul 2024 16:40:01 -0400 Subject: [PATCH 443/489] Migrate `run-make/print-calling-conventions` to ui-test --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../print-calling-conventions/Makefile | 4 --- tests/ui/print-calling-conventions.rs | 2 ++ tests/ui/print-calling-conventions.stdout | 34 +++++++++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) delete mode 100644 tests/run-make/print-calling-conventions/Makefile create mode 100644 tests/ui/print-calling-conventions.rs create mode 100644 tests/ui/print-calling-conventions.stdout diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index a04e239abb0e1..93226c41a235f 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -23,7 +23,6 @@ run-make/no-alloc-shim/Makefile run-make/pdb-buildinfo-cl-cmd/Makefile run-make/pgo-gen-lto/Makefile run-make/pgo-indirect-call-promotion/Makefile -run-make/print-calling-conventions/Makefile run-make/print-target-list/Makefile run-make/raw-dylib-alt-calling-convention/Makefile run-make/raw-dylib-c/Makefile diff --git a/tests/run-make/print-calling-conventions/Makefile b/tests/run-make/print-calling-conventions/Makefile deleted file mode 100644 index 27b87e610862d..0000000000000 --- a/tests/run-make/print-calling-conventions/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) --print calling-conventions diff --git a/tests/ui/print-calling-conventions.rs b/tests/ui/print-calling-conventions.rs new file mode 100644 index 0000000000000..302ed088142d8 --- /dev/null +++ b/tests/ui/print-calling-conventions.rs @@ -0,0 +1,2 @@ +//@ compile-flags: --print calling-conventions +//@ build-pass diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout new file mode 100644 index 0000000000000..da67a57f420d7 --- /dev/null +++ b/tests/ui/print-calling-conventions.stdout @@ -0,0 +1,34 @@ +C +C-cmse-nonsecure-call +C-unwind +Rust +aapcs +aapcs-unwind +avr-interrupt +avr-non-blocking-interrupt +cdecl +cdecl-unwind +efiapi +fastcall +fastcall-unwind +msp430-interrupt +ptx-kernel +riscv-interrupt-m +riscv-interrupt-s +rust-call +rust-cold +rust-intrinsic +stdcall +stdcall-unwind +system +system-unwind +sysv64 +sysv64-unwind +thiscall +thiscall-unwind +unadjusted +vectorcall +vectorcall-unwind +win64 +win64-unwind +x86-interrupt From f9d7e4c0a96f17a25e8246a22195ad86d796fb5d Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 3 Aug 2024 16:59:29 +0000 Subject: [PATCH 444/489] Remove cygpath from run-make-support --- .../src/external_deps/c_build.rs | 4 +-- .../run-make-support/src/external_deps/cc.rs | 10 +++--- .../src/external_deps/cygpath.rs | 35 ------------------- .../run-make-support/src/external_deps/mod.rs | 3 -- 4 files changed, 5 insertions(+), 47 deletions(-) delete mode 100644 src/tools/run-make-support/src/external_deps/cygpath.rs diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index 15e02d04393ce..fb22780eaa0cf 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -1,6 +1,5 @@ use std::path::PathBuf; -use super::cygpath::get_windows_path; use crate::artifact_names::{dynamic_lib_name, static_lib_name}; use crate::external_deps::cc::{cc, cxx}; use crate::external_deps::llvm::llvm_ar; @@ -44,8 +43,7 @@ pub fn build_native_dynamic_lib(lib_name: &str) -> PathBuf { }; let obj_file = if is_msvc() { format!("{lib_name}.obj") } else { format!("{lib_name}.o") }; if is_msvc() { - let mut out_arg = "-out:".to_owned(); - out_arg.push_str(&get_windows_path(&lib_path)); + let out_arg = format!("-out:{lib_path}"); cc().input(&obj_file).args(&["-link", "-dll", &out_arg]).run(); } else if is_darwin() { cc().out_exe(&lib_path).input(&obj_file).args(&["-dynamiclib", "-Wl,-dylib"]).run(); diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/cc.rs index 39ac3efef3948..36cef15781f13 100644 --- a/src/tools/run-make-support/src/external_deps/cc.rs +++ b/src/tools/run-make-support/src/external_deps/cc.rs @@ -1,7 +1,5 @@ use std::path::Path; -// FIXME(jieyouxu): can we get rid of the `cygpath` external dependency? -use super::cygpath::get_windows_path; use crate::command::Command; use crate::{env_var, is_msvc, is_windows, uname}; @@ -97,12 +95,12 @@ impl Cc { if is_msvc() { path.set_extension("exe"); - let fe_path = get_windows_path(&path); + let fe_path = path.clone(); path.set_extension(""); path.set_extension("obj"); - let fo_path = get_windows_path(path); - self.cmd.arg(format!("-Fe:{fe_path}")); - self.cmd.arg(format!("-Fo:{fo_path}")); + let fo_path = path; + self.cmd.arg(format!("-Fe:{}", fe_path.to_str().unwrap())); + self.cmd.arg(format!("-Fo:{}", fo_path.to_str().unwrap())); } else { self.cmd.arg("-o"); self.cmd.arg(name); diff --git a/src/tools/run-make-support/src/external_deps/cygpath.rs b/src/tools/run-make-support/src/external_deps/cygpath.rs deleted file mode 100644 index 07d8e840a63a8..0000000000000 --- a/src/tools/run-make-support/src/external_deps/cygpath.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::panic; -use std::path::Path; - -use crate::command::Command; -use crate::util::handle_failed_output; - -/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is -/// available on the platform! -/// -/// # FIXME -/// -/// FIXME(jieyouxu): we should consider not depending on `cygpath`. -/// -/// > The cygpath program is a utility that converts Windows native filenames to Cygwin POSIX-style -/// > pathnames and vice versa. -/// > -/// > [irrelevant entries omitted...] -/// > -/// > `-w, --windows print Windows form of NAMEs (C:\WINNT)` -/// > -/// > -- *from [cygpath documentation](https://cygwin.com/cygwin-ug-net/cygpath.html)*. -#[track_caller] -#[must_use] -pub fn get_windows_path>(path: P) -> String { - let caller = panic::Location::caller(); - let mut cygpath = Command::new("cygpath"); - cygpath.arg("-w"); - cygpath.arg(path.as_ref()); - let output = cygpath.run(); - if !output.status().success() { - handle_failed_output(&cygpath, output, caller.line()); - } - // cygpath -w can attach a newline - output.stdout_utf8().trim().to_string() -} diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs index a2dc426f3f229..f7c84724d0e07 100644 --- a/src/tools/run-make-support/src/external_deps/mod.rs +++ b/src/tools/run-make-support/src/external_deps/mod.rs @@ -9,6 +9,3 @@ pub mod llvm; pub mod python; pub mod rustc; pub mod rustdoc; - -// Library-internal external dependency. -mod cygpath; From 9e5c9c14c7fb3bc6032fff6e9031e641ed2a104a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sun, 4 Aug 2024 01:42:14 +0000 Subject: [PATCH 445/489] tests: add regression test for incorrect "builtin attribute is checked" assertion ICE See . --- tests/ui/attributes/check-builtin-attr-ice.rs | 58 +++++++++++++++++++ .../attributes/check-builtin-attr-ice.stderr | 21 +++++++ 2 files changed, 79 insertions(+) create mode 100644 tests/ui/attributes/check-builtin-attr-ice.rs create mode 100644 tests/ui/attributes/check-builtin-attr-ice.stderr diff --git a/tests/ui/attributes/check-builtin-attr-ice.rs b/tests/ui/attributes/check-builtin-attr-ice.rs new file mode 100644 index 0000000000000..9ef5890601f6b --- /dev/null +++ b/tests/ui/attributes/check-builtin-attr-ice.rs @@ -0,0 +1,58 @@ +//! Regression test for #128622. +//! +//! PR #128581 introduced an assertion that all builtin attributes are actually checked via +//! `CheckAttrVisitor` and aren't accidentally usable on completely unrelated HIR nodes. +//! Unfortunately, the check had correctness problems. +//! +//! The match on attribute path segments looked like +//! +//! ```rs,ignore +//! [sym::should_panic] => /* check is implemented */ +//! match BUILTIN_ATTRIBUTE_MAP.get(name) { +//! // checked below +//! Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} +//! Some(_) => { +//! if !name.as_str().starts_with("rustc_") { +//! span_bug!( +//! attr.span, +//! "builtin attribute {name:?} not handled by `CheckAttrVisitor`" +//! ) +//! } +//! } +//! None => (), +//! } +//! ``` +//! +//! However, it failed to account for edge cases such as an attribute whose: +//! +//! 1. path segments *starts* with a builtin attribute such as `should_panic` +//! 2. which does not start with `rustc_`, and +//! 3. is also an `AttributeType::Normal` attribute upon registration with the builtin attribute map +//! +//! These conditions when all satisfied cause the span bug to be issued for e.g. +//! `#[should_panic::skip]` because the `[sym::should_panic]` arm is not matched (since it's +//! `[sym::should_panic, sym::skip]`). +//! +//! This test checks that the span bug is not fired for such cases. +//! +//! issue: rust-lang/rust#128622 + +// Notably, `should_panic` is a `AttributeType::Normal` attribute that is checked separately. + +struct Foo { + #[should_panic::skip] + //~^ ERROR failed to resolve + pub field: u8, + + #[should_panic::a::b::c] + //~^ ERROR failed to resolve + pub field2: u8, +} + +fn foo() {} + +fn main() { + #[deny::skip] + //~^ ERROR failed to resolve + foo(); +} diff --git a/tests/ui/attributes/check-builtin-attr-ice.stderr b/tests/ui/attributes/check-builtin-attr-ice.stderr new file mode 100644 index 0000000000000..5a27da565a857 --- /dev/null +++ b/tests/ui/attributes/check-builtin-attr-ice.stderr @@ -0,0 +1,21 @@ +error[E0433]: failed to resolve: use of undeclared crate or module `should_panic` + --> $DIR/check-builtin-attr-ice.rs:43:7 + | +LL | #[should_panic::skip] + | ^^^^^^^^^^^^ use of undeclared crate or module `should_panic` + +error[E0433]: failed to resolve: use of undeclared crate or module `should_panic` + --> $DIR/check-builtin-attr-ice.rs:47:7 + | +LL | #[should_panic::a::b::c] + | ^^^^^^^^^^^^ use of undeclared crate or module `should_panic` + +error[E0433]: failed to resolve: use of undeclared crate or module `deny` + --> $DIR/check-builtin-attr-ice.rs:55:7 + | +LL | #[deny::skip] + | ^^^^ use of undeclared crate or module `deny` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0433`. From 9d0eaa2ad78ca2995d4f2c4edb61f762ba79846b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sun, 4 Aug 2024 01:39:05 +0000 Subject: [PATCH 446/489] check_attr: cover multi-segment attributes on specific check arms PR #128581 introduced an assertion that all builtin attributes are actually checked via `CheckAttrVisitor` and aren't accidentally usable on completely unrelated HIR nodes. Unfortunately, the check had correctness problems. The match on attribute path segments looked like ```rust,ignore [sym::should_panic] => /* check is implemented */ match BUILTIN_ATTRIBUTE_MAP.get(name) { // checked below Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} Some(_) => { if !name.as_str().starts_with("rustc_") { span_bug!( attr.span, "builtin attribute {name:?} not handled by `CheckAttrVisitor`" ) } } None => (), } ``` However, it failed to account for edge cases such as an attribute whose: 1. path segments *starts* with a builtin attribute such as `should_panic` 2. which does not start with `rustc_`, and 3. is also an `AttributeType::Normal` attribute upon registration with the builtin attribute map These conditions when all satisfied cause the span bug to be issued for e.g. `#[should_panic::skip]` because the `[sym::should_panic]` arm is not matched (since it's `[sym::should_panic, sym::skip]`). See . --- compiler/rustc_passes/src/check_attr.rs | 144 ++++++++++++------------ 1 file changed, 73 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 755f67b3f4fe0..a0d0d80b9572e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -116,130 +116,130 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let attrs = self.tcx.hir().attrs(hir_id); for attr in attrs { match attr.path().as_slice() { - [sym::diagnostic, sym::do_not_recommend] => { + [sym::diagnostic, sym::do_not_recommend, ..] => { self.check_do_not_recommend(attr.span, hir_id, target) } - [sym::diagnostic, sym::on_unimplemented] => { + [sym::diagnostic, sym::on_unimplemented, ..] => { self.check_diagnostic_on_unimplemented(attr.span, hir_id, target) } - [sym::inline] => self.check_inline(hir_id, attr, span, target), - [sym::coverage] => self.check_coverage(attr, span, target), - [sym::optimize] => self.check_optimize(hir_id, attr, target), - [sym::non_exhaustive] => self.check_non_exhaustive(hir_id, attr, span, target), - [sym::marker] => self.check_marker(hir_id, attr, span, target), - [sym::target_feature] => { + [sym::inline, ..] => self.check_inline(hir_id, attr, span, target), + [sym::coverage, ..] => self.check_coverage(attr, span, target), + [sym::optimize, ..] => self.check_optimize(hir_id, attr, target), + [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target), + [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), + [sym::target_feature, ..] => { self.check_target_feature(hir_id, attr, span, target, attrs) } - [sym::thread_local] => self.check_thread_local(attr, span, target), - [sym::track_caller] => { + [sym::thread_local, ..] => self.check_thread_local(attr, span, target), + [sym::track_caller, ..] => { self.check_track_caller(hir_id, attr.span, attrs, span, target) } - [sym::doc] => self.check_doc_attrs( + [sym::doc, ..] => self.check_doc_attrs( attr, hir_id, target, &mut specified_inline, &mut doc_aliases, ), - [sym::no_link] => self.check_no_link(hir_id, attr, span, target), - [sym::export_name] => self.check_export_name(hir_id, attr, span, target), - [sym::rustc_layout_scalar_valid_range_start] - | [sym::rustc_layout_scalar_valid_range_end] => { + [sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target), + [sym::export_name, ..] => self.check_export_name(hir_id, attr, span, target), + [sym::rustc_layout_scalar_valid_range_start, ..] + | [sym::rustc_layout_scalar_valid_range_end, ..] => { self.check_rustc_layout_scalar_valid_range(attr, span, target) } - [sym::allow_internal_unstable] => { + [sym::allow_internal_unstable, ..] => { self.check_allow_internal_unstable(hir_id, attr, span, target, attrs) } - [sym::debugger_visualizer] => self.check_debugger_visualizer(attr, target), - [sym::rustc_allow_const_fn_unstable] => { + [sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target), + [sym::rustc_allow_const_fn_unstable, ..] => { self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target) } - [sym::rustc_std_internal_symbol] => { + [sym::rustc_std_internal_symbol, ..] => { self.check_rustc_std_internal_symbol(attr, span, target) } - [sym::naked] => self.check_naked(hir_id, attr, span, target, attrs), - [sym::rustc_never_returns_null_ptr] => { + [sym::naked, ..] => self.check_naked(hir_id, attr, span, target, attrs), + [sym::rustc_never_returns_null_ptr, ..] => { self.check_applied_to_fn_or_method(hir_id, attr, span, target) } - [sym::rustc_legacy_const_generics] => { + [sym::rustc_legacy_const_generics, ..] => { self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item) } - [sym::rustc_lint_query_instability] => { + [sym::rustc_lint_query_instability, ..] => { self.check_rustc_lint_query_instability(hir_id, attr, span, target) } - [sym::rustc_lint_diagnostics] => { + [sym::rustc_lint_diagnostics, ..] => { self.check_rustc_lint_diagnostics(hir_id, attr, span, target) } - [sym::rustc_lint_opt_ty] => self.check_rustc_lint_opt_ty(attr, span, target), - [sym::rustc_lint_opt_deny_field_access] => { + [sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target), + [sym::rustc_lint_opt_deny_field_access, ..] => { self.check_rustc_lint_opt_deny_field_access(attr, span, target) } - [sym::rustc_clean] - | [sym::rustc_dirty] - | [sym::rustc_if_this_changed] - | [sym::rustc_then_this_would_need] => self.check_rustc_dirty_clean(attr), - [sym::rustc_coinductive] - | [sym::rustc_must_implement_one_of] - | [sym::rustc_deny_explicit_impl] - | [sym::const_trait] => self.check_must_be_applied_to_trait(attr, span, target), - [sym::cmse_nonsecure_entry] => { + [sym::rustc_clean, ..] + | [sym::rustc_dirty, ..] + | [sym::rustc_if_this_changed, ..] + | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr), + [sym::rustc_coinductive, ..] + | [sym::rustc_must_implement_one_of, ..] + | [sym::rustc_deny_explicit_impl, ..] + | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target), + [sym::cmse_nonsecure_entry, ..] => { self.check_cmse_nonsecure_entry(hir_id, attr, span, target) } - [sym::collapse_debuginfo] => self.check_collapse_debuginfo(attr, span, target), - [sym::must_not_suspend] => self.check_must_not_suspend(attr, span, target), - [sym::must_use] => self.check_must_use(hir_id, attr, target), - [sym::rustc_pass_by_value] => self.check_pass_by_value(attr, span, target), - [sym::rustc_allow_incoherent_impl] => { + [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), + [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), + [sym::must_use, ..] => self.check_must_use(hir_id, attr, target), + [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target), + [sym::rustc_allow_incoherent_impl, ..] => { self.check_allow_incoherent_impl(attr, span, target) } - [sym::rustc_has_incoherent_inherent_impls] => { + [sym::rustc_has_incoherent_inherent_impls, ..] => { self.check_has_incoherent_inherent_impls(attr, span, target) } - [sym::ffi_pure] => self.check_ffi_pure(attr.span, attrs, target), - [sym::ffi_const] => self.check_ffi_const(attr.span, target), - [sym::rustc_const_unstable] - | [sym::rustc_const_stable] - | [sym::unstable] - | [sym::stable] - | [sym::rustc_allowed_through_unstable_modules] - | [sym::rustc_promotable] => self.check_stability_promotable(attr, target), - [sym::link_ordinal] => self.check_link_ordinal(attr, span, target), - [sym::rustc_confusables] => self.check_confusables(attr, target), - [sym::rustc_safe_intrinsic] => { + [sym::ffi_pure, ..] => self.check_ffi_pure(attr.span, attrs, target), + [sym::ffi_const, ..] => self.check_ffi_const(attr.span, target), + [sym::rustc_const_unstable, ..] + | [sym::rustc_const_stable, ..] + | [sym::unstable, ..] + | [sym::stable, ..] + | [sym::rustc_allowed_through_unstable_modules, ..] + | [sym::rustc_promotable, ..] => self.check_stability_promotable(attr, target), + [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), + [sym::rustc_confusables, ..] => self.check_confusables(attr, target), + [sym::rustc_safe_intrinsic, ..] => { self.check_rustc_safe_intrinsic(hir_id, attr, span, target) } - [sym::cold] => self.check_cold(hir_id, attr, span, target), - [sym::link] => self.check_link(hir_id, attr, span, target), - [sym::link_name] => self.check_link_name(hir_id, attr, span, target), - [sym::link_section] => self.check_link_section(hir_id, attr, span, target), - [sym::no_mangle] => self.check_no_mangle(hir_id, attr, span, target), - [sym::deprecated] => self.check_deprecated(hir_id, attr, span, target), - [sym::macro_use] | [sym::macro_escape] => { + [sym::cold, ..] => self.check_cold(hir_id, attr, span, target), + [sym::link, ..] => self.check_link(hir_id, attr, span, target), + [sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target), + [sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target), + [sym::no_mangle, ..] => self.check_no_mangle(hir_id, attr, span, target), + [sym::deprecated, ..] => self.check_deprecated(hir_id, attr, span, target), + [sym::macro_use, ..] | [sym::macro_escape, ..] => { self.check_macro_use(hir_id, attr, target) } - [sym::path] => self.check_generic_attr(hir_id, attr, target, Target::Mod), - [sym::macro_export] => self.check_macro_export(hir_id, attr, target), - [sym::ignore] | [sym::should_panic] => { + [sym::path, ..] => self.check_generic_attr(hir_id, attr, target, Target::Mod), + [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target), + [sym::ignore, ..] | [sym::should_panic, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Fn) } - [sym::automatically_derived] => { + [sym::automatically_derived, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Impl) } - [sym::no_implicit_prelude] => { + [sym::no_implicit_prelude, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Mod) } - [sym::rustc_object_lifetime_default] => self.check_object_lifetime_default(hir_id), - [sym::proc_macro] => { + [sym::rustc_object_lifetime_default, ..] => self.check_object_lifetime_default(hir_id), + [sym::proc_macro, ..] => { self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike) } - [sym::proc_macro_attribute] => { + [sym::proc_macro_attribute, ..] => { self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute); } - [sym::proc_macro_derive] => { + [sym::proc_macro_derive, ..] => { self.check_generic_attr(hir_id, attr, target, Target::Fn); self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - [sym::coroutine] => { + [sym::coroutine, ..] => { self.check_coroutine(attr, target); } [ @@ -273,14 +273,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::default_lib_allocator | sym::start | sym::custom_mir, + .. ] => {} [name, ..] => { match BUILTIN_ATTRIBUTE_MAP.get(name) { // checked below Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {} Some(_) => { - // FIXME: differentiate between unstable and internal attributes just like we do with features instead - // of just accepting `rustc_` attributes by name. That should allow trimming the above list, too. + // FIXME: differentiate between unstable and internal attributes just + // like we do with features instead of just accepting `rustc_` + // attributes by name. That should allow trimming the above list, too. if !name.as_str().starts_with("rustc_") { span_bug!( attr.span, From 1ca959e3f00fcf01395b18bb6e3b9dd86b3e478c Mon Sep 17 00:00:00 2001 From: Jerry Wang Date: Wed, 17 Jul 2024 16:55:13 -0400 Subject: [PATCH 447/489] Migrate `print-target-list` to `rmake` --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/print-target-list/Makefile | 8 ------- tests/run-make/print-target-list/rmake.rs | 21 +++++++++++++++++++ 3 files changed, 21 insertions(+), 9 deletions(-) delete mode 100644 tests/run-make/print-target-list/Makefile create mode 100644 tests/run-make/print-target-list/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 93226c41a235f..088d5ba0c2b37 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -23,7 +23,6 @@ run-make/no-alloc-shim/Makefile run-make/pdb-buildinfo-cl-cmd/Makefile run-make/pgo-gen-lto/Makefile run-make/pgo-indirect-call-promotion/Makefile -run-make/print-target-list/Makefile run-make/raw-dylib-alt-calling-convention/Makefile run-make/raw-dylib-c/Makefile run-make/redundant-libs/Makefile diff --git a/tests/run-make/print-target-list/Makefile b/tests/run-make/print-target-list/Makefile deleted file mode 100644 index f23c40d4281e3..0000000000000 --- a/tests/run-make/print-target-list/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -include ../tools.mk - -# Checks that all the targets returned by `rustc --print target-list` are valid -# target specifications -all: - for target in $(shell $(BARE_RUSTC) --print target-list); do \ - $(BARE_RUSTC) --target $$target --print sysroot; \ - done diff --git a/tests/run-make/print-target-list/rmake.rs b/tests/run-make/print-target-list/rmake.rs new file mode 100644 index 0000000000000..743ed52069dea --- /dev/null +++ b/tests/run-make/print-target-list/rmake.rs @@ -0,0 +1,21 @@ +// Checks that all the targets returned by `rustc --print target-list` are valid +// target specifications + +use run_make_support::bare_rustc; + +// FIXME(127877): certain experimental targets fail with creating a 'LLVM TargetMachine' +// in CI, so we skip them +const EXPERIMENTAL_TARGETS: &[&str] = &["avr", "m68k", "csky", "xtensa"]; + +fn main() { + let targets = bare_rustc().print("target-list").run().stdout_utf8(); + + for target in targets.lines() { + // skip experimental targets that would otherwise fail + if EXPERIMENTAL_TARGETS.iter().any(|experimental| target.contains(experimental)) { + continue; + } + + bare_rustc().target(target).print("sysroot").run(); + } +} From 36cf385e886da13b5b1f98a8b62b1aa63f7e1722 Mon Sep 17 00:00:00 2001 From: Jerry Wang Date: Wed, 17 Jul 2024 17:54:06 -0400 Subject: [PATCH 448/489] Ensure `Rustc::print` use in `rmake` tests --- tests/run-make/print-cfg/rmake.rs | 5 +---- tests/run-make/print-check-cfg/rmake.rs | 2 +- tests/run-make/print-to-output/rmake.rs | 5 +---- tests/run-make/rustdoc-scrape-examples-macros/rmake.rs | 3 +-- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/tests/run-make/print-cfg/rmake.rs b/tests/run-make/print-cfg/rmake.rs index d83e8a36f2c08..471a99b90d982 100644 --- a/tests/run-make/print-cfg/rmake.rs +++ b/tests/run-make/print-cfg/rmake.rs @@ -6,7 +6,6 @@ //! It also checks that some targets have the correct set cfgs. use std::collections::HashSet; -use std::ffi::OsString; use std::iter::FromIterator; use std::path::PathBuf; @@ -91,10 +90,8 @@ fn check(PrintCfg { target, includes, disallow }: PrintCfg) { // --print=cfg=PATH { let tmp_path = PathBuf::from(format!("{target}.cfg")); - let mut print_arg = OsString::from("--print=cfg="); - print_arg.push(tmp_path.as_os_str()); - rustc().target(target).arg(print_arg).run(); + rustc().target(target).print(&format!("cfg={}", tmp_path.display())).run(); let output = rfs::read_to_string(&tmp_path); diff --git a/tests/run-make/print-check-cfg/rmake.rs b/tests/run-make/print-check-cfg/rmake.rs index 4a79910c8e05e..b10336f88c649 100644 --- a/tests/run-make/print-check-cfg/rmake.rs +++ b/tests/run-make/print-check-cfg/rmake.rs @@ -87,7 +87,7 @@ fn main() { fn check(CheckCfg { args, contains }: CheckCfg) { let output = - rustc().input("lib.rs").arg("-Zunstable-options").arg("--print=check-cfg").args(args).run(); + rustc().input("lib.rs").arg("-Zunstable-options").print("check-cfg").args(args).run(); let stdout = output.stdout_utf8(); diff --git a/tests/run-make/print-to-output/rmake.rs b/tests/run-make/print-to-output/rmake.rs index d0cba725b3679..db2a291f8e737 100644 --- a/tests/run-make/print-to-output/rmake.rs +++ b/tests/run-make/print-to-output/rmake.rs @@ -1,7 +1,6 @@ //! This checks the output of some `--print` options when //! output to a file (instead of stdout) -use std::ffi::OsString; use std::path::PathBuf; use run_make_support::{rfs, rustc, target}; @@ -44,10 +43,8 @@ fn check(args: Option) { // --print={option}=PATH let output = { let tmp_path = PathBuf::from(format!("{}.txt", args.option)); - let mut print_arg = OsString::from(format!("--print={}=", args.option)); - print_arg.push(tmp_path.as_os_str()); - rustc().target(args.target).arg(print_arg).run(); + rustc().target(args.target).print(&format!("{}={}", args.option, tmp_path.display())).run(); rfs::read_to_string(&tmp_path) }; diff --git a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs index bfe4a1df4569d..b77df7adc8d9e 100644 --- a/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-macros/rmake.rs @@ -11,8 +11,7 @@ fn main() { let dylib_name = rustc() .crate_name(proc_crate_name) .crate_type("dylib") - .arg("--print") - .arg("file-names") + .print("file-names") .arg("-") .run() .stdout_utf8(); From 007d9e1c26da1e509ff7887604e6685f1445982a Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Sat, 3 Aug 2024 20:51:28 -0700 Subject: [PATCH 449/489] rustdoc: Re-add missing `stripped_mod` check; explain orphan impls Co-authored-by: Michael Howell --- src/librustdoc/formats/cache.rs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index d2d0f5a4380b6..3fdc878647175 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -486,10 +486,30 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It ParentStackItem::Type(item_id) => item_id.as_def_id(), }; let Some(parent_did) = parent_did else { return }; - // The current stack not necessarily has correlation - // for where the type was defined. On the other - // hand, `paths` always has the right - // information if present. + // The current stack reflects the CacheBuilder's recursive + // walk over HIR. For associated items, this is the module + // where the `impl` block is defined. That's an implementation + // detail that we don't want to affect the search engine. + // + // In particular, you can arrange things like this: + // + // #![crate_name="me"] + // mod private_mod { + // impl Clone for MyThing { fn clone(&self) -> MyThing { MyThing } } + // } + // pub struct MyThing; + // + // When that happens, we need to: + // - ignore the `cache.stripped_mod` flag, since the Clone impl is actually + // part of the public API even though it's defined in a private module + // - present the method as `me::MyThing::clone`, its publicly-visible path + // - deal with the fact that the recursive walk hasn't actually reached `MyThing` + // until it's already past `private_mod`, since that's first, and doesn't know + // yet if `MyThing` will actually be public or not (it could be re-exported) + // + // We accomplish the last two points by recording children of "orphan impls" + // in a field of the cache whose elements are added to the search index later, + // after cache building is complete (see `handle_orphan_impl_child`). match cache.paths.get(&parent_did) { Some((fqp, _)) => (Some(parent_did), &fqp[..fqp.len() - 1]), None => { @@ -500,7 +520,8 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It } _ => { // Don't index if item is crate root, which is inserted later on when serializing the index. - if item_def_id.is_crate_root() { + // Don't index if containing module is stripped (i.e., private), + if item_def_id.is_crate_root() || cache.stripped_mod { return; } (None, &*cache.stack) From 90521399b4bfa889916cb62e2394b69f295e22cf Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 21 Feb 2024 23:12:19 +0100 Subject: [PATCH 450/489] Stabilize Wasm relaxed SIMD --- compiler/rustc_target/src/target_features.rs | 2 +- tests/ui/target-feature/wasm-relaxed-simd.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tests/ui/target-feature/wasm-relaxed-simd.rs diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index e52f2fc06df06..843e28b17b0b5 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -333,7 +333,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("mutable-globals", Stable), ("nontrapping-fptoint", Stable), ("reference-types", Unstable(sym::wasm_target_feature)), - ("relaxed-simd", Unstable(sym::wasm_target_feature)), + ("relaxed-simd", Stable), ("sign-ext", Stable), ("simd128", Stable), // tidy-alphabetical-end diff --git a/tests/ui/target-feature/wasm-relaxed-simd.rs b/tests/ui/target-feature/wasm-relaxed-simd.rs new file mode 100644 index 0000000000000..3c80647fdfe17 --- /dev/null +++ b/tests/ui/target-feature/wasm-relaxed-simd.rs @@ -0,0 +1,9 @@ +//@ only-wasm32-wasip1 +//@ compile-flags: -Ctarget-feature=+relaxed-simd,+simd128 --crate-type=lib +//@ build-pass + +use std::arch::wasm32::*; + +pub fn test(a: v128, b: v128, m: v128) -> v128 { + i64x2_relaxed_laneselect(a, b, m) +} From 80b74d397fffc9deaafd2b44552ba3a9107b4d5b Mon Sep 17 00:00:00 2001 From: daxpedda Date: Sat, 13 Jul 2024 00:10:33 +0200 Subject: [PATCH 451/489] Implement a implicit target feature mechanism --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 16 ++++++++++++++++ .../rustc_codegen_ssa/src/target_features.rs | 8 ++++++++ compiler/rustc_target/src/target_features.rs | 11 +++++++++++ tests/ui/target-feature/implicit-features-cli.rs | 9 +++++++++ tests/ui/target-feature/implicit-features.rs | 10 ++++++++++ tests/ui/target-feature/wasm-relaxed-simd.rs | 2 +- 6 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/ui/target-feature/implicit-features-cli.rs create mode 100644 tests/ui/target-feature/implicit-features.rs diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index dc21b92a95f76..af8a9be1ccbfd 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -646,6 +646,22 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec, which didn't make + // it into a released version of LLVM yet. + // + // This doesn't use the "implicit target feature" system because it is only + // used for function attributes in other targets, which fixes this bug as + // well on the function attribute level. + if sess.target.families.contains(&"wasm".into()) { + if features.iter().any(|f| f == "+relaxed-simd") + && !features.iter().any(|f| f == "+simd128") + { + features.push("+simd128".into()); + } + } + if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) { sess.dcx().emit_err(TargetFeatureDisableOrEnable { features: f, diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b52e6259944d7..127244a34f8f0 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -97,6 +97,14 @@ pub fn from_target_feature( Some(Symbol::intern(feature)) })); } + + for (feature, requires) in tcx.sess.target.implicit_target_features() { + if target_features.iter().any(|f| f.as_str() == *feature) + && !target_features.iter().any(|f| f.as_str() == *requires) + { + target_features.push(Symbol::intern(requires)); + } + } } /// Computes the set of target features used in a function for the purposes of diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 843e28b17b0b5..4e2617c467949 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -339,6 +339,8 @@ const WASM_ALLOWED_FEATURES: &[(&str, Stability)] = &[ // tidy-alphabetical-end ]; +const WASM_IMPLICIT_FEATURES: &[(&str, &str)] = &[("relaxed-simd", "simd128")]; + const BPF_ALLOWED_FEATURES: &[(&str, Stability)] = &[("alu32", Unstable(sym::bpf_target_feature))]; const CSKY_ALLOWED_FEATURES: &[(&str, Stability)] = &[ @@ -455,4 +457,13 @@ impl super::spec::Target { _ => &[], } } + + /// Returns a list of target features. Each items first target feature + /// implicitly enables the second one. + pub fn implicit_target_features(&self) -> &'static [(&'static str, &'static str)] { + match &*self.arch { + "wasm32" | "wasm64" => WASM_IMPLICIT_FEATURES, + _ => &[], + } + } } diff --git a/tests/ui/target-feature/implicit-features-cli.rs b/tests/ui/target-feature/implicit-features-cli.rs new file mode 100644 index 0000000000000..34e7c3d506659 --- /dev/null +++ b/tests/ui/target-feature/implicit-features-cli.rs @@ -0,0 +1,9 @@ +//@ only-wasm32-wasip1 +//@ compile-flags: -Ctarget-feature=+relaxed-simd --crate-type=lib +//@ build-pass + +use std::arch::wasm32::*; + +pub fn test(a: v128, b: v128, m: v128) -> v128 { + i64x2_relaxed_laneselect(a, b, m) +} diff --git a/tests/ui/target-feature/implicit-features.rs b/tests/ui/target-feature/implicit-features.rs new file mode 100644 index 0000000000000..b9c48b0822d53 --- /dev/null +++ b/tests/ui/target-feature/implicit-features.rs @@ -0,0 +1,10 @@ +//@ only-wasm32-wasip1 +//@ compile-flags: --crate-type=lib +//@ build-pass + +use std::arch::wasm32::*; + +#[target_feature(enable = "relaxed-simd")] +pub fn test(a: v128, b: v128, m: v128) -> v128 { + i64x2_relaxed_laneselect(a, b, m) +} diff --git a/tests/ui/target-feature/wasm-relaxed-simd.rs b/tests/ui/target-feature/wasm-relaxed-simd.rs index 3c80647fdfe17..34e7c3d506659 100644 --- a/tests/ui/target-feature/wasm-relaxed-simd.rs +++ b/tests/ui/target-feature/wasm-relaxed-simd.rs @@ -1,5 +1,5 @@ //@ only-wasm32-wasip1 -//@ compile-flags: -Ctarget-feature=+relaxed-simd,+simd128 --crate-type=lib +//@ compile-flags: -Ctarget-feature=+relaxed-simd --crate-type=lib //@ build-pass use std::arch::wasm32::*; From 249afea2ff4a1e3cfbe5f40c42c6f84938ee3143 Mon Sep 17 00:00:00 2001 From: bohan Date: Sun, 4 Aug 2024 15:38:11 +0800 Subject: [PATCH 452/489] docs(resolve): more explain about `target` --- compiler/rustc_resolve/src/imports.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 0fa5cde9424b5..c7af21027b8d3 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -48,6 +48,7 @@ pub(crate) enum ImportKind<'a> { /// `source` in `use prefix::source as target`. source: Ident, /// `target` in `use prefix::source as target`. + /// It will directly use `source` when the format is `use prefix::source`. target: Ident, /// Bindings to which `source` refers to. source_bindings: PerNS, Determinacy>>>, From 2ac09692e7a79fa49031994351c36d70aa0e752e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 4 Aug 2024 10:59:28 +0300 Subject: [PATCH 453/489] handle crates when they are not specified for std docs This fixes a regression from https://github.com/rust-lang/rust/pull/128182. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/doc.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 1541396bfdd98..2cd5db706c26a 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -599,6 +599,16 @@ impl Step for Std { fn run(self, builder: &Builder<'_>) { let stage = self.stage; let target = self.target; + let crates = if self.crates.is_empty() { + builder + .in_tree_crates("sysroot", Some(target)) + .iter() + .map(|c| c.name.to_string()) + .collect() + } else { + self.crates + }; + let out = match self.format { DocumentationFormat::Html => builder.doc_out(target), DocumentationFormat::Json => builder.json_doc_out(target), @@ -627,7 +637,7 @@ impl Step for Std { extra_args.push("--disable-minification"); } - doc_std(builder, self.format, stage, target, &out, &extra_args, &self.crates); + doc_std(builder, self.format, stage, target, &out, &extra_args, &crates); // Don't open if the format is json if let DocumentationFormat::Json = self.format { @@ -639,7 +649,7 @@ impl Step for Std { let index = out.join("std").join("index.html"); builder.open_in_browser(index); } else { - for requested_crate in &*self.crates { + for requested_crate in crates { if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) { let index = out.join(requested_crate).join("index.html"); builder.open_in_browser(index); From 178886e923058327900f945b26afb3759872839e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 4 Aug 2024 15:25:59 +0000 Subject: [PATCH 454/489] Update incorrect comment --- src/bootstrap/src/core/metadata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs index c11230744c395..1016607fc8318 100644 --- a/src/bootstrap/src/core/metadata.rs +++ b/src/bootstrap/src/core/metadata.rs @@ -86,7 +86,7 @@ fn workspace_members(build: &Build) -> Vec { packages }; - // Collects `metadata.packages` from all workspaces. + // Collects `metadata.packages` from the root and library workspaces. let mut packages = vec![]; packages.extend(collect_metadata("Cargo.toml")); packages.extend(collect_metadata("library/Cargo.toml")); From 69de294c311cd38c85f3f143fb4cf997518e8bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 4 Aug 2024 21:25:49 +0200 Subject: [PATCH 455/489] tests: more crashes --- tests/crashes/128094.rs | 14 ++++++++++++++ tests/crashes/128176.rs | 13 +++++++++++++ tests/crashes/128190.rs | 7 +++++++ tests/crashes/128327.rs | 5 +++++ tests/crashes/128346.rs | 13 +++++++++++++ tests/crashes/128621-2.rs | 16 ++++++++++++++++ tests/crashes/128621.rs | 19 +++++++++++++++++++ 7 files changed, 87 insertions(+) create mode 100644 tests/crashes/128094.rs create mode 100644 tests/crashes/128176.rs create mode 100644 tests/crashes/128190.rs create mode 100644 tests/crashes/128327.rs create mode 100644 tests/crashes/128346.rs create mode 100644 tests/crashes/128621-2.rs create mode 100644 tests/crashes/128621.rs diff --git a/tests/crashes/128094.rs b/tests/crashes/128094.rs new file mode 100644 index 0000000000000..105a1c84a6565 --- /dev/null +++ b/tests/crashes/128094.rs @@ -0,0 +1,14 @@ +//@ known-bug: rust-lang/rust#128094 +//@ compile-flags: -Zmir-opt-level=5 --edition=2018 + +pub enum Request { + TestSome(T), +} + +pub async fn handle_event(event: Request) { + async move { + static instance: Request = Request { bar: 17 }; + &instance + } + .await; +} diff --git a/tests/crashes/128176.rs b/tests/crashes/128176.rs new file mode 100644 index 0000000000000..70fada4f0fec2 --- /dev/null +++ b/tests/crashes/128176.rs @@ -0,0 +1,13 @@ +//@ known-bug: rust-lang/rust#128176 + +#![feature(generic_const_exprs)] +#![feature(object_safe_for_dispatch)] +trait X { + type Y; +} + +const _: () = { + fn f2<'a>(arg: Box = &'a ()>>) {} +}; + +fn main() {} diff --git a/tests/crashes/128190.rs b/tests/crashes/128190.rs new file mode 100644 index 0000000000000..0fa7027ae6091 --- /dev/null +++ b/tests/crashes/128190.rs @@ -0,0 +1,7 @@ +//@ known-bug: rust-lang/rust#128190 + +fn a(&self) { + 15 +} + +reuse a as b { struct S; } diff --git a/tests/crashes/128327.rs b/tests/crashes/128327.rs new file mode 100644 index 0000000000000..a63f758c317cf --- /dev/null +++ b/tests/crashes/128327.rs @@ -0,0 +1,5 @@ +//@ known-bug: rust-lang/rust#128327 + +use std::ops::Deref; +struct Apple((Apple, <&'static [f64] as Deref>::Target(Banana ? Citron))); +fn main(){} diff --git a/tests/crashes/128346.rs b/tests/crashes/128346.rs new file mode 100644 index 0000000000000..93d9c40a544e9 --- /dev/null +++ b/tests/crashes/128346.rs @@ -0,0 +1,13 @@ +//@ known-bug: rust-lang/rust#128346 + +macro_rules! one_rep { + ( $($a:ident)* ) => { + A( + const ${concat($a, Z)}: i32 = 3; + )* + }; +} + +fn main() { + one_rep!(A B C); +} diff --git a/tests/crashes/128621-2.rs b/tests/crashes/128621-2.rs new file mode 100644 index 0000000000000..b1cdaf94984a8 --- /dev/null +++ b/tests/crashes/128621-2.rs @@ -0,0 +1,16 @@ +//@ known-bug: rust-lang/rust#128621 + +#![feature(ptr_metadata)] +use std::{ops::FnMut, ptr::Pointee}; + +pub type EmplacerFn<'a, T> = dyn for<'b> FnMut(::Metadata) + 'a; + +pub struct Emplacer<'a, T>(EmplacerFn<'a, T>); + +impl<'a, T> Emplacer<'a, T> { + pub unsafe fn from_fn<'b>(emplacer_fn: &'b mut EmplacerFn<'a, T>) -> &'b mut Self { + unsafe { &mut *((emplacer_fn as *mut EmplacerFn<'a, T>) as *mut Self) } + } +} + +pub fn main() {} diff --git a/tests/crashes/128621.rs b/tests/crashes/128621.rs new file mode 100644 index 0000000000000..0a02352236dbb --- /dev/null +++ b/tests/crashes/128621.rs @@ -0,0 +1,19 @@ +//@ known-bug: rust-lang/rust#128621 + +trait Trait { + type Associated; +} + +impl Trait for i32 { + type Associated = i64; +} + +trait Generic {} + +type TraitObject = dyn Generic<::Associated>; + +struct Wrap(TraitObject); + +fn cast(x: *mut TraitObject) { + x as *mut Wrap; +} From 249d686c7005ebb4d05234e9db6d29c2923296e2 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 15:25:13 -0700 Subject: [PATCH 456/489] rustdoc: Rename `SelfTy` to `ReceiverTy` `SelfTy` makes it sound like it is literally the `Self` type, whereas in fact it may be `&Self` or other types. Plus, I want to use the name `SelfTy` for a new variant of `clean::Type`. Having both causes resolution conflicts or at least confusion. --- src/librustdoc/clean/types.rs | 10 +++++----- src/librustdoc/html/format.rs | 2 +- src/librustdoc/html/render/mod.rs | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7d5a16bc7e3d5..32e795e565ed2 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -34,7 +34,7 @@ use thin_vec::ThinVec; use {rustc_ast as ast, rustc_hir as hir}; pub(crate) use self::ItemKind::*; -pub(crate) use self::SelfTy::*; +pub(crate) use self::ReceiverTy::*; pub(crate) use self::Type::{ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, RawPointer, Slice, Tuple, @@ -1384,8 +1384,8 @@ pub(crate) struct FnDecl { } impl FnDecl { - pub(crate) fn self_type(&self) -> Option { - self.inputs.values.get(0).and_then(|v| v.to_self()) + pub(crate) fn receiver_type(&self) -> Option { + self.inputs.values.get(0).and_then(|v| v.to_receiver()) } } @@ -1404,14 +1404,14 @@ pub(crate) struct Argument { } #[derive(Clone, PartialEq, Debug)] -pub(crate) enum SelfTy { +pub(crate) enum ReceiverTy { SelfValue, SelfBorrowed(Option, Mutability), SelfExplicit(Type), } impl Argument { - pub(crate) fn to_self(&self) -> Option { + pub(crate) fn to_receiver(&self) -> Option { if self.name != kw::SelfLower { return None; } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bb5ac303ffd63..6476c8bd7c0d3 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1452,7 +1452,7 @@ impl clean::FnDecl { let last_input_index = self.inputs.values.len().checked_sub(1); for (i, input) in self.inputs.values.iter().enumerate() { - if let Some(selfty) = input.to_self() { + if let Some(selfty) = input.to_receiver() { match selfty { clean::SelfValue => { write!(f, "self")?; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 9617f0d9a1f25..b7bcda2a604cf 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -58,7 +58,7 @@ use serde::{Serialize, Serializer}; pub(crate) use self::context::*; pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc}; -use crate::clean::{self, ItemId, RenderedLink, SelfTy}; +use crate::clean::{self, ItemId, ReceiverTy, RenderedLink}; use crate::error::Error; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -1372,21 +1372,21 @@ fn render_deref_methods( fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { let self_type_opt = match *item.kind { - clean::MethodItem(ref method, _) => method.decl.self_type(), - clean::TyMethodItem(ref method) => method.decl.self_type(), + clean::MethodItem(ref method, _) => method.decl.receiver_type(), + clean::TyMethodItem(ref method) => method.decl.receiver_type(), _ => None, }; if let Some(self_ty) = self_type_opt { let (by_mut_ref, by_box, by_value) = match self_ty { - SelfTy::SelfBorrowed(_, mutability) - | SelfTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { + ReceiverTy::SelfBorrowed(_, mutability) + | ReceiverTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { (mutability == Mutability::Mut, false, false) } - SelfTy::SelfExplicit(clean::Type::Path { path }) => { + ReceiverTy::SelfExplicit(clean::Type::Path { path }) => { (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false) } - SelfTy::SelfValue => (false, false, true), + ReceiverTy::SelfValue => (false, false, true), _ => (false, false, false), }; From 664b3ffbe932d93677ac7dff52252e02aee60ef9 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 16:45:05 -0700 Subject: [PATCH 457/489] rustdoc: Create `SelfTy` to replace `Generic(kw::SelfUpper)` Rustdoc often has to special-case `Self` because it is, well, a special type of generic parameter (although it also behaves as an alias in concrete impls). Instead of spreading this special-casing throughout the code base, create a new variant of the `clean::Type` enum that is for `Self` types. This is a refactoring that has almost no impact on rustdoc's behavior, except that `&Self`, `(Self,)`, `&[Self]`, and other similar occurrences of `Self` no longer link to the wrapping type (reference primitive, tuple primitive, etc.) as regular generics do. I felt this made more sense since users would expect `Self` to link to the containing trait or aliased type (though those are usually expanded), not the primitive that is wrapping it. For an example of the change, see the docs for `std::alloc::Allocator::by_ref`. --- src/librustdoc/clean/inline.rs | 16 +++++----------- src/librustdoc/clean/mod.rs | 11 ++++++----- src/librustdoc/clean/simplify.rs | 1 - src/librustdoc/clean/types.rs | 10 +++++++--- src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/html/format.rs | 1 + src/librustdoc/html/render/search_index.rs | 15 ++++++++++++--- src/librustdoc/json/conversions.rs | 4 +++- 8 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d92bc8456649f..f8953f0ebcfb5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{sym, Symbol}; use thin_vec::{thin_vec, ThinVec}; use {rustc_ast as ast, rustc_hir as hir}; @@ -792,11 +792,7 @@ fn build_macro( fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics { for pred in &mut g.where_predicates { match *pred { - clean::WherePredicate::BoundPredicate { - ty: clean::Generic(ref s), - ref mut bounds, - .. - } if *s == kw::SelfUpper => { + clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref mut bounds, .. } => { bounds.retain(|bound| match bound { clean::GenericBound::TraitBound(clean::PolyTrait { trait_, .. }, _) => { trait_.def_id() != trait_did @@ -812,13 +808,13 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: clean::WherePredicate::BoundPredicate { ty: clean::QPath(box clean::QPathData { - self_type: clean::Generic(ref s), + self_type: clean::Generic(_), trait_: Some(trait_), .. }), bounds, .. - } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did), + } => !bounds.is_empty() && trait_.def_id() != trait_did, _ => true, }); g @@ -832,9 +828,7 @@ fn separate_supertrait_bounds( ) -> (clean::Generics, Vec) { let mut ty_bounds = Vec::new(); g.where_predicates.retain(|pred| match *pred { - clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. } - if *s == kw::SelfUpper => - { + clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => { ty_bounds.extend(bounds.iter().cloned()); false } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 324b633e8ea7e..cffadc7c10a91 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1351,11 +1351,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( let self_arg_ty = tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder(); if self_arg_ty == self_ty { - item.decl.inputs.values[0].type_ = Generic(kw::SelfUpper); + item.decl.inputs.values[0].type_ = SelfTy; } else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() { if ty == self_ty { match item.decl.inputs.values[0].type_ { - BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper), + BorrowedRef { ref mut type_, .. } => **type_ = SelfTy, _ => unreachable!(), } } @@ -1439,9 +1439,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( if trait_.def_id() != assoc_item.container_id(tcx) { return true; } - match *self_type { - Generic(ref s) if *s == kw::SelfUpper => {} - _ => return true, + if *self_type != SelfTy { + return true; } match &assoc.args { GenericArgs::AngleBracketed { args, constraints } => { @@ -2228,6 +2227,8 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Param(ref p) => { if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) { ImplTrait(bounds) + } else if p.name == kw::SelfUpper { + SelfTy } else { Generic(p.name) } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 739f6eb8cc89d..1d81ae3eb8ba7 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -145,7 +145,6 @@ pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generi // should be handled when cleaning associated types. generics.where_predicates.retain(|pred| { if let WP::BoundPredicate { ty: clean::Generic(param), bounds, .. } = pred - && *param != rustc_span::symbol::kw::SelfUpper && bounds.iter().any(|b| b.is_sized_bound(cx)) { sized_params.insert(*param); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 32e795e565ed2..82f1312364a5b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -37,7 +37,7 @@ pub(crate) use self::ItemKind::*; pub(crate) use self::ReceiverTy::*; pub(crate) use self::Type::{ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, - RawPointer, Slice, Tuple, + RawPointer, SelfTy, Slice, Tuple, }; use crate::clean::cfg::Cfg; use crate::clean::clean_middle_path; @@ -1477,6 +1477,8 @@ pub(crate) enum Type { DynTrait(Vec, Option), /// A type parameter. Generic(Symbol), + /// The `Self` type. + SelfTy, /// A primitive (aka, builtin) type. Primitive(PrimitiveType), /// A function pointer: `extern "ABI" fn(...) -> ...` @@ -1571,6 +1573,8 @@ impl Type { // If both sides are generic, this returns true. (_, Type::Generic(_)) => true, (Type::Generic(_), _) => false, + // `Self` only matches itself. + (Type::SelfTy, Type::SelfTy) => true, // Paths account for both the path itself and its generics. (Type::Path { path: a }, Type::Path { path: b }) => { a.def_id() == b.def_id() @@ -1642,7 +1646,7 @@ impl Type { pub(crate) fn is_self_type(&self) -> bool { match *self { - Generic(name) => name == kw::SelfUpper, + SelfTy => true, _ => false, } } @@ -1700,7 +1704,7 @@ impl Type { Type::Pat(..) => PrimitiveType::Pat, RawPointer(..) => PrimitiveType::RawPointer, QPath(box QPathData { ref self_type, .. }) => return self_type.def_id(cache), - Generic(_) | Infer | ImplTrait(_) => return None, + Generic(_) | SelfTy | Infer | ImplTrait(_) => return None, }; Primitive(t).def_id(cache) } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 2dd3041ab4c61..68266f3506a01 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -468,7 +468,7 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type { match path.res { Res::PrimTy(p) => Primitive(PrimitiveType::from(p)), Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } if path.segments.len() == 1 => { - Generic(kw::SelfUpper) + Type::SelfTy } Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name), _ => { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6476c8bd7c0d3..0fe535ade9b2a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1006,6 +1006,7 @@ fn fmt_type<'cx>( match *t { clean::Generic(name) => f.write_str(name.as_str()), + clean::SelfTy => f.write_str("Self"), clean::Type::Path { ref path } => { // Paths like `T::Output` and `Self::Output` should be rendered with all segments. let did = path.def_id(); diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index b3f4d82e054b8..fc3d6c99b809f 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -797,7 +797,11 @@ fn get_index_type_id( } } // Not supported yet - clean::Type::Pat(..) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None, + clean::Type::Pat(..) + | clean::Generic(_) + | clean::SelfTy + | clean::ImplTrait(_) + | clean::Infer => None, } } @@ -848,13 +852,18 @@ fn simplify_fn_type<'tcx, 'a>( (false, arg) }; + let as_arg_s = |t: &Type| match *t { + Type::Generic(arg_s) => Some(arg_s), + Type::SelfTy => Some(kw::SelfUpper), + _ => None, + }; // If this argument is a type parameter and not a trait bound or a type, we need to look // for its bounds. - if let Type::Generic(arg_s) = *arg { + if let Some(arg_s) = as_arg_s(arg) { // First we check if the bounds are in a `where` predicate... let mut type_bounds = Vec::new(); for where_pred in generics.where_predicates.iter().filter(|g| match g { - WherePredicate::BoundPredicate { ty: Type::Generic(ty_s), .. } => *ty_s == arg_s, + WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, _ => false, }) { let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index b56244f2d3b6d..b97d710c007ce 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -578,7 +578,7 @@ impl FromWithTcx for Type { fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { use clean::Type::{ Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath, - RawPointer, Slice, Tuple, + RawPointer, SelfTy, Slice, Tuple, }; match ty { @@ -588,6 +588,8 @@ impl FromWithTcx for Type { traits: bounds.into_tcx(tcx), }), Generic(s) => Type::Generic(s.to_string()), + // FIXME: add dedicated variant to json Type? + SelfTy => Type::Generic("Self".to_owned()), Primitive(p) => Type::Primitive(p.as_sym().to_string()), BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), Tuple(t) => Type::Tuple(t.into_tcx(tcx)), From 4e348fa803723a38553138d9795cb2c6b7fb964a Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 17:06:32 -0700 Subject: [PATCH 458/489] rustdoc: Stop treating `Self` as a generic in search index We already have special-cased code to handle inlining `Self` as the type or trait it refers to, and this was just causing glitches like the search `A -> B` yielding blanket `Into` impls. --- src/librustdoc/html/render/search_index.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index fc3d6c99b809f..e4d948b8c9c1a 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -852,14 +852,9 @@ fn simplify_fn_type<'tcx, 'a>( (false, arg) }; - let as_arg_s = |t: &Type| match *t { - Type::Generic(arg_s) => Some(arg_s), - Type::SelfTy => Some(kw::SelfUpper), - _ => None, - }; // If this argument is a type parameter and not a trait bound or a type, we need to look // for its bounds. - if let Some(arg_s) = as_arg_s(arg) { + if let Type::Generic(arg_s) = *arg { // First we check if the bounds are in a `where` predicate... let mut type_bounds = Vec::new(); for where_pred in generics.where_predicates.iter().filter(|g| match g { From e452e3def69deca6a671b6067b1faf14b4cf83f2 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 17:17:14 -0700 Subject: [PATCH 459/489] Use `match` instead of sequence of `if let`s This is much more readable and idiomatic, and also may help performance since `match`es usually use switches while `if`s may not. I also fixed an incorrect comment. --- src/librustdoc/html/render/search_index.rs | 477 +++++++++++---------- 1 file changed, 243 insertions(+), 234 deletions(-) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index e4d948b8c9c1a..8a2f31f7413e1 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -854,34 +854,70 @@ fn simplify_fn_type<'tcx, 'a>( // If this argument is a type parameter and not a trait bound or a type, we need to look // for its bounds. - if let Type::Generic(arg_s) = *arg { - // First we check if the bounds are in a `where` predicate... - let mut type_bounds = Vec::new(); - for where_pred in generics.where_predicates.iter().filter(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, - _ => false, - }) { - let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); - for bound in bounds.iter() { - if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); + match *arg { + Type::Generic(arg_s) => { + // First we check if the bounds are in a `where` predicate... + let mut type_bounds = Vec::new(); + for where_pred in generics.where_predicates.iter().filter(|g| match g { + WherePredicate::BoundPredicate { ty, .. } => *ty == *arg, + _ => false, + }) { + let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); + for bound in bounds.iter() { + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut type_bounds, + rgen, + is_return, + cache, + ); + } + } + } + // Otherwise we check if the trait bounds are "inlined" like `T: Option`... + if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { + for bound in bound.get_bounds().unwrap_or(&[]) { + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut type_bounds, + rgen, + is_return, + cache, + ); + } } } + if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) { + res.push(RenderType { + id: Some(RenderTypeId::Index(*idx)), + generics: None, + bindings: None, + }); + } else { + let idx = -isize::try_from(rgen.len() + 1).unwrap(); + rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds)); + res.push(RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }); + } } - // Otherwise we check if the trait bounds are "inlined" like `T: Option`... - if let Some(bound) = generics.params.iter().find(|g| g.is_type() && g.name == arg_s) { - for bound in bound.get_bounds().unwrap_or(&[]) { + Type::ImplTrait(ref bounds) => { + let mut type_bounds = Vec::new(); + for bound in bounds { if let Some(path) = bound.get_trait_path() { let ty = Type::Path { path }; simplify_fn_type( @@ -897,84 +933,22 @@ fn simplify_fn_type<'tcx, 'a>( ); } } - } - if let Some((idx, _)) = rgen.get(&SimplifiedParam::Symbol(arg_s)) { - res.push(RenderType { - id: Some(RenderTypeId::Index(*idx)), - generics: None, - bindings: None, - }); - } else { - let idx = -isize::try_from(rgen.len() + 1).unwrap(); - rgen.insert(SimplifiedParam::Symbol(arg_s), (idx, type_bounds)); - res.push(RenderType { - id: Some(RenderTypeId::Index(idx)), - generics: None, - bindings: None, - }); - } - } else if let Type::ImplTrait(ref bounds) = *arg { - let mut type_bounds = Vec::new(); - for bound in bounds { - if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); + if is_return && !type_bounds.is_empty() { + // In return position, `impl Trait` is a unique thing. + res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None }); + } else { + // In parameter position, `impl Trait` is the same as an unnamed generic parameter. + let idx = -isize::try_from(rgen.len() + 1).unwrap(); + rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds)); + res.push(RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }); } } - if is_return && !type_bounds.is_empty() { - // In parameter position, `impl Trait` is a unique thing. - res.push(RenderType { id: None, generics: Some(type_bounds), bindings: None }); - } else { - // In parameter position, `impl Trait` is the same as an unnamed generic parameter. - let idx = -isize::try_from(rgen.len() + 1).unwrap(); - rgen.insert(SimplifiedParam::Anonymous(idx), (idx, type_bounds)); - res.push(RenderType { - id: Some(RenderTypeId::Index(idx)), - generics: None, - bindings: None, - }); - } - } else if let Type::Slice(ref ty) = *arg { - let mut ty_generics = Vec::new(); - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); - } else if let Type::Array(ref ty, _) = *arg { - let mut ty_generics = Vec::new(); - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); - } else if let Type::Tuple(ref tys) = *arg { - let mut ty_generics = Vec::new(); - for ty in tys { + Type::Slice(ref ty) => { + let mut ty_generics = Vec::new(); simplify_fn_type( self_, generics, @@ -986,15 +960,14 @@ fn simplify_fn_type<'tcx, 'a>( is_return, cache, ); + res.push(get_index_type(arg, ty_generics, rgen)); } - res.push(get_index_type(arg, ty_generics, rgen)); - } else if let Type::BareFunction(ref bf) = *arg { - let mut ty_generics = Vec::new(); - for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) { + Type::Array(ref ty, _) => { + let mut ty_generics = Vec::new(); simplify_fn_type( self_, generics, - ty, + &ty, tcx, recurse + 1, &mut ty_generics, @@ -1002,62 +975,11 @@ fn simplify_fn_type<'tcx, 'a>( is_return, cache, ); + res.push(get_index_type(arg, ty_generics, rgen)); } - // The search index, for simplicity's sake, represents fn pointers and closures - // the same way: as a tuple for the parameters, and an associated type for the - // return type. - let mut ty_output = Vec::new(); - simplify_fn_type( - self_, - generics, - &bf.decl.output, - tcx, - recurse + 1, - &mut ty_output, - rgen, - is_return, - cache, - ); - let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; - res.push(RenderType { - id: get_index_type_id(&arg, rgen), - bindings: Some(ty_bindings), - generics: Some(ty_generics), - }); - } else if let Type::BorrowedRef { lifetime: _, mutability, ref type_ } = *arg { - let mut ty_generics = Vec::new(); - if mutability.is_mut() { - ty_generics.push(RenderType { - id: Some(RenderTypeId::Mut), - generics: None, - bindings: None, - }); - } - simplify_fn_type( - self_, - generics, - &type_, - tcx, - recurse + 1, - &mut ty_generics, - rgen, - is_return, - cache, - ); - res.push(get_index_type(arg, ty_generics, rgen)); - } else { - // This is not a type parameter. So for example if we have `T, U: Option`, and we're - // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't. - // - // So in here, we can add it directly and look for its own type parameters (so for `Option`, - // we will look for them but not for `T`). - let mut ty_generics = Vec::new(); - let mut ty_constraints = Vec::new(); - if let Some(arg_generics) = arg.generic_args() { - for ty in arg_generics.into_iter().filter_map(|param| match param { - clean::GenericArg::Type(ty) => Some(ty), - _ => None, - }) { + Type::Tuple(ref tys) => { + let mut ty_generics = Vec::new(); + for ty in tys { simplify_fn_type( self_, generics, @@ -1070,94 +992,181 @@ fn simplify_fn_type<'tcx, 'a>( cache, ); } - for constraint in arg_generics.constraints() { - simplify_fn_constraint( + res.push(get_index_type(arg, ty_generics, rgen)); + } + Type::BareFunction(ref bf) => { + let mut ty_generics = Vec::new(); + for ty in bf.decl.inputs.values.iter().map(|arg| &arg.type_) { + simplify_fn_type( self_, generics, - &constraint, + ty, tcx, recurse + 1, - &mut ty_constraints, + &mut ty_generics, rgen, is_return, cache, ); } + // The search index, for simplicity's sake, represents fn pointers and closures + // the same way: as a tuple for the parameters, and an associated type for the + // return type. + let mut ty_output = Vec::new(); + simplify_fn_type( + self_, + generics, + &bf.decl.output, + tcx, + recurse + 1, + &mut ty_output, + rgen, + is_return, + cache, + ); + let ty_bindings = vec![(RenderTypeId::AssociatedType(sym::Output), ty_output)]; + res.push(RenderType { + id: get_index_type_id(&arg, rgen), + bindings: Some(ty_bindings), + generics: Some(ty_generics), + }); } - // Every trait associated type on self gets assigned to a type parameter index - // this same one is used later for any appearances of these types - // - // for example, Iterator::next is: - // - // trait Iterator { - // fn next(&mut self) -> Option - // } - // - // Self is technically just Iterator, but we want to pretend it's more like this: - // - // fn next(self: Iterator) -> Option - if is_self - && let Type::Path { path } = arg - && let def_id = path.def_id() - && let Some(trait_) = cache.traits.get(&def_id) - && trait_.items.iter().any(|at| at.is_ty_associated_type()) - { - for assoc_ty in &trait_.items { - if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind - && let Some(name) = assoc_ty.name - { - let idx = -isize::try_from(rgen.len() + 1).unwrap(); - let (idx, stored_bounds) = rgen - .entry(SimplifiedParam::AssociatedType(def_id, name)) - .or_insert_with(|| (idx, Vec::new())); - let idx = *idx; - if stored_bounds.is_empty() { - // Can't just pass stored_bounds to simplify_fn_type, - // because it also accepts rgen as a parameter. - // Instead, have it fill in this local, then copy it into the map afterward. - let mut type_bounds = Vec::new(); - for bound in bounds { - if let Some(path) = bound.get_trait_path() { - let ty = Type::Path { path }; - simplify_fn_type( - self_, - generics, - &ty, - tcx, - recurse + 1, - &mut type_bounds, - rgen, - is_return, - cache, - ); - } - } - let stored_bounds = &mut rgen - .get_mut(&SimplifiedParam::AssociatedType(def_id, name)) - .unwrap() - .1; + Type::BorrowedRef { lifetime: _, mutability, ref type_ } => { + let mut ty_generics = Vec::new(); + if mutability.is_mut() { + ty_generics.push(RenderType { + id: Some(RenderTypeId::Mut), + generics: None, + bindings: None, + }); + } + simplify_fn_type( + self_, + generics, + &type_, + tcx, + recurse + 1, + &mut ty_generics, + rgen, + is_return, + cache, + ); + res.push(get_index_type(arg, ty_generics, rgen)); + } + _ => { + // This is not a type parameter. So for example if we have `T, U: Option`, and we're + // looking at `Option`, we enter this "else" condition, otherwise if it's `T`, we don't. + // + // So in here, we can add it directly and look for its own type parameters (so for `Option`, + // we will look for them but not for `T`). + let mut ty_generics = Vec::new(); + let mut ty_constraints = Vec::new(); + if let Some(arg_generics) = arg.generic_args() { + for ty in arg_generics.into_iter().filter_map(|param| match param { + clean::GenericArg::Type(ty) => Some(ty), + _ => None, + }) { + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut ty_generics, + rgen, + is_return, + cache, + ); + } + for constraint in arg_generics.constraints() { + simplify_fn_constraint( + self_, + generics, + &constraint, + tcx, + recurse + 1, + &mut ty_constraints, + rgen, + is_return, + cache, + ); + } + } + // Every trait associated type on self gets assigned to a type parameter index + // this same one is used later for any appearances of these types + // + // for example, Iterator::next is: + // + // trait Iterator { + // fn next(&mut self) -> Option + // } + // + // Self is technically just Iterator, but we want to pretend it's more like this: + // + // fn next(self: Iterator) -> Option + if is_self + && let Type::Path { path } = arg + && let def_id = path.def_id() + && let Some(trait_) = cache.traits.get(&def_id) + && trait_.items.iter().any(|at| at.is_ty_associated_type()) + { + for assoc_ty in &trait_.items { + if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &*assoc_ty.kind + && let Some(name) = assoc_ty.name + { + let idx = -isize::try_from(rgen.len() + 1).unwrap(); + let (idx, stored_bounds) = rgen + .entry(SimplifiedParam::AssociatedType(def_id, name)) + .or_insert_with(|| (idx, Vec::new())); + let idx = *idx; if stored_bounds.is_empty() { - *stored_bounds = type_bounds; + // Can't just pass stored_bounds to simplify_fn_type, + // because it also accepts rgen as a parameter. + // Instead, have it fill in this local, then copy it into the map afterward. + let mut type_bounds = Vec::new(); + for bound in bounds { + if let Some(path) = bound.get_trait_path() { + let ty = Type::Path { path }; + simplify_fn_type( + self_, + generics, + &ty, + tcx, + recurse + 1, + &mut type_bounds, + rgen, + is_return, + cache, + ); + } + } + let stored_bounds = &mut rgen + .get_mut(&SimplifiedParam::AssociatedType(def_id, name)) + .unwrap() + .1; + if stored_bounds.is_empty() { + *stored_bounds = type_bounds; + } } + ty_constraints.push(( + RenderTypeId::AssociatedType(name), + vec![RenderType { + id: Some(RenderTypeId::Index(idx)), + generics: None, + bindings: None, + }], + )) } - ty_constraints.push(( - RenderTypeId::AssociatedType(name), - vec![RenderType { - id: Some(RenderTypeId::Index(idx)), - generics: None, - bindings: None, - }], - )) } } - } - let id = get_index_type_id(&arg, rgen); - if id.is_some() || !ty_generics.is_empty() { - res.push(RenderType { - id, - bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) }, - generics: if ty_generics.is_empty() { None } else { Some(ty_generics) }, - }); + let id = get_index_type_id(&arg, rgen); + if id.is_some() || !ty_generics.is_empty() { + res.push(RenderType { + id, + bindings: if ty_constraints.is_empty() { None } else { Some(ty_constraints) }, + generics: if ty_generics.is_empty() { None } else { Some(ty_generics) }, + }); + } } } } From b4f77df9f8540f48744794c641e12ef66e0e57ba Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 17:33:13 -0700 Subject: [PATCH 460/489] rustdoc: Delete `ReceiverTy` (formerly known as `SelfTy`) It was barely used, and the places that used it are actually clearer without it since they were often undoing some of its work. This also avoids an unnecessary clone of the receiver type and removes a layer of logical indirection in the code. --- src/librustdoc/clean/types.rs | 25 +++---------------------- src/librustdoc/html/format.rs | 27 ++++++++++----------------- src/librustdoc/html/render/mod.rs | 11 +++++------ 3 files changed, 18 insertions(+), 45 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 82f1312364a5b..4850500a1bfae 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -34,7 +34,6 @@ use thin_vec::ThinVec; use {rustc_ast as ast, rustc_hir as hir}; pub(crate) use self::ItemKind::*; -pub(crate) use self::ReceiverTy::*; pub(crate) use self::Type::{ Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive, QPath, RawPointer, SelfTy, Slice, Tuple, @@ -1384,7 +1383,7 @@ pub(crate) struct FnDecl { } impl FnDecl { - pub(crate) fn receiver_type(&self) -> Option { + pub(crate) fn receiver_type(&self) -> Option<&Type> { self.inputs.values.get(0).and_then(|v| v.to_receiver()) } } @@ -1403,27 +1402,9 @@ pub(crate) struct Argument { pub(crate) is_const: bool, } -#[derive(Clone, PartialEq, Debug)] -pub(crate) enum ReceiverTy { - SelfValue, - SelfBorrowed(Option, Mutability), - SelfExplicit(Type), -} - impl Argument { - pub(crate) fn to_receiver(&self) -> Option { - if self.name != kw::SelfLower { - return None; - } - if self.type_.is_self_type() { - return Some(SelfValue); - } - match self.type_ { - BorrowedRef { ref lifetime, mutability, ref type_ } if type_.is_self_type() => { - Some(SelfBorrowed(lifetime.clone(), mutability)) - } - _ => Some(SelfExplicit(self.type_.clone())), - } + pub(crate) fn to_receiver(&self) -> Option<&Type> { + if self.name == kw::SelfLower { Some(&self.type_) } else { None } } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0fe535ade9b2a..b5ab6a35fdb9d 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1455,27 +1455,20 @@ impl clean::FnDecl { for (i, input) in self.inputs.values.iter().enumerate() { if let Some(selfty) = input.to_receiver() { match selfty { - clean::SelfValue => { + clean::SelfTy => { write!(f, "self")?; } - clean::SelfBorrowed(Some(ref lt), mutability) => { - write!( - f, - "{amp}{lifetime} {mutability}self", - lifetime = lt.print(), - mutability = mutability.print_with_space(), - )?; - } - clean::SelfBorrowed(None, mutability) => { - write!( - f, - "{amp}{mutability}self", - mutability = mutability.print_with_space(), - )?; + clean::BorrowedRef { lifetime, mutability, type_: box clean::SelfTy } => { + write!(f, "{amp}")?; + match lifetime { + Some(lt) => write!(f, "{lt} ", lt = lt.print())?, + None => {} + } + write!(f, "{mutability}self", mutability = mutability.print_with_space())?; } - clean::SelfExplicit(ref typ) => { + _ => { write!(f, "self: ")?; - typ.print(cx).fmt(f)?; + selfty.print(cx).fmt(f)?; } } } else { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index b7bcda2a604cf..9074e40a53614 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -58,7 +58,7 @@ use serde::{Serialize, Serializer}; pub(crate) use self::context::*; pub(crate) use self::span_map::{collect_spans_and_sources, LinkFromSrc}; -use crate::clean::{self, ItemId, ReceiverTy, RenderedLink}; +use crate::clean::{self, ItemId, RenderedLink}; use crate::error::Error; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; @@ -1378,15 +1378,14 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> }; if let Some(self_ty) = self_type_opt { - let (by_mut_ref, by_box, by_value) = match self_ty { - ReceiverTy::SelfBorrowed(_, mutability) - | ReceiverTy::SelfExplicit(clean::BorrowedRef { mutability, .. }) => { + let (by_mut_ref, by_box, by_value) = match *self_ty { + clean::Type::BorrowedRef { mutability, .. } => { (mutability == Mutability::Mut, false, false) } - ReceiverTy::SelfExplicit(clean::Type::Path { path }) => { + clean::Type::Path { ref path } => { (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false) } - ReceiverTy::SelfValue => (false, false, true), + clean::Type::SelfTy => (false, false, true), _ => (false, false, false), }; From dac7f20e1308ea17655d17f43dffaca813857300 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 31 Jul 2024 20:13:17 -0700 Subject: [PATCH 461/489] Add test for `Self` not being a generic in search index --- tests/rustdoc-js/self-is-not-generic.js | 22 ++++++++++++++++++++++ tests/rustdoc-js/self-is-not-generic.rs | 11 +++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/rustdoc-js/self-is-not-generic.js create mode 100644 tests/rustdoc-js/self-is-not-generic.rs diff --git a/tests/rustdoc-js/self-is-not-generic.js b/tests/rustdoc-js/self-is-not-generic.js new file mode 100644 index 0000000000000..0fdf5b4117d8f --- /dev/null +++ b/tests/rustdoc-js/self-is-not-generic.js @@ -0,0 +1,22 @@ +// exact-check + +const EXPECTED = [ + { + 'query': 'A -> A', + 'others': [ + { 'path': 'self_is_not_generic::Thing', 'name': 'from' } + ], + }, + { + 'query': 'A -> B', + 'others': [ + { 'path': 'self_is_not_generic::Thing', 'name': 'try_from' } + ], + }, + { + 'query': 'Combine -> Combine', + 'others': [ + { 'path': 'self_is_not_generic::Combine', 'name': 'combine' } + ], + } +]; diff --git a/tests/rustdoc-js/self-is-not-generic.rs b/tests/rustdoc-js/self-is-not-generic.rs new file mode 100644 index 0000000000000..d6a96acb73caf --- /dev/null +++ b/tests/rustdoc-js/self-is-not-generic.rs @@ -0,0 +1,11 @@ +pub trait Combine { + fn combine(&self, other: &Self) -> Self; +} + +pub struct Thing; + +impl Combine for Thing { + fn combine(&self, other: &Self) -> Self { + Self + } +} From 41ec376edde29fb4df2b1d6fd89ceab93a248ab2 Mon Sep 17 00:00:00 2001 From: Mahmoud Mazouz Date: Sun, 4 Aug 2024 21:59:03 +0200 Subject: [PATCH 462/489] Add `Debug` impls to API types in `rustc_codegen_ssa` --- compiler/rustc_codegen_ssa/src/common.rs | 10 +++++----- compiler/rustc_codegen_ssa/src/mir/operand.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/builder.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 741c0f090e98d..a972c0cd99d10 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -8,7 +8,7 @@ use rustc_span::Span; use crate::traits::*; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum IntPredicate { IntEQ, IntNE, @@ -22,7 +22,7 @@ pub enum IntPredicate { IntSLE, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum RealPredicate { RealPredicateFalse, RealOEQ, @@ -42,7 +42,7 @@ pub enum RealPredicate { RealPredicateTrue, } -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum AtomicRmwBinOp { AtomicXchg, AtomicAdd, @@ -57,7 +57,7 @@ pub enum AtomicRmwBinOp { AtomicUMin, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum AtomicOrdering { Unordered, Relaxed, @@ -67,7 +67,7 @@ pub enum AtomicOrdering { SequentiallyConsistent, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum SynchronizationScope { SingleThread, CrossThread, diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 2bc2d0f70bfaf..cceb99b605e32 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -131,7 +131,7 @@ impl OperandValue { /// to avoid nasty edge cases. In particular, using `Builder::store` /// directly is sure to cause problems -- use `OperandRef::store` /// instead. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct OperandRef<'tcx, V> { /// The value. pub val: OperandValue, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 0495902dda511..2b802240e03b9 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -23,7 +23,7 @@ use crate::mir::operand::{OperandRef, OperandValue}; use crate::mir::place::{PlaceRef, PlaceValue}; use crate::MemFlags; -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub enum OverflowOp { Add, Sub, From 70ab51f988ae44afb9f50151b7732ba10c37e4a8 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sun, 4 Aug 2024 07:11:11 +0900 Subject: [PATCH 463/489] Correct the const stabilization of `<[T]>::last_chunk` `<[T]>::first_chunk` became const stable in 1.77, but `<[T]>::last_chunk` was left out. This was fixed in 3488679768d, which reached stable in 1.80, making `<[T]>::last_chunk` const stable as of that version, but it is documented as being const stable as 1.77. While this is what should have happened, the documentation should reflect what actually did happen. --- library/core/src/slice/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 45dc828eb2ed9..b1440214d795a 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -522,7 +522,7 @@ impl [T] { /// ``` #[inline] #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] - #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "const_slice_last_chunk", since = "1.80.0")] pub const fn last_chunk(&self) -> Option<&[T; N]> { if self.len() < N { None From 9411844aff6a3a62c1de71874bf20bf6290d009f Mon Sep 17 00:00:00 2001 From: Mahmoud Mazouz Date: Mon, 5 Aug 2024 10:30:27 +0200 Subject: [PATCH 464/489] `OperandRef` already had a `Debug` impl Co-authored-by: Jubilee <46493976+workingjubilee@users.noreply.github.com> --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index cceb99b605e32..2bc2d0f70bfaf 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -131,7 +131,7 @@ impl OperandValue { /// to avoid nasty edge cases. In particular, using `Builder::store` /// directly is sure to cause problems -- use `OperandRef::store` /// instead. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] pub struct OperandRef<'tcx, V> { /// The value. pub val: OperandValue, From d28083728d493533a72e5a7fe9b9820b824cfcac Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 10:49:01 +0200 Subject: [PATCH 465/489] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index f03fe70aa2149..b74f9759ebed6 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -1df0458781d6fd753a68c4cdc4de5313b1635dbd +29e924841f06bb181d87494eba2783761bc1ddec From 61463fd042520b1454fecfca0437180535ea8497 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 11:04:40 +0200 Subject: [PATCH 466/489] fmt --- src/tools/miri/src/machine.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index fec345c8de1da..3e45a3a7e1a12 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -932,7 +932,10 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.machine.validation != ValidationMode::No } #[inline(always)] - fn enforce_validity_recursively(ecx: &InterpCx<'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool { + fn enforce_validity_recursively( + ecx: &InterpCx<'tcx, Self>, + _layout: TyAndLayout<'tcx>, + ) -> bool { ecx.machine.validation == ValidationMode::Deep } From 7499e21a1ef918ed503fb8c4e5ab5c808d71bb44 Mon Sep 17 00:00:00 2001 From: schvv31n Date: Tue, 30 Jul 2024 12:27:15 +0100 Subject: [PATCH 467/489] rustdoc-json: discard non-local inherent impls --- src/librustdoc/formats/cache.rs | 38 ++++++++++++------------------ src/librustdoc/json/mod.rs | 6 ----- tests/rustdoc-json/the_smallest.rs | 5 ++++ 3 files changed, 20 insertions(+), 29 deletions(-) create mode 100644 tests/rustdoc-json/the_smallest.rs diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 9f284486616a0..fab45e977b0df 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -442,16 +442,16 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { // `public_items` map, so we can skip inserting into the // paths map if there was already an entry present and we're // not a public item. - if !self.cache.paths.contains_key(&item.item_id.expect_def_id()) + let item_def_id = item.item_id.expect_def_id(); + if !self.cache.paths.contains_key(&item_def_id) || self .cache .effective_visibilities - .is_directly_public(self.tcx, item.item_id.expect_def_id()) + .is_directly_public(self.tcx, item_def_id) { - self.cache.paths.insert( - item.item_id.expect_def_id(), - (self.cache.stack.clone(), item.type_()), - ); + self.cache + .paths + .insert(item_def_id, (self.cache.stack.clone(), item.type_())); } } } @@ -514,9 +514,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { && adt.is_fundamental() { for ty in generics { - if let Some(did) = ty.def_id(self.cache) { - dids.insert(did); - } + dids.extend(ty.def_id(self.cache)); } } } @@ -529,32 +527,26 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { .primitive_type() .and_then(|t| self.cache.primitive_locations.get(&t).cloned()); - if let Some(did) = did { - dids.insert(did); - } + dids.extend(did); } } if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { for bound in generics { - if let Some(did) = bound.def_id(self.cache) { - dids.insert(did); - } + dids.extend(bound.def_id(self.cache)); } } let impl_item = Impl { impl_item: item }; - if impl_item.trait_did().map_or(true, |d| self.cache.traits.contains_key(&d)) { + let impl_did = impl_item.def_id(); + let trait_did = impl_item.trait_did(); + if trait_did.map_or(true, |d| self.cache.traits.contains_key(&d)) { for did in dids { - if self.impl_ids.entry(did).or_default().insert(impl_item.def_id()) { - self.cache - .impls - .entry(did) - .or_insert_with(Vec::new) - .push(impl_item.clone()); + if self.impl_ids.entry(did).or_default().insert(impl_did) { + self.cache.impls.entry(did).or_default().push(impl_item.clone()); } } } else { - let trait_did = impl_item.trait_did().expect("no trait did"); + let trait_did = trait_did.expect("no trait did"); self.cache.orphan_trait_impls.push((trait_did, dids, impl_item)); } None diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 033f01864f149..3c3c16a563caa 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -217,13 +217,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { fn after_krate(&mut self) -> Result<(), Error> { debug!("Done with crate"); - debug!("Adding Primitive impls"); - for primitive in Rc::clone(&self.cache).primitive_locations.values() { - self.get_impls(*primitive); - } - let e = ExternalCrate { crate_num: LOCAL_CRATE }; - let index = (*self.index).clone().into_inner(); debug!("Constructing Output"); diff --git a/tests/rustdoc-json/the_smallest.rs b/tests/rustdoc-json/the_smallest.rs new file mode 100644 index 0000000000000..2f6f91e6e2751 --- /dev/null +++ b/tests/rustdoc-json/the_smallest.rs @@ -0,0 +1,5 @@ +// This test asserts that `index` is not polluted with unrelated items. +// See https://github.com/rust-lang/rust/issues/114039 + +//@ count "$.index[*]" 1 +fn main() {} From 6a891ec4fe0db4790e9d000b15c5ec79907605b3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 18 Jul 2024 11:37:19 -0400 Subject: [PATCH 468/489] Enforce supertrait outlives obligations hold when confirming impl --- .../src/solve/trait_goals.rs | 13 +++++++ .../src/traits/select/mod.rs | 34 +++++++++++++++++-- compiler/rustc_type_ir/src/inherent.rs | 2 ++ ...implied-bounds-unnorm-associated-type-5.rs | 1 + ...ied-bounds-unnorm-associated-type-5.stderr | 17 ++++++++-- tests/ui/static/static-lifetime.rs | 1 + tests/ui/static/static-lifetime.stderr | 30 ++++++++++++++-- .../wf-in-where-clause-static.current.stderr | 12 +++++++ .../wf/wf-in-where-clause-static.next.stderr | 12 +++++++ tests/ui/wf/wf-in-where-clause-static.rs | 10 +++--- 10 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 tests/ui/wf/wf-in-where-clause-static.current.stderr create mode 100644 tests/ui/wf/wf-in-where-clause-static.next.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 4474bbc235198..77ce81e44a0b0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -87,6 +87,19 @@ where .map(|pred| goal.with(cx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); + // We currently elaborate all supertrait obligations from impls. This + // can be removed when we actually do coinduction correctly and just + // register that the impl header must be WF. + let goal_clause: I::Clause = goal.predicate.upcast(cx); + for clause in elaborate::elaborate(cx, [goal_clause]) { + if matches!( + clause.kind().skip_binder(), + ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..) + ) { + ecx.add_goal(GoalSource::Misc, goal.with(cx, clause)); + } + } + ecx.evaluate_added_goals_and_make_canonical_response(maximal_certainty) }) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cc9174d3aad52..2bc2a8fe693c5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -7,6 +7,7 @@ use std::fmt::{self, Display}; use std::ops::ControlFlow; use std::{cmp, iter}; +use hir::def::DefKind; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; @@ -14,8 +15,9 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; use rustc_infer::infer::relate::TypeRelation; -use rustc_infer::infer::BoundRegionConversionTime::HigherRankedType; -use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; +use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; +use rustc_infer::infer::DefineOpaqueTypes; +use rustc_infer::traits::util::elaborate; use rustc_infer::traits::TraitObligation; use rustc_middle::bug; use rustc_middle::dep_graph::{dep_kinds, DepNodeIndex}; @@ -2798,6 +2800,34 @@ impl<'tcx> SelectionContext<'_, 'tcx> { }); } + if matches!(self.tcx().def_kind(def_id), DefKind::Impl { of_trait: true }) + && let Some(header) = self.tcx().impl_trait_header(def_id) + { + let trait_clause: ty::Clause<'tcx> = + header.trait_ref.instantiate(self.tcx(), args).upcast(self.tcx()); + for clause in elaborate(self.tcx(), [trait_clause]) { + if matches!( + clause.kind().skip_binder(), + ty::ClauseKind::TypeOutlives(..) | ty::ClauseKind::RegionOutlives(..) + ) { + let clause = normalize_with_depth_to( + self, + param_env, + cause.clone(), + recursion_depth, + clause, + &mut obligations, + ); + obligations.push(Obligation { + cause: cause.clone(), + recursion_depth, + param_env, + predicate: clause.as_predicate(), + }); + } + } + } + obligations } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index e1a3764fa76b4..263ba676427c5 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -451,6 +451,8 @@ pub trait Clause>: + UpcastFrom>> + UpcastFrom> + UpcastFrom>> + + UpcastFrom> + + UpcastFrom>> + UpcastFrom> + UpcastFrom>> + IntoKind>> diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs index a7489f6fbaff4..38be3250c7d66 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.rs @@ -5,6 +5,7 @@ trait Trait<'a>: 'a { // if the `T: 'a` bound gets implied we would probably get ub here again impl<'a, T> Trait<'a> for T { //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR the parameter type `T` may not live long enough type Type = (); } diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr index b898df0835c2a..b2aa1abbbdb6e 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-5.stderr @@ -16,8 +16,21 @@ help: consider adding an explicit lifetime bound LL | impl<'a, T: 'a> Trait<'a> for T { | ++++ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:27 + | +LL | impl<'a, T> Trait<'a> for T { + | -- ^ ...so that the type `T` will meet its required lifetime bounds + | | + | the parameter type `T` must be valid for the lifetime `'a` as defined here... + | +help: consider adding an explicit lifetime bound + | +LL | impl<'a, T: 'a> Trait<'a> for T { + | ++++ + error[E0505]: cannot move out of `x` because it is borrowed - --> $DIR/implied-bounds-unnorm-associated-type-5.rs:21:10 + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:22:10 | LL | let x = String::from("Hello World!"); | - binding `x` declared here @@ -33,7 +46,7 @@ help: consider cloning the value if the performance cost is acceptable LL | let y = f(&x.clone(), ()); | ++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0309, E0505. For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/static/static-lifetime.rs b/tests/ui/static/static-lifetime.rs index ce1eeb6105f09..a861a2ffedab4 100644 --- a/tests/ui/static/static-lifetime.rs +++ b/tests/ui/static/static-lifetime.rs @@ -1,6 +1,7 @@ pub trait Arbitrary: Sized + 'static {} impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound +//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'a` fn main() { } diff --git a/tests/ui/static/static-lifetime.stderr b/tests/ui/static/static-lifetime.stderr index 8c9434ce3cb0b..7a956dbfeef6e 100644 --- a/tests/ui/static/static-lifetime.stderr +++ b/tests/ui/static/static-lifetime.stderr @@ -11,6 +11,32 @@ LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} | ^^ = note: but lifetime parameter must outlive the static lifetime -error: aborting due to 1 previous error +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements + --> $DIR/static-lifetime.rs:3:34 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'a` as defined here... + --> $DIR/static-lifetime.rs:3:6 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^ +note: ...so that the types are compatible + --> $DIR/static-lifetime.rs:3:34 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected ` as Arbitrary>` + found ` as Arbitrary>` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/static-lifetime.rs:3:34 + | +LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0478`. +Some errors have detailed explanations: E0478, E0495. +For more information about an error, try `rustc --explain E0478`. diff --git a/tests/ui/wf/wf-in-where-clause-static.current.stderr b/tests/ui/wf/wf-in-where-clause-static.current.stderr new file mode 100644 index 0000000000000..d0bb89884c68a --- /dev/null +++ b/tests/ui/wf/wf-in-where-clause-static.current.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/wf-in-where-clause-static.rs:18:18 + | +LL | let s = foo(&String::from("blah blah blah")); + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/wf/wf-in-where-clause-static.next.stderr b/tests/ui/wf/wf-in-where-clause-static.next.stderr new file mode 100644 index 0000000000000..d0bb89884c68a --- /dev/null +++ b/tests/ui/wf/wf-in-where-clause-static.next.stderr @@ -0,0 +1,12 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/wf-in-where-clause-static.rs:18:18 + | +LL | let s = foo(&String::from("blah blah blah")); + | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/wf/wf-in-where-clause-static.rs b/tests/ui/wf/wf-in-where-clause-static.rs index a3d360e1fb56b..8ee654ef7cff4 100644 --- a/tests/ui/wf/wf-in-where-clause-static.rs +++ b/tests/ui/wf/wf-in-where-clause-static.rs @@ -1,9 +1,6 @@ -//@ check-pass -//@ known-bug: #98117 - -// Should fail. Functions are responsible for checking the well-formedness of -// their own where clauses, so this should fail and require an explicit bound -// `T: 'static`. +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver use std::fmt::Display; @@ -19,5 +16,6 @@ where fn main() { let s = foo(&String::from("blah blah blah")); + //~^ ERROR temporary value dropped while borrowed println!("{}", s); } From fa9ae7b9d3e78a6605199efe358c0f1383d2f166 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 18 Jul 2024 12:08:57 -0400 Subject: [PATCH 469/489] Elaborate supertraits in dyn candidates --- .../src/solve/assembly/structural_traits.rs | 14 +++++++++++--- .../src/solve/trait_goals.rs | 6 +++--- .../rustc_trait_selection/src/traits/select/mod.rs | 1 + 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 60beaa0df84ca..e69d8d84d7d89 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -7,7 +7,7 @@ use rustc_type_ir::data_structures::HashMap; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; -use rustc_type_ir::{self as ty, Interner, Upcast as _}; +use rustc_type_ir::{self as ty, elaborate, Interner, Upcast as _}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::instrument; @@ -671,11 +671,19 @@ where { let cx = ecx.cx(); let mut requirements = vec![]; - requirements.extend( + // Elaborating all supertrait outlives obligations here is not soundness critical, + // since if we just used the unelaborated set, then the transitive supertraits would + // be reachable when proving the former. However, since we elaborate all supertrait + // outlives obligations when confirming impls, we would end up with a different set + // of outlives obligations here if we didn't do the same, leading to ambiguity. + // FIXME(-Znext-solver=coinductive): Adding supertraits here can be removed once we + // make impls coinductive always, since they'll always need to prove their supertraits. + requirements.extend(elaborate::elaborate( + cx, cx.explicit_super_predicates_of(trait_ref.def_id) .iter_instantiated(cx, trait_ref.args) .map(|(pred, _)| pred), - ); + )); // FIXME(associated_const_equality): Also add associated consts to // the requirements here. diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 77ce81e44a0b0..b1dba712f797a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -87,9 +87,9 @@ where .map(|pred| goal.with(cx, pred)); ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); - // We currently elaborate all supertrait obligations from impls. This - // can be removed when we actually do coinduction correctly and just - // register that the impl header must be WF. + // We currently elaborate all supertrait outlives obligations from impls. + // This can be removed when we actually do coinduction correctly, and prove + // all supertrait obligations unconditionally. let goal_clause: I::Clause = goal.predicate.upcast(cx); for clause in elaborate::elaborate(cx, [goal_clause]) { if matches!( diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2bc2a8fe693c5..1d9a90f0300ab 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2800,6 +2800,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { }); } + // Register any outlives obligations from the trait here, cc #124336. if matches!(self.tcx().def_kind(def_id), DefKind::Impl { of_trait: true }) && let Some(header) = self.tcx().impl_trait_header(def_id) { From 34e087890c25e259955d41d2830e603a75e62463 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Aug 2024 12:59:42 -0400 Subject: [PATCH 470/489] Don't re-elaborated already elaborated caller bounds in method probe --- compiler/rustc_hir_typeck/src/method/probe.rs | 28 +++++++++++-------- .../rustc_trait_selection/src/traits/mod.rs | 2 +- compiler/rustc_type_ir/src/elaborate.rs | 9 ------ 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 82f732d69dc52..28f537c87c4ee 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -774,18 +774,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // instantiation that replaces `Self` with the object type itself. Hence, // a `&self` method will wind up with an argument type like `&dyn Trait`. let trait_ref = principal.with_self_ty(self.tcx, self_ty); - self.elaborate_bounds(iter::once(trait_ref), |this, new_trait_ref, item| { - this.push_candidate( - Candidate { item, kind: ObjectCandidate(new_trait_ref), import_ids: smallvec![] }, - true, - ); - }); + self.assemble_candidates_for_bounds( + traits::supertraits(self.tcx, trait_ref), + |this, new_trait_ref, item| { + this.push_candidate( + Candidate { + item, + kind: ObjectCandidate(new_trait_ref), + import_ids: smallvec![], + }, + true, + ); + }, + ); } #[instrument(level = "debug", skip(self))] fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { - // FIXME: do we want to commit to this behavior for param bounds? - let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| { let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { @@ -806,7 +811,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } }); - self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { + self.assemble_candidates_for_bounds(bounds, |this, poly_trait_ref, item| { this.push_candidate( Candidate { item, @@ -820,15 +825,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Do a search through a list of bounds, using a callback to actually // create the candidates. - fn elaborate_bounds( + fn assemble_candidates_for_bounds( &mut self, bounds: impl Iterator>, mut mk_cand: F, ) where F: for<'b> FnMut(&mut ProbeContext<'b, 'tcx>, ty::PolyTraitRef<'tcx>, ty::AssocItem), { - let tcx = self.tcx; - for bound_trait_ref in traits::transitive_bounds(tcx, bounds) { + for bound_trait_ref in bounds { debug!("elaborate_bounds(bound_trait_ref={:?})", bound_trait_ref); for item in self.impl_or_trait_item(bound_trait_ref.def_id()) { if !self.has_applicable_self(&item) { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index f7b8d99593ec2..a350b76a7049a 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -62,7 +62,7 @@ pub use self::specialize::{ }; pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::{ - elaborate, expand_trait_aliases, impl_item_is_final, supertraits, transitive_bounds, + elaborate, expand_trait_aliases, impl_item_is_final, supertraits, transitive_bounds_that_define_assoc_item, upcast_choices, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer, TraitAliasExpander, TraitAliasExpansionInfo, }; diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 0246996c27f95..f30419c801f18 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -264,15 +264,6 @@ pub fn supertraits( elaborate(cx, [trait_ref.upcast(cx)]).filter_only_self().filter_to_traits() } -pub fn transitive_bounds( - cx: I, - trait_refs: impl Iterator>>, -) -> FilterToTraits> { - elaborate(cx, trait_refs.map(|trait_ref| trait_ref.upcast(cx))) - .filter_only_self() - .filter_to_traits() -} - impl Elaborator { fn filter_to_traits(self) -> FilterToTraits { FilterToTraits { _cx: PhantomData, base_iterator: self } From ab690d31ceeff606cb7d0359717b50c173c7b21e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 5 Aug 2024 17:55:42 +0300 Subject: [PATCH 471/489] fix the invalid argument type in `helpers::get_closest_merge_base_commit` Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/helpers.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 16959ce7e8249..65e75f114bbeb 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -536,8 +536,7 @@ pub fn get_closest_merge_base_commit( let merge_base = get_git_merge_base(config, source_dir).unwrap_or_else(|_| "HEAD".into()); - git.arg(Path::new("rev-list")); - git.args([&format!("--author={author}"), "-n1", "--first-parent", &merge_base]); + git.args(["rev-list", &format!("--author={author}"), "-n1", "--first-parent", &merge_base]); if !target_paths.is_empty() { git.arg("--").args(target_paths); From 212417b87f8415d92ea0a365605011050a555e28 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 18:23:14 +0200 Subject: [PATCH 472/489] custom MIR: add support for tail calls --- .../src/build/custom/parse/instruction.rs | 22 +++++++++++++++++++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics/mir.rs | 8 +++++++ tests/mir-opt/building/custom/terminators.rs | 12 ++++++++++ .../terminators.tail_call.built.after.mir | 11 ++++++++++ 5 files changed, 54 insertions(+) create mode 100644 tests/mir-opt/building/custom/terminators.tail_call.built.after.mir diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 3d4b706aa652b..56896d945e5f3 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -75,6 +75,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { @call(mir_call, args) => { self.parse_call(args) }, + @call(mir_tail_call, args) => { + self.parse_tail_call(args) + }, ExprKind::Match { scrutinee, arms, .. } => { let discr = self.parse_operand(*scrutinee)?; self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t }) @@ -187,6 +190,25 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { ) } + fn parse_tail_call(&self, args: &[ExprId]) -> PResult> { + parse_by_kind!(self, args[0], _, "tail call", + ExprKind::Call { fun, args, fn_span, .. } => { + let fun = self.parse_operand(*fun)?; + let args = args + .iter() + .map(|arg| + Ok(Spanned { node: self.parse_operand(*arg)?, span: self.thir.exprs[*arg].span } ) + ) + .collect::>>()?; + Ok(TerminatorKind::TailCall { + func: fun, + args, + fn_span: *fn_span, + }) + }, + ) + } + fn parse_rvalue(&self, expr_id: ExprId) -> PResult> { parse_by_kind!(self, expr_id, expr, "rvalue", @call(mir_discriminant, args) => self.parse_place(args[0]).map(Rvalue::Discriminant), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9977fa7425a3e..94cf21da4efb8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1216,6 +1216,7 @@ symbols! { mir_static_mut, mir_storage_dead, mir_storage_live, + mir_tail_call, mir_unreachable, mir_unwind_cleanup, mir_unwind_continue, diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index fd49a96eaa049..c7cec396e1f2e 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -247,6 +247,8 @@ //! otherwise branch. //! - [`Call`] has an associated function as well, with special syntax: //! `Call(ret_val = function(arg1, arg2, ...), ReturnTo(next_block), UnwindContinue())`. +//! - [`TailCall`] does not have a return destination or next block, so its syntax is just +//! `TailCall(function(arg1, arg2, ...))`. #![unstable( feature = "custom_mir", @@ -350,6 +352,12 @@ define!("mir_call", /// - [`UnwindCleanup`] fn Call(call: (), goto: ReturnToArg, unwind_action: UnwindActionArg) ); +define!("mir_tail_call", + /// Call a function. + /// + /// The argument must be of the form `fun(arg1, arg2, ...)`. + fn TailCall(call: T) +); define!("mir_unwind_resume", /// A terminator that resumes the unwinding. fn UnwindResume() diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs index a8e0b4b35bf47..ed08040a2a58c 100644 --- a/tests/mir-opt/building/custom/terminators.rs +++ b/tests/mir-opt/building/custom/terminators.rs @@ -22,6 +22,18 @@ fn direct_call(x: i32) -> i32 { } } +// EMIT_MIR terminators.tail_call.built.after.mir +#[custom_mir(dialect = "built")] +fn tail_call(x: i32) -> i32 { + mir! { + let y; + { + y = x + 42; + TailCall(ident(y)) + } + } +} + // EMIT_MIR terminators.indirect_call.built.after.mir #[custom_mir(dialect = "built")] fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 { diff --git a/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir b/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir new file mode 100644 index 0000000000000..4cf6e459aa820 --- /dev/null +++ b/tests/mir-opt/building/custom/terminators.tail_call.built.after.mir @@ -0,0 +1,11 @@ +// MIR for `tail_call` after built + +fn tail_call(_1: i32) -> i32 { + let mut _0: i32; + let mut _2: i32; + + bb0: { + _2 = Add(_1, const 42_i32); + tailcall ident::(Spanned { node: _2, span: $DIR/terminators.rs:32:28: 32:29 (#0) }); + } +} From 9213c6c93f43b0b208466879e0c1af8dce127193 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 19:00:29 +0200 Subject: [PATCH 473/489] bump rustc-build-sysroot dependency --- src/tools/miri/cargo-miri/Cargo.lock | 4 ++-- src/tools/miri/cargo-miri/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index 8bd8f1030532e..b91f6a7b90260 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -178,9 +178,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa3ca63cc537c1cb69e4c2c0afc5fda2ccd36ac84c97d5a4ae05e69b1c834afb" +checksum = "2471f8f296262437d7e848e527b4210b44a96e53a3b4435b890227ce3e6da106" dependencies = [ "anyhow", "rustc_version", diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml index 6acdbc46f642a..477c60db162a3 100644 --- a/src/tools/miri/cargo-miri/Cargo.toml +++ b/src/tools/miri/cargo-miri/Cargo.toml @@ -18,7 +18,7 @@ directories = "5" rustc_version = "0.4" serde_json = "1.0.40" cargo_metadata = "0.18.0" -rustc-build-sysroot = "0.5.2" +rustc-build-sysroot = "0.5.3" # Enable some feature flags that dev-dependencies need but dependencies # do not. This makes `./miri install` after `./miri build` faster. From b113bbec4f9590e0546d323fd6d8acc610fd585f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 19:25:56 +0200 Subject: [PATCH 474/489] use a Miri-specific folder for ui tests --- src/tools/miri/tests/ui.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/tests/ui.rs b/src/tools/miri/tests/ui.rs index 3a8b098ccbe36..95f8b05410293 100644 --- a/src/tools/miri/tests/ui.rs +++ b/src/tools/miri/tests/ui.rs @@ -73,7 +73,7 @@ fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> stdout_filters: stdout_filters().into(), mode, program, - out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("ui"), + out_dir: PathBuf::from(std::env::var_os("CARGO_TARGET_DIR").unwrap()).join("miri_ui"), edition: Some("2021".into()), // keep in sync with `./miri run` threads: std::env::var("MIRI_TEST_THREADS") .ok() From 014fdb56b455a15ac45a054d80b24b0fa49392de Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 19:01:21 +0200 Subject: [PATCH 475/489] bump dependencies --- src/tools/miri/Cargo.lock | 236 ++++++++++-------- src/tools/miri/cargo-miri/Cargo.lock | 149 ++++++----- src/tools/miri/test_dependencies/Cargo.lock | 217 ++++++---------- .../miri/tests/fail-dep/tokio/sleep.stderr | 2 +- 4 files changed, 297 insertions(+), 307 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index eecb158d707be..e4bfd9bd12282 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "autocfg" @@ -85,26 +85,32 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", "serde", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -134,9 +140,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.96" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" [[package]] name = "cfg-if" @@ -258,18 +264,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-common" @@ -320,9 +326,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -356,9 +362,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -401,9 +407,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -426,9 +432,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "levenshtein" @@ -438,9 +444,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libffi" @@ -463,12 +469,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -483,9 +489,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" @@ -499,9 +505,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "measureme" @@ -519,9 +525,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -534,9 +540,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -631,9 +637,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -649,7 +655,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -716,15 +722,18 @@ checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettydiff" @@ -738,9 +747,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -786,9 +795,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags", ] @@ -806,9 +815,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -818,9 +827,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -829,15 +838,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" @@ -881,9 +890,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" @@ -893,27 +902,27 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.200" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -922,11 +931,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -954,9 +964,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.60" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -965,30 +975,31 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -1087,9 +1098,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "valuable" @@ -1099,9 +1110,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1146,7 +1157,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -1166,18 +1177,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1188,9 +1199,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -1200,9 +1211,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -1212,15 +1223,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -1230,9 +1241,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -1242,9 +1253,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -1254,9 +1265,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -1266,9 +1277,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "yansi-term" @@ -1278,3 +1289,24 @@ checksum = "fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1" dependencies = [ "winapi", ] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index b91f6a7b90260..7369a3fbf09ae 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -4,21 +4,21 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ "serde", ] @@ -88,9 +88,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -104,9 +104,9 @@ checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -121,9 +121,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -137,9 +137,21 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "memchr" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "option-ext" @@ -149,9 +161,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -218,9 +230,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -233,27 +245,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.200" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -262,20 +274,21 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "syn" -version = "2.0.60" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -284,30 +297,31 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -338,11 +352,11 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -360,7 +374,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -380,18 +403,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -402,9 +425,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -414,9 +437,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -426,15 +449,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -444,9 +467,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -456,9 +479,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -468,9 +491,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -480,6 +503,6 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index d534fdab2914e..e94bef529521e 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -34,9 +34,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bumpalo" @@ -46,9 +46,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "cc" -version = "1.0.96" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" [[package]] name = "cfg-if" @@ -58,12 +58,12 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "hermit-abi" @@ -119,46 +119,47 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ + "hermit-abi", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -166,13 +167,13 @@ name = "miri-test-deps" version = "0.1.0" dependencies = [ "getrandom 0.1.16", - "getrandom 0.2.14", + "getrandom 0.2.15", "libc", "num_cpus", "page_size", "tempfile", "tokio", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -187,9 +188,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -218,9 +219,9 @@ checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -236,9 +237,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" @@ -250,7 +251,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -269,14 +270,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "syn" -version = "2.0.60" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -285,38 +286,38 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "tokio" -version = "1.37.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "libc", "mio", - "num_cpus", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -417,141 +418,75 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr index 4b12729bbff9c..6d19faab90570 100644 --- a/src/tools/miri/tests/fail-dep/tokio/sleep.stderr +++ b/src/tools/miri/tests/fail-dep/tokio/sleep.stderr @@ -2,7 +2,7 @@ error: unsupported operation: returning ready events from epoll_wait is not yet --> CARGO_REGISTRY/.../epoll.rs:LL:CC | LL | / syscall!(epoll_wait( -LL | | self.ep, +LL | | self.ep.as_raw_fd(), LL | | events.as_mut_ptr(), LL | | events.capacity() as i32, LL | | timeout, From c6f8672dd5e128766298ed0d53bb32a94188f886 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Aug 2024 14:04:40 -0400 Subject: [PATCH 476/489] Normalize when equating dyn tails in MIR borrowck --- compiler/rustc_borrowck/src/type_check/mod.rs | 6 ++++++ tests/crashes/128621-2.rs | 16 ---------------- .../cast/dyn-tails-need-normalization.rs} | 4 +++- 3 files changed, 9 insertions(+), 17 deletions(-) delete mode 100644 tests/crashes/128621-2.rs rename tests/{crashes/128621.rs => ui/cast/dyn-tails-need-normalization.rs} (87%) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index bbb5daccfd639..b13773ffe1460 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2330,10 +2330,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match (cast_ty_from, cast_ty_to) { (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => { let mut normalize = |t| self.normalize(t, location); + + // N.B. `struct_tail_with_normalize` only "structurally resolves" + // the type. It is not fully normalized, so we have to normalize it + // afterwards. let src_tail = tcx.struct_tail_with_normalize(src.ty, &mut normalize, || ()); + let src_tail = normalize(src_tail); let dst_tail = tcx.struct_tail_with_normalize(dst.ty, &mut normalize, || ()); + let dst_tail = normalize(dst_tail); // This checks (lifetime part of) vtable validity for pointer casts, // which is irrelevant when there are aren't principal traits on both sides (aka only auto traits). diff --git a/tests/crashes/128621-2.rs b/tests/crashes/128621-2.rs deleted file mode 100644 index b1cdaf94984a8..0000000000000 --- a/tests/crashes/128621-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#128621 - -#![feature(ptr_metadata)] -use std::{ops::FnMut, ptr::Pointee}; - -pub type EmplacerFn<'a, T> = dyn for<'b> FnMut(::Metadata) + 'a; - -pub struct Emplacer<'a, T>(EmplacerFn<'a, T>); - -impl<'a, T> Emplacer<'a, T> { - pub unsafe fn from_fn<'b>(emplacer_fn: &'b mut EmplacerFn<'a, T>) -> &'b mut Self { - unsafe { &mut *((emplacer_fn as *mut EmplacerFn<'a, T>) as *mut Self) } - } -} - -pub fn main() {} diff --git a/tests/crashes/128621.rs b/tests/ui/cast/dyn-tails-need-normalization.rs similarity index 87% rename from tests/crashes/128621.rs rename to tests/ui/cast/dyn-tails-need-normalization.rs index 0a02352236dbb..719e0e892430d 100644 --- a/tests/crashes/128621.rs +++ b/tests/ui/cast/dyn-tails-need-normalization.rs @@ -1,4 +1,4 @@ -//@ known-bug: rust-lang/rust#128621 +//@ check-pass trait Trait { type Associated; @@ -17,3 +17,5 @@ struct Wrap(TraitObject); fn cast(x: *mut TraitObject) { x as *mut Wrap; } + +fn main() {} From f6edc8a07c831a423e367049f39a96eb10137320 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 20:39:56 +0200 Subject: [PATCH 477/489] update lockfile --- Cargo.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 470a19bfb00f5..a4b4e49f82c2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2282,6 +2282,7 @@ dependencies = [ "smallvec", "tempfile", "ui_test 0.21.2", + "windows-sys 0.52.0", ] [[package]] @@ -3156,9 +3157,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa3ca63cc537c1cb69e4c2c0afc5fda2ccd36ac84c97d5a4ae05e69b1c834afb" +checksum = "2471f8f296262437d7e848e527b4210b44a96e53a3b4435b890227ce3e6da106" dependencies = [ "anyhow", "rustc_version", From 46896d6f667bad2307efe22a75fc39f040302ae5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 5 Aug 2024 20:35:52 +0200 Subject: [PATCH 478/489] interpret: move nullary-op evaluation into operator.rs --- .../src/const_eval/machine.rs | 2 +- .../src/interpret/intrinsics.rs | 4 +- .../src/interpret/operator.rs | 37 +++++++++++++++- .../rustc_const_eval/src/interpret/step.rs | 43 ++++--------------- src/tools/miri/src/intrinsics/mod.rs | 2 +- .../generic_const_exprs/issue-80742.stderr | 2 +- 6 files changed, 49 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 901149825bfd6..79e8e2127765a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -458,7 +458,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { _unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option>> { // Shared intrinsics. - if ecx.emulate_intrinsic(instance, args, dest, target)? { + if ecx.eval_intrinsic(instance, args, dest, target)? { return Ok(None); } let intrinsic_name = ecx.tcx.item_name(instance.def_id()); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 16a0a76a316e6..9210ec4e16fd0 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -97,7 +97,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Returns `true` if emulation happened. /// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own /// intrinsic handling. - pub fn emulate_intrinsic( + pub fn eval_intrinsic( &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, M::Provenance>], @@ -447,7 +447,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Ok(true) } - pub(super) fn emulate_nondiverging_intrinsic( + pub(super) fn eval_nondiverging_intrinsic( &mut self, intrinsic: &NonDivergingIntrinsic<'tcx>, ) -> InterpResult<'tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index fe5869ad7fa7a..2f860f9f942b2 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -1,8 +1,9 @@ use either::Either; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::interpret::{InterpResult, Scalar}; +use rustc_middle::mir::NullOp; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, FloatTy, ScalarInt}; +use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::symbol::sym; use tracing::trace; @@ -480,4 +481,38 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } } + + pub fn nullary_op( + &self, + null_op: NullOp<'tcx>, + arg_ty: Ty<'tcx>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { + use rustc_middle::mir::NullOp::*; + + let layout = self.layout_of(arg_ty)?; + let usize_layout = || self.layout_of(self.tcx.types.usize).unwrap(); + + Ok(match null_op { + SizeOf => { + if !layout.abi.is_sized() { + span_bug!(self.cur_span(), "unsized type for `NullaryOp::SizeOf`"); + } + let val = layout.size.bytes(); + ImmTy::from_uint(val, usize_layout()) + } + AlignOf => { + if !layout.abi.is_sized() { + span_bug!(self.cur_span(), "unsized type for `NullaryOp::AlignOf`"); + } + let val = layout.align.abi.bytes(); + ImmTy::from_uint(val, usize_layout()) + } + OffsetOf(fields) => { + let val = + self.tcx.offset_of_subfield(self.param_env, layout, fields.iter()).bytes(); + ImmTy::from_uint(val, usize_layout()) + } + UbChecks => ImmTy::from_bool(self.tcx.sess.ub_checks(), *self.tcx), + }) + } } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 211a7b2300222..28cf1068f4081 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -4,8 +4,7 @@ use either::Either; use rustc_index::IndexSlice; -use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::{bug, mir, span_bug}; +use rustc_middle::{bug, mir}; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; use tracing::{info, instrument, trace}; @@ -94,7 +93,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { M::retag_place_contents(self, *kind, &dest)?; } - Intrinsic(box intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?, + Intrinsic(box intrinsic) => self.eval_nondiverging_intrinsic(intrinsic)?, // Evaluate the place expression, without reading from it. PlaceMention(box place) => { @@ -179,6 +178,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_immediate(*result, &dest)?; } + NullaryOp(null_op, ty) => { + let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?; + let val = self.nullary_op(null_op, ty)?; + self.write_immediate(*val, &dest)?; + } + Aggregate(box ref kind, ref operands) => { self.write_aggregate(kind, operands, &dest)?; } @@ -230,38 +235,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_immediate(*val, &dest)?; } - NullaryOp(ref null_op, ty) => { - let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?; - let layout = self.layout_of(ty)?; - if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op - && layout.is_unsized() - { - span_bug!( - self.frame().current_span(), - "{null_op:?} MIR operator called for unsized type {ty}", - ); - } - let val = match null_op { - mir::NullOp::SizeOf => { - let val = layout.size.bytes(); - Scalar::from_target_usize(val, self) - } - mir::NullOp::AlignOf => { - let val = layout.align.abi.bytes(); - Scalar::from_target_usize(val, self) - } - mir::NullOp::OffsetOf(fields) => { - let val = self - .tcx - .offset_of_subfield(self.param_env, layout, fields.iter()) - .bytes(); - Scalar::from_target_usize(val, self) - } - mir::NullOp::UbChecks => Scalar::from_bool(self.tcx.sess.ub_checks()), - }; - self.write_scalar(val, &dest)?; - } - ShallowInitBox(ref operand, _) => { let src = self.eval_operand(operand, None)?; let v = self.read_immediate(&src)?; diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index d60119e75f16d..18b22827bdb15 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -33,7 +33,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); // See if the core engine can handle this intrinsic. - if this.emulate_intrinsic(instance, args, dest, ret)? { + if this.eval_intrinsic(instance, args, dest, ret)? { return Ok(None); } let intrinsic_name = this.tcx.item_name(instance.def_id()); diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr index 8d59235e2f448..01529599d37d0 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: compiler/rustc_const_eval/src/interpret/step.rs:LL:CC: SizeOf MIR operator called for unsized type dyn Debug +error: internal compiler error: compiler/rustc_const_eval/src/interpret/operator.rs:LL:CC: unsized type for `NullaryOp::SizeOf` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL Box From 1bbaf6eb2f08a4f3d5c442560909f7109b66bf95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 21 Jun 2024 19:22:59 +0000 Subject: [PATCH 479/489] On short error format, append primary span label to message The `error-format=short` output only displays the path, error code and main error message all in the same line. We now add the primary span label as well after the error message, to provide more context. --- compiler/rustc_errors/src/emitter.rs | 22 ++++++++++++++++++- .../issues/issue-81662-shortness.rs | 2 +- .../issues/issue-81662-shortness.stdout | 2 +- .../json/json-bom-plus-crlf-multifile.stderr | 8 +++---- tests/ui/json/json-bom-plus-crlf.stderr | 8 +++---- tests/ui/json/json-short.stderr | 2 +- tests/ui/short-error-format.stderr | 4 ++-- 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 8963b009c31ec..c22375795e530 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1346,10 +1346,11 @@ impl HumanEmitter { buffer.append(0, ": ", header_style); label_width += 2; } + let mut line = 0; for (text, _) in msgs.iter() { let text = self.translate_message(text, args).map_err(Report::new).unwrap(); // Account for newlines to align output to its label. - for (line, text) in normalize_whitespace(&text).lines().enumerate() { + for text in normalize_whitespace(&text).lines() { buffer.append( line, &format!( @@ -1359,6 +1360,25 @@ impl HumanEmitter { ), header_style, ); + line += 1; + } + } + if self.short_message { + let labels = msp + .span_labels() + .into_iter() + .filter_map(|label| match label.label { + Some(msg) if label.is_primary => { + let text = self.translate_message(&msg, args).ok()?; + if !text.trim().is_empty() { Some(text.to_string()) } else { None } + } + _ => None, + }) + .collect::>() + .join(", "); + if !labels.is_empty() { + buffer.append(line, ": ", Style::NoStyle); + buffer.append(line, &labels, Style::NoStyle); } } } diff --git a/tests/rustdoc-ui/issues/issue-81662-shortness.rs b/tests/rustdoc-ui/issues/issue-81662-shortness.rs index 02207d2a736d7..7df63261ce7ee 100644 --- a/tests/rustdoc-ui/issues/issue-81662-shortness.rs +++ b/tests/rustdoc-ui/issues/issue-81662-shortness.rs @@ -1,6 +1,6 @@ //@ compile-flags:--test --error-format=short //@ check-stdout -//@ error-pattern:cannot find function `foo` in this scope +//@ error-pattern:cannot find function `foo` //@ normalize-stdout-test: "tests/rustdoc-ui/issues" -> "$$DIR" //@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ failure-status: 101 diff --git a/tests/rustdoc-ui/issues/issue-81662-shortness.stdout b/tests/rustdoc-ui/issues/issue-81662-shortness.stdout index f32f51e12f2c3..8fcc7ed272f0c 100644 --- a/tests/rustdoc-ui/issues/issue-81662-shortness.stdout +++ b/tests/rustdoc-ui/issues/issue-81662-shortness.stdout @@ -5,7 +5,7 @@ test $DIR/issue-81662-shortness.rs - foo (line 8) ... FAILED failures: ---- $DIR/issue-81662-shortness.rs - foo (line 8) stdout ---- -$DIR/issue-81662-shortness.rs:9:1: error[E0425]: cannot find function `foo` in this scope +$DIR/issue-81662-shortness.rs:9:1: error[E0425]: cannot find function `foo` in this scope: not found in this scope error: aborting due to 1 previous error Couldn't compile the test. diff --git a/tests/ui/json/json-bom-plus-crlf-multifile.stderr b/tests/ui/json/json-bom-plus-crlf-multifile.stderr index 2ed26f9a8a576..9c88a7e5a2564 100644 --- a/tests/ui/json/json-bom-plus-crlf-multifile.stderr +++ b/tests/ui/json/json-bom-plus-crlf-multifile.stderr @@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":623,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":613,"byte_end":619,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":623,"byte_end":623,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":622,"byte_end":623,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":613,"byte_end":619,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":623,"byte_end":623,"line_start":17,"line_end":17,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -52,7 +52,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":683,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":673,"byte_end":679,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":683,"byte_end":683,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":682,"byte_end":683,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":673,"byte_end":679,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":683,"byte_end":683,"line_start":19,"line_end":19,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -80,7 +80,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":747,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":736,"byte_end":742,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":747,"byte_end":747,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":746,"byte_end":747,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":736,"byte_end":742,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":747,"byte_end":747,"line_start":23,"line_end":23,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -108,7 +108,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":802,"byte_end":810,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":793,"byte_end":799,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":802,"byte_end":810,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":793,"byte_end":799,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types: expected `String`, found `()` "} {"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors "} diff --git a/tests/ui/json/json-bom-plus-crlf.stderr b/tests/ui/json/json-bom-plus-crlf.stderr index b5e6f658616c3..cd1e3665b3e58 100644 --- a/tests/ui/json/json-bom-plus-crlf.stderr +++ b/tests/ui/json/json-bom-plus-crlf.stderr @@ -24,7 +24,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":608,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":598,"byte_end":604,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":608,"byte_end":608,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":607,"byte_end":608,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":598,"byte_end":604,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":608,"byte_end":608,"line_start":16,"line_end":16,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -52,7 +52,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":668,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":658,"byte_end":664,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":668,"byte_end":668,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":667,"byte_end":668,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":658,"byte_end":664,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":668,"byte_end":668,"line_start":18,"line_end":18,"column_start":23,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":23,"highlight_end":23}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -80,7 +80,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":732,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":721,"byte_end":727,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":732,"byte_end":732,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":731,"byte_end":732,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected `String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":721,"byte_end":727,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":732,"byte_end":732,"line_start":22,"line_end":22,"column_start":2,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":2,"highlight_end":2}],"label":null,"suggested_replacement":".to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types: expected `String`, found integer "} {"$message_type":"diagnostic","message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. @@ -108,7 +108,7 @@ This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in the function declaration. -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":787,"byte_end":795,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":778,"byte_end":784,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":787,"byte_end":795,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected `String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":778,"byte_end":784,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types: expected `String`, found `()` "} {"$message_type":"diagnostic","message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors "} diff --git a/tests/ui/json/json-short.stderr b/tests/ui/json/json-short.stderr index a3d579cadccff..8a4a55edf68e9 100644 --- a/tests/ui/json/json-short.stderr +++ b/tests/ui/json/json-short.stderr @@ -13,7 +13,7 @@ If you don't know the basics of Rust, you can look at the [Rust Book][rust-book] to get started. [rust-book]: https://doc.rust-lang.org/book/ -"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":63,"byte_end":63,"line_start":1,"line_end":1,"column_start":64,"column_end":64,"is_primary":true,"text":[{"text":"//@ compile-flags: --json=diagnostic-short --error-format=json","highlight_start":64,"highlight_end":64}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:64: error[E0601]: `main` function not found in crate `json_short` +"},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":63,"byte_end":63,"line_start":1,"line_end":1,"column_start":64,"column_end":64,"is_primary":true,"text":[{"text":"//@ compile-flags: --json=diagnostic-short --error-format=json","highlight_start":64,"highlight_end":64}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:64: error[E0601]: `main` function not found in crate `json_short`: consider adding a `main` function to `$DIR/json-short.rs` "} {"$message_type":"diagnostic","message":"aborting due to 1 previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 1 previous error "} diff --git a/tests/ui/short-error-format.stderr b/tests/ui/short-error-format.stderr index 8a22d673b9821..1a4a6d4df88e7 100644 --- a/tests/ui/short-error-format.stderr +++ b/tests/ui/short-error-format.stderr @@ -1,3 +1,3 @@ -$DIR/short-error-format.rs:6:9: error[E0308]: mismatched types -$DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope +$DIR/short-error-format.rs:6:9: error[E0308]: mismatched types: expected `u32`, found `String` +$DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope: method not found in `u32` error: aborting due to 2 previous errors From ba0d6c973994915faef00e0e15e2957ff2b286b7 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Thu, 4 Jul 2024 18:34:35 +0100 Subject: [PATCH 480/489] Update generate-copyright This tool now scans for cargo dependencies and includes any important looking license files. We do this because cargo package metadata is not sufficient - the Apache-2.0 license says you have to include any NOTICE file, for example. And authors != copyright holders (cargo has the former, we must include the latter). --- Cargo.lock | 2 + src/bootstrap/src/core/build_steps/run.rs | 2 + src/tools/collect-license-metadata/Cargo.toml | 2 + .../collect-license-metadata/src/main.rs | 5 + src/tools/generate-copyright/Cargo.toml | 3 + .../generate-copyright/src/cargo_metadata.rs | 196 ++++++++++++++++++ src/tools/generate-copyright/src/main.rs | 122 +++++++++-- 7 files changed, 320 insertions(+), 12 deletions(-) create mode 100644 src/tools/generate-copyright/src/cargo_metadata.rs diff --git a/Cargo.lock b/Cargo.lock index a4b4e49f82c2e..0f3a106512d20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1408,6 +1408,8 @@ dependencies = [ "anyhow", "serde", "serde_json", + "tempfile", + "thiserror", ] [[package]] diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index fde1693646a8b..29d7bcc425bea 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -217,6 +217,8 @@ impl Step for GenerateCopyright { let mut cmd = builder.tool_cmd(Tool::GenerateCopyright); cmd.env("LICENSE_METADATA", &license_metadata); cmd.env("DEST", &dest); + cmd.env("OUT_DIR", &builder.out); + cmd.env("CARGO", &builder.initial_cargo); cmd.run(builder); dest diff --git a/src/tools/collect-license-metadata/Cargo.toml b/src/tools/collect-license-metadata/Cargo.toml index d0820cfc2a0e4..edf9e5c5393ea 100644 --- a/src/tools/collect-license-metadata/Cargo.toml +++ b/src/tools/collect-license-metadata/Cargo.toml @@ -2,6 +2,8 @@ name = "collect-license-metadata" version = "0.1.0" edition = "2021" +description = "Runs the reuse tool and caches the output, so rust toolchain devs don't need to have reuse installed" +license = "MIT OR Apache-2.0" [dependencies] anyhow = "1.0.65" diff --git a/src/tools/collect-license-metadata/src/main.rs b/src/tools/collect-license-metadata/src/main.rs index ca6aa01d78c04..dce36bb17b600 100644 --- a/src/tools/collect-license-metadata/src/main.rs +++ b/src/tools/collect-license-metadata/src/main.rs @@ -8,6 +8,11 @@ use anyhow::Error; use crate::licenses::LicensesInterner; +/// The entry point to the binary. +/// +/// You should probably let `bootstrap` execute this program instead of running it directly. +/// +/// Run `x.py run collect-license-metadata` fn main() -> Result<(), Error> { let reuse_exe: PathBuf = std::env::var_os("REUSE_EXE").expect("Missing REUSE_EXE").into(); let dest: PathBuf = std::env::var_os("DEST").expect("Missing DEST").into(); diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index 899ef0f8a6c26..bf643876a042b 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -2,6 +2,7 @@ name = "generate-copyright" version = "0.1.0" edition = "2021" +description = "Produces a manifest of all the copyrighted materials in the Rust Toolchain" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -9,3 +10,5 @@ edition = "2021" anyhow = "1.0.65" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" +thiserror = "1" +tempfile = "3" diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs new file mode 100644 index 0000000000000..721a6b1c6e627 --- /dev/null +++ b/src/tools/generate-copyright/src/cargo_metadata.rs @@ -0,0 +1,196 @@ +//! Gets metadata about a workspace from Cargo + +use std::collections::{BTreeMap, BTreeSet}; +use std::ffi::{OsStr, OsString}; +use std::path::Path; + +/// Describes how this module can fail +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Failed to run cargo metadata: {0:?}")] + LaunchingMetadata(#[from] std::io::Error), + #[error("Failed get output from cargo metadata: {0:?}")] + GettingMetadata(String), + #[error("Failed parse JSON output from cargo metadata: {0:?}")] + ParsingJson(#[from] serde_json::Error), + #[error("Failed find expected JSON element {0} in output from cargo metadata")] + MissingJsonElement(&'static str), + #[error("Failed find expected JSON element {0} in output from cargo metadata for package {1}")] + MissingJsonElementForPackage(String, String), + #[error("Failed to run cargo vendor: {0:?}")] + LaunchingVendor(std::io::Error), + #[error("Failed to complete cargo vendor")] + RunningVendor, +} + +/// Describes one of our dependencies +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Dependency { + /// The name of the package + pub name: String, + /// The version number + pub version: String, + /// The license it is under + pub license: String, + /// The list of authors from the package metadata + pub authors: Vec, + /// A list of important files from the package, with their contents. + /// + /// This includes *COPYRIGHT*, *NOTICE*, *AUTHOR*, *LICENSE*, and *LICENCE* files, case-insensitive. + pub notices: BTreeMap, +} + +/// Use `cargo` to get a list of dependencies and their license data. +/// +/// This will involve running `cargo vendor` into `${BUILD}/vendor` so we can +/// grab the license files. +/// +/// Any dependency with a path beginning with `root_path` is ignored, as we +/// assume `reuse` has covered it already. +pub fn get( + cargo: &Path, + dest: &Path, + root_path: &Path, + manifest_paths: &[&Path], +) -> Result, Error> { + let mut temp_set = BTreeSet::new(); + // Look at the metadata for each manifest + for manifest_path in manifest_paths { + if manifest_path.file_name() != Some(OsStr::new("Cargo.toml")) { + panic!("cargo_manifest::get requires a path to a Cargo.toml file"); + } + let metadata_json = get_metadata_json(cargo, manifest_path)?; + let packages = metadata_json["packages"] + .as_array() + .ok_or_else(|| Error::MissingJsonElement("packages array"))?; + for package in packages { + let package = + package.as_object().ok_or_else(|| Error::MissingJsonElement("package object"))?; + let manifest_path = package + .get("manifest_path") + .and_then(|v| v.as_str()) + .map(Path::new) + .ok_or_else(|| Error::MissingJsonElement("package.manifest_path"))?; + if manifest_path.starts_with(&root_path) { + // it's an in-tree dependency and reuse covers it + continue; + } + // otherwise it's an out-of-tree dependency + let get_string = |field_name: &str, package_name: &str| { + package.get(field_name).and_then(|v| v.as_str()).ok_or_else(|| { + Error::MissingJsonElementForPackage( + format!("package.{field_name}"), + package_name.to_owned(), + ) + }) + }; + let name = get_string("name", "unknown")?; + let license = get_string("license", name)?; + let version = get_string("version", name)?; + let authors_list = package + .get("authors") + .and_then(|v| v.as_array()) + .ok_or_else(|| Error::MissingJsonElement("package.authors"))?; + let authors: Vec = + authors_list.iter().filter_map(|v| v.as_str()).map(|s| s.to_owned()).collect(); + temp_set.insert(Dependency { + name: name.to_owned(), + version: version.to_owned(), + license: license.to_owned(), + authors, + notices: BTreeMap::new(), + }); + } + } + + // Now do a cargo-vendor and grab everything + let vendor_path = dest.join("vendor"); + println!("Vendoring deps into {}...", vendor_path.display()); + run_cargo_vendor(cargo, &vendor_path, manifest_paths)?; + + // Now for each dependency we found, go and grab any important looking files + let mut output = BTreeSet::new(); + for mut dep in temp_set { + load_important_files(&mut dep, &vendor_path)?; + output.insert(dep); + } + + Ok(output) +} + +/// Get cargo-metdata for a package, as JSON +fn get_metadata_json(cargo: &Path, manifest_path: &Path) -> Result { + let metadata_output = std::process::Command::new(cargo) + .arg("metadata") + .arg("--format-version=1") + .arg("--all-features") + .arg("--manifest-path") + .arg(manifest_path) + .env("RUSTC_BOOTSTRAP", "1") + .output() + .map_err(|e| Error::LaunchingMetadata(e))?; + if !metadata_output.status.success() { + return Err(Error::GettingMetadata( + String::from_utf8(metadata_output.stderr).expect("UTF-8 output from cargo"), + )); + } + let json = serde_json::from_slice(&metadata_output.stdout)?; + Ok(json) +} + +/// Run cargo-vendor, fetching into the given dir +fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Result<(), Error> { + let mut vendor_command = std::process::Command::new(cargo); + vendor_command.env("RUSTC_BOOTSTRAP", "1"); + vendor_command.arg("vendor"); + vendor_command.arg("--quiet"); + vendor_command.arg("--versioned-dirs"); + for manifest_path in manifest_paths { + vendor_command.arg("-s"); + vendor_command.arg(manifest_path); + } + vendor_command.arg(dest); + + let vendor_status = vendor_command.status().map_err(|e| Error::LaunchingVendor(e))?; + + if !vendor_status.success() { + return Err(Error::RunningVendor); + } + + Ok(()) +} + +/// Add important files off disk into this dependency. +/// +/// Maybe one-day Cargo.toml will contain enough information that we don't need +/// to do this manual scraping. +fn load_important_files(dep: &mut Dependency, vendor_root: &Path) -> Result<(), Error> { + let name_version = format!("{}-{}", dep.name, dep.version); + println!("Scraping notices for {}...", name_version); + let dep_vendor_path = vendor_root.join(name_version); + for entry in std::fs::read_dir(dep_vendor_path)? { + let entry = entry?; + let metadata = entry.metadata()?; + let path = entry.path(); + if let Some(filename) = path.file_name() { + let lc_filename = filename.to_ascii_lowercase(); + let lc_filename_str = lc_filename.to_string_lossy(); + let mut keep = false; + for m in ["copyright", "licence", "license", "author", "notice"] { + if lc_filename_str.contains(m) { + keep = true; + break; + } + } + if keep { + if metadata.is_dir() { + // scoop up whole directory + } else if metadata.is_file() { + println!("Scraping {}", filename.to_string_lossy()); + dep.notices.insert(filename.to_owned(), std::fs::read_to_string(path)?); + } + } + } + } + Ok(()) +} diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index dce1a558697e6..6191cd158bc9b 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -1,54 +1,114 @@ use std::io::Write; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use anyhow::Error; +mod cargo_metadata; + +/// The entry point to the binary. +/// +/// You should probably let `bootstrap` execute this program instead of running it directly. +/// +/// Run `x.py run generate-metadata` fn main() -> Result<(), Error> { - let dest = env_path("DEST")?; + let dest_file = env_path("DEST")?; + let out_dir = env_path("OUT_DIR")?; + let cargo = env_path("CARGO")?; let license_metadata = env_path("LICENSE_METADATA")?; - let metadata: Metadata = serde_json::from_slice(&std::fs::read(&license_metadata)?)?; + let collected_tree_metadata: Metadata = + serde_json::from_slice(&std::fs::read(&license_metadata)?)?; + + let root_path = std::path::absolute(".")?; + let workspace_paths = [ + Path::new("./Cargo.toml"), + Path::new("./src/tools/cargo/Cargo.toml"), + Path::new("./library/std/Cargo.toml"), + ]; + let collected_cargo_metadata = + cargo_metadata::get(&cargo, &out_dir, &root_path, &workspace_paths)?; let mut buffer = Vec::new(); - render_recursive(&metadata.files, &mut buffer, 0)?; - std::fs::write(&dest, &buffer)?; + writeln!(buffer, "# COPYRIGHT for Rust")?; + writeln!(buffer)?; + writeln!( + buffer, + "This file describes the copyright and licensing information for the source code within The Rust Project git tree, and the third-party dependencies used when building the Rust toolchain (including the Rust Standard Library)" + )?; + writeln!(buffer)?; + writeln!(buffer, "## Table of Contents")?; + writeln!(buffer)?; + writeln!(buffer, "* [In-tree files](#in-tree-files)")?; + writeln!(buffer, "* [Out-of-tree files](#out-of-tree-files)")?; + // writeln!(buffer, "* [License Texts](#license-texts)")?; + writeln!(buffer)?; + + writeln!(buffer, "## In-tree files")?; + writeln!(buffer)?; + writeln!( + buffer, + "The following licenses cover the in-tree source files that were used in this release:" + )?; + writeln!(buffer)?; + render_tree_recursive(&collected_tree_metadata.files, &mut buffer, 0)?; + + writeln!(buffer)?; + + writeln!(buffer, "## Out-of-tree files")?; + writeln!(buffer)?; + writeln!( + buffer, + "The following licenses cover the out-of-tree crates that were used in this release:" + )?; + writeln!(buffer)?; + render_deps(collected_cargo_metadata.iter(), &mut buffer)?; + + std::fs::write(&dest_file, &buffer)?; Ok(()) } -fn render_recursive(node: &Node, buffer: &mut Vec, depth: usize) -> Result<(), Error> { +/// Recursively draw the tree of files/folders we found on disk and their licenses, as +/// markdown, into the given Vec. +fn render_tree_recursive(node: &Node, buffer: &mut Vec, depth: usize) -> Result<(), Error> { let prefix = std::iter::repeat("> ").take(depth + 1).collect::(); match node { Node::Root { children } => { for child in children { - render_recursive(child, buffer, depth)?; + render_tree_recursive(child, buffer, depth)?; } } Node::Directory { name, children, license } => { - render_license(&prefix, std::iter::once(name), license.as_ref(), buffer)?; + render_tree_license(&prefix, std::iter::once(name), license.as_ref(), buffer)?; if !children.is_empty() { writeln!(buffer, "{prefix}")?; writeln!(buffer, "{prefix}*Exceptions:*")?; for child in children { writeln!(buffer, "{prefix}")?; - render_recursive(child, buffer, depth + 1)?; + render_tree_recursive(child, buffer, depth + 1)?; } } } Node::Group { files, directories, license } => { - render_license(&prefix, directories.iter().chain(files.iter()), Some(license), buffer)?; + render_tree_license( + &prefix, + directories.iter().chain(files.iter()), + Some(license), + buffer, + )?; } Node::File { name, license } => { - render_license(&prefix, std::iter::once(name), Some(license), buffer)?; + render_tree_license(&prefix, std::iter::once(name), Some(license), buffer)?; } } Ok(()) } -fn render_license<'a>( +/// Draw a series of sibling files/folders, as markdown, into the given Vec. +fn render_tree_license<'a>( prefix: &str, names: impl Iterator, license: Option<&License>, @@ -67,11 +127,47 @@ fn render_license<'a>( Ok(()) } +/// Render a list of out-of-tree dependencies as markdown into the given Vec. +fn render_deps<'a, 'b>( + deps: impl Iterator, + buffer: &'b mut Vec, +) -> Result<(), Error> { + for dep in deps { + let authors_list = dep.authors.join(", ").replace("<", "\\<").replace(">", "\\>"); + let url = format!("https://crates.io/crates/{}/{}", dep.name, dep.version); + writeln!(buffer)?; + writeln!( + buffer, + "### [{name} {version}]({url})", + name = dep.name, + version = dep.version, + url = url, + )?; + writeln!(buffer)?; + writeln!(buffer, "* Authors: {}", authors_list)?; + writeln!(buffer, "* License: {}", dep.license)?; + for (name, contents) in &dep.notices { + writeln!(buffer)?; + writeln!(buffer, "#### {}", name.to_string_lossy())?; + writeln!(buffer)?; + writeln!(buffer, "
    Click to expand")?; + writeln!(buffer)?; + writeln!(buffer, "```")?; + writeln!(buffer, "{}", contents)?; + writeln!(buffer, "```")?; + writeln!(buffer)?; + writeln!(buffer, "
    ")?; + } + } + Ok(()) +} +/// Describes a tree of metadata for our filesystem tree #[derive(serde::Deserialize)] struct Metadata { files: Node, } +/// Describes one node in our metadata tree #[derive(serde::Deserialize)] #[serde(rename_all = "kebab-case", tag = "type")] pub(crate) enum Node { @@ -81,12 +177,14 @@ pub(crate) enum Node { Group { files: Vec, directories: Vec, license: License }, } +/// A License has an SPDX license name and a list of copyright holders. #[derive(serde::Deserialize)] struct License { spdx: String, copyright: Vec, } +/// Grab an environment variable as a PathBuf, or fail nicely. fn env_path(var: &str) -> Result { if let Some(var) = std::env::var_os(var) { Ok(var.into()) From 204e3eadf1323ebd886ee159b193e231ec4906c9 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Mon, 29 Jul 2024 11:41:02 +0100 Subject: [PATCH 481/489] generate-copyright: Produce HTML, not Markdown This format works better with large amounts of structured data. We also mark which deps are in the stdlib --- src/bootstrap/src/core/build_steps/run.rs | 2 +- .../generate-copyright/src/cargo_metadata.rs | 81 +++++---- src/tools/generate-copyright/src/main.rs | 172 ++++++++++-------- 3 files changed, 152 insertions(+), 103 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 29d7bcc425bea..65d635c0bd69f 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -212,7 +212,7 @@ impl Step for GenerateCopyright { let license_metadata = builder.ensure(CollectLicenseMetadata); // Temporary location, it will be moved to the proper one once it's accurate. - let dest = builder.out.join("COPYRIGHT.md"); + let dest = builder.out.join("COPYRIGHT.html"); let mut cmd = builder.tool_cmd(Tool::GenerateCopyright); cmd.env("LICENSE_METADATA", &license_metadata); diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs index 721a6b1c6e627..eda53c73c0af6 100644 --- a/src/tools/generate-copyright/src/cargo_metadata.rs +++ b/src/tools/generate-copyright/src/cargo_metadata.rs @@ -1,6 +1,6 @@ //! Gets metadata about a workspace from Cargo -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::ffi::{OsStr, OsString}; use std::path::Path; @@ -23,13 +23,18 @@ pub enum Error { RunningVendor, } -/// Describes one of our dependencies +/// Uniquely describes a package on crates.io #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Dependency { +pub struct Package { /// The name of the package pub name: String, /// The version number pub version: String, +} + +/// Extra data about a package +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct PackageMetadata { /// The license it is under pub license: String, /// The list of authors from the package metadata @@ -40,20 +45,44 @@ pub struct Dependency { pub notices: BTreeMap, } -/// Use `cargo` to get a list of dependencies and their license data. +/// Use `cargo metadata` and `cargo vendor` to get a list of dependencies and their license data. /// /// This will involve running `cargo vendor` into `${BUILD}/vendor` so we can /// grab the license files. /// /// Any dependency with a path beginning with `root_path` is ignored, as we /// assume `reuse` has covered it already. -pub fn get( +pub fn get_metadata_and_notices( cargo: &Path, dest: &Path, root_path: &Path, manifest_paths: &[&Path], -) -> Result, Error> { - let mut temp_set = BTreeSet::new(); +) -> Result, Error> { + let mut output = get_metadata(cargo, root_path, manifest_paths)?; + + // Now do a cargo-vendor and grab everything + let vendor_path = dest.join("vendor"); + println!("Vendoring deps into {}...", vendor_path.display()); + run_cargo_vendor(cargo, &vendor_path, manifest_paths)?; + + // Now for each dependency we found, go and grab any important looking files + for (package, metadata) in output.iter_mut() { + load_important_files(package, metadata, &vendor_path)?; + } + + Ok(output) +} + +/// Use `cargo metadata` to get a list of dependencies and their license data. +/// +/// Any dependency with a path beginning with `root_path` is ignored, as we +/// assume `reuse` has covered it already. +pub fn get_metadata( + cargo: &Path, + root_path: &Path, + manifest_paths: &[&Path], +) -> Result, Error> { + let mut output = BTreeMap::new(); // Look at the metadata for each manifest for manifest_path in manifest_paths { if manifest_path.file_name() != Some(OsStr::new("Cargo.toml")) { @@ -71,7 +100,7 @@ pub fn get( .and_then(|v| v.as_str()) .map(Path::new) .ok_or_else(|| Error::MissingJsonElement("package.manifest_path"))?; - if manifest_path.starts_with(&root_path) { + if manifest_path.starts_with(root_path) { // it's an in-tree dependency and reuse covers it continue; } @@ -93,28 +122,14 @@ pub fn get( .ok_or_else(|| Error::MissingJsonElement("package.authors"))?; let authors: Vec = authors_list.iter().filter_map(|v| v.as_str()).map(|s| s.to_owned()).collect(); - temp_set.insert(Dependency { - name: name.to_owned(), - version: version.to_owned(), - license: license.to_owned(), - authors, - notices: BTreeMap::new(), - }); + let package = Package { name: name.to_owned(), version: version.to_owned() }; + output.insert( + package.clone(), + PackageMetadata { license: license.to_owned(), authors, notices: BTreeMap::new() }, + ); } } - // Now do a cargo-vendor and grab everything - let vendor_path = dest.join("vendor"); - println!("Vendoring deps into {}...", vendor_path.display()); - run_cargo_vendor(cargo, &vendor_path, manifest_paths)?; - - // Now for each dependency we found, go and grab any important looking files - let mut output = BTreeSet::new(); - for mut dep in temp_set { - load_important_files(&mut dep, &vendor_path)?; - output.insert(dep); - } - Ok(output) } @@ -128,7 +143,7 @@ fn get_metadata_json(cargo: &Path, manifest_path: &Path) -> Result Resu } vendor_command.arg(dest); - let vendor_status = vendor_command.status().map_err(|e| Error::LaunchingVendor(e))?; + let vendor_status = vendor_command.status().map_err(Error::LaunchingVendor)?; if !vendor_status.success() { return Err(Error::RunningVendor); @@ -164,8 +179,12 @@ fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Resu /// /// Maybe one-day Cargo.toml will contain enough information that we don't need /// to do this manual scraping. -fn load_important_files(dep: &mut Dependency, vendor_root: &Path) -> Result<(), Error> { - let name_version = format!("{}-{}", dep.name, dep.version); +fn load_important_files( + package: &Package, + dep: &mut PackageMetadata, + vendor_root: &Path, +) -> Result<(), Error> { + let name_version = format!("{}-{}", package.name, package.version); println!("Scraping notices for {}...", name_version); let dep_vendor_path = vendor_root.join(name_version); for entry in std::fs::read_dir(dep_vendor_path)? { diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index 6191cd158bc9b..efccba0651e4d 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -1,3 +1,4 @@ +use std::collections::BTreeMap; use std::io::Write; use std::path::{Path, PathBuf}; @@ -5,6 +6,33 @@ use anyhow::Error; mod cargo_metadata; +static TOP_BOILERPLATE: &str = r##" + + + + + Copyright notices for The Rust Toolchain + + + +

    Copyright notices for The Rust Toolchain

    + +

    This file describes the copyright and licensing information for the source +code within The Rust Project git tree, and the third-party dependencies used +when building the Rust toolchain (including the Rust Standard Library).

    + +

    Table of Contents

    +
    +"##; + +static BOTTOM_BOILERPLATE: &str = r#" + + +"#; + /// The entry point to the binary. /// /// You should probably let `bootstrap` execute this program instead of running it directly. @@ -26,43 +54,28 @@ fn main() -> Result<(), Error> { Path::new("./library/std/Cargo.toml"), ]; let collected_cargo_metadata = - cargo_metadata::get(&cargo, &out_dir, &root_path, &workspace_paths)?; + cargo_metadata::get_metadata_and_notices(&cargo, &out_dir, &root_path, &workspace_paths)?; + + let stdlib_set = + cargo_metadata::get_metadata(&cargo, &root_path, &[Path::new("./library/std/Cargo.toml")])?; let mut buffer = Vec::new(); - writeln!(buffer, "# COPYRIGHT for Rust")?; - writeln!(buffer)?; - writeln!( - buffer, - "This file describes the copyright and licensing information for the source code within The Rust Project git tree, and the third-party dependencies used when building the Rust toolchain (including the Rust Standard Library)" - )?; - writeln!(buffer)?; - writeln!(buffer, "## Table of Contents")?; - writeln!(buffer)?; - writeln!(buffer, "* [In-tree files](#in-tree-files)")?; - writeln!(buffer, "* [Out-of-tree files](#out-of-tree-files)")?; - // writeln!(buffer, "* [License Texts](#license-texts)")?; - writeln!(buffer)?; - - writeln!(buffer, "## In-tree files")?; - writeln!(buffer)?; + writeln!(buffer, "{}", TOP_BOILERPLATE)?; + writeln!( buffer, - "The following licenses cover the in-tree source files that were used in this release:" + r#"

    In-tree files

    The following licenses cover the in-tree source files that were used in this release:

    "# )?; - writeln!(buffer)?; - render_tree_recursive(&collected_tree_metadata.files, &mut buffer, 0)?; - - writeln!(buffer)?; + render_tree_recursive(&collected_tree_metadata.files, &mut buffer)?; - writeln!(buffer, "## Out-of-tree files")?; - writeln!(buffer)?; writeln!( buffer, - "The following licenses cover the out-of-tree crates that were used in this release:" + r#"

    Out-of-tree dependencies

    The following licenses cover the out-of-tree crates that were used in this release:

    "# )?; - writeln!(buffer)?; - render_deps(collected_cargo_metadata.iter(), &mut buffer)?; + render_deps(&collected_cargo_metadata, &stdlib_set, &mut buffer)?; + + writeln!(buffer, "{}", BOTTOM_BOILERPLATE)?; std::fs::write(&dest_file, &buffer)?; @@ -71,56 +84,51 @@ fn main() -> Result<(), Error> { /// Recursively draw the tree of files/folders we found on disk and their licenses, as /// markdown, into the given Vec. -fn render_tree_recursive(node: &Node, buffer: &mut Vec, depth: usize) -> Result<(), Error> { - let prefix = std::iter::repeat("> ").take(depth + 1).collect::(); - +fn render_tree_recursive(node: &Node, buffer: &mut Vec) -> Result<(), Error> { + writeln!(buffer, r#"
    "#)?; match node { Node::Root { children } => { for child in children { - render_tree_recursive(child, buffer, depth)?; + render_tree_recursive(child, buffer)?; } } Node::Directory { name, children, license } => { - render_tree_license(&prefix, std::iter::once(name), license.as_ref(), buffer)?; + render_tree_license(std::iter::once(name), license.as_ref(), buffer)?; if !children.is_empty() { - writeln!(buffer, "{prefix}")?; - writeln!(buffer, "{prefix}*Exceptions:*")?; + writeln!(buffer, "

    Exceptions:

    ")?; for child in children { - writeln!(buffer, "{prefix}")?; - render_tree_recursive(child, buffer, depth + 1)?; + render_tree_recursive(child, buffer)?; } } } Node::Group { files, directories, license } => { - render_tree_license( - &prefix, - directories.iter().chain(files.iter()), - Some(license), - buffer, - )?; + render_tree_license(directories.iter().chain(files.iter()), Some(license), buffer)?; } Node::File { name, license } => { - render_tree_license(&prefix, std::iter::once(name), Some(license), buffer)?; + render_tree_license(std::iter::once(name), Some(license), buffer)?; } } + writeln!(buffer, "
    ")?; Ok(()) } /// Draw a series of sibling files/folders, as markdown, into the given Vec. fn render_tree_license<'a>( - prefix: &str, names: impl Iterator, license: Option<&License>, buffer: &mut Vec, ) -> Result<(), Error> { + writeln!(buffer, "

    File/Directory: ")?; for name in names { - writeln!(buffer, "{prefix}**`{name}`** ")?; + writeln!(buffer, "{name}")?; } + writeln!(buffer, "

    ")?; + if let Some(license) = license { - writeln!(buffer, "{prefix}License: `{}`", license.spdx)?; + writeln!(buffer, "

    License: {}

    ", license.spdx)?; for copyright in license.copyright.iter() { - writeln!(buffer, "{prefix}Copyright: {copyright}")?; + writeln!(buffer, "

    Copyright: {copyright}

    ")?; } } @@ -128,36 +136,48 @@ fn render_tree_license<'a>( } /// Render a list of out-of-tree dependencies as markdown into the given Vec. -fn render_deps<'a, 'b>( - deps: impl Iterator, - buffer: &'b mut Vec, +fn render_deps( + all_deps: &BTreeMap, + stdlib_set: &BTreeMap, + buffer: &mut Vec, ) -> Result<(), Error> { - for dep in deps { - let authors_list = dep.authors.join(", ").replace("<", "\\<").replace(">", "\\>"); - let url = format!("https://crates.io/crates/{}/{}", dep.name, dep.version); + for (package, metadata) in all_deps { + let authors_list = if metadata.authors.is_empty() { + "None Specified".to_owned() + } else { + metadata.authors.join(", ") + }; + let url = format!("https://crates.io/crates/{}/{}", package.name, package.version); writeln!(buffer)?; writeln!( buffer, - "### [{name} {version}]({url})", - name = dep.name, - version = dep.version, - url = url, + r#"

    📦 {name}-{version}

    "#, + name = package.name, + version = package.version, )?; - writeln!(buffer)?; - writeln!(buffer, "* Authors: {}", authors_list)?; - writeln!(buffer, "* License: {}", dep.license)?; - for (name, contents) in &dep.notices { - writeln!(buffer)?; - writeln!(buffer, "#### {}", name.to_string_lossy())?; - writeln!(buffer)?; - writeln!(buffer, "
    Click to expand")?; - writeln!(buffer)?; - writeln!(buffer, "```")?; - writeln!(buffer, "{}", contents)?; - writeln!(buffer, "```")?; - writeln!(buffer)?; - writeln!(buffer, "
    ")?; + writeln!(buffer, r#"

    URL: {url}

    "#,)?; + writeln!( + buffer, + "

    In libstd: {}

    ", + if stdlib_set.contains_key(package) { "Yes" } else { "No" } + )?; + writeln!(buffer, "

    Authors: {}

    ", escape_html(&authors_list))?; + writeln!(buffer, "

    License: {}

    ", escape_html(&metadata.license))?; + writeln!(buffer, "

    Notices: ")?; + if metadata.notices.is_empty() { + writeln!(buffer, "None")?; + } else { + for (name, contents) in &metadata.notices { + writeln!( + buffer, + "

    {}", + name.to_string_lossy() + )?; + writeln!(buffer, "
    \n{}\n
    ", contents)?; + writeln!(buffer, "
    ")?; + } } + writeln!(buffer, "

    ")?; } Ok(()) } @@ -192,3 +212,13 @@ fn env_path(var: &str) -> Result { anyhow::bail!("missing environment variable {var}") } } + +/// Escapes any invalid HTML characters +fn escape_html(input: &str) -> String { + static MAPPING: [(char, &str); 3] = [('&', "&"), ('<', "<"), ('>', ">")]; + let mut output = input.to_owned(); + for (ch, s) in &MAPPING { + output = output.replace(*ch, s); + } + output +} From 56f84796a4e819be108721f723d8c1b229e5dbdd Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Tue, 30 Jul 2024 13:54:48 +0100 Subject: [PATCH 482/489] generate-copyright: Fix typo --- src/tools/generate-copyright/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index efccba0651e4d..af69ab8c8bf36 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -37,7 +37,7 @@ static BOTTOM_BOILERPLATE: &str = r#" /// /// You should probably let `bootstrap` execute this program instead of running it directly. /// -/// Run `x.py run generate-metadata` +/// Run `x.py run generate-copyright` fn main() -> Result<(), Error> { let dest_file = env_path("DEST")?; let out_dir = env_path("OUT_DIR")?; From dbab595d78f12c0514cfe2ac4c7c9d083445c14f Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Tue, 30 Jul 2024 13:56:17 +0100 Subject: [PATCH 483/489] generate-copyright: use cargo-metadata --- Cargo.lock | 1 + src/tools/generate-copyright/Cargo.toml | 1 + .../generate-copyright/src/cargo_metadata.rs | 80 +++++-------------- 3 files changed, 20 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f3a106512d20..eeaeff79ebb25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1406,6 +1406,7 @@ name = "generate-copyright" version = "0.1.0" dependencies = [ "anyhow", + "cargo_metadata 0.18.1", "serde", "serde_json", "tempfile", diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index bf643876a042b..c94cc35fb5036 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -12,3 +12,4 @@ serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" thiserror = "1" tempfile = "3" +cargo_metadata = "0.18.1" diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs index eda53c73c0af6..655d73715e036 100644 --- a/src/tools/generate-copyright/src/cargo_metadata.rs +++ b/src/tools/generate-copyright/src/cargo_metadata.rs @@ -7,16 +7,10 @@ use std::path::Path; /// Describes how this module can fail #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("Failed to run cargo metadata: {0:?}")] - LaunchingMetadata(#[from] std::io::Error), - #[error("Failed get output from cargo metadata: {0:?}")] - GettingMetadata(String), - #[error("Failed parse JSON output from cargo metadata: {0:?}")] - ParsingJson(#[from] serde_json::Error), - #[error("Failed find expected JSON element {0} in output from cargo metadata")] - MissingJsonElement(&'static str), - #[error("Failed find expected JSON element {0} in output from cargo metadata for package {1}")] - MissingJsonElementForPackage(String, String), + #[error("I/O Error: {0:?}")] + Io(#[from] std::io::Error), + #[error("Failed get output from cargo-metadata: {0:?}")] + GettingMetadata(#[from] cargo_metadata::Error), #[error("Failed to run cargo vendor: {0:?}")] LaunchingVendor(std::io::Error), #[error("Failed to complete cargo vendor")] @@ -88,44 +82,26 @@ pub fn get_metadata( if manifest_path.file_name() != Some(OsStr::new("Cargo.toml")) { panic!("cargo_manifest::get requires a path to a Cargo.toml file"); } - let metadata_json = get_metadata_json(cargo, manifest_path)?; - let packages = metadata_json["packages"] - .as_array() - .ok_or_else(|| Error::MissingJsonElement("packages array"))?; - for package in packages { - let package = - package.as_object().ok_or_else(|| Error::MissingJsonElement("package object"))?; - let manifest_path = package - .get("manifest_path") - .and_then(|v| v.as_str()) - .map(Path::new) - .ok_or_else(|| Error::MissingJsonElement("package.manifest_path"))?; + let metadata = cargo_metadata::MetadataCommand::new() + .cargo_path(cargo) + .env("RUSTC_BOOTSTRAP", "1") + .manifest_path(manifest_path) + .exec()?; + for package in metadata.packages { + let manifest_path = package.manifest_path.as_path(); if manifest_path.starts_with(root_path) { // it's an in-tree dependency and reuse covers it continue; } // otherwise it's an out-of-tree dependency - let get_string = |field_name: &str, package_name: &str| { - package.get(field_name).and_then(|v| v.as_str()).ok_or_else(|| { - Error::MissingJsonElementForPackage( - format!("package.{field_name}"), - package_name.to_owned(), - ) - }) - }; - let name = get_string("name", "unknown")?; - let license = get_string("license", name)?; - let version = get_string("version", name)?; - let authors_list = package - .get("authors") - .and_then(|v| v.as_array()) - .ok_or_else(|| Error::MissingJsonElement("package.authors"))?; - let authors: Vec = - authors_list.iter().filter_map(|v| v.as_str()).map(|s| s.to_owned()).collect(); - let package = Package { name: name.to_owned(), version: version.to_owned() }; + let package_id = Package { name: package.name, version: package.version.to_string() }; output.insert( - package.clone(), - PackageMetadata { license: license.to_owned(), authors, notices: BTreeMap::new() }, + package_id, + PackageMetadata { + license: package.license.unwrap_or_else(|| String::from("Unspecified")), + authors: package.authors, + notices: BTreeMap::new(), + }, ); } } @@ -133,26 +109,6 @@ pub fn get_metadata( Ok(output) } -/// Get cargo-metdata for a package, as JSON -fn get_metadata_json(cargo: &Path, manifest_path: &Path) -> Result { - let metadata_output = std::process::Command::new(cargo) - .arg("metadata") - .arg("--format-version=1") - .arg("--all-features") - .arg("--manifest-path") - .arg(manifest_path) - .env("RUSTC_BOOTSTRAP", "1") - .output() - .map_err(Error::LaunchingMetadata)?; - if !metadata_output.status.success() { - return Err(Error::GettingMetadata( - String::from_utf8(metadata_output.stderr).expect("UTF-8 output from cargo"), - )); - } - let json = serde_json::from_slice(&metadata_output.stdout)?; - Ok(json) -} - /// Run cargo-vendor, fetching into the given dir fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Result<(), Error> { let mut vendor_command = std::process::Command::new(cargo); From f7e6bf61a9c3492115d19dc112071adea90a7038 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Tue, 30 Jul 2024 19:39:06 +0100 Subject: [PATCH 484/489] generate-copyright: use rinja to format the output I can't find a way to derive rinja::Template for Node - I think because it is a recursive type. So I rendered it manually using html_escape. --- src/tools/generate-copyright/Cargo.toml | 6 +- .../generate-copyright/src/cargo_metadata.rs | 12 +- src/tools/generate-copyright/src/main.rs | 226 +++++++----------- .../templates/COPYRIGHT.html | 54 +++++ 4 files changed, 146 insertions(+), 152 deletions(-) create mode 100644 src/tools/generate-copyright/templates/COPYRIGHT.html diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index c94cc35fb5036..c00292cf33108 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -8,8 +8,10 @@ description = "Produces a manifest of all the copyrighted materials in the Rust [dependencies] anyhow = "1.0.65" +cargo_metadata = "0.18.1" +html-escape = "0.2.13" +rinja = "0.2.0" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" -thiserror = "1" tempfile = "3" -cargo_metadata = "0.18.1" +thiserror = "1" diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs index 655d73715e036..d02b9eeb6f922 100644 --- a/src/tools/generate-copyright/src/cargo_metadata.rs +++ b/src/tools/generate-copyright/src/cargo_metadata.rs @@ -1,7 +1,7 @@ //! Gets metadata about a workspace from Cargo use std::collections::BTreeMap; -use std::ffi::{OsStr, OsString}; +use std::ffi::OsStr; use std::path::Path; /// Describes how this module can fail @@ -36,7 +36,9 @@ pub struct PackageMetadata { /// A list of important files from the package, with their contents. /// /// This includes *COPYRIGHT*, *NOTICE*, *AUTHOR*, *LICENSE*, and *LICENCE* files, case-insensitive. - pub notices: BTreeMap, + pub notices: BTreeMap, + /// If this is true, this dep is in the Rust Standard Library + pub is_in_libstd: Option, } /// Use `cargo metadata` and `cargo vendor` to get a list of dependencies and their license data. @@ -101,6 +103,7 @@ pub fn get_metadata( license: package.license.unwrap_or_else(|| String::from("Unspecified")), authors: package.authors, notices: BTreeMap::new(), + is_in_libstd: None, }, ); } @@ -161,8 +164,9 @@ fn load_important_files( if metadata.is_dir() { // scoop up whole directory } else if metadata.is_file() { - println!("Scraping {}", filename.to_string_lossy()); - dep.notices.insert(filename.to_owned(), std::fs::read_to_string(path)?); + let filename = filename.to_string_lossy(); + println!("Scraping {}", filename); + dep.notices.insert(filename.to_string(), std::fs::read_to_string(path)?); } } } diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index af69ab8c8bf36..03b789b739298 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -1,37 +1,17 @@ use std::collections::BTreeMap; -use std::io::Write; use std::path::{Path, PathBuf}; use anyhow::Error; +use rinja::Template; mod cargo_metadata; -static TOP_BOILERPLATE: &str = r##" - - - - - Copyright notices for The Rust Toolchain - - - -

    Copyright notices for The Rust Toolchain

    - -

    This file describes the copyright and licensing information for the source -code within The Rust Project git tree, and the third-party dependencies used -when building the Rust toolchain (including the Rust Standard Library).

    - -

    Table of Contents

    - -"##; - -static BOTTOM_BOILERPLATE: &str = r#" - - -"#; +#[derive(Template)] +#[template(path = "COPYRIGHT.html")] +struct CopyrightTemplate { + in_tree: Node, + dependencies: BTreeMap, +} /// The entry point to the binary. /// @@ -53,150 +33,114 @@ fn main() -> Result<(), Error> { Path::new("./src/tools/cargo/Cargo.toml"), Path::new("./library/std/Cargo.toml"), ]; - let collected_cargo_metadata = + let mut collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(&cargo, &out_dir, &root_path, &workspace_paths)?; let stdlib_set = cargo_metadata::get_metadata(&cargo, &root_path, &[Path::new("./library/std/Cargo.toml")])?; - let mut buffer = Vec::new(); + for (key, value) in collected_cargo_metadata.iter_mut() { + value.is_in_libstd = Some(stdlib_set.contains_key(key)); + } - writeln!(buffer, "{}", TOP_BOILERPLATE)?; + let template = CopyrightTemplate { + in_tree: collected_tree_metadata.files, + dependencies: collected_cargo_metadata, + }; - writeln!( - buffer, - r#"

    In-tree files

    The following licenses cover the in-tree source files that were used in this release:

    "# - )?; - render_tree_recursive(&collected_tree_metadata.files, &mut buffer)?; + let output = template.render()?; - writeln!( - buffer, - r#"

    Out-of-tree dependencies

    The following licenses cover the out-of-tree crates that were used in this release:

    "# - )?; - render_deps(&collected_cargo_metadata, &stdlib_set, &mut buffer)?; + std::fs::write(&dest_file, output)?; - writeln!(buffer, "{}", BOTTOM_BOILERPLATE)?; + Ok(()) +} - std::fs::write(&dest_file, &buffer)?; +/// Describes a tree of metadata for our filesystem tree +#[derive(serde::Deserialize)] +struct Metadata { + files: Node, +} +/// Describes one node in our metadata tree +#[derive(serde::Deserialize)] +#[serde(rename_all = "kebab-case", tag = "type")] +pub(crate) enum Node { + Root { children: Vec }, + Directory { name: String, children: Vec, license: Option }, + File { name: String, license: License }, + Group { files: Vec, directories: Vec, license: License }, +} + +fn with_box(fmt: &mut std::fmt::Formatter<'_>, inner: F) -> std::fmt::Result +where + F: FnOnce(&mut std::fmt::Formatter<'_>) -> std::fmt::Result, +{ + writeln!(fmt, r#"
    "#)?; + inner(fmt)?; + writeln!(fmt, "
    ")?; Ok(()) } -/// Recursively draw the tree of files/folders we found on disk and their licenses, as -/// markdown, into the given Vec. -fn render_tree_recursive(node: &Node, buffer: &mut Vec) -> Result<(), Error> { - writeln!(buffer, r#"
    "#)?; - match node { - Node::Root { children } => { - for child in children { - render_tree_recursive(child, buffer)?; +impl std::fmt::Display for Node { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Node::Root { children } => { + if children.len() > 1 { + with_box(fmt, |f| { + for child in children { + writeln!(f, "{child}")?; + } + Ok(()) + }) + } else { + for child in children { + writeln!(fmt, "{child}")?; + } + Ok(()) + } } - } - Node::Directory { name, children, license } => { - render_tree_license(std::iter::once(name), license.as_ref(), buffer)?; - if !children.is_empty() { - writeln!(buffer, "

    Exceptions:

    ")?; - for child in children { - render_tree_recursive(child, buffer)?; + Node::Directory { name, children, license } => with_box(fmt, |f| { + render_tree_license(std::iter::once(name), license.as_ref(), f)?; + if !children.is_empty() { + writeln!(f, "

    Exceptions:

    ")?; + for child in children { + writeln!(f, "{child}")?; + } } + Ok(()) + }), + Node::Group { files, directories, license } => with_box(fmt, |f| { + render_tree_license(directories.iter().chain(files.iter()), Some(license), f) + }), + Node::File { name, license } => { + with_box(fmt, |f| render_tree_license(std::iter::once(name), Some(license), f)) } } - Node::Group { files, directories, license } => { - render_tree_license(directories.iter().chain(files.iter()), Some(license), buffer)?; - } - Node::File { name, license } => { - render_tree_license(std::iter::once(name), Some(license), buffer)?; - } } - writeln!(buffer, "
    ")?; - - Ok(()) } -/// Draw a series of sibling files/folders, as markdown, into the given Vec. +/// Draw a series of sibling files/folders, as HTML, into the given formatter. fn render_tree_license<'a>( names: impl Iterator, license: Option<&License>, - buffer: &mut Vec, -) -> Result<(), Error> { - writeln!(buffer, "

    File/Directory: ")?; + f: &mut std::fmt::Formatter<'_>, +) -> std::fmt::Result { + writeln!(f, "

    File/Directory: ")?; for name in names { - writeln!(buffer, "{name}")?; + writeln!(f, "{}", html_escape::encode_text(&name))?; } - writeln!(buffer, "

    ")?; + writeln!(f, "

    ")?; if let Some(license) = license { - writeln!(buffer, "

    License: {}

    ", license.spdx)?; + writeln!(f, "

    License: {}

    ", html_escape::encode_text(&license.spdx))?; for copyright in license.copyright.iter() { - writeln!(buffer, "

    Copyright: {copyright}

    ")?; + writeln!(f, "

    Copyright: {}

    ", html_escape::encode_text(©right))?; } } Ok(()) } -/// Render a list of out-of-tree dependencies as markdown into the given Vec. -fn render_deps( - all_deps: &BTreeMap, - stdlib_set: &BTreeMap, - buffer: &mut Vec, -) -> Result<(), Error> { - for (package, metadata) in all_deps { - let authors_list = if metadata.authors.is_empty() { - "None Specified".to_owned() - } else { - metadata.authors.join(", ") - }; - let url = format!("https://crates.io/crates/{}/{}", package.name, package.version); - writeln!(buffer)?; - writeln!( - buffer, - r#"

    📦 {name}-{version}

    "#, - name = package.name, - version = package.version, - )?; - writeln!(buffer, r#"

    URL: {url}

    "#,)?; - writeln!( - buffer, - "

    In libstd: {}

    ", - if stdlib_set.contains_key(package) { "Yes" } else { "No" } - )?; - writeln!(buffer, "

    Authors: {}

    ", escape_html(&authors_list))?; - writeln!(buffer, "

    License: {}

    ", escape_html(&metadata.license))?; - writeln!(buffer, "

    Notices: ")?; - if metadata.notices.is_empty() { - writeln!(buffer, "None")?; - } else { - for (name, contents) in &metadata.notices { - writeln!( - buffer, - "

    {}", - name.to_string_lossy() - )?; - writeln!(buffer, "
    \n{}\n
    ", contents)?; - writeln!(buffer, "
    ")?; - } - } - writeln!(buffer, "

    ")?; - } - Ok(()) -} -/// Describes a tree of metadata for our filesystem tree -#[derive(serde::Deserialize)] -struct Metadata { - files: Node, -} - -/// Describes one node in our metadata tree -#[derive(serde::Deserialize)] -#[serde(rename_all = "kebab-case", tag = "type")] -pub(crate) enum Node { - Root { children: Vec }, - Directory { name: String, children: Vec, license: Option }, - File { name: String, license: License }, - Group { files: Vec, directories: Vec, license: License }, -} - /// A License has an SPDX license name and a list of copyright holders. #[derive(serde::Deserialize)] struct License { @@ -212,13 +156,3 @@ fn env_path(var: &str) -> Result { anyhow::bail!("missing environment variable {var}") } } - -/// Escapes any invalid HTML characters -fn escape_html(input: &str) -> String { - static MAPPING: [(char, &str); 3] = [('&', "&"), ('<', "<"), ('>', ">")]; - let mut output = input.to_owned(); - for (ch, s) in &MAPPING { - output = output.replace(*ch, s); - } - output -} diff --git a/src/tools/generate-copyright/templates/COPYRIGHT.html b/src/tools/generate-copyright/templates/COPYRIGHT.html new file mode 100644 index 0000000000000..ccb177a54d419 --- /dev/null +++ b/src/tools/generate-copyright/templates/COPYRIGHT.html @@ -0,0 +1,54 @@ + + + + + Copyright notices for The Rust Toolchain + + + +

    Copyright notices for The Rust Toolchain

    + +

    This file describes the copyright and licensing information for the source +code within The Rust Project git tree, and the third-party dependencies used +when building the Rust toolchain (including the Rust Standard Library).

    + +

    Table of Contents

    + + +

    In-tree files

    + +

    The following licenses cover the in-tree source files that were used in this +release:

    + +{{ in_tree|safe }} + +

    Out-of-tree dependencies

    + +

    The following licenses cover the out-of-tree crates that were used in this +release:

    + +{% for (key, value) in dependencies %} +

    📦 {{key.name}}-{{key.version}}

    +

    URL: https://crates.io/crates/{{ key.name }}/{{ key.version }}

    +

    In libstd: {% if value.is_in_libstd.unwrap() %} Yes {% else %} No {% endif %}

    +

    Authors: {{ value.authors|join(", ") }}

    +

    License: {{ value.license }}

    + {% let len = value.notices.len() %} + {% if len > 0 %} +

    Notices: + {% for (notice_name, notice_text) in value.notices %} +

    + {{ notice_name }} +
    +{{ notice_text }}
    +                
    +
    + {% endfor %} +

    + {% endif %} +{% endfor %} + + \ No newline at end of file From 37ab09010cb627df6b3ffb2d4e95c2cacaf93efb Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Tue, 30 Jul 2024 19:39:38 +0100 Subject: [PATCH 485/489] REUSE.toml: Copyright text isn't parsed as Markdown. --- REUSE.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REUSE.toml b/REUSE.toml index 1a30d8016c9ea..efd705552478d 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -163,7 +163,7 @@ SPDX-License-Identifier = "MIT OR Apache-2.0" path = "src/llvm-project/**" precedence = "override" SPDX-FileCopyrightText = [ - "2003-2019 by the contributors listed in [CREDITS.TXT](https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)", + "2003-2019 by the contributors listed in CREDITS.TXT (https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)", "2010 Apple Inc", "2003-2019 University of Illinois at Urbana-Champaign.", ] From 30ac7c9a817793a86d870eeab5a8238acb29b186 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Wed, 31 Jul 2024 19:26:44 +0100 Subject: [PATCH 486/489] generate-copyright: Render Node with rinja too. --- Cargo.lock | 46 +++++++++++- src/tools/generate-copyright/Cargo.toml | 2 - src/tools/generate-copyright/src/main.rs | 73 +------------------ .../generate-copyright/templates/Node.html | 71 ++++++++++++++++++ 4 files changed, 115 insertions(+), 77 deletions(-) create mode 100644 src/tools/generate-copyright/templates/Node.html diff --git a/Cargo.lock b/Cargo.lock index eeaeff79ebb25..54454e84b5a97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1407,9 +1407,9 @@ version = "0.1.0" dependencies = [ "anyhow", "cargo_metadata 0.18.1", + "rinja 0.2.0", "serde", "serde_json", - "tempfile", "thiserror", ] @@ -3100,6 +3100,18 @@ dependencies = [ "walkdir", ] +[[package]] +name = "rinja" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d47a46d7729e891c8accf260e9daa02ae6d570aa2a94fb1fb27eb5364a2323" +dependencies = [ + "humansize", + "num-traits", + "percent-encoding", + "rinja_derive 0.2.0", +] + [[package]] name = "rinja" version = "0.3.0" @@ -3107,7 +3119,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d3762e3740cdbf2fd2be465cc2c26d643ad17353cc2e0223d211c1b096118bd" dependencies = [ "itoa", - "rinja_derive", + "rinja_derive 0.3.0", +] + +[[package]] +name = "rinja_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44dae9afe59d58ed8d988d67d1945f3638125d2fd2104058399382e11bd3ea2a" +dependencies = [ + "basic-toml", + "mime", + "mime_guess", + "once_map", + "proc-macro2", + "quote", + "rinja_parser 0.2.0", + "serde", + "syn 2.0.67", ] [[package]] @@ -3123,11 +3152,20 @@ dependencies = [ "once_map", "proc-macro2", "quote", - "rinja_parser", + "rinja_parser 0.3.0", "serde", "syn 2.0.67", ] +[[package]] +name = "rinja_parser" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1771c78cd5d3b1646ef8d8f2ed100db936e8b291d3cc06e92a339ff346858c" +dependencies = [ + "nom", +] + [[package]] name = "rinja_parser" version = "0.3.0" @@ -4606,7 +4644,7 @@ dependencies = [ "minifier", "pulldown-cmark 0.9.6", "regex", - "rinja", + "rinja 0.3.0", "rustdoc-json-types", "serde", "serde_json", diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index c00292cf33108..d200e2ec9f1e1 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -9,9 +9,7 @@ description = "Produces a manifest of all the copyrighted materials in the Rust [dependencies] anyhow = "1.0.65" cargo_metadata = "0.18.1" -html-escape = "0.2.13" rinja = "0.2.0" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" -tempfile = "3" thiserror = "1" diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index 03b789b739298..37de24648d56d 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -62,8 +62,9 @@ struct Metadata { } /// Describes one node in our metadata tree -#[derive(serde::Deserialize)] +#[derive(serde::Deserialize, rinja::Template)] #[serde(rename_all = "kebab-case", tag = "type")] +#[template(path = "Node.html")] pub(crate) enum Node { Root { children: Vec }, Directory { name: String, children: Vec, license: Option }, @@ -71,76 +72,6 @@ pub(crate) enum Node { Group { files: Vec, directories: Vec, license: License }, } -fn with_box(fmt: &mut std::fmt::Formatter<'_>, inner: F) -> std::fmt::Result -where - F: FnOnce(&mut std::fmt::Formatter<'_>) -> std::fmt::Result, -{ - writeln!(fmt, r#"
    "#)?; - inner(fmt)?; - writeln!(fmt, "
    ")?; - Ok(()) -} - -impl std::fmt::Display for Node { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Node::Root { children } => { - if children.len() > 1 { - with_box(fmt, |f| { - for child in children { - writeln!(f, "{child}")?; - } - Ok(()) - }) - } else { - for child in children { - writeln!(fmt, "{child}")?; - } - Ok(()) - } - } - Node::Directory { name, children, license } => with_box(fmt, |f| { - render_tree_license(std::iter::once(name), license.as_ref(), f)?; - if !children.is_empty() { - writeln!(f, "

    Exceptions:

    ")?; - for child in children { - writeln!(f, "{child}")?; - } - } - Ok(()) - }), - Node::Group { files, directories, license } => with_box(fmt, |f| { - render_tree_license(directories.iter().chain(files.iter()), Some(license), f) - }), - Node::File { name, license } => { - with_box(fmt, |f| render_tree_license(std::iter::once(name), Some(license), f)) - } - } - } -} - -/// Draw a series of sibling files/folders, as HTML, into the given formatter. -fn render_tree_license<'a>( - names: impl Iterator, - license: Option<&License>, - f: &mut std::fmt::Formatter<'_>, -) -> std::fmt::Result { - writeln!(f, "

    File/Directory: ")?; - for name in names { - writeln!(f, "{}", html_escape::encode_text(&name))?; - } - writeln!(f, "

    ")?; - - if let Some(license) = license { - writeln!(f, "

    License: {}

    ", html_escape::encode_text(&license.spdx))?; - for copyright in license.copyright.iter() { - writeln!(f, "

    Copyright: {}

    ", html_escape::encode_text(©right))?; - } - } - - Ok(()) -} - /// A License has an SPDX license name and a list of copyright holders. #[derive(serde::Deserialize)] struct License { diff --git a/src/tools/generate-copyright/templates/Node.html b/src/tools/generate-copyright/templates/Node.html new file mode 100644 index 0000000000000..a71a1bf3b73d7 --- /dev/null +++ b/src/tools/generate-copyright/templates/Node.html @@ -0,0 +1,71 @@ +{% match self %} + +{% when Node::Root { children } %} + +{% for child in children %} +{{ child|safe }} +{% endfor %} + +{% when Node::Directory { name, children, license } %} + +
    + +

    + File/Directory: {{ name }} +

    + + {% if let Some(license) = license %} + +

    License: {{ license.spdx }}

    + {% for copyright in license.copyright.iter() %} +

    Copyright: {{ copyright }}

    + {% endfor %} + + {% endif %} + + {% if !children.is_empty() %} + +

    Exceptions:

    + {% for child in children %} + {{ child|safe }} + {% endfor %} + + {% endif %} + +
    + +{% when Node::File { name, license } %} + +
    +

    + File/Directory: {{ name }} +

    + +

    License: {{ license.spdx }}

    + {% for copyright in license.copyright.iter() %} +

    Copyright: {{ copyright }}

    + {% endfor %} +
    + +{% when Node::Group { files, directories, license } %} + +
    + +

    + File/Directory: + {% for name in files %} + {{ name }} + {% endfor %} + {% for name in directories %} + {{ name }} + {% endfor %} +

    + +

    License: {{ license.spdx }}

    + {% for copyright in license.copyright.iter() %} +

    Copyright: {{ copyright }}

    + {% endfor %} + +
    + +{% endmatch %} From 5277b67b6977e3fcef64b0ce21cecd3a5dc9c22a Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Tue, 6 Aug 2024 11:02:11 +0100 Subject: [PATCH 487/489] generate-copyright: gather files inside interesting folders --- .../generate-copyright/src/cargo_metadata.rs | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs index d02b9eeb6f922..c85e4aa371a2a 100644 --- a/src/tools/generate-copyright/src/cargo_metadata.rs +++ b/src/tools/generate-copyright/src/cargo_metadata.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use std::ffi::OsStr; -use std::path::Path; +use std::path::{Path, PathBuf}; /// Describes how this module can fail #[derive(Debug, thiserror::Error)] @@ -15,6 +15,8 @@ pub enum Error { LaunchingVendor(std::io::Error), #[error("Failed to complete cargo vendor")] RunningVendor, + #[error("Bad path {0:?} whilst scraping files")] + Scraping(PathBuf), } /// Uniquely describes a package on crates.io @@ -150,24 +152,38 @@ fn load_important_files( let entry = entry?; let metadata = entry.metadata()?; let path = entry.path(); - if let Some(filename) = path.file_name() { - let lc_filename = filename.to_ascii_lowercase(); - let lc_filename_str = lc_filename.to_string_lossy(); - let mut keep = false; - for m in ["copyright", "licence", "license", "author", "notice"] { - if lc_filename_str.contains(m) { - keep = true; - break; - } + let Some(filename) = path.file_name() else { + return Err(Error::Scraping(path)); + }; + let lc_filename = filename.to_ascii_lowercase(); + let lc_filename_str = lc_filename.to_string_lossy(); + let mut keep = false; + for m in ["copyright", "licence", "license", "author", "notice"] { + if lc_filename_str.contains(m) { + keep = true; + break; } - if keep { - if metadata.is_dir() { - // scoop up whole directory - } else if metadata.is_file() { - let filename = filename.to_string_lossy(); - println!("Scraping {}", filename); - dep.notices.insert(filename.to_string(), std::fs::read_to_string(path)?); + } + if keep { + if metadata.is_dir() { + for inner_entry in std::fs::read_dir(entry.path())? { + let inner_entry = inner_entry?; + if inner_entry.metadata()?.is_file() { + let inner_filename = inner_entry.file_name(); + let inner_filename_str = inner_filename.to_string_lossy(); + let qualified_filename = + format!("{}/{}", lc_filename_str, inner_filename_str); + println!("Scraping {}", qualified_filename); + dep.notices.insert( + qualified_filename.to_string(), + std::fs::read_to_string(inner_entry.path())?, + ); + } } + } else if metadata.is_file() { + let filename = filename.to_string_lossy(); + println!("Scraping {}", filename); + dep.notices.insert(filename.to_string(), std::fs::read_to_string(path)?); } } } From 4e24e9b1adb8ffd57d7315028407922c44069f26 Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Tue, 6 Aug 2024 12:03:37 +0100 Subject: [PATCH 488/489] Update to rinja 0.3 --- Cargo.lock | 49 ++++--------------------- src/tools/generate-copyright/Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 54454e84b5a97..67fee5b3f059f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1407,7 +1407,7 @@ version = "0.1.0" dependencies = [ "anyhow", "cargo_metadata 0.18.1", - "rinja 0.2.0", + "rinja", "serde", "serde_json", "thiserror", @@ -3100,43 +3100,17 @@ dependencies = [ "walkdir", ] -[[package]] -name = "rinja" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d47a46d7729e891c8accf260e9daa02ae6d570aa2a94fb1fb27eb5364a2323" -dependencies = [ - "humansize", - "num-traits", - "percent-encoding", - "rinja_derive 0.2.0", -] - [[package]] name = "rinja" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d3762e3740cdbf2fd2be465cc2c26d643ad17353cc2e0223d211c1b096118bd" dependencies = [ + "humansize", "itoa", - "rinja_derive 0.3.0", -] - -[[package]] -name = "rinja_derive" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44dae9afe59d58ed8d988d67d1945f3638125d2fd2104058399382e11bd3ea2a" -dependencies = [ - "basic-toml", - "mime", - "mime_guess", - "once_map", - "proc-macro2", - "quote", - "rinja_parser 0.2.0", - "serde", - "syn 2.0.67", + "num-traits", + "percent-encoding", + "rinja_derive", ] [[package]] @@ -3152,20 +3126,11 @@ dependencies = [ "once_map", "proc-macro2", "quote", - "rinja_parser 0.3.0", + "rinja_parser", "serde", "syn 2.0.67", ] -[[package]] -name = "rinja_parser" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1771c78cd5d3b1646ef8d8f2ed100db936e8b291d3cc06e92a339ff346858c" -dependencies = [ - "nom", -] - [[package]] name = "rinja_parser" version = "0.3.0" @@ -4644,7 +4609,7 @@ dependencies = [ "minifier", "pulldown-cmark 0.9.6", "regex", - "rinja 0.3.0", + "rinja", "rustdoc-json-types", "serde", "serde_json", diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index d200e2ec9f1e1..404101abd41bf 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -9,7 +9,7 @@ description = "Produces a manifest of all the copyrighted materials in the Rust [dependencies] anyhow = "1.0.65" cargo_metadata = "0.18.1" -rinja = "0.2.0" +rinja = "0.3.0" serde = { version = "1.0.147", features = ["derive"] } serde_json = "1.0.85" thiserror = "1" From 99579f3ec1ee070d3d8203df1168f948b05b48dc Mon Sep 17 00:00:00 2001 From: Jonathan Pallant Date: Tue, 6 Aug 2024 12:12:57 +0100 Subject: [PATCH 489/489] Apparently library/std is now part of a workspace at library/ --- src/tools/generate-copyright/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/generate-copyright/src/main.rs b/src/tools/generate-copyright/src/main.rs index 37de24648d56d..afa75d0d67140 100644 --- a/src/tools/generate-copyright/src/main.rs +++ b/src/tools/generate-copyright/src/main.rs @@ -31,7 +31,7 @@ fn main() -> Result<(), Error> { let workspace_paths = [ Path::new("./Cargo.toml"), Path::new("./src/tools/cargo/Cargo.toml"), - Path::new("./library/std/Cargo.toml"), + Path::new("./library/Cargo.toml"), ]; let mut collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(&cargo, &out_dir, &root_path, &workspace_paths)?;