about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--compiler/rustc_ast/src/token.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs70
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs207
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs36
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs1
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs13
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp27
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp51
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs95
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs20
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs8
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs10
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs39
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs14
-rw-r--r--compiler/rustc_target/src/spec/mod.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/i386_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_linux_android.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs13
-rw-r--r--compiler/stable_mir/src/lib.rs4
-rw-r--r--compiler/stable_mir/src/mir/body.rs77
-rw-r--r--compiler/stable_mir/src/mir/pretty.rs209
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile59
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile2
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-llvm-16/script.sh (renamed from src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh)0
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile2
-rw-r--r--src/ci/github-actions/ci.yml7
-rw-r--r--src/tools/rust-analyzer/Cargo.lock304
-rw-r--r--src/tools/rust-analyzer/crates/base-db/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/fixture.rs28
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs189
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/cfg/src/lib.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs69
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs28
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs77
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/extend_selection.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/project_json.rs3
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs52
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs67
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_A.json140
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_B.json66
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt16
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs27
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs26
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/docs/user/manual.adoc2
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json5
-rw-r--r--src/tools/rust-analyzer/editors/code/src/client.ts3
-rw-r--r--src/tools/rust-analyzer/editors/code/src/lang_client.ts26
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/lib.rs169
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--tests/assembly/asm/loongarch-type.rs3
-rw-r--r--tests/assembly/x86-stack-probes.rs1
-rw-r--r--tests/codegen/issues/issue-101048.rs1
-rw-r--r--tests/codegen/issues/issue-101082.rs1
-rw-r--r--tests/codegen/issues/issue-101814.rs1
-rw-r--r--tests/codegen/issues/issue-103132.rs1
-rw-r--r--tests/codegen/issues/issue-103327.rs1
-rw-r--r--tests/codegen/issues/issue-103840.rs1
-rw-r--r--tests/codegen/issues/issue-75978.rs1
-rw-r--r--tests/codegen/issues/issue-99960.rs1
-rw-r--r--tests/codegen/sanitizer/kasan-emits-instrumentation.rs2
-rw-r--r--tests/codegen/slice-iter-fold.rs1
-rw-r--r--tests/codegen/stack-probes-call.rs24
-rw-r--r--tests/codegen/stack-probes-inline.rs2
-rw-r--r--tests/codegen/vec-in-place.rs1
-rw-r--r--tests/run-make/compressed-debuginfo/Makefile1
-rw-r--r--tests/run-make/pass-linker-flags-flavor/Makefile8
-rw-r--r--tests/run-make/pass-linker-flags-flavor/rs.rs1
-rw-r--r--tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs14
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.rs1
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.stderr10
-rw-r--r--tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr1
-rw-r--r--tests/ui/const_prop/apfloat-f64-roundtrip.rs1
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.32bit.stderr130
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.64bit.stderr130
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.rs15
-rw-r--r--tests/ui/consts/std/alloc.32bit.stderr25
-rw-r--r--tests/ui/consts/std/alloc.64bit.stderr25
-rw-r--r--tests/ui/consts/std/alloc.rs19
-rw-r--r--tests/ui/match/match-tail-expr-never-type-error.rs16
-rw-r--r--tests/ui/match/match-tail-expr-never-type-error.stderr21
-rw-r--r--tests/ui/numbers-arithmetic/issue-105626.rs1
-rw-r--r--tests/ui/pattern/pattern-bad-ref-box-order.fixed14
-rw-r--r--tests/ui/pattern/pattern-bad-ref-box-order.rs14
-rw-r--r--tests/ui/pattern/pattern-bad-ref-box-order.stderr8
-rw-r--r--tests/ui/sanitize/cfg-kasan.rs2
-rw-r--r--tests/ui/suggestions/range-index-instead-of-colon.rs7
-rw-r--r--tests/ui/suggestions/range-index-instead-of-colon.stderr13
-rw-r--r--triagebot.toml1
149 files changed, 2045 insertions, 1023 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5f659a1c306..a0d9eb8c452 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -56,7 +56,7 @@ jobs:
           - name: mingw-check-tidy
             os: ubuntu-20.04-4core-16gb
             env: {}
-          - name: x86_64-gnu-llvm-15
+          - name: x86_64-gnu-llvm-16
             env:
               ENABLE_GCC_CODEGEN: "1"
             os: ubuntu-20.04-16core-64gb
@@ -302,10 +302,6 @@ jobs:
             env:
               RUST_BACKTRACE: 1
             os: ubuntu-20.04-8core-32gb
-          - name: x86_64-gnu-llvm-15
-            env:
-              RUST_BACKTRACE: 1
-            os: ubuntu-20.04-8core-32gb
           - name: x86_64-gnu-nopt
             os: ubuntu-20.04-4core-16gb
             env: {}
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 3189fcf7ff9..a7c6f8c5d8c 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -756,6 +756,11 @@ impl Token {
         )
     }
 
+    /// Returns `true` if the token is the integer literal.
+    pub fn is_integer_lit(&self) -> bool {
+        matches!(self.kind, Literal(Lit { kind: LitKind::Integer, .. }))
+    }
+
     /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
     pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
         match self.ident() {
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index e6c5085cc0e..92a8c00510b 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -134,18 +134,6 @@ pub unsafe fn create_module<'ll>(
 
     let mut target_data_layout = sess.target.data_layout.to_string();
     let llvm_version = llvm_util::get_version();
-    if llvm_version < (16, 0, 0) {
-        if sess.target.arch == "s390x" {
-            // LLVM 16 data layout changed to always set 64-bit vector alignment,
-            // which is conditional in earlier LLVM versions.
-            // https://reviews.llvm.org/D131158 for the discussion.
-            target_data_layout = target_data_layout.replace("-v128:64", "");
-        } else if sess.target.arch == "riscv64" {
-            // LLVM 16 introduced this change so as to produce more efficient code.
-            // See https://reviews.llvm.org/D116735 for the discussion.
-            target_data_layout = target_data_layout.replace("-n32:64-", "-n64-");
-        }
-    }
     if llvm_version < (17, 0, 0) {
         if sess.target.arch.starts_with("powerpc") {
             // LLVM 17 specifies function pointer alignment for ppc:
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index ac13d61229e..be895417bbe 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -44,7 +44,7 @@ use tempfile::Builder as TempFileBuilder;
 use itertools::Itertools;
 use std::cell::OnceCell;
 use std::collections::BTreeSet;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::fs::{read, File, OpenOptions};
 use std::io::{BufWriter, Write};
 use std::ops::Deref;
@@ -2527,7 +2527,7 @@ fn add_native_libs_from_crate(
             NativeLibKind::WasmImportModule => {}
             NativeLibKind::LinkArg => {
                 if link_static {
-                    cmd.arg(name);
+                    cmd.linker_arg(OsStr::new(name), verbatim);
                 }
             }
         }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 4dd688c2234..f65afd99e39 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -196,6 +196,14 @@ pub trait Linker {
     fn add_no_exec(&mut self) {}
     fn add_as_needed(&mut self) {}
     fn reset_per_library_state(&mut self) {}
+    fn linker_arg(&mut self, arg: &OsStr, verbatim: bool) {
+        self.linker_args(&[arg], verbatim);
+    }
+    fn linker_args(&mut self, args: &[&OsStr], _verbatim: bool) {
+        args.into_iter().for_each(|a| {
+            self.cmd().arg(a);
+        });
+    }
 }
 
 impl dyn Linker + '_ {
@@ -223,38 +231,12 @@ pub struct GccLinker<'a> {
 }
 
 impl<'a> GccLinker<'a> {
-    /// Passes an argument directly to the linker.
-    ///
-    /// When the linker is not ld-like such as when using a compiler as a linker, the argument is
-    /// prepended by `-Wl,`.
-    fn linker_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
-        self.linker_args(&[arg]);
-        self
+    fn linker_arg(&mut self, arg: impl AsRef<OsStr>) {
+        Linker::linker_arg(self, arg.as_ref(), false);
     }
-
-    /// Passes a series of arguments directly to the linker.
-    ///
-    /// When the linker is ld-like, the arguments are simply appended to the command. When the
-    /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
-    /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
-    /// single argument is appended to the command to ensure that the order of the arguments is
-    /// preserved by the compiler.
-    fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) -> &mut Self {
-        if self.is_ld {
-            args.into_iter().for_each(|a| {
-                self.cmd.arg(a);
-            });
-        } else {
-            if !args.is_empty() {
-                let mut s = OsString::from("-Wl");
-                for a in args {
-                    s.push(",");
-                    s.push(a);
-                }
-                self.cmd.arg(s);
-            }
-        }
-        self
+    fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) {
+        let args_vec: Vec<&OsStr> = args.iter().map(|x| x.as_ref()).collect();
+        Linker::linker_args(self, &args_vec, false);
     }
 
     fn takes_hints(&self) -> bool {
@@ -361,6 +343,30 @@ impl<'a> GccLinker<'a> {
 }
 
 impl<'a> Linker for GccLinker<'a> {
+    /// Passes a series of arguments directly to the linker.
+    ///
+    /// When the linker is ld-like, the arguments are simply appended to the command. When the
+    /// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
+    /// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
+    /// single argument is appended to the command to ensure that the order of the arguments is
+    /// preserved by the compiler.
+    fn linker_args(&mut self, args: &[&OsStr], verbatim: bool) {
+        if self.is_ld || verbatim {
+            args.into_iter().for_each(|a| {
+                self.cmd.arg(a);
+            });
+        } else {
+            if !args.is_empty() {
+                let mut s = OsString::from("-Wl");
+                for a in args {
+                    s.push(",");
+                    s.push(a);
+                }
+                self.cmd.arg(s);
+            }
+        }
+    }
+
     fn cmd(&mut self) -> &mut Command {
         &mut self.cmd
     }
@@ -531,7 +537,7 @@ impl<'a> Linker for GccLinker<'a> {
             self.linker_arg("-force_load");
             self.linker_arg(&lib);
         } else {
-            self.linker_arg("--whole-archive").cmd.arg(lib);
+            self.linker_args(&[OsString::from("--whole-archive"), lib.into()]);
             self.linker_arg("--no-whole-archive");
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 94b182e09f6..b9a4806e6c2 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -26,12 +26,13 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{walk_generics, Visitor as _};
 use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
-use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{
-    self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt,
+    self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Ty, TyCtxt,
+    TypeVisitableExt,
 };
 use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
 use rustc_span::edit_distance::find_best_match_for_name;
@@ -39,8 +40,7 @@ use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, BytePos, Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use rustc_trait_selection::traits::wf::object_region_bounds;
-use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt};
-use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+use rustc_trait_selection::traits::{self, ObligationCtxt};
 
 use std::fmt::Display;
 use std::slice;
@@ -1606,133 +1606,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors
         // when inside of an ADT (#108491) or where clause.
         let param_env = tcx.param_env(block.owner);
-        let cause = ObligationCause::misc(span, block.owner.def_id);
 
-        let mut fulfillment_errors = Vec::new();
-        let mut applicable_candidates: Vec<_> = infcx.probe(|_| {
-            // Regions are not considered during selection.
-            let self_ty = self_ty
-                .fold_with(&mut BoundVarEraser { tcx, universe: infcx.create_next_universe() });
-
-            struct BoundVarEraser<'tcx> {
-                tcx: TyCtxt<'tcx>,
-                universe: ty::UniverseIndex,
-            }
-
-            // FIXME(non_lifetime_binders): Don't assign the same universe to each placeholder.
-            impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarEraser<'tcx> {
-                fn interner(&self) -> TyCtxt<'tcx> {
-                    self.tcx
-                }
+        let mut universes = if self_ty.has_escaping_bound_vars() {
+            vec![None; self_ty.outer_exclusive_binder().as_usize()]
+        } else {
+            vec![]
+        };
 
-                fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-                    // FIXME(@lcnr): This is broken, erasing bound regions
-                    // impacts selection as it results in different types.
-                    if r.is_bound() { self.tcx.lifetimes.re_erased } else { r }
-                }
+        let (impl_, (assoc_item, def_scope)) =
+            crate::traits::project::with_replaced_escaping_bound_vars(
+                infcx,
+                &mut universes,
+                self_ty,
+                |self_ty| {
+                    self.select_inherent_assoc_type_candidates(
+                        infcx, name, span, self_ty, param_env, candidates,
+                    )
+                },
+            )?;
+
+        self.check_assoc_ty(assoc_item, name, def_scope, block, span);
+
+        // FIXME(fmease): Currently creating throwaway `parent_args` to please
+        // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
+        // not require the parent args logic.
+        let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
+        let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
+        let args = tcx.mk_args_from_iter(
+            std::iter::once(ty::GenericArg::from(self_ty))
+                .chain(args.into_iter().skip(parent_args.len())),
+        );
 
-                fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                    match *ty.kind() {
-                        ty::Bound(_, bv) => Ty::new_placeholder(
-                            self.tcx,
-                            ty::PlaceholderType { universe: self.universe, bound: bv },
-                        ),
-                        _ => ty.super_fold_with(self),
-                    }
-                }
+        let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
 
-                fn fold_const(
-                    &mut self,
-                    ct: ty::Const<'tcx>,
-                ) -> <TyCtxt<'tcx> as rustc_type_ir::Interner>::Const {
-                    assert!(!ct.ty().has_escaping_bound_vars());
-
-                    match ct.kind() {
-                        ty::ConstKind::Bound(_, bv) => ty::Const::new_placeholder(
-                            self.tcx,
-                            ty::PlaceholderConst { universe: self.universe, bound: bv },
-                            ct.ty(),
-                        ),
-                        _ => ct.super_fold_with(self),
-                    }
-                }
-            }
+        Ok(Some((ty, assoc_item)))
+    }
 
-            let InferOk { value: self_ty, obligations } =
-                infcx.at(&cause, param_env).normalize(self_ty);
+    fn select_inherent_assoc_type_candidates(
+        &self,
+        infcx: &InferCtxt<'tcx>,
+        name: Ident,
+        span: Span,
+        self_ty: Ty<'tcx>,
+        param_env: ParamEnv<'tcx>,
+        candidates: Vec<(DefId, (DefId, DefId))>,
+    ) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> {
+        let tcx = self.tcx();
+        let mut fulfillment_errors = Vec::new();
 
-            candidates
-                .iter()
-                .copied()
-                .filter(|&(impl_, _)| {
-                    infcx.probe(|_| {
-                        let ocx = ObligationCtxt::new(infcx);
-                        ocx.register_obligations(obligations.clone());
-
-                        let impl_args = infcx.fresh_args_for_item(span, impl_);
-                        let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
-                        let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
-
-                        // Check that the self types can be related.
-                        if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
-                            return false;
-                        }
+        let applicable_candidates: Vec<_> = candidates
+            .iter()
+            .copied()
+            .filter(|&(impl_, _)| {
+                infcx.probe(|_| {
+                    let ocx = ObligationCtxt::new(infcx);
+                    let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty);
+
+                    let impl_args = infcx.fresh_args_for_item(span, impl_);
+                    let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args);
+                    let impl_ty = ocx.normalize(&ObligationCause::dummy(), param_env, impl_ty);
+
+                    // Check that the self types can be related.
+                    if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
+                        return false;
+                    }
 
-                        // Check whether the impl imposes obligations we have to worry about.
-                        let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
-                        let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds);
-                        let impl_obligations = traits::predicates_for_generics(
-                            |_, _| cause.clone(),
-                            param_env,
-                            impl_bounds,
-                        );
-                        ocx.register_obligations(impl_obligations);
+                    // Check whether the impl imposes obligations we have to worry about.
+                    let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args);
+                    let impl_bounds =
+                        ocx.normalize(&ObligationCause::dummy(), param_env, impl_bounds);
+                    let impl_obligations = traits::predicates_for_generics(
+                        |_, _| ObligationCause::dummy(),
+                        param_env,
+                        impl_bounds,
+                    );
+                    ocx.register_obligations(impl_obligations);
 
-                        let mut errors = ocx.select_where_possible();
-                        if !errors.is_empty() {
-                            fulfillment_errors.append(&mut errors);
-                            return false;
-                        }
+                    let mut errors = ocx.select_where_possible();
+                    if !errors.is_empty() {
+                        fulfillment_errors.append(&mut errors);
+                        return false;
+                    }
 
-                        true
-                    })
+                    true
                 })
-                .collect()
-        });
+            })
+            .collect();
 
-        if applicable_candidates.len() > 1 {
-            return Err(self.complain_about_ambiguous_inherent_assoc_type(
+        match &applicable_candidates[..] {
+            &[] => Err(self.complain_about_inherent_assoc_type_not_found(
                 name,
-                applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
+                self_ty,
+                candidates,
+                fulfillment_errors,
                 span,
-            ));
-        }
+            )),
 
-        if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() {
-            self.check_assoc_ty(assoc_item, name, def_scope, block, span);
-
-            // FIXME(fmease): Currently creating throwaway `parent_args` to please
-            // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to
-            // not require the parent args logic.
-            let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_);
-            let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args);
-            let args = tcx.mk_args_from_iter(
-                std::iter::once(ty::GenericArg::from(self_ty))
-                    .chain(args.into_iter().skip(parent_args.len())),
-            );
-
-            let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args));
+            &[applicable_candidate] => Ok(applicable_candidate),
 
-            return Ok(Some((ty, assoc_item)));
+            &[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_type(
+                name,
+                applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(),
+                span,
+            )),
         }
-
-        Err(self.complain_about_inherent_assoc_type_not_found(
-            name,
-            self_ty,
-            candidates,
-            fulfillment_errors,
-            span,
-        ))
     }
 
     fn lookup_assoc_ty(
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index a29d9c95e5e..e7cbbc71335 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -139,7 +139,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &cause,
                 Some(arm.body),
                 arm_ty,
-                |err| self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm),
+                |err| {
+                    self.explain_never_type_coerced_to_unit(err, arm, arm_ty, prior_arm, expr);
+                },
                 false,
             );
 
@@ -177,6 +179,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         coercion.complete(self)
     }
 
+    fn explain_never_type_coerced_to_unit(
+        &self,
+        err: &mut Diagnostic,
+        arm: &hir::Arm<'tcx>,
+        arm_ty: Ty<'tcx>,
+        prior_arm: Option<(Option<hir::HirId>, Ty<'tcx>, Span)>,
+        expr: &hir::Expr<'tcx>,
+    ) {
+        if let hir::ExprKind::Block(block, _) = arm.body.kind
+            && let Some(expr) = block.expr
+            && let arm_tail_ty = self.node_ty(expr.hir_id)
+            && arm_tail_ty.is_never()
+            && !arm_ty.is_never()
+        {
+            err.span_label(
+                expr.span,
+                format!(
+                    "this expression is of type `!`, but it is coerced to `{arm_ty}` due to its \
+                     surrounding expression",
+                ),
+            );
+            self.suggest_mismatched_types_on_tail(
+                err,
+                expr,
+                arm_ty,
+                prior_arm.map_or(arm_tail_ty, |(_, ty, _)| ty),
+                expr.hir_id,
+            );
+        }
+        self.suggest_removing_semicolon_for_coerce(err, expr, arm_ty, prior_arm)
+    }
+
     fn suggest_removing_semicolon_for_coerce(
         &self,
         diag: &mut Diagnostic,
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index ae2a4a9504c..587038d57bd 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1715,6 +1715,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         // label pointing out the cause for the type coercion will be wrong
         // as prior return coercions would not be relevant (#57664).
         let fn_decl = if let (Some(expr), Some(blk_id)) = (expression, blk_id) {
+            fcx.suggest_missing_semicolon(&mut err, expr, expected, false);
             let pointing_at_return_type =
                 fcx.suggest_mismatched_types_on_tail(&mut err, expr, expected, found, blk_id);
             if let (Some(cond_expr), true, false) = (
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f16269795e9..7f15478349e 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -663,8 +663,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     coerce.coerce_forced_unit(
                         self,
                         &cause,
-                        |err| {
-                            self.suggest_mismatched_types_on_tail(err, expr, ty, e_ty, target_id);
+                        |mut err| {
+                            self.suggest_missing_semicolon(&mut err, expr, e_ty, false);
+                            self.suggest_mismatched_types_on_tail(
+                                &mut err, expr, ty, e_ty, target_id,
+                            );
                             let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
                             self.annotate_loop_expected_due_to_inference(err, expr, error);
                             if let Some(val) = ty_kind_suggestion(ty) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 6660bea03d8..c74ef8f2713 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -72,7 +72,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         blk_id: hir::HirId,
     ) -> bool {
         let expr = expr.peel_drop_temps();
-        self.suggest_missing_semicolon(err, expr, expected, false);
         let mut pointing_at_return_type = false;
         if let hir::ExprKind::Break(..) = expr.kind {
             // `break` type mismatches provide better context for tail `loop` expressions.
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index 32966011932..b3cfd843ace 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -101,12 +101,19 @@ pub fn report_object_safety_error<'tcx>(
          to be resolvable dynamically; for more information visit \
          <https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
     );
+
+    // Only provide the help if its a local trait, otherwise it's not actionable.
     if trait_span.is_some() {
         let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
         reported_violations.sort();
-        for violation in reported_violations {
-            // Only provide the help if its a local trait, otherwise it's not actionable.
-            violation.solution(&mut err);
+
+        let mut potential_solutions: Vec<_> =
+            reported_violations.into_iter().map(|violation| violation.solution()).collect();
+        potential_solutions.sort();
+        // Allows us to skip suggesting that the same item should be moved to another trait multiple times.
+        potential_solutions.dedup();
+        for solution in potential_solutions {
+            solution.add_to(&mut err);
         }
     }
 
diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
index 142384e6d0c..ad97ede8e9c 100644
--- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
+++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
@@ -42,11 +42,7 @@
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/Linker/Linker.h"
 
-#if LLVM_VERSION_GE(16, 0)
 #include "llvm/TargetParser/Triple.h"
-#else
-#include "llvm/ADT/Triple.h"
-#endif
 
 extern "C" void LLVMRustSetLastError(const char *);
 
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index d2cd79b456a..7f033265136 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -204,11 +204,7 @@ enum class LLVMRustCodeModel {
   None,
 };
 
-#if LLVM_VERSION_LT(16, 0)
-static Optional<CodeModel::Model>
-#else
 static std::optional<CodeModel::Model>
-#endif
 fromRust(LLVMRustCodeModel Model) {
   switch (Model) {
   case LLVMRustCodeModel::Tiny:
@@ -222,11 +218,7 @@ fromRust(LLVMRustCodeModel Model) {
   case LLVMRustCodeModel::Large:
     return CodeModel::Large;
   case LLVMRustCodeModel::None:
-#if LLVM_VERSION_LT(16, 0)
-    return None;
-#else
     return std::nullopt;
-#endif
   default:
     report_fatal_error("Bad CodeModel.");
   }
@@ -452,7 +444,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
   if (OutputObjFile) {
       Options.ObjectFilenameForDebug = OutputObjFile;
   }
-#if LLVM_VERSION_GE(16, 0)
   if (!strcmp("zlib", DebugInfoCompression) && llvm::compression::zlib::isAvailable()) {
     Options.CompressDebugSections = DebugCompressionType::Zlib;
   } else if (!strcmp("zstd", DebugInfoCompression) && llvm::compression::zstd::isAvailable()) {
@@ -460,7 +451,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
   } else if (!strcmp("none", DebugInfoCompression)) {
     Options.CompressDebugSections = DebugCompressionType::None;
   }
-#endif
 
   Options.RelaxELFRelocations = RelaxELFRelocations;
   Options.UseInitArray = UseInitArray;
@@ -734,22 +724,14 @@ LLVMRustOptimize(
   bool DebugPassManager = false;
 
   PassInstrumentationCallbacks PIC;
-#if LLVM_VERSION_LT(16, 0)
-  StandardInstrumentations SI(DebugPassManager);
-#else
   StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
-#endif
   SI.registerCallbacks(PIC);
 
   if (LlvmSelfProfiler){
     LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
   }
 
-#if LLVM_VERSION_LT(16, 0)
-  Optional<PGOOptions> PGOOpt;
-#else
   std::optional<PGOOptions> PGOOpt;
-#endif
 #if LLVM_VERSION_GE(17, 0)
   auto FS = vfs::getRealFileSystem();
 #endif
@@ -882,12 +864,7 @@ LLVMRustOptimize(
           /*EagerChecks=*/true);
       OptimizerLastEPCallbacks.push_back(
         [Options](ModulePassManager &MPM, OptimizationLevel Level) {
-#if LLVM_VERSION_LT(16, 0)
-          MPM.addPass(ModuleMemorySanitizerPass(Options));
-          MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
-#else
           MPM.addPass(MemorySanitizerPass(Options));
-#endif
         }
       );
     }
@@ -912,11 +889,7 @@ LLVMRustOptimize(
             /*UseAfterScope=*/true,
             AsanDetectStackUseAfterReturnMode::Runtime,
           };
-#if LLVM_VERSION_LT(16, 0)
-          MPM.addPass(ModuleAddressSanitizerPass(opts));
-#else
           MPM.addPass(AddressSanitizerPass(opts));
-#endif
         }
       );
     }
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 7ada2eff593..bf870e28acd 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -14,18 +14,13 @@
 #include "llvm/Remarks/RemarkSerializer.h"
 #include "llvm/Remarks/RemarkFormat.h"
 #include "llvm/Support/ToolOutputFile.h"
-#if LLVM_VERSION_GE(16, 0)
 #include "llvm/Support/ModRef.h"
-#endif
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/COFFImportFile.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Pass.h"
 #include "llvm/Bitcode/BitcodeWriter.h"
 #include "llvm/Support/Signals.h"
-#if LLVM_VERSION_LT(16, 0)
-#include "llvm/ADT/Optional.h"
-#endif
 
 #include <iostream>
 
@@ -347,13 +342,7 @@ extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Asy
 }
 
 extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) {
-  return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg,
-#if LLVM_VERSION_LT(16, 0)
-                                              None
-#else
-                                              std::nullopt
-#endif
-                                              ));
+  return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, std::nullopt));
 }
 
 // These values **must** match ffi::AllocKindFlags.
@@ -416,7 +405,6 @@ enum class LLVMRustMemoryEffects {
 
 extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C,
                                                             LLVMRustMemoryEffects Effects) {
-#if LLVM_VERSION_GE(16, 0)
   switch (Effects) {
     case LLVMRustMemoryEffects::None:
       return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none()));
@@ -428,18 +416,6 @@ extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C,
     default:
       report_fatal_error("bad MemoryEffects.");
   }
-#else
-  switch (Effects) {
-    case LLVMRustMemoryEffects::None:
-      return wrap(Attribute::get(*unwrap(C), Attribute::ReadNone));
-    case LLVMRustMemoryEffects::ReadOnly:
-      return wrap(Attribute::get(*unwrap(C), Attribute::ReadOnly));
-    case LLVMRustMemoryEffects::InaccessibleMemOnly:
-      return wrap(Attribute::get(*unwrap(C), Attribute::InaccessibleMemOnly));
-    default:
-      report_fatal_error("bad MemoryEffects.");
-  }
-#endif
 }
 
 // Enable a fast-math flag
@@ -726,18 +702,10 @@ enum class LLVMRustChecksumKind {
   SHA256,
 };
 
-#if LLVM_VERSION_LT(16, 0)
-static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
-#else
 static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
-#endif
   switch (Kind) {
   case LLVMRustChecksumKind::None:
-#if LLVM_VERSION_LT(16, 0)
-    return None;
-#else
     return std::nullopt;
-#endif
   case LLVMRustChecksumKind::MD5:
     return DIFile::ChecksumKind::CSK_MD5;
   case LLVMRustChecksumKind::SHA1:
@@ -810,17 +778,8 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
     const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
     const char *Checksum, size_t ChecksumLen) {
 
-#if LLVM_VERSION_LT(16, 0)
-  Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
-#else
   std::optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
-#endif
-
-#if LLVM_VERSION_LT(16, 0)
-  Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
-#else
   std::optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
-#endif
   if (llvmCSKind)
     CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
   return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
@@ -2053,17 +2012,9 @@ extern "C" bool LLVMRustIsNonGVFunctionPointerTy(LLVMValueRef V) {
 }
 
 extern "C" bool LLVMRustLLVMHasZlibCompressionForDebugSymbols() {
-#if LLVM_VERSION_GE(16, 0)
   return llvm::compression::zlib::isAvailable();
-#else
-  return false;
-#endif
 }
 
 extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() {
-#if LLVM_VERSION_GE(16, 0)
   return llvm::compression::zstd::isAvailable();
-#else
-  return false;
-#endif
 }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 853eea1a609..5d0187a8598 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -832,50 +832,31 @@ impl ObjectSafetyViolation {
         }
     }
 
-    pub fn solution(&self, err: &mut Diagnostic) {
+    pub fn solution(&self) -> ObjectSafetyViolationSolution {
         match self {
             ObjectSafetyViolation::SizedSelf(_)
             | ObjectSafetyViolation::SupertraitSelf(_)
-            | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {}
+            | ObjectSafetyViolation::SupertraitNonLifetimeBinder(..) => {
+                ObjectSafetyViolationSolution::None
+            }
             ObjectSafetyViolation::Method(
                 name,
                 MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
                 _,
-            ) => {
-                err.span_suggestion(
-                    add_self_sugg.1,
-                    format!(
-                        "consider turning `{name}` into a method by giving it a `&self` argument"
-                    ),
-                    add_self_sugg.0.to_string(),
-                    Applicability::MaybeIncorrect,
-                );
-                err.span_suggestion(
-                    make_sized_sugg.1,
-                    format!(
-                        "alternatively, consider constraining `{name}` so it does not apply to \
-                             trait objects"
-                    ),
-                    make_sized_sugg.0.to_string(),
-                    Applicability::MaybeIncorrect,
-                );
-            }
+            ) => ObjectSafetyViolationSolution::AddSelfOrMakeSized {
+                name: *name,
+                add_self_sugg: add_self_sugg.clone(),
+                make_sized_sugg: make_sized_sugg.clone(),
+            },
             ObjectSafetyViolation::Method(
                 name,
                 MethodViolationCode::UndispatchableReceiver(Some(span)),
                 _,
-            ) => {
-                err.span_suggestion(
-                    *span,
-                    format!("consider changing method `{name}`'s `self` parameter to be `&self`"),
-                    "&Self",
-                    Applicability::MachineApplicable,
-                );
-            }
+            ) => ObjectSafetyViolationSolution::ChangeToRefSelf(*name, *span),
             ObjectSafetyViolation::AssocConst(name, _)
             | ObjectSafetyViolation::GAT(name, _)
             | ObjectSafetyViolation::Method(name, ..) => {
-                err.help(format!("consider moving `{name}` to another trait"));
+                ObjectSafetyViolationSolution::MoveToAnotherTrait(*name)
             }
         }
     }
@@ -899,6 +880,60 @@ impl ObjectSafetyViolation {
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum ObjectSafetyViolationSolution {
+    None,
+    AddSelfOrMakeSized {
+        name: Symbol,
+        add_self_sugg: (String, Span),
+        make_sized_sugg: (String, Span),
+    },
+    ChangeToRefSelf(Symbol, Span),
+    MoveToAnotherTrait(Symbol),
+}
+
+impl ObjectSafetyViolationSolution {
+    pub fn add_to(self, err: &mut Diagnostic) {
+        match self {
+            ObjectSafetyViolationSolution::None => {}
+            ObjectSafetyViolationSolution::AddSelfOrMakeSized {
+                name,
+                add_self_sugg,
+                make_sized_sugg,
+            } => {
+                err.span_suggestion(
+                    add_self_sugg.1,
+                    format!(
+                        "consider turning `{name}` into a method by giving it a `&self` argument"
+                    ),
+                    add_self_sugg.0,
+                    Applicability::MaybeIncorrect,
+                );
+                err.span_suggestion(
+                    make_sized_sugg.1,
+                    format!(
+                        "alternatively, consider constraining `{name}` so it does not apply to \
+                             trait objects"
+                    ),
+                    make_sized_sugg.0,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            ObjectSafetyViolationSolution::ChangeToRefSelf(name, span) => {
+                err.span_suggestion(
+                    span,
+                    format!("consider changing method `{name}`'s `self` parameter to be `&self`"),
+                    "&Self",
+                    Applicability::MachineApplicable,
+                );
+            }
+            ObjectSafetyViolationSolution::MoveToAnotherTrait(name) => {
+                err.help(format!("consider moving `{name}` to another trait"));
+            }
+        }
+    }
+}
+
 /// Reasons a method might not be object-safe.
 #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
 pub enum MethodViolationCode {
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 2bde339ec77..d50743bc207 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -283,7 +283,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     /// from at least one local module, and returns `true`. If the crate defining `def_id` is
     /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
     fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
-        if NO_VISIBLE_PATH.with(|flag| flag.get()) {
+        if with_no_visible_paths() {
             return Ok(false);
         }
 
@@ -367,7 +367,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
     /// Try to see if this path can be trimmed to a unique symbol name.
     fn try_print_trimmed_def_path(&mut self, def_id: DefId) -> Result<bool, PrintError> {
-        if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+        if with_forced_trimmed_paths() {
             let trimmed = self.force_print_trimmed_def_path(def_id)?;
             if trimmed {
                 return Ok(true);
@@ -375,8 +375,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         }
         if !self.tcx().sess.opts.unstable_opts.trim_diagnostic_paths
             || matches!(self.tcx().sess.opts.trimmed_def_paths, TrimmedDefPaths::Never)
-            || NO_TRIMMED_PATH.with(|flag| flag.get())
-            || SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get())
+            || with_no_trimmed_paths()
+            || with_crate_prefix()
         {
             return Ok(false);
         }
@@ -861,7 +861,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                             p!("@", print_def_path(did.to_def_id(), args));
                         } else {
                             let span = self.tcx().def_span(did);
-                            let preference = if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+                            let preference = if with_forced_trimmed_paths() {
                                 FileNameDisplayPreference::Short
                             } else {
                                 FileNameDisplayPreference::Remapped
@@ -1102,7 +1102,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
             write!(self, "Sized")?;
         }
 
-        if !FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+        if !with_forced_trimmed_paths() {
             for re in lifetimes {
                 write!(self, " + ")?;
                 self.print_region(re)?;
@@ -1886,7 +1886,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
             // available, and filename/line-number is mostly uninteresting.
             let use_types = !def_id.is_local() || {
                 // Otherwise, use filename/line-number if forced.
-                let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
+                let force_no_types = with_forced_impl_filename_line();
                 !force_no_types
             };
 
@@ -1951,7 +1951,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
         if cnum == LOCAL_CRATE {
             if self.tcx.sess.at_least_rust_2018() {
                 // We add the `crate::` keyword on Rust 2018, only when desired.
-                if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
+                if with_crate_prefix() {
                     write!(self, "{}", kw::Crate)?;
                     self.empty_path = false;
                 }
@@ -2154,7 +2154,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
             return true;
         }
 
-        if FORCE_TRIMMED_PATH.with(|flag| flag.get()) {
+        if with_forced_trimmed_paths() {
             return false;
         }
 
@@ -2437,7 +2437,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
         } else {
             let tcx = self.tcx;
 
-            let trim_path = FORCE_TRIMMED_PATH.with(|flag| flag.get());
+            let trim_path = with_forced_trimmed_paths();
             // Closure used in `RegionFolder` to create names for anonymous late-bound
             // regions. We use two `DebruijnIndex`es (one for the currently folded
             // late-bound region and the other for the binder level) to determine
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 49a2c414467..83bbfeb2805 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -721,6 +721,9 @@ parse_sugg_wrap_pattern_in_parens = wrap the pattern in parentheses
 parse_switch_mut_let_order =
     switch the order of `mut` and `let`
 
+parse_switch_ref_box_order = switch the order of `ref` and `box`
+    .suggestion = swap them
+
 parse_ternary_operator = Rust has no ternary operator
     .help = use an `if-else` expression instead
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 7ce348619c6..0a919240ce5 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -138,6 +138,14 @@ pub(crate) enum InvalidVariableDeclarationSub {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_switch_ref_box_order)]
+pub(crate) struct SwitchRefBoxOrder {
+    #[primary_span]
+    #[suggestion(applicability = "machine-applicable", code = "box ref")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_invalid_comparison_operator)]
 pub(crate) struct InvalidComparisonOperator {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 15491cac56a..8f5f4459d64 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -5,8 +5,8 @@ use crate::errors::{
     ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax,
     InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
     PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern,
-    TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed,
-    UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
+    SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
+    TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedVertVertBeforeFunctionParam,
     UnexpectedVertVertInPattern,
 };
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
@@ -374,6 +374,12 @@ impl<'a> Parser<'a> {
         } else if self.eat_keyword(kw::Mut) {
             self.parse_pat_ident_mut(syntax_loc)?
         } else if self.eat_keyword(kw::Ref) {
+            if self.check_keyword(kw::Box) {
+                // Suggest `box ref` and quit parsing pattern to prevent series of
+                // misguided diagnostics from later stages of the compiler.
+                let span = self.prev_token.span.to(self.token.span);
+                return Err(self.sess.create_err(SwitchRefBoxOrder { span }));
+            }
             // Parse ref ident @ pat / ref mut ident @ pat
             let mutbl = self.parse_mutability();
             self.parse_pat_ident(BindingAnnotation(ByRef::Yes, mutbl), syntax_loc)?
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 5316dde6096..620ba4a3cb3 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -567,20 +567,37 @@ impl<'a> Parser<'a> {
                         snapshot.recover_diff_marker();
                     }
                     if self.token == token::Colon {
-                        // if next token is following a colon, it's likely a path
-                        // and we can suggest a path separator
-                        self.bump();
-                        if self.token.span.lo() == self.prev_token.span.hi() {
+                        // if a previous and next token of the current one is
+                        // integer literal (e.g. `1:42`), it's likely a range
+                        // expression for Pythonistas and we can suggest so.
+                        if self.prev_token.is_integer_lit()
+                            && self.may_recover()
+                            && self.look_ahead(1, |token| token.is_integer_lit())
+                        {
+                            // FIXME(hkmatsumoto): Might be better to trigger
+                            // this only when parsing an index expression.
                             err.span_suggestion_verbose(
-                                self.prev_token.span,
-                                "maybe write a path separator here",
-                                "::",
+                                self.token.span,
+                                "you might have meant a range expression",
+                                "..",
                                 Applicability::MaybeIncorrect,
                             );
-                        }
-                        if self.sess.unstable_features.is_nightly_build() {
-                            // FIXME(Nilstrieb): Remove this again after a few months.
-                            err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
+                        } else {
+                            // if next token is following a colon, it's likely a path
+                            // and we can suggest a path separator
+                            self.bump();
+                            if self.token.span.lo() == self.prev_token.span.hi() {
+                                err.span_suggestion_verbose(
+                                    self.prev_token.span,
+                                    "maybe write a path separator here",
+                                    "::",
+                                    Applicability::MaybeIncorrect,
+                                );
+                            }
+                            if self.sess.unstable_features.is_nightly_build() {
+                                // FIXME(Nilstrieb): Remove this again after a few months.
+                                err.note("type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728>");
+                            }
                         }
                     }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index 62a26bc089a..e9b835f90db 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -578,13 +578,13 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
             }
             mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
                 discr: discr.stable(tables),
-                targets: targets
-                    .iter()
-                    .map(|(value, target)| stable_mir::mir::SwitchTarget {
-                        value,
-                        target: target.as_usize(),
-                    })
-                    .collect(),
+                targets: {
+                    let (value_vec, mut target_vec): (Vec<_>, Vec<_>) =
+                        targets.iter().map(|(value, target)| (value, target.as_usize())).unzip();
+                    // We need to push otherwise as last element to ensure it's same as in MIR.
+                    target_vec.push(targets.otherwise().as_usize());
+                    stable_mir::mir::SwitchTargets { value: value_vec, targets: target_vec }
+                },
                 otherwise: targets.otherwise().as_usize(),
             },
             mir::TerminatorKind::UnwindResume => TerminatorKind::Resume,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 9b0fedba092..dbce2f30f93 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1155,10 +1155,6 @@ pub enum StackProbeType {
 }
 
 impl StackProbeType {
-    // LLVM X86 targets (ix86 and x86_64) can use inline-asm stack probes starting with LLVM 16.
-    // Notable past issues were rust#83139 (fixed in 14) and rust#84667 (fixed in 16).
-    const X86: Self = Self::InlineOrCall { min_llvm_version_for_inline: (16, 0, 0) };
-
     fn from_json(json: &Json) -> Result<Self, String> {
         let object = json.as_object().ok_or_else(|| "expected a JSON object")?;
         let kind = object
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
index 88fa6d5a762..63a8144f69f 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
@@ -14,6 +14,11 @@ pub fn target() -> Target {
     let opts = TargetOptions {
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
+        // Enable the Cortex-A53 errata 843419 mitigation by default
+        pre_link_args: TargetOptions::link_args(
+            LinkerFlavor::Gnu(Cc::No, Lld::No),
+            &["--fix-cortex-a53-843419"],
+        ),
         features: "+v8a,+strict-align,+neon,+fp-armv8".into(),
         supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
         relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index ed2c990ffa6..ce0d604f57c 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
         arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(64),
-            stack_probes: StackProbeType::X86,
+            stack_probes: StackProbeType::Inline,
             ..opts("ios", arch)
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
index 06089391623..3ebf4bcf523 100644
--- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
                 &["-Vgcc_ntox86_cxx"],
             ),
             env: "nto70".into(),
-            stack_probes: StackProbeType::X86,
+            stack_probes: StackProbeType::Inline,
             ..base::nto_qnx::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index 242fe5ed98a..c4c9023419d 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -7,7 +7,7 @@ pub fn target() -> Target {
     let mut base = opts("macos", arch);
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.frame_pointer = FramePointer::Always;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
index 987265598eb..79471040f0d 100644
--- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
     // https://developer.android.com/ndk/guides/abis.html#x86
     base.cpu = "pentiumpro".into();
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into();
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "i686-linux-android".into(),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
index 70aa0b47962..927b2ab877d 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-znotext"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "i686-unknown-freebsd".into(),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
index 9715f6c21d9..bc7fd6fbc68 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "i686-unknown-haiku".into(),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
index 0ca058b2fd2..3b7be48dbbc 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS;
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
index ce0df3a7234..ef58b4fb458 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     // The unwinder used by i686-unknown-linux-musl, the LLVM libunwind
     // implementation, apparently relies on frame pointers existing... somehow.
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
index 2a3ac5932d3..5f3afbe5afd 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "i686-unknown-netbsdelf".into(),
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
index 45883542bea..f44584a10be 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-fuse-ld=lld"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "i686-unknown-openbsd".into(),
diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
index 965a895972c..ee501c5165e 100644
--- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 9170a10d254..81173a16f96 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -8,7 +8,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(128); // penryn+ supports cmpxchg16b
     base.frame_pointer = FramePointer::Always;
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index d9f3f7de655..221635526d1 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -14,7 +14,7 @@ pub fn target() -> Target {
         arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(128),
-            stack_probes: StackProbeType::X86,
+            stack_probes: StackProbeType::Inline,
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index 5e6fbac34d7..5f6b4b500d0 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -17,7 +17,7 @@ pub fn target() -> Target {
         arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(128),
-            stack_probes: StackProbeType::X86,
+            stack_probes: StackProbeType::Inline,
             ..base
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index 1c4d9196c18..a7d5f28e0e5 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(128),
-            stack_probes: StackProbeType::X86,
+            stack_probes: StackProbeType::Inline,
             ..opts("tvos", arch)
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index 9faf9b1ca3f..3c5bf30ef5f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -11,7 +11,7 @@ pub fn target() -> Target {
         arch: arch.target_arch(),
         options: TargetOptions {
             max_atomic_width: Some(128),
-            stack_probes: StackProbeType::X86,
+            stack_probes: StackProbeType::Inline,
             ..opts("watchos", arch)
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
index 6cffda44fa9..0e6d41abc9b 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.supports_xray = true;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
index ca6a6dc500b..f15ad8dda63 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
@@ -7,7 +7,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.vendor = "pc".into();
     base.max_atomic_width = Some(64);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
index c12cb1ab00e..e6159fca3ae 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
             plt_by_default: false,
             pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]),
             max_atomic_width: Some(64),
-            stack_probes: StackProbeType::X86,
+            stack_probes: StackProbeType::Inline,
             ..base::unikraft_linux_musl::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
index 68d1a755b79..80adb8fa2d9 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "x86_64-unknown-dragonfly".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
index e3f29fa5afa..fa321035367 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD;
     base.supports_xray = true;
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
index c8850d703e3..f0515615b19 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "x86-64".into();
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
index ca55e6514dd..0f927be962b 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     // This option is required to build executables on Haiku x86_64
     base.position_independent_executables = true;
 
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
index 3cc50d40dda..df191f515bd 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
             features: "+rdrnd,+rdseed".into(),
             plt_by_default: false,
             max_atomic_width: Some(64),
-            stack_probes: StackProbeType::X86,
+            stack_probes: StackProbeType::Inline,
             ..base::hermit::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
index 80e267c163f..bf10f7e5d2d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.static_position_independent_executables = true;
     base.supported_sanitizers = SanitizerSet::ADDRESS
         | SanitizerSet::CFI
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
index 622bfe8bbe8..1856c6afd52 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.abi = "x32".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mx32"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.has_thread_local = false;
     // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
     // breaks code gen. See LLVM bug 36743
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
index d74ff466a01..8dc5503e336 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.static_position_independent_executables = true;
     base.supported_sanitizers = SanitizerSet::ADDRESS
         | SanitizerSet::CFI
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
index 87b004df001..35862656aa2 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
@@ -5,7 +5,7 @@ pub fn target() -> Target {
     base.cpu = "x86-64".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.static_position_independent_executables = true;
     base.supported_sanitizers = SanitizerSet::ADDRESS
         | SanitizerSet::CFI
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
index 04060513abc..e2cee0513ba 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
@@ -8,7 +8,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers = SanitizerSet::ADDRESS
         | SanitizerSet::CFI
         | SanitizerSet::LEAK
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
index 9aa95a35f8e..8f7655d8ccd 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
         cpu: "x86-64".into(),
         plt_by_default: false,
         max_atomic_width: Some(64),
-        stack_probes: StackProbeType::X86,
+        stack_probes: StackProbeType::Inline,
         position_independent_executables: true,
         static_position_independent_executables: true,
         relro_level: RelroLevel::Full,
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
index 5e6e7efb2de..1133b50f3d2 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.supports_xray = true;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
index 382ff71f019..c1f57311292 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
 
     Target {
         llvm_target: "x86_64-unknown-redox".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
index 4b221fe6959..765239bdd39 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     base.plt_by_default = false;
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.disable_redzone = true;
 
     Target {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index a30e9d17cef..32d15c18678 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -8,7 +8,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(128);
     base.frame_pointer = FramePointer::Always;
     base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
-    base.stack_probes = StackProbeType::X86;
+    base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
 
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 5d5440094fd..8268273884d 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -192,7 +192,7 @@ fn lint_object_unsafe_trait(
             );
             if node.is_some() {
                 // Only provide the help if its a local trait, otherwise it's not
-                violation.solution(err);
+                violation.solution().add_to(err);
             }
             err
         },
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 8f5afdf0a1f..3be14951703 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1454,7 +1454,18 @@ pub fn compute_inherent_assoc_ty_args<'a, 'b, 'tcx>(
 
     // Infer the generic parameters of the impl by unifying the
     // impl type with the self type of the projection.
-    let self_ty = alias_ty.self_ty();
+    let mut self_ty = alias_ty.self_ty();
+    if !selcx.infcx.next_trait_solver() {
+        self_ty = normalize_with_depth_to(
+            selcx,
+            param_env,
+            cause.clone(),
+            depth + 1,
+            self_ty,
+            obligations,
+        );
+    }
+
     match selcx.infcx.at(&cause, param_env).eq(DefineOpaqueTypes::No, impl_ty, self_ty) {
         Ok(mut ok) => obligations.append(&mut ok.obligations),
         Err(_) => {
diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs
index 1f75dfb69cf..2099c485c6f 100644
--- a/compiler/stable_mir/src/lib.rs
+++ b/compiler/stable_mir/src/lib.rs
@@ -16,7 +16,7 @@
 //!
 //! The goal is to eventually be published on
 //! [crates.io](https://crates.io).
-
+#![feature(type_alias_impl_trait)]
 #[macro_use]
 extern crate scoped_tls;
 
@@ -184,7 +184,7 @@ impl std::fmt::Display for Opaque {
 
 impl std::fmt::Debug for Opaque {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "{:?}", self.0)
+        write!(f, "{}", self.0)
     }
 }
 
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 8d237fc9f1d..02a28687676 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -1,10 +1,9 @@
-use crate::mir::pretty::{function_body, pretty_statement};
+use crate::mir::pretty::{function_body, pretty_statement, pretty_terminator};
 use crate::ty::{
     AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
 };
 use crate::{Error, Opaque, Span, Symbol};
-use std::io;
-
+use std::{io, slice};
 /// The SMIR representation of a single function.
 #[derive(Clone, Debug)]
 pub struct Body {
@@ -83,6 +82,8 @@ impl Body {
                         Ok(())
                     })
                     .collect::<Vec<_>>();
+                pretty_terminator(&block.terminator.kind, w)?;
+                writeln!(w, "").unwrap();
                 writeln!(w, "    }}").unwrap();
                 Ok(())
             })
@@ -100,7 +101,7 @@ pub struct LocalDecl {
     pub mutability: Mutability,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 pub struct BasicBlock {
     pub statements: Vec<Statement>,
     pub terminator: Terminator,
@@ -112,6 +113,14 @@ pub struct Terminator {
     pub span: Span,
 }
 
+impl Terminator {
+    pub fn successors(&self) -> Successors<'_> {
+        self.kind.successors()
+    }
+}
+
+pub type Successors<'a> = impl Iterator<Item = usize> + 'a;
+
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub enum TerminatorKind {
     Goto {
@@ -119,7 +128,7 @@ pub enum TerminatorKind {
     },
     SwitchInt {
         discr: Operand,
-        targets: Vec<SwitchTarget>,
+        targets: SwitchTargets,
         otherwise: usize,
     },
     Resume,
@@ -156,6 +165,58 @@ pub enum TerminatorKind {
     },
 }
 
+impl TerminatorKind {
+    pub fn successors(&self) -> Successors<'_> {
+        use self::TerminatorKind::*;
+        match *self {
+            Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
+            | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
+            | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
+            | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => {
+                Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
+            }
+            Goto { target: t }
+            | Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
+            | Call { target: Some(t), unwind: _, .. }
+            | Drop { target: t, unwind: _, .. }
+            | Assert { target: t, unwind: _, .. }
+            | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
+            | InlineAsm { destination: Some(t), unwind: _, .. } => {
+                Some(t).into_iter().chain((&[]).into_iter().copied())
+            }
+
+            CoroutineDrop
+            | Return
+            | Resume
+            | Abort
+            | Unreachable
+            | Call { target: None, unwind: _, .. }
+            | InlineAsm { destination: None, unwind: _, .. } => {
+                None.into_iter().chain((&[]).into_iter().copied())
+            }
+            SwitchInt { ref targets, .. } => {
+                None.into_iter().chain(targets.targets.iter().copied())
+            }
+        }
+    }
+
+    pub fn unwind(&self) -> Option<&UnwindAction> {
+        match *self {
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::CoroutineDrop
+            | TerminatorKind::Resume
+            | TerminatorKind::Abort
+            | TerminatorKind::SwitchInt { .. } => None,
+            TerminatorKind::Call { ref unwind, .. }
+            | TerminatorKind::Assert { ref unwind, .. }
+            | TerminatorKind::Drop { ref unwind, .. }
+            | TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind),
+        }
+    }
+}
+
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct InlineAsmOperand {
     pub in_value: Option<Operand>,
@@ -602,9 +663,9 @@ pub struct Constant {
 }
 
 #[derive(Clone, Debug, Eq, PartialEq)]
-pub struct SwitchTarget {
-    pub value: u128,
-    pub target: usize,
+pub struct SwitchTargets {
+    pub value: Vec<u128>,
+    pub targets: Vec<usize>,
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
diff --git a/compiler/stable_mir/src/mir/pretty.rs b/compiler/stable_mir/src/mir/pretty.rs
index e7bca295b5a..759c3b148df 100644
--- a/compiler/stable_mir/src/mir/pretty.rs
+++ b/compiler/stable_mir/src/mir/pretty.rs
@@ -1,7 +1,11 @@
 use crate::crate_def::CrateDef;
-use crate::mir::{Operand, Rvalue, StatementKind};
+use crate::mir::{Operand, Rvalue, StatementKind, UnwindAction};
 use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy};
 use crate::{with, Body, CrateItem, Mutability};
+use std::io::Write;
+use std::{io, iter};
+
+use super::{AssertMessage, BinOp, TerminatorKind};
 
 pub fn function_name(item: CrateItem) -> String {
     let mut pretty_name = String::new();
@@ -70,6 +74,209 @@ pub fn pretty_statement(statement: &StatementKind) -> String {
     pretty
 }
 
+pub fn pretty_terminator<W: io::Write>(terminator: &TerminatorKind, w: &mut W) -> io::Result<()> {
+    write!(w, "{}", pretty_terminator_head(terminator))?;
+    let successor_count = terminator.successors().count();
+    let labels = pretty_successor_labels(terminator);
+
+    let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_)));
+    let fmt_unwind = |fmt: &mut dyn Write| -> io::Result<()> {
+        write!(fmt, "unwind ")?;
+        match terminator.unwind() {
+            None | Some(UnwindAction::Cleanup(_)) => unreachable!(),
+            Some(UnwindAction::Continue) => write!(fmt, "continue"),
+            Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"),
+            Some(UnwindAction::Terminate) => write!(fmt, "terminate"),
+        }
+    };
+
+    match (successor_count, show_unwind) {
+        (0, false) => Ok(()),
+        (0, true) => {
+            write!(w, " -> ")?;
+            fmt_unwind(w)?;
+            Ok(())
+        }
+        (1, false) => {
+            write!(w, " -> {:?}", terminator.successors().next().unwrap())?;
+            Ok(())
+        }
+        _ => {
+            write!(w, " -> [")?;
+            for (i, target) in terminator.successors().enumerate() {
+                if i > 0 {
+                    write!(w, ", ")?;
+                }
+                write!(w, "{}: bb{:?}", labels[i], target)?;
+            }
+            if show_unwind {
+                write!(w, ", ")?;
+                fmt_unwind(w)?;
+            }
+            write!(w, "]")
+        }
+    }?;
+
+    Ok(())
+}
+
+pub fn pretty_terminator_head(terminator: &TerminatorKind) -> String {
+    use self::TerminatorKind::*;
+    let mut pretty = String::new();
+    match terminator {
+        Goto { .. } => format!("        goto"),
+        SwitchInt { discr, .. } => {
+            format!("        switchInt(_{})", pretty_operand(discr))
+        }
+        Resume => format!("        resume"),
+        Abort => format!("        abort"),
+        Return => format!("        return"),
+        Unreachable => format!("        unreachable"),
+        Drop { place, .. } => format!("        drop(_{:?})", place.local),
+        Call { func, args, destination, .. } => {
+            pretty.push_str("        ");
+            pretty.push_str(format!("_{} = ", destination.local).as_str());
+            pretty.push_str(&pretty_operand(func));
+            pretty.push_str("(");
+            args.iter().enumerate().for_each(|(i, arg)| {
+                if i > 0 {
+                    pretty.push_str(", ");
+                }
+                pretty.push_str(&pretty_operand(arg));
+            });
+            pretty.push_str(")");
+            pretty
+        }
+        Assert { cond, expected, msg, target: _, unwind: _ } => {
+            pretty.push_str("        assert(");
+            if !expected {
+                pretty.push_str("!");
+            }
+            pretty.push_str(format!("{} bool),", &pretty_operand(cond)).as_str());
+            pretty.push_str(&pretty_assert_message(msg));
+            pretty.push_str(")");
+            pretty
+        }
+        CoroutineDrop => format!("        coroutine_drop"),
+        InlineAsm { .. } => todo!(),
+    }
+}
+
+pub fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec<String> {
+    use self::TerminatorKind::*;
+    match terminator {
+        Resume | Abort | Return | Unreachable | CoroutineDrop => vec![],
+        Goto { .. } => vec!["".to_string()],
+        SwitchInt { targets, .. } => targets
+            .value
+            .iter()
+            .map(|target| format!("{}", target))
+            .chain(iter::once("otherwise".into()))
+            .collect(),
+        Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
+        Drop { unwind: _, .. } => vec!["return".into()],
+        Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
+            vec!["return".into(), "unwind".into()]
+        }
+        Call { target: Some(_), unwind: _, .. } => vec!["return".into()],
+        Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
+        Call { target: None, unwind: _, .. } => vec![],
+        Assert { unwind: UnwindAction::Cleanup(_), .. } => {
+            vec!["success".into(), "unwind".into()]
+        }
+        Assert { unwind: _, .. } => vec!["success".into()],
+        InlineAsm { .. } => todo!(),
+    }
+}
+
+pub fn pretty_assert_message(msg: &AssertMessage) -> String {
+    let mut pretty = String::new();
+    match msg {
+        AssertMessage::BoundsCheck { len, index } => {
+            let pretty_len = pretty_operand(len);
+            let pretty_index = pretty_operand(index);
+            pretty.push_str(format!("\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}").as_str());
+            pretty
+        }
+        AssertMessage::Overflow(BinOp::Add, l, r) => {
+            let pretty_l = pretty_operand(l);
+            let pretty_r = pretty_operand(r);
+            pretty.push_str(format!("\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
+            pretty
+        }
+        AssertMessage::Overflow(BinOp::Sub, l, r) => {
+            let pretty_l = pretty_operand(l);
+            let pretty_r = pretty_operand(r);
+            pretty.push_str(format!("\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
+            pretty
+        }
+        AssertMessage::Overflow(BinOp::Mul, l, r) => {
+            let pretty_l = pretty_operand(l);
+            let pretty_r = pretty_operand(r);
+            pretty.push_str(format!("\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
+            pretty
+        }
+        AssertMessage::Overflow(BinOp::Div, l, r) => {
+            let pretty_l = pretty_operand(l);
+            let pretty_r = pretty_operand(r);
+            pretty.push_str(format!("\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
+            pretty
+        }
+        AssertMessage::Overflow(BinOp::Rem, l, r) => {
+            let pretty_l = pretty_operand(l);
+            let pretty_r = pretty_operand(r);
+            pretty.push_str(format!("\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
+            pretty
+        }
+        AssertMessage::Overflow(BinOp::Shr, _, r) => {
+            let pretty_r = pretty_operand(r);
+            pretty.push_str(
+                format!("\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}")
+                    .as_str(),
+            );
+            pretty
+        }
+        AssertMessage::Overflow(BinOp::Shl, _, r) => {
+            let pretty_r = pretty_operand(r);
+            pretty.push_str(
+                format!("\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}")
+                    .as_str(),
+            );
+            pretty
+        }
+        AssertMessage::OverflowNeg(op) => {
+            let pretty_op = pretty_operand(op);
+            pretty.push_str(
+                format!("\"attempt to negate `{{}}`, which would overflow\", {pretty_op}").as_str(),
+            );
+            pretty
+        }
+        AssertMessage::DivisionByZero(op) => {
+            let pretty_op = pretty_operand(op);
+            pretty.push_str(format!("\"attempt to divide `{{}}` by zero\", {pretty_op}").as_str());
+            pretty
+        }
+        AssertMessage::RemainderByZero(op) => {
+            let pretty_op = pretty_operand(op);
+            pretty.push_str(
+                format!("\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}").as_str(),
+            );
+            pretty
+        }
+        AssertMessage::ResumedAfterReturn(_) => {
+            format!("attempt to resume a generator after completion")
+        }
+        AssertMessage::ResumedAfterPanic(_) => format!("attempt to resume a panicked generator"),
+        AssertMessage::MisalignedPointerDereference { required, found } => {
+            let pretty_required = pretty_operand(required);
+            let pretty_found = pretty_operand(found);
+            pretty.push_str(format!("\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}").as_str());
+            pretty
+        }
+        _ => todo!(),
+    }
+}
+
 pub fn pretty_operand(operand: &Operand) -> String {
     let mut pretty = String::new();
     match operand {
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index f014ef51c75..7c119b0273b 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -569,11 +569,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
     let version = output(cmd.arg("--version"));
     let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
     if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
-        if major >= 15 {
+        if major >= 16 {
             return;
         }
     }
-    panic!("\n\nbad LLVM version: {version}, need >=15.0\n\n")
+    panic!("\n\nbad LLVM version: {version}, need >=16.0\n\n")
 }
 
 fn configure_cmake(
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
deleted file mode 100644
index cefdcad7643..00000000000
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/Dockerfile
+++ /dev/null
@@ -1,59 +0,0 @@
-FROM ubuntu:22.04
-
-ARG DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  gcc-multilib \
-  make \
-  ninja-build \
-  file \
-  curl \
-  ca-certificates \
-  python3.11 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  llvm-15-tools \
-  llvm-15-dev \
-  libedit-dev \
-  libssl-dev \
-  pkg-config \
-  zlib1g-dev \
-  xz-utils \
-  nodejs \
-  mingw-w64 \
-  libgccjit-12-dev \
-  && rm -rf /var/lib/apt/lists/*
-
-# Install powershell (universal package) so we can test x.ps1 on Linux
-RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
-    dpkg -i powershell.deb && \
-    rm -f powershell.deb
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-# Make `libgccjit.so` accessible to the linker.
-RUN ln -s /usr/lib/gcc/x86_64-linux-gnu/12/libgccjit.so /usr/lib/x86_64-linux-gnu/libgccjit.so
-
-# We are disabling CI LLVM since this builder is intentionally using a host
-# LLVM, rather than the typical src/llvm-project LLVM.
-ENV NO_DOWNLOAD_CI_LLVM 1
-
-# This is not the latest LLVM version, so some components required by tests may
-# be missing.
-ENV IS_NOT_LATEST_LLVM 1
-
-# Using llvm-link-shared due to libffi issues -- see #34486
-ENV RUST_CONFIGURE_ARGS \
-      --build=x86_64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-15 \
-      --enable-llvm-link-shared \
-      $USE_NEW_MANGLING \
-      --set rust.thin-lto-import-instr-limit=10
-
-COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/
-
-ENV SCRIPT /tmp/script.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
index c177e7387fc..4757c3e7329 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
@@ -49,6 +49,6 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-llvm-link-shared \
       --set rust.thin-lto-import-instr-limit=10
 
-COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/
+COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/
 
 ENV SCRIPT /tmp/script.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/script.sh
index 2eb751ca376..2eb751ca376 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-15/script.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/script.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
index 76846f1fed7..dc5a04d4e06 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
@@ -45,6 +45,6 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-llvm-link-shared \
       --set rust.thin-lto-import-instr-limit=10
 
-COPY host-x86_64/x86_64-gnu-llvm-15/script.sh /tmp/
+COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/
 
 ENV SCRIPT /tmp/script.sh
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index da29ffb8e5f..5b9c90273a3 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -334,7 +334,7 @@ jobs:
           - name: mingw-check-tidy
             <<: *job-linux-4c
 
-          - name: x86_64-gnu-llvm-15
+          - name: x86_64-gnu-llvm-16
             env:
               ENABLE_GCC_CODEGEN: "1"
             <<: *job-linux-16c
@@ -486,11 +486,6 @@ jobs:
               RUST_BACKTRACE: 1
             <<: *job-linux-8c
 
-          - name: x86_64-gnu-llvm-15
-            env:
-              RUST_BACKTRACE: 1
-            <<: *job-linux-8c
-
           - name: x86_64-gnu-nopt
             <<: *job-linux-4c
 
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 701e36d74a6..5a8d971c3d4 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -72,8 +72,8 @@ dependencies = [
  "cfg",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "profile",
+ "rust-analyzer-salsa",
  "rustc-hash",
- "salsa",
  "stdx",
  "syntax",
  "test-utils",
@@ -160,32 +160,32 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chalk-derive"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0322d5289ceba3217a03c9af72aa403d87542822b753daa1da32e4b992a4e80"
+checksum = "329427f28cd2bddaacd47c4dcd3d7082d315c61fb164394c690fe98c1b6ee9d3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
  "synstructure",
 ]
 
 [[package]]
 name = "chalk-ir"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0946cbc6d9136980a24a2dddf1888b5f0aa978dda300a3aa470b55b777b6bf3c"
+checksum = "9e1e1659238bd598d0f7dbc5034cf1ff46010a3d6827704c9ed443c8359cb484"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.4.1",
  "chalk-derive",
  "lazy_static",
 ]
 
 [[package]]
 name = "chalk-recursive"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cd93fedbeeadc0cd4d0eb73bd061b621af99f5324a6a518264c8ef5e526e0ec"
+checksum = "b3e0bff0ba1bed11407384fcec0353aeb6888901e63cb47d04505ec47adad847"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -196,15 +196,15 @@ dependencies = [
 
 [[package]]
 name = "chalk-solve"
-version = "0.94.0"
+version = "0.95.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a254cff72303c58c82df421cfe9465606372b81588923fcf179922b7eaad9a53"
+checksum = "eb9c46d501cf83732a91056c0c846ae7a16d6b3c67a6a6bb5e9cc0a2e91563b6"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
  "ena",
- "indexmap 2.1.0",
- "itertools 0.10.5",
+ "indexmap",
+ "itertools",
  "petgraph",
  "rustc-hash",
  "tracing",
@@ -216,7 +216,7 @@ version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916"
 dependencies = [
- "nix",
+ "nix 0.26.2",
  "winapi",
 ]
 
@@ -290,6 +290,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "ctrlc"
+version = "3.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
+dependencies = [
+ "nix 0.27.1",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "dashmap"
 version = "5.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -299,7 +309,7 @@ dependencies = [
  "hashbrown 0.12.3",
  "lock_api",
  "once_cell",
- "parking_lot_core 0.9.6",
+ "parking_lot_core",
 ]
 
 [[package]]
@@ -310,7 +320,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -450,12 +460,9 @@ checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
 
 [[package]]
 name = "heck"
-version = "0.3.3"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
-dependencies = [
- "unicode-segmentation",
-]
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "hermit-abi"
@@ -477,7 +484,7 @@ dependencies = [
  "hir-def",
  "hir-expand",
  "hir-ty",
- "itertools 0.12.0",
+ "itertools",
  "once_cell",
  "profile",
  "rustc-hash",
@@ -504,9 +511,9 @@ dependencies = [
  "fst",
  "hashbrown 0.12.3",
  "hir-expand",
- "indexmap 2.1.0",
+ "indexmap",
  "intern",
- "itertools 0.12.0",
+ "itertools",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "limit",
  "mbe",
@@ -534,7 +541,7 @@ dependencies = [
  "expect-test",
  "hashbrown 0.12.3",
  "intern",
- "itertools 0.12.0",
+ "itertools",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "limit",
  "mbe",
@@ -566,7 +573,7 @@ dependencies = [
  "hir-def",
  "hir-expand",
  "intern",
- "itertools 0.12.0",
+ "itertools",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "limit",
  "nohash-hasher",
@@ -613,7 +620,7 @@ dependencies = [
  "ide-db",
  "ide-diagnostics",
  "ide-ssr",
- "itertools 0.12.0",
+ "itertools",
  "nohash-hasher",
  "oorandom",
  "profile",
@@ -639,7 +646,7 @@ dependencies = [
  "expect-test",
  "hir",
  "ide-db",
- "itertools 0.12.0",
+ "itertools",
  "profile",
  "smallvec",
  "sourcegen",
@@ -658,7 +665,7 @@ dependencies = [
  "expect-test",
  "hir",
  "ide-db",
- "itertools 0.12.0",
+ "itertools",
  "once_cell",
  "profile",
  "smallvec",
@@ -679,8 +686,8 @@ dependencies = [
  "expect-test",
  "fst",
  "hir",
- "indexmap 2.1.0",
- "itertools 0.12.0",
+ "indexmap",
+ "itertools",
  "limit",
  "line-index 0.1.0-pre.1",
  "memchr",
@@ -711,7 +718,7 @@ dependencies = [
  "expect-test",
  "hir",
  "ide-db",
- "itertools 0.12.0",
+ "itertools",
  "once_cell",
  "profile",
  "serde_json",
@@ -730,7 +737,7 @@ dependencies = [
  "expect-test",
  "hir",
  "ide-db",
- "itertools 0.12.0",
+ "itertools",
  "nohash-hasher",
  "parser",
  "stdx",
@@ -752,16 +759,6 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown 0.12.3",
-]
-
-[[package]]
-name = "indexmap"
 version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
@@ -791,15 +788,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "instant"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
 name = "intern"
 version = "0.0.0"
 dependencies = [
@@ -811,15 +799,6 @@ dependencies = [
 
 [[package]]
 name = "itertools"
-version = "0.10.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itertools"
 version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
@@ -931,7 +910,7 @@ dependencies = [
  "crossbeam-channel",
  "ide",
  "ide-db",
- "itertools 0.12.0",
+ "itertools",
  "proc-macro-api",
  "project-model",
  "tracing",
@@ -961,6 +940,7 @@ name = "lsp-server"
 version = "0.7.4"
 dependencies = [
  "crossbeam-channel",
+ "ctrlc",
  "log",
  "lsp-types",
  "serde",
@@ -1101,6 +1081,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "nix"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
+dependencies = [
+ "bitflags 2.4.1",
+ "cfg-if",
+ "libc",
+]
+
+[[package]]
 name = "nohash-hasher"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1176,37 +1167,12 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
 
 [[package]]
 name = "parking_lot"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
-dependencies = [
- "instant",
- "lock_api",
- "parking_lot_core 0.8.6",
-]
-
-[[package]]
-name = "parking_lot"
 version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.6",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
-dependencies = [
- "cfg-if",
- "instant",
- "libc",
- "redox_syscall 0.2.16",
- "smallvec",
- "winapi",
+ "parking_lot_core",
 ]
 
 [[package]]
@@ -1276,7 +1242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
 dependencies = [
  "fixedbitset",
- "indexmap 2.1.0",
+ "indexmap",
 ]
 
 [[package]]
@@ -1371,7 +1337,7 @@ dependencies = [
  "cargo_metadata",
  "cfg",
  "expect-test",
- "itertools 0.12.0",
+ "itertools",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "paths",
  "profile",
@@ -1436,50 +1402,43 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.19.0"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2ea80a299f04a896000ce17b76f3aa1d2fe59f347fbc99c4b8970316ef5a0d"
+checksum = "b5f38444d48da534b3bb612713fce9b0aeeffb2e0dfa242764f55482acc5b52d"
 dependencies = [
  "bitflags 1.3.2",
- "ra-ap-rustc_index 0.19.0",
+ "ra-ap-rustc_index",
  "tracing",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "643ca3609870b1778d9cd1f2a8e4ccb4af0f48f3637cc257a09494d087bd93dc"
-dependencies = [
- "arrayvec",
- "smallvec",
-]
-
-[[package]]
-name = "ra-ap-rustc_index"
-version = "0.19.0"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4556489ef652e5eb6cdad6078fff08507badac80bfc1f79085c85a6d8b77ab5c"
+checksum = "69fb5da07e1a39222d9c311203123c3b6a86420fa06dc695aa1661b0aecf8d16"
 dependencies = [
  "arrayvec",
+ "ra-ap-rustc_index_macros",
  "smallvec",
 ]
 
 [[package]]
-name = "ra-ap-rustc_lexer"
-version = "0.14.0"
+name = "ra-ap-rustc_index_macros"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ffd24f9ba4f1d25ff27ca1469b8d22a3bdfb12cf644fc8bfcb63121fa5da6b"
+checksum = "3d69f9f6af58124f2da0cb8b0c3d8494e0d883a5fe0c6732258bde81ac5a87cc"
 dependencies = [
- "unicode-properties",
- "unicode-xid",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
 ]
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.19.0"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90e573bf707e01fe2841dbdedeed42012004274db0edc0314e6e3e58a40598fc"
+checksum = "9d5e8650195795c4023d8321846466994a975bc457cb8a91c0b3b17a5fc8ba40"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1487,12 +1446,12 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.14.0"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "207b5ac1a21d4926695e03b605ffb9f63d4968e0488e9197c04c512c37303aa7"
+checksum = "0a6b325ee1ec90e4dbd4394913adf4ef32e4fcf2b311ec9563a0fa50cd549af6"
 dependencies = [
- "ra-ap-rustc_index 0.14.0",
- "ra-ap-rustc_lexer 0.14.0",
+ "ra-ap-rustc_index",
+ "ra-ap-rustc_lexer",
 ]
 
 [[package]]
@@ -1563,7 +1522,7 @@ dependencies = [
  "ide",
  "ide-db",
  "ide-ssr",
- "itertools 0.12.0",
+ "itertools",
  "load-cargo",
  "lsp-server 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "lsp-types",
@@ -1573,8 +1532,8 @@ dependencies = [
  "nohash-hasher",
  "num_cpus",
  "oorandom",
- "parking_lot 0.12.1",
- "parking_lot_core 0.9.6",
+ "parking_lot",
+ "parking_lot_core",
  "parser",
  "proc-macro-api",
  "profile",
@@ -1604,6 +1563,35 @@ dependencies = [
 ]
 
 [[package]]
+name = "rust-analyzer-salsa"
+version = "0.17.0-pre.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ca92b657d614d076800aa7bf5d5ba33564e71fa7f16cd79eacdfe301a50ab1c"
+dependencies = [
+ "crossbeam-utils",
+ "indexmap",
+ "lock_api",
+ "log",
+ "oorandom",
+ "parking_lot",
+ "rust-analyzer-salsa-macros",
+ "rustc-hash",
+ "smallvec",
+]
+
+[[package]]
+name = "rust-analyzer-salsa-macros"
+version = "0.17.0-pre.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b190359266d293f2ee13eaa502a766dc8b77b63fbaa5d460d24fd0210675ceef"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "rustc-demangle"
 version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1614,8 +1602,8 @@ name = "rustc-dependencies"
 version = "0.0.0"
 dependencies = [
  "ra-ap-rustc_abi",
- "ra-ap-rustc_index 0.19.0",
- "ra-ap-rustc_lexer 0.19.0",
+ "ra-ap-rustc_index",
+ "ra-ap-rustc_lexer",
  "ra-ap-rustc_parse_format",
 ]
 
@@ -1632,35 +1620,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 
 [[package]]
-name = "salsa"
-version = "0.17.0-pre.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b223dccb46c32753144d0b51290da7230bb4aedcd8379d6b4c9a474c18bf17a"
-dependencies = [
- "crossbeam-utils",
- "indexmap 1.9.3",
- "lock_api",
- "log",
- "oorandom",
- "parking_lot 0.11.2",
- "rustc-hash",
- "salsa-macros",
- "smallvec",
-]
-
-[[package]]
-name = "salsa-macros"
-version = "0.17.0-pre.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac6c2e352df550bf019da7b16164ed2f7fa107c39653d1311d1bba42d1582ff7"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
 name = "same-file"
 version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1701,22 +1660,22 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.192"
+version = "1.0.193"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
+checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.192"
+version = "1.0.193"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
+checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -1725,7 +1684,7 @@ version = "1.0.108"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
 dependencies = [
- "indexmap 2.1.0",
+ "indexmap",
  "itoa",
  "ryu",
  "serde",
@@ -1739,7 +1698,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -1800,17 +1759,6 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
 version = "2.0.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
@@ -1828,7 +1776,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
  "unicode-xid",
 ]
 
@@ -1839,8 +1787,8 @@ dependencies = [
  "cov-mark",
  "either",
  "expect-test",
- "indexmap 2.1.0",
- "itertools 0.12.0",
+ "indexmap",
+ "itertools",
  "once_cell",
  "parser",
  "proc-macro2",
@@ -1874,7 +1822,7 @@ dependencies = [
 name = "text-edit"
 version = "0.0.0"
 dependencies = [
- "itertools 0.12.0",
+ "itertools",
  "text-size",
 ]
 
@@ -1901,7 +1849,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -2002,7 +1950,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.39",
+ "syn",
 ]
 
 [[package]]
@@ -2113,12 +2061,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0"
 
 [[package]]
-name = "unicode-segmentation"
-version = "1.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
-
-[[package]]
 name = "unicode-xid"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2153,7 +2095,7 @@ name = "vfs"
 version = "0.0.0"
 dependencies = [
  "fst",
- "indexmap 2.1.0",
+ "indexmap",
  "nohash-hasher",
  "paths",
  "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 171c113a950..5ad88f65188 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -12,7 +12,7 @@ rust-version.workspace = true
 doctest = false
 
 [dependencies]
-salsa = "0.17.0-pre.2"
+rust-analyzer-salsa = "0.17.0-pre.3"
 rustc-hash = "1.1.0"
 
 triomphe.workspace = true
diff --git a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
index 3f5ccb621c7..3da555a47ac 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
@@ -13,9 +13,9 @@ use vfs::{file_set::FileSet, VfsPath};
 
 use crate::{
     input::{CrateName, CrateOrigin, LangCrateOrigin},
-    Change, CrateDisplayName, CrateGraph, CrateId, Dependency, Edition, Env, FileId, FilePosition,
-    FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacros, ReleaseChannel,
-    SourceDatabaseExt, SourceRoot, SourceRootId,
+    Change, CrateDisplayName, CrateGraph, CrateId, Dependency, DependencyKind, Edition, Env,
+    FileId, FilePosition, FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
+    ProcMacros, ReleaseChannel, SourceDatabaseExt, SourceRoot, SourceRootId,
 };
 
 pub const WORKSPACE: SourceRootId = SourceRootId(0);
@@ -237,7 +237,12 @@ impl ChangeFixture {
                 crate_graph
                     .add_dep(
                         from_id,
-                        Dependency::with_prelude(CrateName::new(&to).unwrap(), to_id, prelude),
+                        Dependency::with_prelude(
+                            CrateName::new(&to).unwrap(),
+                            to_id,
+                            prelude,
+                            DependencyKind::Normal,
+                        ),
                     )
                     .unwrap();
             }
@@ -275,7 +280,14 @@ impl ChangeFixture {
 
             for krate in all_crates {
                 crate_graph
-                    .add_dep(krate, Dependency::new(CrateName::new("core").unwrap(), core_crate))
+                    .add_dep(
+                        krate,
+                        Dependency::new(
+                            CrateName::new("core").unwrap(),
+                            core_crate,
+                            DependencyKind::Normal,
+                        ),
+                    )
                     .unwrap();
             }
         }
@@ -317,7 +329,11 @@ impl ChangeFixture {
                 crate_graph
                     .add_dep(
                         krate,
-                        Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate),
+                        Dependency::new(
+                            CrateName::new("proc_macros").unwrap(),
+                            proc_macros_crate,
+                            DependencyKind::Normal,
+                        ),
                     )
                     .unwrap();
             }
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 65db5c0fc7d..e4f78321e21 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -155,6 +155,10 @@ impl CrateOrigin {
     pub fn is_local(&self) -> bool {
         matches!(self, CrateOrigin::Local { .. })
     }
+
+    pub fn is_lib(&self) -> bool {
+        matches!(self, CrateOrigin::Library { .. })
+    }
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -324,6 +328,62 @@ pub struct CrateData {
     pub channel: Option<ReleaseChannel>,
 }
 
+impl CrateData {
+    /// Check if [`other`] is almost equal to [`self`] ignoring `CrateOrigin` value.
+    pub fn eq_ignoring_origin_and_deps(&self, other: &CrateData, ignore_dev_deps: bool) -> bool {
+        // This method has some obscure bits. These are mostly there to be compliant with
+        // some patches. References to the patches are given.
+        if self.root_file_id != other.root_file_id {
+            return false;
+        }
+
+        if self.display_name != other.display_name {
+            return false;
+        }
+
+        if self.is_proc_macro != other.is_proc_macro {
+            return false;
+        }
+
+        if self.edition != other.edition {
+            return false;
+        }
+
+        if self.version != other.version {
+            return false;
+        }
+
+        let mut opts = self.cfg_options.difference(&other.cfg_options);
+        if let Some(it) = opts.next() {
+            // Don't care if rust_analyzer CfgAtom is the only cfg in the difference set of self's and other's cfgs.
+            // https://github.com/rust-lang/rust-analyzer/blob/0840038f02daec6ba3238f05d8caa037d28701a0/crates/project-model/src/workspace.rs#L894
+            if it.to_string() != "rust_analyzer" {
+                return false;
+            }
+
+            if let Some(_) = opts.next() {
+                return false;
+            }
+        }
+
+        if self.env != other.env {
+            return false;
+        }
+
+        let slf_deps = self.dependencies.iter();
+        let other_deps = other.dependencies.iter();
+
+        if ignore_dev_deps {
+            return slf_deps
+                .clone()
+                .filter(|it| it.kind != DependencyKind::Dev)
+                .eq(other_deps.clone().filter(|it| it.kind != DependencyKind::Dev));
+        }
+
+        slf_deps.eq(other_deps)
+    }
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum Edition {
     Edition2015,
@@ -351,26 +411,43 @@ impl Env {
     }
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum DependencyKind {
+    Normal,
+    Dev,
+    Build,
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Dependency {
     pub crate_id: CrateId,
     pub name: CrateName,
+    kind: DependencyKind,
     prelude: bool,
 }
 
 impl Dependency {
-    pub fn new(name: CrateName, crate_id: CrateId) -> Self {
-        Self { name, crate_id, prelude: true }
+    pub fn new(name: CrateName, crate_id: CrateId, kind: DependencyKind) -> Self {
+        Self { name, crate_id, prelude: true, kind }
     }
 
-    pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool) -> Self {
-        Self { name, crate_id, prelude }
+    pub fn with_prelude(
+        name: CrateName,
+        crate_id: CrateId,
+        prelude: bool,
+        kind: DependencyKind,
+    ) -> Self {
+        Self { name, crate_id, prelude, kind }
     }
 
     /// Whether this dependency is to be added to the depending crate's extern prelude.
     pub fn is_prelude(&self) -> bool {
         self.prelude
     }
+
+    pub fn kind(&self) -> DependencyKind {
+        self.kind
+    }
 }
 
 impl CrateGraph {
@@ -574,23 +651,46 @@ impl CrateGraph {
     pub fn extend(&mut self, mut other: CrateGraph, proc_macros: &mut ProcMacroPaths) {
         let topo = other.crates_in_topological_order();
         let mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default();
-
         for topo in topo {
             let crate_data = &mut other.arena[topo];
+
             crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]);
             crate_data.dependencies.sort_by_key(|dep| dep.crate_id);
-
-            let res = self.arena.iter().find_map(
-                |(id, data)| {
-                    if data == crate_data {
-                        Some(id)
-                    } else {
-                        None
+            let res = self.arena.iter().find_map(|(id, data)| {
+                match (&data.origin, &crate_data.origin) {
+                    (a, b) if a == b => {
+                        if data.eq_ignoring_origin_and_deps(&crate_data, false) {
+                            return Some((id, false));
+                        }
+                    }
+                    (a @ CrateOrigin::Local { .. }, CrateOrigin::Library { .. })
+                    | (a @ CrateOrigin::Library { .. }, CrateOrigin::Local { .. }) => {
+                        // If the origins differ, check if the two crates are equal without
+                        // considering the dev dependencies, if they are, they most likely are in
+                        // different loaded workspaces which may cause issues. We keep the local
+                        // version and discard the library one as the local version may have
+                        // dev-dependencies that we want to keep resolving. See #15656 for more
+                        // information.
+                        if data.eq_ignoring_origin_and_deps(&crate_data, true) {
+                            return Some((id, if a.is_local() { false } else { true }));
+                        }
                     }
-                },
-            );
-            if let Some(res) = res {
+                    (_, _) => return None,
+                }
+
+                None
+            });
+
+            if let Some((res, should_update_lib_to_local)) = res {
                 id_map.insert(topo, res);
+                if should_update_lib_to_local {
+                    assert!(self.arena[res].origin.is_lib());
+                    assert!(crate_data.origin.is_local());
+                    self.arena[res].origin = crate_data.origin.clone();
+
+                    // Move local's dev dependencies into the newly-local-formerly-lib crate.
+                    self.arena[res].dependencies = crate_data.dependencies.clone();
+                }
             } else {
                 let id = self.arena.alloc(crate_data.clone());
                 id_map.insert(topo, id);
@@ -636,9 +736,11 @@ impl CrateGraph {
         match (cfg_if, std) {
             (Some(cfg_if), Some(std)) => {
                 self.arena[cfg_if].dependencies.clear();
-                self.arena[std]
-                    .dependencies
-                    .push(Dependency::new(CrateName::new("cfg_if").unwrap(), cfg_if));
+                self.arena[std].dependencies.push(Dependency::new(
+                    CrateName::new("cfg_if").unwrap(),
+                    cfg_if,
+                    DependencyKind::Normal,
+                ));
                 true
             }
             _ => false,
@@ -658,6 +760,8 @@ impl ops::Index<CrateId> for CrateGraph {
 }
 
 impl CrateData {
+    /// Add a dependency to `self` without checking if the dependency
+    // is existent among `self.dependencies`.
     fn add_dep(&mut self, dep: Dependency) {
         self.dependencies.push(dep)
     }
@@ -759,7 +863,7 @@ impl fmt::Display for CyclicDependenciesError {
 
 #[cfg(test)]
 mod tests {
-    use crate::CrateOrigin;
+    use crate::{CrateOrigin, DependencyKind};
 
     use super::{CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId};
 
@@ -806,13 +910,22 @@ mod tests {
             None,
         );
         assert!(graph
-            .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
+            .add_dep(
+                crate1,
+                Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
+            )
             .is_ok());
         assert!(graph
-            .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3))
+            .add_dep(
+                crate2,
+                Dependency::new(CrateName::new("crate3").unwrap(), crate3, DependencyKind::Normal)
+            )
             .is_ok());
         assert!(graph
-            .add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1))
+            .add_dep(
+                crate3,
+                Dependency::new(CrateName::new("crate1").unwrap(), crate1, DependencyKind::Normal)
+            )
             .is_err());
     }
 
@@ -846,10 +959,16 @@ mod tests {
             None,
         );
         assert!(graph
-            .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
+            .add_dep(
+                crate1,
+                Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
+            )
             .is_ok());
         assert!(graph
-            .add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
+            .add_dep(
+                crate2,
+                Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
+            )
             .is_err());
     }
 
@@ -896,10 +1015,16 @@ mod tests {
             None,
         );
         assert!(graph
-            .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
+            .add_dep(
+                crate1,
+                Dependency::new(CrateName::new("crate2").unwrap(), crate2, DependencyKind::Normal)
+            )
             .is_ok());
         assert!(graph
-            .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3))
+            .add_dep(
+                crate2,
+                Dependency::new(CrateName::new("crate3").unwrap(), crate3, DependencyKind::Normal)
+            )
             .is_ok());
     }
 
@@ -935,12 +1060,20 @@ mod tests {
         assert!(graph
             .add_dep(
                 crate1,
-                Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2)
+                Dependency::new(
+                    CrateName::normalize_dashes("crate-name-with-dashes"),
+                    crate2,
+                    DependencyKind::Normal
+                )
             )
             .is_ok());
         assert_eq!(
             graph[crate1].dependencies,
-            vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2)]
+            vec![Dependency::new(
+                CrateName::new("crate_name_with_dashes").unwrap(),
+                crate2,
+                DependencyKind::Normal
+            )]
         );
     }
 }
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index c5c4afa30f7..40cfab88afd 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -12,6 +12,7 @@ use rustc_hash::FxHashSet;
 use syntax::{ast, Parse, SourceFile, TextRange, TextSize};
 use triomphe::Arc;
 
+pub use crate::input::DependencyKind;
 pub use crate::{
     change::Change,
     input::{
diff --git a/src/tools/rust-analyzer/crates/cfg/src/lib.rs b/src/tools/rust-analyzer/crates/cfg/src/lib.rs
index 0aeb0b05052..8bbe5e2a8c2 100644
--- a/src/tools/rust-analyzer/crates/cfg/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/cfg/src/lib.rs
@@ -58,6 +58,13 @@ impl CfgOptions {
         self.enabled.insert(CfgAtom::KeyValue { key, value });
     }
 
+    pub fn difference<'a>(
+        &'a self,
+        other: &'a CfgOptions,
+    ) -> impl Iterator<Item = &'a CfgAtom> + 'a {
+        self.enabled.difference(&other.enabled)
+    }
+
     pub fn apply_diff(&mut self, diff: CfgDiff) {
         for atom in diff.enable {
             self.enabled.insert(atom);
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 460a908b6db..4c1b8f306c5 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
@@ -183,15 +183,6 @@ impl DefMap {
         shadow: BuiltinShadowMode,
         expected_macro_subns: Option<MacroSubNs>,
     ) -> ResolvePathResult {
-        let graph = db.crate_graph();
-        let _cx = stdx::panic_context::enter(format!(
-            "DefMap {:?} crate_name={:?} block={:?} path={}",
-            self.krate,
-            graph[self.krate].display_name,
-            self.block,
-            path.display(db.upcast())
-        ));
-
         let mut segments = path.segments().iter().enumerate();
         let mut curr_per_ns = match path.kind {
             PathKind::DollarCrate(krate) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index f2d2451511f..bbcb76a43ff 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -23,10 +23,10 @@ oorandom = "11.1.3"
 tracing.workspace = true
 rustc-hash = "1.1.0"
 scoped-tls = "1.0.0"
-chalk-solve = { version = "0.94.0", default-features = false }
-chalk-ir = "0.94.0"
-chalk-recursive = { version = "0.94.0", default-features = false }
-chalk-derive = "0.94.0"
+chalk-solve = { version = "0.95.0", default-features = false }
+chalk-ir = "0.95.0"
+chalk-recursive = { version = "0.95.0", default-features = false }
+chalk-derive = "0.95.0"
 la-arena.workspace = true
 once_cell = "1.17.0"
 triomphe.workspace = true
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 0a68a9f3b58..ac39bdf5bf5 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
@@ -43,7 +43,7 @@ where
 }
 
 impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
-    pub(super) fn apply_solution(
+    pub(crate) fn apply_solution(
         &self,
         ctx: &mut InferenceTable<'_>,
         solution: Canonical<Substitution>,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index c8a85b4a9ff..04005311b67 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -1097,10 +1097,25 @@ impl<'a> TyLoweringContext<'a> {
                     binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
                 );
                 if let Some(type_ref) = &binding.type_ref {
-                    let ty = self.lower_ty(type_ref);
-                    let alias_eq =
-                        AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
-                    predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
+                    if let (TypeRef::ImplTrait(bounds), ImplTraitLoweringState::Disallowed) =
+                        (type_ref, &self.impl_trait_mode)
+                    {
+                        for bound in bounds {
+                            predicates.extend(
+                                self.lower_type_bound(
+                                    bound,
+                                    TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
+                                        .intern(Interner),
+                                    false,
+                                ),
+                            );
+                        }
+                    } else {
+                        let ty = self.lower_ty(type_ref);
+                        let alias_eq =
+                            AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
+                        predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
+                    }
                 }
                 for bound in binding.bounds.iter() {
                     predicates.extend(self.lower_type_bound(
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 87c93283361..732643566a2 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
@@ -27,8 +27,9 @@ use crate::{
     primitive::{FloatTy, IntTy, UintTy},
     static_lifetime, to_chalk_trait_id,
     utils::all_super_traits,
-    AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, InEnvironment,
-    Interner, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt,
+    AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, Goal, Guidance,
+    InEnvironment, Interner, Scalar, Solution, Substitution, TraitEnvironment, TraitRef,
+    TraitRefExt, Ty, TyBuilder, TyExt,
 };
 
 /// This is used as a key for indexing impls.
@@ -1478,26 +1479,52 @@ fn is_valid_fn_candidate(
             // We need to consider the bounds on the impl to distinguish functions of the same name
             // for a type.
             let predicates = db.generic_predicates(impl_id.into());
-            let valid = predicates
-                .iter()
-                .map(|predicate| {
-                    let (p, b) = predicate
-                        .clone()
-                        .substitute(Interner, &impl_subst)
-                        // Skipping the inner binders is ok, as we don't handle quantified where
-                        // clauses yet.
-                        .into_value_and_skipped_binders();
-                    stdx::always!(b.len(Interner) == 0);
-                    p
-                })
-                // It's ok to get ambiguity here, as we may not have enough information to prove
-                // obligations. We'll check if the user is calling the selected method properly
-                // later anyway.
-                .all(|p| table.try_obligation(p.cast(Interner)).is_some());
-            match valid {
-                true => IsValidCandidate::Yes,
-                false => IsValidCandidate::No,
+            let goals = predicates.iter().map(|p| {
+                let (p, b) = p
+                    .clone()
+                    .substitute(Interner, &impl_subst)
+                    // Skipping the inner binders is ok, as we don't handle quantified where
+                    // clauses yet.
+                    .into_value_and_skipped_binders();
+                stdx::always!(b.len(Interner) == 0);
+
+                p.cast::<Goal>(Interner)
+            });
+
+            for goal in goals.clone() {
+                let in_env = InEnvironment::new(&table.trait_env.env, goal);
+                let canonicalized = table.canonicalize(in_env);
+                let solution = table.db.trait_solve(
+                    table.trait_env.krate,
+                    table.trait_env.block,
+                    canonicalized.value.clone(),
+                );
+
+                match solution {
+                    Some(Solution::Unique(canonical_subst)) => {
+                        canonicalized.apply_solution(
+                            table,
+                            Canonical {
+                                binders: canonical_subst.binders,
+                                value: canonical_subst.value.subst,
+                            },
+                        );
+                    }
+                    Some(Solution::Ambig(Guidance::Definite(substs))) => {
+                        canonicalized.apply_solution(table, substs);
+                    }
+                    Some(_) => (),
+                    None => return IsValidCandidate::No,
+                }
             }
+
+            for goal in goals {
+                if table.try_obligation(goal).is_none() {
+                    return IsValidCandidate::No;
+                }
+            }
+
+            IsValidCandidate::Yes
         } else {
             // For `ItemContainerId::TraitId`, we check if `self_ty` implements the trait in
             // `iterate_trait_method_candidates()`.
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index 48dd9540329..003ae60e8e5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -2598,6 +2598,34 @@ fn test<T: Trait>() {
 }
 
 #[test]
+fn associated_type_in_type_bound() {
+    check_types(
+        r#"
+//- minicore: deref
+fn fb(f: Foo<&u8>) {
+    f.foobar();
+  //^^^^^^^^^^ u8
+}
+trait Bar {
+    fn bar(&self) -> u8;
+}
+impl Bar for u8 {
+    fn bar(&self) -> u8 { *self }
+}
+
+struct Foo<F> {
+    foo: F,
+}
+impl<F: core::ops::Deref<Target = impl Bar>> Foo<F> {
+    fn foobar(&self) -> u8 {
+        self.foo.deref().bar()
+    }
+}
+"#,
+    )
+}
+
+#[test]
 fn dyn_trait_through_chalk() {
     check_types(
         r#"
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index bdc11aa3561..1bfbf7212bf 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -667,21 +667,21 @@ impl Module {
                 let items = &db.trait_data(trait_.into()).items;
                 let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
                     AssocItemId::FunctionId(it) => !db.function_data(it).has_body(),
-                    AssocItemId::ConstId(_) => true,
+                    AssocItemId::ConstId(id) => Const::from(id).value(db).is_none(),
                     AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(),
                 });
-                impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().map(
+                impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().filter_map(
                     |&item| {
-                        (
+                        Some((
                             item,
                             match item {
                                 AssocItemId::FunctionId(it) => db.function_data(it).name.clone(),
                                 AssocItemId::ConstId(it) => {
-                                    db.const_data(it).name.as_ref().unwrap().clone()
+                                    db.const_data(it).name.as_ref()?.clone()
                                 }
                                 AssocItemId::TypeAliasId(it) => db.type_alias_data(it).name.clone(),
                             },
-                        )
+                        ))
                     },
                 ));
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs
index b7d57f02be5..f864ee50c81 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/toggle_ignore.rs
@@ -55,7 +55,7 @@ pub(crate) fn toggle_ignore(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
 }
 
 fn has_ignore_attribute(fn_def: &ast::Fn) -> Option<ast::Attr> {
-    fn_def.attrs().find(|attr| attr.path().map(|it| it.syntax().text() == "ignore") == Some(true))
+    fn_def.attrs().find(|attr| attr.path().is_some_and(|it| it.syntax().text() == "ignore"))
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
index 0bf1782a489..0876246e90b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
@@ -91,7 +91,7 @@ fn add_import(
 ) {
     if let Some(path_segment) = qualifier.segment() {
         // for `<i32 as std::ops::Add>`
-        let path_type = path_segment.syntax().children().filter_map(ast::PathType::cast).last();
+        let path_type = path_segment.qualifying_trait();
         let import = match path_type {
             Some(it) => {
                 if let Some(path) = it.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 c5bbb7f8d75..5bcc867fe18 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
@@ -1095,4 +1095,81 @@ fn test(s: S<Unknown>) {
             "#]],
         );
     }
+
+    #[test]
+    fn assoc_impl_1() {
+        check(
+            r#"
+//- minicore: deref
+fn main() {
+    let foo: Foo<&u8> = Foo::new(&42_u8);
+    foo.$0
+}
+
+trait Bar {
+    fn bar(&self);
+}
+
+impl Bar for u8 {
+    fn bar(&self) {}
+}
+
+struct Foo<F> {
+    foo: F,
+}
+
+impl<F> Foo<F> {
+    fn new(foo: F) -> Foo<F> {
+        Foo { foo }
+    }
+}
+
+impl<F: core::ops::Deref<Target = impl Bar>> Foo<F> {
+    fn foobar(&self) {
+        self.foo.deref().bar()
+    }
+}
+"#,
+            expect![[r#"
+                fd foo      &u8
+                me foobar() fn(&self)
+            "#]],
+        );
+    }
+
+    #[test]
+    fn assoc_impl_2() {
+        check(
+            r#"
+//- minicore: deref
+fn main() {
+    let foo: Foo<&u8> = Foo::new(&42_u8);
+    foo.$0
+}
+
+trait Bar {
+    fn bar(&self);
+}
+
+struct Foo<F> {
+    foo: F,
+}
+
+impl<F> Foo<F> {
+    fn new(foo: F) -> Foo<F> {
+        Foo { foo }
+    }
+}
+
+impl<B: Bar, F: core::ops::Deref<Target = B>> Foo<F> {
+    fn foobar(&self) {
+        self.foo.deref().bar()
+    }
+}
+"#,
+            expect![[r#"
+            fd foo &u8
+        "#]],
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
index ed74ef7b667..99b895eed4d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -26,6 +26,10 @@ use crate::{
 pub struct CompletionItem {
     /// Label in the completion pop up which identifies completion.
     pub label: SmolStr,
+    /// Additional label details in the completion pop up that are
+    /// displayed and aligned on the right side after the label.
+    pub label_detail: Option<SmolStr>,
+
     /// Range of identifier that is being completed.
     ///
     /// It should be used primarily for UI, but we also use this to convert
@@ -425,13 +429,14 @@ impl Builder {
     pub(crate) fn build(self, db: &RootDatabase) -> CompletionItem {
         let _p = profile::span("item::Builder::build");
 
-        let mut label = self.label;
+        let label = self.label;
+        let mut label_detail = None;
         let mut lookup = self.lookup.unwrap_or_else(|| label.clone());
         let insert_text = self.insert_text.unwrap_or_else(|| label.to_string());
 
         if !self.doc_aliases.is_empty() {
             let doc_aliases = self.doc_aliases.iter().join(", ");
-            label = SmolStr::from(format!("{label} (alias {doc_aliases})"));
+            label_detail.replace(SmolStr::from(format!(" (alias {doc_aliases})")));
             let lookup_doc_aliases = self
                 .doc_aliases
                 .iter()
@@ -454,10 +459,17 @@ impl Builder {
         if let [import_edit] = &*self.imports_to_add {
             // snippets can have multiple imports, but normal completions only have up to one
             if let Some(original_path) = import_edit.original_path.as_ref() {
-                label = SmolStr::from(format!("{label} (use {})", original_path.display(db)));
+                label_detail.replace(SmolStr::from(format!(
+                    "{} (use {})",
+                    label_detail.as_deref().unwrap_or_default(),
+                    original_path.display(db)
+                )));
             }
         } else if let Some(trait_name) = self.trait_name {
-            label = SmolStr::from(format!("{label} (as {trait_name})"));
+            label_detail.replace(SmolStr::from(format!(
+                "{} (as {trait_name})",
+                label_detail.as_deref().unwrap_or_default(),
+            )));
         }
 
         let text_edit = match self.text_edit {
@@ -479,6 +491,7 @@ impl Builder {
         CompletionItem {
             source_range: self.source_range,
             label,
+            label_detail,
             text_edit,
             is_snippet: self.is_snippet,
             detail: self.detail,
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 dfe8fe7e2f7..00a9081985b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -557,7 +557,11 @@ mod tests {
 
                 let tag = it.kind.tag();
                 let relevance = display_relevance(it.relevance);
-                items.push(format!("{tag} {} {relevance}\n", it.label));
+                items.push(format!(
+                    "{tag} {}{} {relevance}\n",
+                    it.label,
+                    it.label_detail.clone().unwrap_or_default(),
+                ));
 
                 if let Some((label, _indel, relevance)) = it.ref_match() {
                     let relevance = display_relevance(relevance);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
index 9db8e972dd4..f28afacc586 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
@@ -150,16 +150,29 @@ fn render_completion_list(completions: Vec<CompletionItem>) -> String {
     fn monospace_width(s: &str) -> usize {
         s.chars().count()
     }
-    let label_width =
-        completions.iter().map(|it| monospace_width(&it.label)).max().unwrap_or_default().min(22);
+    let label_width = completions
+        .iter()
+        .map(|it| {
+            monospace_width(&it.label)
+                + monospace_width(it.label_detail.as_deref().unwrap_or_default())
+        })
+        .max()
+        .unwrap_or_default()
+        .min(22);
     completions
         .into_iter()
         .map(|it| {
             let tag = it.kind.tag();
             let var_name = format!("{tag} {}", it.label);
             let mut buf = var_name;
+            if let Some(ref label_detail) = it.label_detail {
+                format_to!(buf, "{label_detail}");
+            }
             if let Some(detail) = it.detail {
-                let width = label_width.saturating_sub(monospace_width(&it.label));
+                let width = label_width.saturating_sub(
+                    monospace_width(&it.label)
+                        + monospace_width(&it.label_detail.unwrap_or_default()),
+                );
                 format_to!(buf, "{:width$} {}", "", detail, width = width);
             }
             if it.deprecated {
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 40d0b6fdd4b..51923797ac9 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
@@ -36,6 +36,19 @@ mod tests {
     use crate::tests::check_diagnostics;
 
     #[test]
+    fn trait_with_default_value() {
+        check_diagnostics(
+            r#"
+trait Marker {
+    const FLAG: bool = false;
+}
+struct Foo;
+impl Marker for Foo {}
+            "#,
+        )
+    }
+
+    #[test]
     fn simple() {
         check_diagnostics(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
index 3d89599c583..9b2ff070c74 100644
--- a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
@@ -108,7 +108,7 @@ fn try_extend_selection(
 
     let node = shallowest_node(&node);
 
-    if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) {
+    if node.parent().is_some_and(|n| list_kinds.contains(&n.kind())) {
         if let Some(range) = extend_list_item(&node) {
             return Some(range);
         }
diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
index 46a0464e9e6..a7f5ae92a4c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -43,7 +43,7 @@ pub struct HighlightRelatedConfig {
 //
 // . if on an identifier, highlights all references to that identifier in the current file
 // .. additionally, if the identifier is a trait in a where clause, type parameter trait bound or use item, highlights all references to that trait's assoc items in the corresponding scope
-// . if on an `async` or `await token, highlights all yield points for that async context
+// . if on an `async` or `await` token, highlights all yield points for that async context
 // . if on a `return` or `fn` keyword, `?` character or `->` return type arrow, highlights all exit points for that context
 // . if on a `break`, `loop`, `while` or `for` token, highlights all break points for that loop or block context
 // . if on a `move` or `|` token that belongs to a closure, highlights all captures of the closure.
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 80897f7478c..931eba11576 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
@@ -49,7 +49,7 @@
 //! user explores them belongs to that extension (it's totally valid to change
 //! rust-project.json over time via configuration request!)
 
-use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, Edition};
+use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, DependencyKind, Edition};
 use la_arena::RawIdx;
 use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::FxHashMap;
@@ -135,6 +135,7 @@ impl ProjectJson {
                                 Dependency::new(
                                     dep_data.name,
                                     CrateId::from_raw(RawIdx::from(dep_data.krate as u32)),
+                                    DependencyKind::Normal,
                                 )
                             })
                             .collect::<Vec<_>>(),
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 7815b9dda77..98f3063bb98 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -249,3 +249,55 @@ fn crate_graph_dedup() {
     crate_graph.extend(regex_crate_graph, &mut regex_proc_macros);
     assert_eq!(crate_graph.iter().count(), 118);
 }
+
+#[test]
+fn test_deduplicate_origin_dev() {
+    let path_map = &mut Default::default();
+    let (mut crate_graph, _proc_macros) =
+        load_cargo_with_sysroot(path_map, "deduplication_crate_graph_A.json");
+    crate_graph.sort_deps();
+    let (crate_graph_1, mut _proc_macros_2) =
+        load_cargo_with_sysroot(path_map, "deduplication_crate_graph_B.json");
+
+    crate_graph.extend(crate_graph_1, &mut _proc_macros_2);
+
+    let mut crates_named_p2 = vec![];
+    for id in crate_graph.iter() {
+        let krate = &crate_graph[id];
+        if let Some(name) = krate.display_name.as_ref() {
+            if name.to_string() == "p2" {
+                crates_named_p2.push(krate);
+            }
+        }
+    }
+
+    assert!(crates_named_p2.len() == 1);
+    let p2 = crates_named_p2[0];
+    assert!(p2.origin.is_local());
+}
+
+#[test]
+fn test_deduplicate_origin_dev_rev() {
+    let path_map = &mut Default::default();
+    let (mut crate_graph, _proc_macros) =
+        load_cargo_with_sysroot(path_map, "deduplication_crate_graph_B.json");
+    crate_graph.sort_deps();
+    let (crate_graph_1, mut _proc_macros_2) =
+        load_cargo_with_sysroot(path_map, "deduplication_crate_graph_A.json");
+
+    crate_graph.extend(crate_graph_1, &mut _proc_macros_2);
+
+    let mut crates_named_p2 = vec![];
+    for id in crate_graph.iter() {
+        let krate = &crate_graph[id];
+        if let Some(name) = krate.display_name.as_ref() {
+            if name.to_string() == "p2" {
+                crates_named_p2.push(krate);
+            }
+        }
+    }
+
+    assert!(crates_named_p2.len() == 1);
+    let p2 = crates_named_p2[0];
+    assert!(p2.origin.is_local());
+}
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 e0209ca15a5..9333570354a 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -6,8 +6,8 @@ use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr,
 
 use anyhow::{format_err, Context};
 use base_db::{
-    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
-    FileId, LangCrateOrigin, ProcMacroPaths, ReleaseChannel, TargetLayoutLoadResult,
+    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, DependencyKind,
+    Edition, Env, FileId, LangCrateOrigin, ProcMacroPaths, ReleaseChannel, TargetLayoutLoadResult,
 };
 use cfg::{CfgDiff, CfgOptions};
 use paths::{AbsPath, AbsPathBuf};
@@ -834,7 +834,7 @@ fn project_json_to_crate_graph(
 
             for dep in &krate.deps {
                 if let Some(&to) = crates.get(&dep.crate_id) {
-                    add_dep(crate_graph, from, dep.name.clone(), to)
+                    add_dep(crate_graph, from, dep.name.clone(), to, dep.kind().to_owned())
                 }
             }
         }
@@ -979,7 +979,7 @@ fn cargo_to_crate_graph(
                     // cargo metadata does not do any normalization,
                     // so we do it ourselves currently
                     let name = CrateName::normalize_dashes(&name);
-                    add_dep(crate_graph, from, name, to);
+                    add_dep(crate_graph, from, name, to, DependencyKind::Normal);
                 }
             }
         }
@@ -999,7 +999,17 @@ fn cargo_to_crate_graph(
                     continue;
                 }
 
-                add_dep(crate_graph, from, name.clone(), to)
+                add_dep(
+                    crate_graph,
+                    from,
+                    name.clone(),
+                    to,
+                    match dep.kind {
+                        DepKind::Normal => DependencyKind::Normal,
+                        DepKind::Dev => DependencyKind::Dev,
+                        DepKind::Build => DependencyKind::Build,
+                    },
+                )
             }
         }
     }
@@ -1187,7 +1197,17 @@ fn handle_rustc_crates(
             let name = CrateName::new(&dep.name).unwrap();
             if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
                 for &from in rustc_pkg_crates.get(&pkg).into_iter().flatten() {
-                    add_dep(crate_graph, from, name.clone(), to);
+                    add_dep(
+                        crate_graph,
+                        from,
+                        name.clone(),
+                        to,
+                        match dep.kind {
+                            DepKind::Normal => DependencyKind::Normal,
+                            DepKind::Dev => DependencyKind::Dev,
+                            DepKind::Build => DependencyKind::Build,
+                        },
+                    );
                 }
             }
         }
@@ -1209,7 +1229,7 @@ fn handle_rustc_crates(
                     // `rust_analyzer` thinks that it should use the one from the `rustc_source`
                     // instead of the one from `crates.io`
                     if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) {
-                        add_dep(crate_graph, *from, name.clone(), to);
+                        add_dep(crate_graph, *from, name.clone(), to, DependencyKind::Normal);
                     }
                 }
             }
@@ -1308,7 +1328,14 @@ impl SysrootPublicDeps {
     /// Makes `from` depend on the public sysroot crates.
     fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) {
         for (name, krate, prelude) in &self.deps {
-            add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude);
+            add_dep_with_prelude(
+                crate_graph,
+                from,
+                name.clone(),
+                *krate,
+                *prelude,
+                DependencyKind::Normal,
+            );
         }
     }
 }
@@ -1363,7 +1390,7 @@ fn sysroot_to_crate_graph(
         for &to in sysroot[from].deps.iter() {
             let name = CrateName::new(&sysroot[to].name).unwrap();
             if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) {
-                add_dep(crate_graph, from, name, to);
+                add_dep(crate_graph, from, name, to, DependencyKind::Normal);
             }
         }
     }
@@ -1442,8 +1469,14 @@ fn handle_hack_cargo_workspace(
         .collect()
 }
 
-fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) {
-    add_dep_inner(graph, from, Dependency::new(name, to))
+fn add_dep(
+    graph: &mut CrateGraph,
+    from: CrateId,
+    name: CrateName,
+    to: CrateId,
+    kind: DependencyKind,
+) {
+    add_dep_inner(graph, from, Dependency::new(name, to, kind))
 }
 
 fn add_dep_with_prelude(
@@ -1452,12 +1485,20 @@ fn add_dep_with_prelude(
     name: CrateName,
     to: CrateId,
     prelude: bool,
+    kind: DependencyKind,
 ) {
-    add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude))
+    add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude, kind))
 }
 
 fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, prelude: bool) {
-    add_dep_with_prelude(crate_graph, from, CrateName::new("proc_macro").unwrap(), to, prelude);
+    add_dep_with_prelude(
+        crate_graph,
+        from,
+        CrateName::new("proc_macro").unwrap(),
+        to,
+        prelude,
+        DependencyKind::Normal,
+    );
 }
 
 fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) {
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_A.json b/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_A.json
new file mode 100644
index 00000000000..b0fb5845cef
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_A.json
@@ -0,0 +1,140 @@
+{
+  "packages": [
+    {
+      "name": "p1",
+      "version": "0.1.0",
+      "id": "p1 0.1.0 (path+file:///example_project/p1)",
+      "license": null,
+      "license_file": null,
+      "description": null,
+      "source": null,
+      "dependencies": [
+        {
+          "name": "p2",
+          "source": null,
+          "req": "*",
+          "kind": null,
+          "rename": null,
+          "optional": false,
+          "uses_default_features": true,
+          "features": [],
+          "target": null,
+          "registry": null,
+          "path": "$ROOT$example_project/p2"
+        }
+      ],
+      "targets": [
+        {
+          "kind": [
+            "lib"
+          ],
+          "crate_types": [
+            "lib"
+          ],
+          "name": "p1",
+          "src_path": "$ROOT$example_project/p1/src/lib.rs",
+          "edition": "2021",
+          "doc": true,
+          "doctest": true,
+          "test": true
+        }
+      ],
+      "features": {},
+      "manifest_path": "$ROOT$example_project/p1/Cargo.toml",
+      "metadata": null,
+      "publish": null,
+      "authors": [],
+      "categories": [],
+      "keywords": [],
+      "readme": null,
+      "repository": null,
+      "homepage": null,
+      "documentation": null,
+      "edition": "2021",
+      "links": null,
+      "default_run": null,
+      "rust_version": null
+    },
+    {
+      "name": "p2",
+      "version": "0.1.0",
+      "id": "p2 0.1.0 (path+file:///example_project/p2)",
+      "license": null,
+      "license_file": null,
+      "description": null,
+      "source": null,
+      "dependencies": [],
+      "targets": [
+        {
+          "kind": [
+            "lib"
+          ],
+          "crate_types": [
+            "lib"
+          ],
+          "name": "p2",
+          "src_path": "$ROOT$example_project/p2/src/lib.rs",
+          "edition": "2021",
+          "doc": true,
+          "doctest": true,
+          "test": true
+        }
+      ],
+      "features": {},
+      "manifest_path": "$ROOT$example_project/p2/Cargo.toml",
+      "metadata": null,
+      "publish": null,
+      "authors": [],
+      "categories": [],
+      "keywords": [],
+      "readme": null,
+      "repository": null,
+      "homepage": null,
+      "documentation": null,
+      "edition": "2021",
+      "links": null,
+      "default_run": null,
+      "rust_version": null
+    }
+  ],
+  "workspace_members": [
+    "p1 0.1.0 (path+file:///example_project/p1)"
+  ],
+  "workspace_default_members": [
+    "p1 0.1.0 (path+file:///example_project/p1)"
+  ],
+  "resolve": {
+    "nodes": [
+      {
+        "id": "p1 0.1.0 (path+file:///example_project/p1)",
+        "dependencies": [
+          "p2 0.1.0 (path+file:///example_project/p2)"
+        ],
+        "deps": [
+          {
+            "name": "p2",
+            "pkg": "p2 0.1.0 (path+file:///example_project/p2)",
+            "dep_kinds": [
+              {
+                "kind": null,
+                "target": null
+              }
+            ]
+          }
+        ],
+        "features": []
+      },
+      {
+        "id": "p2 0.1.0 (path+file:///example_project/p2)",
+        "dependencies": [],
+        "deps": [],
+        "features": []
+      }
+    ],
+    "root": "p1 0.1.0 (path+file:///example_project/p1)"
+  },
+  "target_directory": "$ROOT$example_project/p1/target",
+  "version": 1,
+  "workspace_root": "$ROOT$example_project/p1",
+  "metadata": null
+}
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_B.json b/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_B.json
new file mode 100644
index 00000000000..b5d1e16e62e
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/deduplication_crate_graph_B.json
@@ -0,0 +1,66 @@
+{
+  "packages": [
+    {
+      "name": "p2",
+      "version": "0.1.0",
+      "id": "p2 0.1.0 (path+file:///example_project/p2)",
+      "license": null,
+      "license_file": null,
+      "description": null,
+      "source": null,
+      "dependencies": [],
+      "targets": [
+        {
+          "kind": [
+            "lib"
+          ],
+          "crate_types": [
+            "lib"
+          ],
+          "name": "p2",
+          "src_path": "$ROOT$example_project/p2/src/lib.rs",
+          "edition": "2021",
+          "doc": true,
+          "doctest": true,
+          "test": true
+        }
+      ],
+      "features": {},
+      "manifest_path": "$ROOT$example_project/p2/Cargo.toml",
+      "metadata": null,
+      "publish": null,
+      "authors": [],
+      "categories": [],
+      "keywords": [],
+      "readme": null,
+      "repository": null,
+      "homepage": null,
+      "documentation": null,
+      "edition": "2021",
+      "links": null,
+      "default_run": null,
+      "rust_version": null
+    }
+  ],
+  "workspace_members": [
+    "p2 0.1.0 (path+file:///example_project/p2)"
+  ],
+  "workspace_default_members": [
+    "p2 0.1.0 (path+file:///example_project/p2)"
+  ],
+  "resolve": {
+    "nodes": [
+      {
+        "id": "p2 0.1.0 (path+file:///example_project/p2)",
+        "dependencies": [],
+        "deps": [],
+        "features": []
+      }
+    ],
+    "root": "p2 0.1.0 (path+file:///example_project/p2)"
+  },
+  "target_directory": "$ROOT$example_project/p2/target",
+  "version": 1,
+  "workspace_root": "$ROOT$example_project/p2",
+  "metadata": null
+}
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index 727d39a3077..e98f016ca7d 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -48,6 +48,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -112,6 +113,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -119,6 +121,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -183,6 +186,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -190,6 +194,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -254,6 +259,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -261,6 +267,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index 727d39a3077..e98f016ca7d 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -48,6 +48,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -112,6 +113,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -119,6 +121,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -183,6 +186,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -190,6 +194,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -254,6 +259,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -261,6 +267,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index 89728babd82..7ecd53572e2 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -47,6 +47,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -110,6 +111,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -117,6 +119,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -180,6 +183,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -187,6 +191,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -250,6 +255,7 @@
                 name: CrateName(
                     "hello_world",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -257,6 +263,7 @@
                 name: CrateName(
                     "libc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index b7bf6cb2774..581a6afc148 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -28,6 +28,7 @@
                 name: CrateName(
                     "core",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -168,6 +169,7 @@
                 name: CrateName(
                     "std",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -175,6 +177,7 @@
                 name: CrateName(
                     "core",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -249,6 +252,7 @@
                 name: CrateName(
                     "alloc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -256,6 +260,7 @@
                 name: CrateName(
                     "panic_unwind",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -263,6 +268,7 @@
                 name: CrateName(
                     "panic_abort",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -270,6 +276,7 @@
                 name: CrateName(
                     "core",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -277,6 +284,7 @@
                 name: CrateName(
                     "profiler_builtins",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -284,6 +292,7 @@
                 name: CrateName(
                     "unwind",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -291,6 +300,7 @@
                 name: CrateName(
                     "std_detect",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -298,6 +308,7 @@
                 name: CrateName(
                     "test",
                 ),
+                kind: Normal,
                 prelude: true,
             },
         ],
@@ -438,6 +449,7 @@
                 name: CrateName(
                     "core",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -445,6 +457,7 @@
                 name: CrateName(
                     "alloc",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -452,6 +465,7 @@
                 name: CrateName(
                     "std",
                 ),
+                kind: Normal,
                 prelude: true,
             },
             Dependency {
@@ -459,6 +473,7 @@
                 name: CrateName(
                     "test",
                 ),
+                kind: Normal,
                 prelude: false,
             },
             Dependency {
@@ -466,6 +481,7 @@
                 name: CrateName(
                     "proc_macro",
                 ),
+                kind: Normal,
                 prelude: false,
             },
         ],
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 aca91570f7c..fb366fd5cc4 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
@@ -1,7 +1,7 @@
 //! Conversion of rust-analyzer specific types to lsp_types equivalents.
 use std::{
     iter::once,
-    path,
+    mem, path,
     sync::atomic::{AtomicU32, Ordering},
 };
 
@@ -301,9 +301,11 @@ fn completion_item(
 
     if config.completion_label_details_support() {
         lsp_item.label_details = Some(lsp_types::CompletionItemLabelDetails {
-            detail: None,
+            detail: item.label_detail.as_ref().map(ToString::to_string),
             description: lsp_item.detail.clone(),
         });
+    } else if let Some(label_detail) = item.label_detail {
+        lsp_item.label.push_str(label_detail.as_str());
     }
 
     set_score(&mut lsp_item, max_relevance, item.relevance);
@@ -1123,13 +1125,20 @@ pub(crate) fn snippet_text_document_ops(
 
 pub(crate) fn snippet_workspace_edit(
     snap: &GlobalStateSnapshot,
-    source_change: SourceChange,
+    mut source_change: SourceChange,
 ) -> Cancellable<lsp_ext::SnippetWorkspaceEdit> {
     let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
 
-    for op in source_change.file_system_edits {
-        let ops = snippet_text_document_ops(snap, op)?;
-        document_changes.extend_from_slice(&ops);
+    for op in &mut source_change.file_system_edits {
+        if let FileSystemEdit::CreateFile { dst, initial_contents } = op {
+            // replace with a placeholder to avoid cloneing the edit
+            let op = FileSystemEdit::CreateFile {
+                dst: dst.clone(),
+                initial_contents: mem::take(initial_contents),
+            };
+            let ops = snippet_text_document_ops(snap, op)?;
+            document_changes.extend_from_slice(&ops);
+        }
     }
     for (file_id, (edit, snippet_edit)) in source_change.source_file_edits {
         let edit = snippet_text_document_edit(
@@ -1141,6 +1150,12 @@ pub(crate) fn snippet_workspace_edit(
         )?;
         document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit));
     }
+    for op in source_change.file_system_edits {
+        if !matches!(op, FileSystemEdit::CreateFile { .. }) {
+            let ops = snippet_text_document_ops(snap, op)?;
+            document_changes.extend_from_slice(&ops);
+        }
+    }
     let mut workspace_edit = lsp_ext::SnippetWorkspaceEdit {
         changes: None,
         document_changes: Some(document_changes),
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 d5991429899..5cd02f78404 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
@@ -984,6 +984,11 @@ fn main() {}
 //- /src/old_file.rs
 
 //- /src/old_folder/mod.rs
+mod nested;
+
+//- /src/old_folder/nested.rs
+struct foo;
+use crate::old_folder::nested::foo as bar;
 
 //- /src/from_mod/mod.rs
 
@@ -1080,6 +1085,27 @@ fn main() {}
                   "newText": "new_folder"
                 }
               ]
+            },
+            {
+              "textDocument": {
+                "uri": format!("file://{}", tmp_dir_path.join("src").join("old_folder").join("nested.rs").to_str().unwrap().to_string().replace("C:\\", "/c:/").replace('\\', "/")),
+                "version": null
+              },
+              "edits": [
+                {
+                  "range": {
+                    "start": {
+                      "line": 1,
+                      "character": 11
+                    },
+                    "end": {
+                      "line": 1,
+                      "character": 21
+                    }
+                  },
+                  "newText": "new_folder"
+                }
+              ]
             }
           ]
         }),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs
index 56b5fcef3c2..45adbf5c573 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs
@@ -316,7 +316,7 @@ fn check_trailing_ws(path: &Path, text: &str) {
         return;
     }
     for (line_number, line) in text.lines().enumerate() {
-        if line.chars().last().map(char::is_whitespace) == Some(true) {
+        if line.chars().last().is_some_and(char::is_whitespace) {
             panic!("Trailing whitespace in {} at line {}", path.display(), line_number + 1)
         }
     }
diff --git a/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml b/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml
index ba36fb0b044..cd7ec305936 100644
--- a/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rustc-dependencies/Cargo.toml
@@ -11,10 +11,10 @@ authors.workspace = true
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-ra-ap-rustc_lexer = { version = "0.19.0" }
-ra-ap-rustc_parse_format = { version = "0.14.0", default-features = false }
-ra-ap-rustc_index = { version = "0.19.0", default-features = false }
-ra-ap-rustc_abi = { version = "0.19.0", default-features = false }
+ra-ap-rustc_lexer = { version = "0.20.0" }
+ra-ap-rustc_parse_format = { version = "0.20.0", default-features = false }
+ra-ap-rustc_index = { version = "0.20.0", default-features = false }
+ra-ap-rustc_abi = { version = "0.20.0", default-features = false }
 
 [features]
 in-rust-tree = []
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index 18d5ddd4d0a..9fc19a7d074 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -174,7 +174,7 @@ $ rustup component add rust-analyzer
 
 The `rust-analyzer` binary can be installed from the repos or AUR (Arch User Repository):
 
-- https://www.archlinux.org/packages/community/x86_64/rust-analyzer/[`rust-analyzer`] (built from latest tagged source)
+- https://www.archlinux.org/packages/extra/x86_64/rust-analyzer/[`rust-analyzer`] (built from latest tagged source)
 - https://aur.archlinux.org/packages/rust-analyzer-git[`rust-analyzer-git`] (latest Git version)
 
 Install it with pacman, for example:
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 265c63f3e2d..c43f2b964fd 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -498,6 +498,11 @@
                     "default": true,
                     "type": "boolean"
                 },
+                "rust-analyzer.showRequestFailedErrorNotification": {
+                    "markdownDescription": "Whether to show error notifications for failing requests.",
+                    "default": true,
+                    "type": "boolean"
+                },
                 "rust-analyzer.showDependenciesExplorer": {
                     "markdownDescription": "Whether to show the dependencies view.",
                     "default": true,
diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts
index 96e888402ba..c27a446b380 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -10,6 +10,7 @@ import { type Config, prepareVSCodeConfig } from "./config";
 import { randomUUID } from "crypto";
 import { sep as pathSeparator } from "path";
 import { unwrapUndefinable } from "./undefinable";
+import { RaLanguageClient } from "./lang_client";
 
 export interface Env {
     [name: string]: string;
@@ -363,7 +364,7 @@ export async function createClient(
         },
     };
 
-    const client = new lc.LanguageClient(
+    const client = new RaLanguageClient(
         "rust-analyzer",
         "Rust Analyzer Language Server",
         serverOptions,
diff --git a/src/tools/rust-analyzer/editors/code/src/lang_client.ts b/src/tools/rust-analyzer/editors/code/src/lang_client.ts
new file mode 100644
index 00000000000..09d64efc048
--- /dev/null
+++ b/src/tools/rust-analyzer/editors/code/src/lang_client.ts
@@ -0,0 +1,26 @@
+import * as lc from "vscode-languageclient/node";
+import * as vscode from "vscode";
+
+export class RaLanguageClient extends lc.LanguageClient {
+    override handleFailedRequest<T>(
+        type: lc.MessageSignature,
+        token: vscode.CancellationToken | undefined,
+        error: any,
+        defaultValue: T,
+        showNotification?: boolean | undefined,
+    ): T {
+        const showError = vscode.workspace
+            .getConfiguration("rust-analyzer")
+            .get("showRequestFailedErrorNotification");
+        if (
+            !showError &&
+            error instanceof lc.ResponseError &&
+            error.code === lc.ErrorCodes.InternalError
+        ) {
+            // Don't show notification for internal errors, these are emitted by r-a when a request fails.
+            showNotification = false;
+        }
+
+        return super.handleFailedRequest(type, token, error, defaultValue, showNotification);
+    }
+}
diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
index 8d00813b0d7..be1573913ff 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
+++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
@@ -14,3 +14,4 @@ crossbeam-channel = "0.5.6"
 
 [dev-dependencies]
 lsp-types = "=0.94"
+ctrlc = "3.4.1"
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs b/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs
index affab60a227..b190c0af73d 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs
@@ -17,7 +17,7 @@ use std::{
     net::{TcpListener, TcpStream, ToSocketAddrs},
 };
 
-use crossbeam_channel::{Receiver, Sender};
+use crossbeam_channel::{Receiver, RecvTimeoutError, Sender};
 
 pub use crate::{
     error::{ExtractError, ProtocolError},
@@ -113,11 +113,62 @@ impl Connection {
     /// }
     /// ```
     pub fn initialize_start(&self) -> Result<(RequestId, serde_json::Value), ProtocolError> {
-        loop {
-            break match self.receiver.recv() {
-                Ok(Message::Request(req)) if req.is_initialize() => Ok((req.id, req.params)),
+        self.initialize_start_while(|| true)
+    }
+
+    /// Starts the initialization process by waiting for an initialize as described in
+    /// [`Self::initialize_start`] as long as `running` returns
+    /// `true` while the return value can be changed through a sig handler such as `CTRL + C`.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::sync::atomic::{AtomicBool, Ordering};
+    /// use std::sync::Arc;
+    /// # use std::error::Error;
+    /// # use lsp_types::{ClientCapabilities, InitializeParams, ServerCapabilities};
+    /// # use lsp_server::{Connection, Message, Request, RequestId, Response};
+    /// # fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
+    /// let running = Arc::new(AtomicBool::new(true));
+    /// # running.store(true, Ordering::SeqCst);
+    /// let r = running.clone();
+    ///
+    /// ctrlc::set_handler(move || {
+    ///     r.store(false, Ordering::SeqCst);
+    /// }).expect("Error setting Ctrl-C handler");
+    ///
+    /// let (connection, io_threads) = Connection::stdio();
+    ///
+    /// let res = connection.initialize_start_while(|| running.load(Ordering::SeqCst));
+    /// # assert!(res.is_err());
+    ///
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn initialize_start_while<C>(
+        &self,
+        running: C,
+    ) -> Result<(RequestId, serde_json::Value), ProtocolError>
+    where
+        C: Fn() -> bool,
+    {
+        while running() {
+            let msg = match self.receiver.recv_timeout(std::time::Duration::from_secs(1)) {
+                Ok(msg) => msg,
+                Err(RecvTimeoutError::Timeout) => {
+                    continue;
+                }
+                Err(e) => {
+                    return Err(ProtocolError(format!(
+                        "expected initialize request, got error: {e}"
+                    )))
+                }
+            };
+
+            match msg {
+                Message::Request(req) if req.is_initialize() => return Ok((req.id, req.params)),
                 // Respond to non-initialize requests with ServerNotInitialized
-                Ok(Message::Request(req)) => {
+                Message::Request(req) => {
                     let resp = Response::new_err(
                         req.id.clone(),
                         ErrorCode::ServerNotInitialized as i32,
@@ -126,15 +177,18 @@ impl Connection {
                     self.sender.send(resp.into()).unwrap();
                     continue;
                 }
-                Ok(Message::Notification(n)) if !n.is_exit() => {
+                Message::Notification(n) if !n.is_exit() => {
                     continue;
                 }
-                Ok(msg) => Err(ProtocolError(format!("expected initialize request, got {msg:?}"))),
-                Err(e) => {
-                    Err(ProtocolError(format!("expected initialize request, got error: {e}")))
+                msg => {
+                    return Err(ProtocolError(format!("expected initialize request, got {msg:?}")));
                 }
             };
         }
+
+        return Err(ProtocolError(String::from(
+            "Initialization has been aborted during initialization",
+        )));
     }
 
     /// Finishes the initialization process by sending an `InitializeResult` to the client
@@ -156,6 +210,51 @@ impl Connection {
         }
     }
 
+    /// Finishes the initialization process as described in [`Self::initialize_finish`] as
+    /// long as `running` returns `true` while the return value can be changed through a sig
+    /// handler such as `CTRL + C`.
+    pub fn initialize_finish_while<C>(
+        &self,
+        initialize_id: RequestId,
+        initialize_result: serde_json::Value,
+        running: C,
+    ) -> Result<(), ProtocolError>
+    where
+        C: Fn() -> bool,
+    {
+        let resp = Response::new_ok(initialize_id, initialize_result);
+        self.sender.send(resp.into()).unwrap();
+
+        while running() {
+            let msg = match self.receiver.recv_timeout(std::time::Duration::from_secs(1)) {
+                Ok(msg) => msg,
+                Err(RecvTimeoutError::Timeout) => {
+                    continue;
+                }
+                Err(e) => {
+                    return Err(ProtocolError(format!(
+                        "expected initialized notification, got error: {e}",
+                    )));
+                }
+            };
+
+            match msg {
+                Message::Notification(n) if n.is_initialized() => {
+                    return Ok(());
+                }
+                msg => {
+                    return Err(ProtocolError(format!(
+                        r#"expected initialized notification, got: {msg:?}"#
+                    )));
+                }
+            }
+        }
+
+        return Err(ProtocolError(String::from(
+            "Initialization has been aborted during initialization",
+        )));
+    }
+
     /// Initialize the connection. Sends the server capabilities
     /// to the client and returns the serialized client capabilities
     /// on success. If more fine-grained initialization is required use
@@ -198,6 +297,58 @@ impl Connection {
         Ok(params)
     }
 
+    /// Initialize the connection as described in [`Self::initialize`] as long as `running` returns
+    /// `true` while the return value can be changed through a sig handler such as `CTRL + C`.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::sync::atomic::{AtomicBool, Ordering};
+    /// use std::sync::Arc;
+    /// # use std::error::Error;
+    /// # use lsp_types::ServerCapabilities;
+    /// # use lsp_server::{Connection, Message, Request, RequestId, Response};
+    ///
+    /// # fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
+    /// let running = Arc::new(AtomicBool::new(true));
+    /// # running.store(true, Ordering::SeqCst);
+    /// let r = running.clone();
+    ///
+    /// ctrlc::set_handler(move || {
+    ///     r.store(false, Ordering::SeqCst);
+    /// }).expect("Error setting Ctrl-C handler");
+    ///
+    /// let (connection, io_threads) = Connection::stdio();
+    ///
+    /// let server_capabilities = serde_json::to_value(&ServerCapabilities::default()).unwrap();
+    /// let initialization_params = connection.initialize_while(
+    ///     server_capabilities,
+    ///     || running.load(Ordering::SeqCst)
+    /// );
+    ///
+    /// # assert!(initialization_params.is_err());
+    /// # Ok(())
+    /// # }
+    /// ```
+    pub fn initialize_while<C>(
+        &self,
+        server_capabilities: serde_json::Value,
+        running: C,
+    ) -> Result<serde_json::Value, ProtocolError>
+    where
+        C: Fn() -> bool,
+    {
+        let (id, params) = self.initialize_start_while(&running)?;
+
+        let initialize_data = serde_json::json!({
+            "capabilities": server_capabilities,
+        });
+
+        self.initialize_finish_while(id, initialize_data, running)?;
+
+        Ok(params)
+    }
+
     /// If `req` is `Shutdown`, respond to it and return `true`, otherwise return `false`
     pub fn handle_shutdown(&self, req: &Request) -> Result<bool, ProtocolError> {
         if !req.is_shutdown() {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index f36893bfb94..1f8edd7937b 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -129,7 +129,6 @@ const EXCEPTIONS_CARGO: ExceptionList = &[
 const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[
     // tidy-alphabetical-start
     ("dissimilar", "Apache-2.0"),
-    ("instant", "BSD-3-Clause"),
     ("notify", "CC0-1.0"),
     ("pulldown-cmark-to-cmark", "Apache-2.0"),
     ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0
diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs
index 4e296f3ade5..4aeecf92d86 100644
--- a/tests/assembly/asm/loongarch-type.rs
+++ b/tests/assembly/asm/loongarch-type.rs
@@ -1,4 +1,3 @@
-// min-llvm-version: 16.0
 // assembly-output: emit-asm
 // compile-flags: --target loongarch64-unknown-linux-gnu
 // needs-llvm-components: loongarch
@@ -42,7 +41,7 @@ extern "C" {
 
 // Hack to avoid function merging
 extern "Rust" {
-   fn dont_merge(s: &str);
+    fn dont_merge(s: &str);
 }
 
 // CHECK-LABEL: sym_fn:
diff --git a/tests/assembly/x86-stack-probes.rs b/tests/assembly/x86-stack-probes.rs
index c7141fb208a..64a4efc0e18 100644
--- a/tests/assembly/x86-stack-probes.rs
+++ b/tests/assembly/x86-stack-probes.rs
@@ -1,4 +1,3 @@
-// min-llvm-version: 16
 // revisions: x86_64 i686
 // assembly-output: emit-asm
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
diff --git a/tests/codegen/issues/issue-101048.rs b/tests/codegen/issues/issue-101048.rs
index efa4db93ec2..e4712cf9cb3 100644
--- a/tests/codegen/issues/issue-101048.rs
+++ b/tests/codegen/issues/issue-101048.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 16
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/issues/issue-101082.rs b/tests/codegen/issues/issue-101082.rs
index 2cbe99942cb..58fcd75a8f2 100644
--- a/tests/codegen/issues/issue-101082.rs
+++ b/tests/codegen/issues/issue-101082.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 16
 // ignore-debug: the debug assertions get in the way
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/issues/issue-101814.rs b/tests/codegen/issues/issue-101814.rs
index 13796352c02..63a8cebcb60 100644
--- a/tests/codegen/issues/issue-101814.rs
+++ b/tests/codegen/issues/issue-101814.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 16
 // ignore-debug: the debug assertions get in the way
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/issues/issue-103132.rs b/tests/codegen/issues/issue-103132.rs
index cc87d7cd2b9..521d424c269 100644
--- a/tests/codegen/issues/issue-103132.rs
+++ b/tests/codegen/issues/issue-103132.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O -C overflow-checks
-// min-llvm-version: 16
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/issues/issue-103327.rs b/tests/codegen/issues/issue-103327.rs
index cee00faccc8..021f1ca0c3a 100644
--- a/tests/codegen/issues/issue-103327.rs
+++ b/tests/codegen/issues/issue-103327.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 16
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/issues/issue-103840.rs b/tests/codegen/issues/issue-103840.rs
index da64692d27d..f19d7031bb3 100644
--- a/tests/codegen/issues/issue-103840.rs
+++ b/tests/codegen/issues/issue-103840.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 16.0
 #![crate_type = "lib"]
 
 pub fn foo(t: &mut Vec<usize>) {
diff --git a/tests/codegen/issues/issue-75978.rs b/tests/codegen/issues/issue-75978.rs
index f335e92c3dc..abfafc35f0b 100644
--- a/tests/codegen/issues/issue-75978.rs
+++ b/tests/codegen/issues/issue-75978.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 16
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/issues/issue-99960.rs b/tests/codegen/issues/issue-99960.rs
index e9c9367fa64..ad0315a8227 100644
--- a/tests/codegen/issues/issue-99960.rs
+++ b/tests/codegen/issues/issue-99960.rs
@@ -1,5 +1,4 @@
 // compile-flags: -O
-// min-llvm-version: 16
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs
index 29d50d8df24..18d315c9598 100644
--- a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs
+++ b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs
@@ -6,10 +6,8 @@
 //[aarch64] needs-llvm-components: aarch64
 //[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf
 //[riscv64imac] needs-llvm-components: riscv
-//[riscv64imac] min-llvm-version: 16
 //[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf
 //[riscv64gc] needs-llvm-components: riscv
-//[riscv64gc] min-llvm-version: 16
 //[x86_64] compile-flags: --target x86_64-unknown-none
 //[x86_64] needs-llvm-components: x86
 
diff --git a/tests/codegen/slice-iter-fold.rs b/tests/codegen/slice-iter-fold.rs
index 9391c176130..a55425cb6bb 100644
--- a/tests/codegen/slice-iter-fold.rs
+++ b/tests/codegen/slice-iter-fold.rs
@@ -1,6 +1,5 @@
 // ignore-debug: the debug assertions get in the way
 // compile-flags: -O
-// min-llvm-version: 16
 #![crate_type = "lib"]
 
 // CHECK-LABEL: @slice_fold_to_last
diff --git a/tests/codegen/stack-probes-call.rs b/tests/codegen/stack-probes-call.rs
deleted file mode 100644
index a18fd41c28c..00000000000
--- a/tests/codegen/stack-probes-call.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Check the "probe-stack" attribute for targets with `StackProbeType::Call`,
-// or `StackProbeType::InlineOrCall` when running on older LLVM.
-
-// compile-flags: -C no-prepopulate-passes
-// revisions: i686 x86_64
-//[i686] compile-flags: --target i686-unknown-linux-gnu
-//[i686] needs-llvm-components: x86
-//[i686] ignore-llvm-version: 16 - 99
-//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
-//[x86_64] needs-llvm-components: x86
-//[x86_64] ignore-llvm-version: 16 - 99
-
-#![crate_type = "rlib"]
-#![feature(no_core, lang_items)]
-#![no_core]
-
-#[lang = "sized"]
-trait Sized {}
-
-#[no_mangle]
-pub fn foo() {
-// CHECK: @foo() unnamed_addr #0
-// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
-}
diff --git a/tests/codegen/stack-probes-inline.rs b/tests/codegen/stack-probes-inline.rs
index a6b781de531..058c363969f 100644
--- a/tests/codegen/stack-probes-inline.rs
+++ b/tests/codegen/stack-probes-inline.rs
@@ -13,10 +13,8 @@
 //[s390x] needs-llvm-components: systemz
 //[i686] compile-flags: --target i686-unknown-linux-gnu
 //[i686] needs-llvm-components: x86
-//[i686] min-llvm-version: 16
 //[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
 //[x86_64] needs-llvm-components: x86
-//[x86_64] min-llvm-version: 16
 
 #![crate_type = "rlib"]
 #![feature(no_core, lang_items)]
diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs
index d68067ceb19..5cf7add836d 100644
--- a/tests/codegen/vec-in-place.rs
+++ b/tests/codegen/vec-in-place.rs
@@ -1,6 +1,5 @@
 // ignore-debug: the debug assertions get in the way
 // compile-flags: -O -Z merge-functions=disabled
-// min-llvm-version: 16
 #![crate_type = "lib"]
 
 // Ensure that trivial casts of vec elements are O(1)
diff --git a/tests/run-make/compressed-debuginfo/Makefile b/tests/run-make/compressed-debuginfo/Makefile
index f9e4927d008..d2f24dde00d 100644
--- a/tests/run-make/compressed-debuginfo/Makefile
+++ b/tests/run-make/compressed-debuginfo/Makefile
@@ -2,7 +2,6 @@
 include ../tools.mk
 
 # only-linux
-# min-llvm-version: 16.0
 #
 # This tests debuginfo-compression.
 
diff --git a/tests/run-make/pass-linker-flags-flavor/Makefile b/tests/run-make/pass-linker-flags-flavor/Makefile
new file mode 100644
index 00000000000..bd3d3ed882f
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-flavor/Makefile
@@ -0,0 +1,8 @@
+# only-linux
+
+include ../tools.mk
+
+all:
+	$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3'
+	$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg:+verbatim=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3'
+	$(RUSTC) rs.rs -Z unstable-options -C linker-flavor=ld -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*"a2".*d1.*"a3"'
diff --git a/tests/run-make/pass-linker-flags-flavor/rs.rs b/tests/run-make/pass-linker-flags-flavor/rs.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/pass-linker-flags-flavor/rs.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs b/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs
new file mode 100644
index 00000000000..b6993f66fe7
--- /dev/null
+++ b/tests/ui/associated-inherent-types/assoc-inherent-late-bound.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+struct Foo<T>(T);
+
+impl<'a> Foo<fn(&'a ())> {
+    type Assoc = &'a ();
+}
+
+fn bar(_: for<'a> fn(Foo<fn(Foo<fn(&'static ())>::Assoc)>::Assoc)) {}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs
index f4ad5d7ff6c..dd62e59f07d 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.rs
+++ b/tests/ui/associated-inherent-types/issue-111404-1.rs
@@ -9,5 +9,6 @@ impl<'a> Foo<fn(&'a ())> {
 
 fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
 //~^ ERROR higher-ranked subtype error
+//~| ERROR higher-ranked subtype error
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr
index 2c78e3a1fb7..cf4d4a5f19b 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr
@@ -4,5 +4,13 @@ error: higher-ranked subtype error
 LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: higher-ranked subtype error
+  --> $DIR/issue-111404-1.rs:10:1
+   |
+LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
index 272d3e74b9c..6f0a6b04333 100644
--- a/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
@@ -14,7 +14,6 @@ LL |     fn test(&self) -> [u8; bar::<Self>()];
    |        |
    |        ...because method `test` references the `Self` type in its `where` clause
    = help: consider moving `test` to another trait
-   = help: consider moving `test` to another trait
    = help: only type `()` implements the trait, consider using it directly instead
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/const_prop/apfloat-f64-roundtrip.rs b/tests/ui/const_prop/apfloat-f64-roundtrip.rs
index 9fb2ac96beb..5f3ec931c82 100644
--- a/tests/ui/const_prop/apfloat-f64-roundtrip.rs
+++ b/tests/ui/const_prop/apfloat-f64-roundtrip.rs
@@ -1,6 +1,5 @@
 // run-pass
 // compile-flags: -O -Zmir-opt-level=3 -Cno-prepopulate-passes
-// min-llvm-version: 16.0 (requires APFloat fixes in LLVM)
 
 // Regression test for a broken MIR optimization (issue #113407).
 pub fn main() {
diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
index c8a99b2d078..43e664ce413 100644
--- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:21:1
+  --> $DIR/raw-bytes.rs:22:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag
@@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:29:1
+  --> $DIR/raw-bytes.rs:30:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag
@@ -21,7 +21,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:43:1
+  --> $DIR/raw-bytes.rs:44:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
@@ -32,7 +32,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:45:1
+  --> $DIR/raw-bytes.rs:46:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
@@ -43,7 +43,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:51:1
+  --> $DIR/raw-bytes.rs:52:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
@@ -54,7 +54,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:55:1
+  --> $DIR/raw-bytes.rs:57:1
    |
 LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -65,7 +65,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:58:1
+  --> $DIR/raw-bytes.rs:60:1
    |
 LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -76,7 +76,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:60:1
+  --> $DIR/raw-bytes.rs:62:1
    |
 LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -87,7 +87,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:66:1
+  --> $DIR/raw-bytes.rs:68:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30
@@ -98,7 +98,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:72:1
+  --> $DIR/raw-bytes.rs:74:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30
@@ -109,7 +109,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:75:1
+  --> $DIR/raw-bytes.rs:77:1
    |
 LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -120,7 +120,7 @@ LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:83:1
+  --> $DIR/raw-bytes.rs:85:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
@@ -131,7 +131,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:87:1
+  --> $DIR/raw-bytes.rs:89:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
@@ -142,7 +142,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:91:1
+  --> $DIR/raw-bytes.rs:93:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
@@ -153,7 +153,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:94:1
+  --> $DIR/raw-bytes.rs:96:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -164,7 +164,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:97:1
+  --> $DIR/raw-bytes.rs:99:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
@@ -175,7 +175,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:100:1
+  --> $DIR/raw-bytes.rs:102:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
@@ -186,7 +186,7 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:103:1
+  --> $DIR/raw-bytes.rs:105:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -197,7 +197,7 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:105:1
+  --> $DIR/raw-bytes.rs:107:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -208,7 +208,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:107:1
+  --> $DIR/raw-bytes.rs:109:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer
@@ -219,7 +219,7 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:113:1
+  --> $DIR/raw-bytes.rs:115:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar
@@ -230,7 +230,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:138:1
+  --> $DIR/raw-bytes.rs:140:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
@@ -241,7 +241,7 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:140:1
+  --> $DIR/raw-bytes.rs:142:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -252,7 +252,7 @@ LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, us
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:142:1
+  --> $DIR/raw-bytes.rs:144:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -263,7 +263,7 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize:
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:145:1
+  --> $DIR/raw-bytes.rs:147:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
@@ -274,7 +274,7 @@ LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:147:1
+  --> $DIR/raw-bytes.rs:149:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
@@ -285,7 +285,7 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:149:1
+  --> $DIR/raw-bytes.rs:151:1
    |
 LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered a pointer, but expected a string
@@ -298,7 +298,7 @@ LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:153:1
+  --> $DIR/raw-bytes.rs:155:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
@@ -309,7 +309,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:155:1
+  --> $DIR/raw-bytes.rs:157:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -320,7 +320,7 @@ LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, is
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:158:1
+  --> $DIR/raw-bytes.rs:160:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
@@ -331,7 +331,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:161:1
+  --> $DIR/raw-bytes.rs:163:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
@@ -342,13 +342,13 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
            }
 
 note: erroneous constant encountered
-  --> $DIR/raw-bytes.rs:161:40
+  --> $DIR/raw-bytes.rs:163:40
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:167:1
+  --> $DIR/raw-bytes.rs:169:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
@@ -359,13 +359,13 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3
            }
 
 note: erroneous constant encountered
-  --> $DIR/raw-bytes.rs:167:42
+  --> $DIR/raw-bytes.rs:169:42
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:171:1
+  --> $DIR/raw-bytes.rs:173:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
@@ -376,13 +376,13 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran
            }
 
 note: erroneous constant encountered
-  --> $DIR/raw-bytes.rs:171:42
+  --> $DIR/raw-bytes.rs:173:42
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:176:1
+  --> $DIR/raw-bytes.rs:178:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer
@@ -393,7 +393,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:180:1
+  --> $DIR/raw-bytes.rs:182:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer
@@ -404,7 +404,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:184:1
+  --> $DIR/raw-bytes.rs:186:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
@@ -415,7 +415,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:187:1
+  --> $DIR/raw-bytes.rs:189:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer
@@ -426,7 +426,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:191:1
+  --> $DIR/raw-bytes.rs:193:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -437,7 +437,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:195:1
+  --> $DIR/raw-bytes.rs:197:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
@@ -448,7 +448,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:197:1
+  --> $DIR/raw-bytes.rs:199:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer
@@ -459,29 +459,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:202:1
-   |
-LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000000, but expected a valid enum tag
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               00 00 00 00 00 10 00 00                         │ ........
-           }
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:206:1
-   |
-LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000003, but expected a valid enum tag
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 8, align: 4) {
-               03 00 00 00 09 00 00 00                         │ ........
-           }
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:210:1
+  --> $DIR/raw-bytes.rs:203:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1]
@@ -492,7 +470,7 @@ LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:211:1
+  --> $DIR/raw-bytes.rs:204:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
@@ -503,7 +481,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:212:1
+  --> $DIR/raw-bytes.rs:205:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
    | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
@@ -514,7 +492,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:216:1
+  --> $DIR/raw-bytes.rs:209:1
    |
 LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
@@ -525,7 +503,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:219:1
+  --> $DIR/raw-bytes.rs:212:1
    |
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
@@ -538,7 +516,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem:
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:222:1
+  --> $DIR/raw-bytes.rs:215:1
    |
 LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
@@ -549,7 +527,7 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:226:1
+  --> $DIR/raw-bytes.rs:219:1
    |
 LL | pub static S7: &[u16] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
@@ -560,7 +538,7 @@ LL | pub static S7: &[u16] = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:233:1
+  --> $DIR/raw-bytes.rs:226:1
    |
 LL | pub static R4: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
@@ -571,7 +549,7 @@ LL | pub static R4: &[u8] = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:238:1
+  --> $DIR/raw-bytes.rs:231:1
    |
 LL | pub static R5: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
@@ -584,7 +562,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:243:1
+  --> $DIR/raw-bytes.rs:236:1
    |
 LL | pub static R6: &[bool] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
@@ -594,6 +572,6 @@ LL | pub static R6: &[bool] = unsafe {
                ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
 
-error: aborting due to 52 previous errors
+error: aborting due to 50 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
index 118ab6019d6..1427cef7d03 100644
--- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:21:1
+  --> $DIR/raw-bytes.rs:22:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000001, but expected a valid enum tag
@@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:29:1
+  --> $DIR/raw-bytes.rs:30:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag
@@ -21,7 +21,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:43:1
+  --> $DIR/raw-bytes.rs:44:1
    |
 LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
@@ -32,7 +32,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:45:1
+  --> $DIR/raw-bytes.rs:46:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
@@ -43,7 +43,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:51:1
+  --> $DIR/raw-bytes.rs:52:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
@@ -54,7 +54,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:55:1
+  --> $DIR/raw-bytes.rs:57:1
    |
 LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -65,7 +65,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:58:1
+  --> $DIR/raw-bytes.rs:60:1
    |
 LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -76,7 +76,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:60:1
+  --> $DIR/raw-bytes.rs:62:1
    |
 LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -87,7 +87,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:66:1
+  --> $DIR/raw-bytes.rs:68:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30
@@ -98,7 +98,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:72:1
+  --> $DIR/raw-bytes.rs:74:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30
@@ -109,7 +109,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:75:1
+  --> $DIR/raw-bytes.rs:77:1
    |
 LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -120,7 +120,7 @@ LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:83:1
+  --> $DIR/raw-bytes.rs:85:1
    |
 LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
@@ -131,7 +131,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:87:1
+  --> $DIR/raw-bytes.rs:89:1
    |
 LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
@@ -142,7 +142,7 @@ LL | const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:91:1
+  --> $DIR/raw-bytes.rs:93:1
    |
 LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference
@@ -153,7 +153,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:94:1
+  --> $DIR/raw-bytes.rs:96:1
    |
 LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box
@@ -164,7 +164,7 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:97:1
+  --> $DIR/raw-bytes.rs:99:1
    |
 LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance)
@@ -175,7 +175,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:100:1
+  --> $DIR/raw-bytes.rs:102:1
    |
 LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance)
@@ -186,7 +186,7 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:103:1
+  --> $DIR/raw-bytes.rs:105:1
    |
 LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -197,7 +197,7 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:105:1
+  --> $DIR/raw-bytes.rs:107:1
    |
 LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -208,7 +208,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:107:1
+  --> $DIR/raw-bytes.rs:109:1
    |
 LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC3, but expected a function pointer
@@ -219,7 +219,7 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:113:1
+  --> $DIR/raw-bytes.rs:115:1
    |
 LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar
@@ -230,7 +230,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:138:1
+  --> $DIR/raw-bytes.rs:140:1
    |
 LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
@@ -241,7 +241,7 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:140:1
+  --> $DIR/raw-bytes.rs:142:1
    |
 LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -252,7 +252,7 @@ LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, us
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:142:1
+  --> $DIR/raw-bytes.rs:144:1
    |
 LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -263,7 +263,7 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize:
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:145:1
+  --> $DIR/raw-bytes.rs:147:1
    |
 LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized memory, but expected a string
@@ -274,7 +274,7 @@ LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:147:1
+  --> $DIR/raw-bytes.rs:149:1
    |
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized memory, but expected a string
@@ -285,7 +285,7 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:149:1
+  --> $DIR/raw-bytes.rs:151:1
    |
 LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered a pointer, but expected a string
@@ -298,7 +298,7 @@ LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:153:1
+  --> $DIR/raw-bytes.rs:155:1
    |
 LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
@@ -309,7 +309,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:155:1
+  --> $DIR/raw-bytes.rs:157:1
    |
 LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -320,7 +320,7 @@ LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, is
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:158:1
+  --> $DIR/raw-bytes.rs:160:1
    |
 LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
@@ -331,7 +331,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:161:1
+  --> $DIR/raw-bytes.rs:163:1
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
@@ -342,13 +342,13 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
            }
 
 note: erroneous constant encountered
-  --> $DIR/raw-bytes.rs:161:40
+  --> $DIR/raw-bytes.rs:163:40
    |
 LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:167:1
+  --> $DIR/raw-bytes.rs:169:1
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
@@ -359,13 +359,13 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3
            }
 
 note: erroneous constant encountered
-  --> $DIR/raw-bytes.rs:167:42
+  --> $DIR/raw-bytes.rs:169:42
    |
 LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:171:1
+  --> $DIR/raw-bytes.rs:173:1
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
@@ -376,13 +376,13 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran
            }
 
 note: erroneous constant encountered
-  --> $DIR/raw-bytes.rs:171:42
+  --> $DIR/raw-bytes.rs:173:42
    |
 LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:176:1
+  --> $DIR/raw-bytes.rs:178:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC17, but expected a vtable pointer
@@ -393,7 +393,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:180:1
+  --> $DIR/raw-bytes.rs:182:1
    |
 LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC19, but expected a vtable pointer
@@ -404,7 +404,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:184:1
+  --> $DIR/raw-bytes.rs:186:1
    |
 LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
@@ -415,7 +415,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:187:1
+  --> $DIR/raw-bytes.rs:189:1
    |
 LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered ALLOC22, but expected a vtable pointer
@@ -426,7 +426,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:191:1
+  --> $DIR/raw-bytes.rs:193:1
    |
 LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -437,7 +437,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:195:1
+  --> $DIR/raw-bytes.rs:197:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
@@ -448,7 +448,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:197:1
+  --> $DIR/raw-bytes.rs:199:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered ALLOC27, but expected a vtable pointer
@@ -459,29 +459,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:202:1
-   |
-LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               00 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 │ ................
-           }
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:206:1
-   |
-LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000003, but expected a valid enum tag
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: 16, align: 8) {
-               03 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00 │ ................
-           }
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:210:1
+  --> $DIR/raw-bytes.rs:203:1
    |
 LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1]
@@ -492,7 +470,7 @@ LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:211:1
+  --> $DIR/raw-bytes.rs:204:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
    | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
@@ -503,7 +481,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:212:1
+  --> $DIR/raw-bytes.rs:205:1
    |
 LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
    | ^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a value of the never type `!`
@@ -514,7 +492,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:216:1
+  --> $DIR/raw-bytes.rs:209:1
    |
 LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
@@ -525,7 +503,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:219:1
+  --> $DIR/raw-bytes.rs:212:1
    |
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
@@ -538,7 +516,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem:
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:222:1
+  --> $DIR/raw-bytes.rs:215:1
    |
 LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
@@ -549,7 +527,7 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4)
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:226:1
+  --> $DIR/raw-bytes.rs:219:1
    |
 LL | pub static S7: &[u16] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[1]: encountered uninitialized memory, but expected an integer
@@ -560,7 +538,7 @@ LL | pub static S7: &[u16] = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:233:1
+  --> $DIR/raw-bytes.rs:226:1
    |
 LL | pub static R4: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered uninitialized memory, but expected an integer
@@ -571,7 +549,7 @@ LL | pub static R4: &[u8] = unsafe {
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:238:1
+  --> $DIR/raw-bytes.rs:231:1
    |
 LL | pub static R5: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered a pointer, but expected an integer
@@ -584,7 +562,7 @@ LL | pub static R5: &[u8] = unsafe {
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/raw-bytes.rs:243:1
+  --> $DIR/raw-bytes.rs:236:1
    |
 LL | pub static R6: &[bool] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x11, but expected a boolean
@@ -594,6 +572,6 @@ LL | pub static R6: &[bool] = unsafe {
                ╾ALLOC_ID╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
            }
 
-error: aborting due to 52 previous errors
+error: aborting due to 50 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs
index aa4a41a7caa..ff2a32d5757 100644
--- a/tests/ui/consts/const-eval/raw-bytes.rs
+++ b/tests/ui/consts/const-eval/raw-bytes.rs
@@ -1,7 +1,6 @@
 // stderr-per-bitwidth
 // ignore-endian-big
 // ignore-tidy-linelength
-// ignore-debug debug assertions catch some UB too early
 // normalize-stderr-test "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?─*╼" -> "╾ALLOC_ID$1╼"
 
 #![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)]
@@ -13,6 +12,8 @@ use std::ptr::NonNull;
 use std::num::{NonZeroU8, NonZeroUsize};
 use std::slice::{from_ptr_range, from_raw_parts};
 
+// # Bad enums and chars
+
 #[repr(usize)]
 #[derive(Copy, Clone)]
 enum Enum {
@@ -51,6 +52,7 @@ const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8)
 const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
 //~^ ERROR is undefined behavior
 
+// # Bad pointers and references
 
 const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
 //~^ ERROR it is undefined behavior to use this value
@@ -197,16 +199,7 @@ const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92
 const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
 //~^ ERROR it is undefined behavior to use this value
 
-
-// not ok, since alignment needs to be non-zero.
-const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
-//~^ ERROR it is undefined behavior to use this value
-
-// not ok, since alignment needs to be a power of two.
-const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) };
-//~^ ERROR it is undefined behavior to use this value
-
-
+// Uninhabited types
 const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
 const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior
 const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; //~ ERROR undefined behavior
diff --git a/tests/ui/consts/std/alloc.32bit.stderr b/tests/ui/consts/std/alloc.32bit.stderr
deleted file mode 100644
index 8c83df53dad..00000000000
--- a/tests/ui/consts/std/alloc.32bit.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/alloc.rs:12:1
-   |
-LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000000, but expected a valid enum tag
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/alloc.rs:16:1
-   |
-LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x00000003, but expected a valid enum tag
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/std/alloc.64bit.stderr b/tests/ui/consts/std/alloc.64bit.stderr
deleted file mode 100644
index addedad1704..00000000000
--- a/tests/ui/consts/std/alloc.64bit.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/alloc.rs:12:1
-   |
-LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/alloc.rs:16:1
-   |
-LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.<enum-tag>: encountered 0x0000000000000003, but expected a valid enum tag
-   |
-   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
-   = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
-               HEX_DUMP
-           }
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/std/alloc.rs b/tests/ui/consts/std/alloc.rs
deleted file mode 100644
index a456a672293..00000000000
--- a/tests/ui/consts/std/alloc.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// stderr-per-bitwidth
-// Strip out raw byte dumps to make comparison platform-independent:
-// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
-// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*a(lloc)?[0-9]+(\+[a-z0-9]+)?─*╼ )+ *│.*" -> "HEX_DUMP"
-// ignore-debug debug assertions catch some UB too early
-use std::alloc::Layout;
-
-// ok
-const LAYOUT_VALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x08) };
-
-// not ok, since alignment needs to be non-zero.
-const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
-//~^ ERROR it is undefined behavior to use this value
-
-// not ok, since alignment needs to be a power of two.
-const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) };
-//~^ ERROR it is undefined behavior to use this value
-
-fn main() {}
diff --git a/tests/ui/match/match-tail-expr-never-type-error.rs b/tests/ui/match/match-tail-expr-never-type-error.rs
new file mode 100644
index 00000000000..786ed3fa904
--- /dev/null
+++ b/tests/ui/match/match-tail-expr-never-type-error.rs
@@ -0,0 +1,16 @@
+fn never() -> ! {
+    loop {}
+}
+
+fn bar(a: bool) {
+    match a {
+        true => 1,
+        false => {
+            never() //~ ERROR `match` arms have incompatible types
+        }
+    }
+}
+fn main() {
+    bar(true);
+    bar(false);
+}
diff --git a/tests/ui/match/match-tail-expr-never-type-error.stderr b/tests/ui/match/match-tail-expr-never-type-error.stderr
new file mode 100644
index 00000000000..226d33daeb2
--- /dev/null
+++ b/tests/ui/match/match-tail-expr-never-type-error.stderr
@@ -0,0 +1,21 @@
+error[E0308]: `match` arms have incompatible types
+  --> $DIR/match-tail-expr-never-type-error.rs:9:13
+   |
+LL |   fn bar(a: bool) {
+   |                  - help: try adding a return type: `-> i32`
+LL | /     match a {
+LL | |         true => 1,
+   | |                 - this is found to be of type `{integer}`
+LL | |         false => {
+LL | |             never()
+   | |             ^^^^^^^
+   | |             |
+   | |             expected integer, found `()`
+   | |             this expression is of type `!`, but it is coerced to `()` due to its surrounding expression
+LL | |         }
+LL | |     }
+   | |_____- `match` arms have incompatible types
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/numbers-arithmetic/issue-105626.rs b/tests/ui/numbers-arithmetic/issue-105626.rs
index f97edd510c9..5466f8e18d4 100644
--- a/tests/ui/numbers-arithmetic/issue-105626.rs
+++ b/tests/ui/numbers-arithmetic/issue-105626.rs
@@ -1,6 +1,5 @@
 // run-pass
 // only-x86
-// min-system-llvm-version: 16
 // compile-flags: -Ctarget-feature=+sse2
 
 use std::hint::black_box;
diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.fixed b/tests/ui/pattern/pattern-bad-ref-box-order.fixed
new file mode 100644
index 00000000000..8825744a08b
--- /dev/null
+++ b/tests/ui/pattern/pattern-bad-ref-box-order.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![feature(box_patterns)]
+#![allow(dead_code)]
+
+fn foo(f: Option<Box<i32>>) {
+    match f {
+        Some(box ref _i) => {},
+        //~^ ERROR switch the order of `ref` and `box`
+        None => {}
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.rs b/tests/ui/pattern/pattern-bad-ref-box-order.rs
new file mode 100644
index 00000000000..f3fcf0ceacf
--- /dev/null
+++ b/tests/ui/pattern/pattern-bad-ref-box-order.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![feature(box_patterns)]
+#![allow(dead_code)]
+
+fn foo(f: Option<Box<i32>>) {
+    match f {
+        Some(ref box _i) => {},
+        //~^ ERROR switch the order of `ref` and `box`
+        None => {}
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/pattern/pattern-bad-ref-box-order.stderr b/tests/ui/pattern/pattern-bad-ref-box-order.stderr
new file mode 100644
index 00000000000..a49f05c1028
--- /dev/null
+++ b/tests/ui/pattern/pattern-bad-ref-box-order.stderr
@@ -0,0 +1,8 @@
+error: switch the order of `ref` and `box`
+  --> $DIR/pattern-bad-ref-box-order.rs:8:14
+   |
+LL |         Some(ref box _i) => {},
+   |              ^^^^^^^ help: swap them: `box ref`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/sanitize/cfg-kasan.rs b/tests/ui/sanitize/cfg-kasan.rs
index d721011f3ee..fb9a6f549ce 100644
--- a/tests/ui/sanitize/cfg-kasan.rs
+++ b/tests/ui/sanitize/cfg-kasan.rs
@@ -8,10 +8,8 @@
 //[aarch64] needs-llvm-components: aarch64
 //[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf
 //[riscv64imac] needs-llvm-components: riscv
-//[riscv64imac] min-llvm-version: 16
 //[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf
 //[riscv64gc] needs-llvm-components: riscv
-//[riscv64gc] min-llvm-version: 16
 //[x86_64] compile-flags: --target x86_64-unknown-none
 //[x86_64] needs-llvm-components: x86
 
diff --git a/tests/ui/suggestions/range-index-instead-of-colon.rs b/tests/ui/suggestions/range-index-instead-of-colon.rs
new file mode 100644
index 00000000000..3267527ecf2
--- /dev/null
+++ b/tests/ui/suggestions/range-index-instead-of-colon.rs
@@ -0,0 +1,7 @@
+// edition:2021
+
+fn main() {
+    &[1, 2, 3][1:2];
+    //~^ ERROR: expected one of
+    //~| HELP: you might have meant a range expression
+}
diff --git a/tests/ui/suggestions/range-index-instead-of-colon.stderr b/tests/ui/suggestions/range-index-instead-of-colon.stderr
new file mode 100644
index 00000000000..df29356cc16
--- /dev/null
+++ b/tests/ui/suggestions/range-index-instead-of-colon.stderr
@@ -0,0 +1,13 @@
+error: expected one of `.`, `?`, `]`, or an operator, found `:`
+  --> $DIR/range-index-instead-of-colon.rs:4:17
+   |
+LL |     &[1, 2, 3][1:2];
+   |                 ^ expected one of `.`, `?`, `]`, or an operator
+   |
+help: you might have meant a range expression
+   |
+LL |     &[1, 2, 3][1..2];
+   |                 ~~
+
+error: aborting due to 1 previous error
+
diff --git a/triagebot.toml b/triagebot.toml
index 593386288b4..ed9d59b1bb9 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -18,6 +18,7 @@ allow-unauthenticated = [
     "relnotes",
     "requires-*",
     "regression-*",
+    "rla-*",
     "perf-*",
     "AsyncAwait-OnDeck",
     "needs-triage",