about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs13
-rw-r--r--compiler/rustc_const_eval/src/errors.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs10
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs4
-rw-r--r--compiler/rustc_interface/src/passes.rs34
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs25
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs6
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs2
-rw-r--r--src/bootstrap/Cargo.lock67
-rw-r--r--src/bootstrap/Cargo.toml4
-rw-r--r--src/bootstrap/src/bin/main.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs2
-rw-r--r--src/bootstrap/src/core/config/config.rs4
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
m---------src/doc/book0
m---------src/doc/embedded-book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/tools/compiletest/Cargo.toml4
-rw-r--r--src/tools/compiletest/src/bin/main.rs24
-rw-r--r--src/tools/compiletest/src/lib.rs28
-rw-r--r--src/tools/compiletest/src/main.rs36
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs4
-rw-r--r--src/tools/miri/src/machine.rs2
-rw-r--r--src/tools/miri/src/provenance_gc.rs6
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs2
-rw-r--r--src/tools/miri/src/shims/unix/mem.rs2
-rw-r--r--src/tools/opt-dist/src/tests.rs2
-rw-r--r--src/tools/rust-analyzer/.github/workflows/ci.yaml39
-rw-r--r--src/tools/rust-analyzer/.github/workflows/release.yaml4
-rw-r--r--src/tools/rust-analyzer/Cargo.lock8
-rw-r--r--src/tools/rust-analyzer/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/base-db/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/cfg/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs35
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/import_map.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs63
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/signatures.rs90
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/visibility.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/generics.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs88
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs76
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/attrs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/diagnostics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs74
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/symbols.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs163
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs31
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide/Cargo.toml1
-rwxr-xr-xsrc/tools/rust-analyzer/crates/ide/src/folding_ranges.rs94
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs239
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs352
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs223
-rw-r--r--src/tools/rust-analyzer/crates/intern/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs2
-rw-r--r--src/tools/rust-analyzer/crates/mbe/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/parser/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs7
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lexed_str.rs131
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rast3
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rs2
-rw-r--r--src/tools/rust-analyzer/crates/paths/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs12
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/profile/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/project-model/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs73
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs8
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/env.rs22
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs115
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs19
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs2
-rw-r--r--src/tools/rust-analyzer/crates/stdx/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs4
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs94
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/validation.rs28
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs150
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/tt/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/vfs/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/docs/book/src/SUMMARY.md1
-rw-r--r--src/tools/rust-analyzer/docs/book/src/configuration_generated.md7
-rw-r--r--src/tools/rust-analyzer/docs/book/src/faq.md7
-rw-r--r--src/tools/rust-analyzer/docs/book/src/non_cargo_based_projects.md3
-rw-r--r--src/tools/rust-analyzer/docs/book/src/troubleshooting.md3
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json10
-rw-r--r--src/tools/rust-analyzer/editors/code/src/client.ts114
-rw-r--r--src/tools/rust-analyzer/editors/code/src/commands.ts4
-rw-r--r--src/tools/rust-analyzer/editors/code/src/main.ts2
-rw-r--r--src/tools/rust-analyzer/editors/code/src/run.ts57
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--tests/ui/stats/macro-stats.rs9
-rw-r--r--tests/ui/stats/macro-stats.stderr3
188 files changed, 2454 insertions, 979 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 3a62cd52a9d..ee43eb736e6 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -133,7 +133,7 @@ pub(crate) fn codegen_const_value<'tcx>(
                 }
             }
             Scalar::Ptr(ptr, _size) => {
-                let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative
+                let (prov, offset) = ptr.prov_and_relative_offset();
                 let alloc_id = prov.alloc_id();
                 let base_addr = match fx.tcx.global_alloc(alloc_id) {
                     GlobalAlloc::Memory(alloc) => {
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index 38348a48e47..dd582834fac 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -240,7 +240,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
                 }
             }
             Scalar::Ptr(ptr, _size) => {
-                let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative
+                let (prov, offset) = ptr.prov_and_relative_offset();
                 let alloc_id = prov.alloc_id();
                 let base_addr = match self.tcx.global_alloc(alloc_id) {
                     GlobalAlloc::Memory(alloc) => {
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index ae5add59322..7cfab25bc50 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -268,7 +268,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
                 }
             }
             Scalar::Ptr(ptr, _size) => {
-                let (prov, offset) = ptr.into_parts();
+                let (prov, offset) = ptr.prov_and_relative_offset();
                 let global_alloc = self.tcx.global_alloc(prov.alloc_id());
                 let base_addr = match global_alloc {
                     GlobalAlloc::Memory(alloc) => {
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 8fddc7e3249..08e1877f0eb 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -209,9 +209,9 @@ pub(super) fn op_to_const<'tcx>(
 
     match immediate {
         Left(ref mplace) => {
-            // We know `offset` is relative to the allocation, so we can use `into_parts`.
-            let (prov, offset) = mplace.ptr().into_parts();
-            let alloc_id = prov.expect("cannot have `fake` place for non-ZST type").alloc_id();
+            let (prov, offset) =
+                mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
+            let alloc_id = prov.alloc_id();
             ConstValue::Indirect { alloc_id, offset }
         }
         // see comment on `let force_as_immediate` above
@@ -232,9 +232,10 @@ pub(super) fn op_to_const<'tcx>(
                     imm.layout.ty,
                 );
                 let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
-                // We know `offset` is relative to the allocation, so we can use `into_parts`.
-                let (prov, offset) = a.to_pointer(ecx).expect(msg).into_parts();
-                let alloc_id = prov.expect(msg).alloc_id();
+                let ptr = a.to_pointer(ecx).expect(msg);
+                let (prov, offset) =
+                    ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
+                let alloc_id = prov.alloc_id();
                 let data = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
                 assert!(offset == abi::Size::ZERO, "{}", msg);
                 let meta = b.to_target_usize(ecx).expect(msg);
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 14abdd8c98c..9133a5fc8ef 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -574,7 +574,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
                 if addr != 0 {
                     diag.arg(
                         "pointer",
-                        Pointer::<Option<CtfeProvenance>>::from_addr_invalid(addr).to_string(),
+                        Pointer::<Option<CtfeProvenance>>::without_provenance(addr).to_string(),
                     );
                 }
 
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index d6d230fbd17..35ec303f961 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -747,7 +747,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
         // Allow these casts, but make the pointer not dereferenceable.
         // (I.e., they behave like transmutation.)
         // This is correct because no pointers can ever be exposed in compile-time evaluation.
-        interp_ok(Pointer::from_addr_invalid(addr))
+        interp_ok(Pointer::without_provenance(addr))
     }
 
     #[inline(always)]
@@ -756,8 +756,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
         ptr: Pointer<CtfeProvenance>,
         _size: i64,
     ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
-        // We know `offset` is relative to the allocation, so we can use `into_parts`.
-        let (prov, offset) = ptr.into_parts();
+        let (prov, offset) = ptr.prov_and_relative_offset();
         Some((prov.alloc_id(), offset, prov.immutable()))
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 69fceb02ff9..3b36bb85985 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -1596,7 +1596,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 Some((alloc_id, offset, extra)) => Ok((alloc_id, offset, extra)),
                 None => {
                     assert!(M::Provenance::OFFSET_IS_ADDR);
-                    let (_, addr) = ptr.into_parts();
+                    // Offset is absolute, as we just asserted.
+                    let (_, addr) = ptr.into_raw_parts();
                     Err(addr.bytes())
                 }
             },
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 3028568dd8f..a3cd35ff0bb 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -118,7 +118,7 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
     pub fn fake_alloc_zst(layout: TyAndLayout<'tcx>) -> Self {
         assert!(layout.is_zst());
         let align = layout.align.abi;
-        let ptr = Pointer::from_addr_invalid(align.bytes()); // no provenance, absolute address
+        let ptr = Pointer::without_provenance(align.bytes()); // no provenance, absolute address
         MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::None, misaligned: None }, layout }
     }
 
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 998ef3729ea..72680019380 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -518,7 +518,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
             Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance {
                 ptr_kind,
                 // FIXME this says "null pointer" when null but we need translate
-                pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(i))
+                pointer: format!("{}", Pointer::<Option<AllocId>>::without_provenance(i))
             },
             Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
                 ptr_kind
@@ -868,7 +868,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
     fn add_data_range(&mut self, ptr: Pointer<Option<M::Provenance>>, size: Size) {
         if let Some(data_bytes) = self.data_bytes.as_mut() {
             // We only have to store the offset, the rest is the same for all pointers here.
-            let (_prov, offset) = ptr.into_parts();
+            // The logic is agnostic to wether the offset is relative or absolute as long as
+            // it is consistent.
+            let (_prov, offset) = ptr.into_raw_parts();
             // Add this.
             data_bytes.add_range(offset, size);
         };
@@ -894,7 +896,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
             .as_mplace_or_imm()
             .expect_left("place must be in memory")
             .ptr();
-        let (_prov, offset) = ptr.into_parts();
+        let (_prov, offset) = ptr.into_raw_parts();
         offset
     }
 
@@ -903,7 +905,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
         // Our value must be in memory, otherwise we would not have set up `data_bytes`.
         let mplace = self.ecx.force_allocation(place)?;
         // Determine starting offset and size.
-        let (_prov, start_offset) = mplace.ptr().into_parts();
+        let (_prov, start_offset) = mplace.ptr().into_raw_parts();
         let (size, _align) = self
             .ecx
             .size_and_align_of_val(&mplace)?
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 4855fc58d03..18490385455 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -1112,7 +1112,9 @@ fn get_backend_from_raw_matches(
     matches: &Matches,
 ) -> Box<dyn CodegenBackend> {
     let debug_flags = matches.opt_strs("Z");
-    let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+    let backend_name = debug_flags
+        .iter()
+        .find_map(|x| x.strip_prefix("codegen-backend=").or(x.strip_prefix("codegen_backend=")));
     let target = parse_target_triple(early_dcx, matches);
     let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from));
     let target = config::build_target_config(early_dcx, &target, sysroot.path());
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index edfb05e2ccd..3fe7c5e4286 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -298,6 +298,16 @@ fn configure_and_expand(
 fn print_macro_stats(ecx: &ExtCtxt<'_>) {
     use std::fmt::Write;
 
+    let crate_name = ecx.ecfg.crate_name.as_str();
+    let crate_name = if crate_name == "build_script_build" {
+        // This is a build script. Get the package name from the environment.
+        let pkg_name =
+            std::env::var("CARGO_PKG_NAME").unwrap_or_else(|_| "<unknown crate>".to_string());
+        format!("{pkg_name} build script")
+    } else {
+        crate_name.to_string()
+    };
+
     // No instability because we immediately sort the produced vector.
     #[allow(rustc::potential_query_instability)]
     let mut macro_stats: Vec<_> = ecx
@@ -327,7 +337,7 @@ fn print_macro_stats(ecx: &ExtCtxt<'_>) {
     // non-interleaving, though.
     let mut s = String::new();
     _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w));
-    _ = writeln!(s, "{prefix} MACRO EXPANSION STATS: {}", ecx.ecfg.crate_name);
+    _ = writeln!(s, "{prefix} MACRO EXPANSION STATS: {}", crate_name);
     _ = writeln!(
         s,
         "{prefix} {:<name_w$}{:>uses_w$}{:>lines_w$}{:>avg_lines_w$}{:>bytes_w$}{:>avg_bytes_w$}",
@@ -341,20 +351,30 @@ fn print_macro_stats(ecx: &ExtCtxt<'_>) {
     }
     for (bytes, lines, uses, name, kind) in macro_stats {
         let mut name = ExpnKind::Macro(kind, *name).descr();
+        let uses_with_underscores = thousands::usize_with_underscores(uses);
         let avg_lines = lines as f64 / uses as f64;
         let avg_bytes = bytes as f64 / uses as f64;
-        if name.len() >= name_w {
-            // If the name is long, print it on a line by itself, then
-            // set the name to empty and print things normally, to show the
-            // stats on the next line.
+
+        // Ensure the "Macro Name" and "Uses" columns are as compact as possible.
+        let mut uses_w = uses_w;
+        if name.len() + uses_with_underscores.len() >= name_w + uses_w {
+            // The name would abut or overlap the uses value. Print the name
+            // on a line by itself, then set the name to empty and print things
+            // normally, to show the stats on the next line.
             _ = writeln!(s, "{prefix} {:<name_w$}", name);
             name = String::new();
-        }
+        } else if name.len() >= name_w {
+            // The name won't abut or overlap with the uses value, but it does
+            // overlap with the empty part of the uses column. Shrink the width
+            // of the uses column to account for the excess name length.
+            uses_w = uses_with_underscores.len() + 1
+        };
+
         _ = writeln!(
             s,
             "{prefix} {:<name_w$}{:>uses_w$}{:>lines_w$}{:>avg_lines_w$}{:>bytes_w$}{:>avg_bytes_w$}",
             name,
-            thousands::usize_with_underscores(uses),
+            uses_with_underscores,
             thousands::usize_with_underscores(lines),
             thousands::f64p1_with_underscores(avg_lines),
             thousands::usize_with_underscores(bytes),
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 2b2ffa71628..16edc240544 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -168,8 +168,9 @@ impl<'tcx> ConstValue<'tcx> {
                     return Some(&[]);
                 }
                 // Non-empty slice, must have memory. We know this is a relative pointer.
-                let (inner_prov, offset) = ptr.into_parts();
-                let data = tcx.global_alloc(inner_prov?.alloc_id()).unwrap_memory();
+                let (inner_prov, offset) =
+                    ptr.into_pointer_or_addr().ok()?.prov_and_relative_offset();
+                let data = tcx.global_alloc(inner_prov.alloc_id()).unwrap_memory();
                 (data, offset.bytes(), offset.bytes() + len)
             }
         };
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index dd55d039794..4198b198ab1 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -526,7 +526,7 @@ impl Allocation {
             let ptr_bytes = &mut bytes[idx..idx + ptr_size];
             let bits = read_target_uint(endian, ptr_bytes).unwrap();
             let (ptr_prov, ptr_offset) =
-                adjust_ptr(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_parts();
+                adjust_ptr(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_raw_parts();
             write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap();
             new_provenance.push((offset, ptr_prov));
         }
@@ -769,7 +769,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
         // as-is into memory. This also double-checks that `val.size()` matches `range.size`.
         let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? {
             Right(ptr) => {
-                let (provenance, offset) = ptr.into_parts();
+                let (provenance, offset) = ptr.into_raw_parts();
                 (u128::from(offset.bytes()), Some(provenance))
             }
             Left(data) => (data, None),
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 25c7c26ddd9..0ff14f15c13 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -288,7 +288,7 @@ impl From<CtfeProvenance> for Pointer {
 impl<Prov> From<Pointer<Prov>> for Pointer<Option<Prov>> {
     #[inline(always)]
     fn from(ptr: Pointer<Prov>) -> Self {
-        let (prov, offset) = ptr.into_parts();
+        let (prov, offset) = ptr.into_raw_parts();
         Pointer::new(Some(prov), offset)
     }
 }
@@ -314,19 +314,17 @@ impl<Prov> Pointer<Option<Prov>> {
         assert!(Prov::OFFSET_IS_ADDR);
         self.offset
     }
-}
 
-impl<Prov> Pointer<Option<Prov>> {
     /// Creates a pointer to the given address, with invalid provenance (i.e., cannot be used for
     /// any memory access).
     #[inline(always)]
-    pub fn from_addr_invalid(addr: u64) -> Self {
+    pub fn without_provenance(addr: u64) -> Self {
         Pointer { provenance: None, offset: Size::from_bytes(addr) }
     }
 
     #[inline(always)]
     pub fn null() -> Self {
-        Pointer::from_addr_invalid(0)
+        Pointer::without_provenance(0)
     }
 }
 
@@ -336,11 +334,11 @@ impl<Prov> Pointer<Prov> {
         Pointer { provenance, offset }
     }
 
-    /// Obtain the constituents of this pointer. Not that the meaning of the offset depends on the type `Prov`!
-    /// This function must only be used in the implementation of `Machine::ptr_get_alloc`,
-    /// and when a `Pointer` is taken apart to be stored efficiently in an `Allocation`.
+    /// Obtain the constituents of this pointer. Note that the meaning of the offset depends on the
+    /// type `Prov`! This is a low-level function that should only be used when absolutely
+    /// necessary. Prefer `prov_and_relative_offset` if possible.
     #[inline(always)]
-    pub fn into_parts(self) -> (Prov, Size) {
+    pub fn into_raw_parts(self) -> (Prov, Size) {
         (self.provenance, self.offset)
     }
 
@@ -361,3 +359,12 @@ impl<Prov> Pointer<Prov> {
         self.wrapping_offset(Size::from_bytes(i as u64), cx)
     }
 }
+
+impl Pointer<CtfeProvenance> {
+    /// Return the provenance and relative offset stored in this pointer. Safer alternative to
+    /// `into_raw_parts` since the type ensures that the offset is indeed relative.
+    #[inline(always)]
+    pub fn prov_and_relative_offset(self) -> (CtfeProvenance, Size) {
+        (self.provenance, self.offset)
+    }
+}
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 7ba0e5b5e07..8092f634dc8 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -109,7 +109,7 @@ impl<Prov> Scalar<Prov> {
     /// Create a Scalar from a pointer with an `Option<_>` provenance (where `None` represents a
     /// plain integer / "invalid" pointer).
     pub fn from_maybe_pointer(ptr: Pointer<Option<Prov>>, cx: &impl HasDataLayout) -> Self {
-        match ptr.into_parts() {
+        match ptr.into_raw_parts() {
             (Some(prov), offset) => Scalar::from_pointer(Pointer::new(prov, offset), cx),
             (None, offset) => {
                 Scalar::Int(ScalarInt::try_from_uint(offset.bytes(), cx.pointer_size()).unwrap())
@@ -276,7 +276,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
             Right(ptr) => interp_ok(ptr.into()),
             Left(bits) => {
                 let addr = u64::try_from(bits).unwrap();
-                interp_ok(Pointer::from_addr_invalid(addr))
+                interp_ok(Pointer::without_provenance(addr))
             }
         }
     }
@@ -299,7 +299,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
                     Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap())
                 } else {
                     // We know `offset` is relative, since `OFFSET_IS_ADDR == false`.
-                    let (prov, offset) = ptr.into_parts();
+                    let (prov, offset) = ptr.into_raw_parts();
                     // Because `OFFSET_IS_ADDR == false`, this unwrap can never fail.
                     Err(Scalar::Ptr(Pointer::new(prov.get_alloc_id().unwrap(), offset), sz))
                 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 1392d1d08fc..bee490b3648 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1755,7 +1755,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
     ) -> Result<(), PrintError> {
         define_scoped_cx!(self);
 
-        let (prov, offset) = ptr.into_parts();
+        let (prov, offset) = ptr.prov_and_relative_offset();
         match ty.kind() {
             // Byte strings (&[u8; N])
             ty::Ref(_, inner, _) => {
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index b17b7f45000..335354c23b6 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -1636,7 +1636,7 @@ fn op_to_prop_const<'tcx>(
         }
 
         let pointer = mplace.ptr().into_pointer_or_addr().ok()?;
-        let (prov, offset) = pointer.into_parts();
+        let (prov, offset) = pointer.prov_and_relative_offset();
         let alloc_id = prov.alloc_id();
         intern_const_alloc_for_constprop(ecx, alloc_id).discard_err()?;
 
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index a6ca699e282..2434a278d55 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -12,6 +12,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
 name = "anstyle"
 version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -62,8 +71,8 @@ dependencies = [
  "toml",
  "tracing",
  "tracing-chrome",
+ "tracing-forest",
  "tracing-subscriber",
- "tracing-tree",
  "walkdir",
  "windows",
  "xz2",
@@ -450,15 +459,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "nu-ansi-term"
-version = "0.50.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
-dependencies = [
- "windows-sys 0.52.0",
-]
-
-[[package]]
 name = "objc2-core-foundation"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -776,6 +776,26 @@ dependencies = [
 ]
 
 [[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "thread_local"
 version = "1.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -838,6 +858,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "tracing-forest"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f"
+dependencies = [
+ "ansi_term",
+ "smallvec",
+ "thiserror",
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
 name = "tracing-log"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -855,7 +888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
 dependencies = [
  "matchers",
- "nu-ansi-term 0.46.0",
+ "nu-ansi-term",
  "once_cell",
  "regex",
  "sharded-slab",
@@ -867,18 +900,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "tracing-tree"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f459ca79f1b0d5f71c54ddfde6debfc59c8b6eeb46808ae492077f739dc7b49c"
-dependencies = [
- "nu-ansi-term 0.50.1",
- "tracing-core",
- "tracing-log",
- "tracing-subscriber",
-]
-
-[[package]]
 name = "typenum"
 version = "1.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 9785a306c9b..073cebdcae2 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -7,7 +7,7 @@ default-run = "bootstrap"
 
 [features]
 build-metrics = ["sysinfo"]
-tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:tracing-tree"]
+tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:tracing-forest"]
 
 [lib]
 path = "src/lib.rs"
@@ -64,7 +64,7 @@ sysinfo = { version = "0.35.0", default-features = false, optional = true, featu
 tracing = { version = "0.1", optional = true, features = ["attributes"] }
 tracing-chrome = { version = "0.7", optional = true }
 tracing-subscriber = { version = "0.3", optional = true, features = ["env-filter", "fmt", "registry", "std"] }
-tracing-tree = { version = "0.4.0", optional = true }
+tracing-forest = { version = "0.1.6", optional = true, default-features =  false, features = ["smallvec", "ansi", "env-filter"] }
 
 [target.'cfg(windows)'.dependencies.junction]
 version = "1.0.0"
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 833f8027951..e1862a451f2 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -217,12 +217,11 @@ fn check_version(config: &Config) -> Option<String> {
 //   "tracing", instrument(..))]`.
 #[cfg(feature = "tracing")]
 fn setup_tracing() -> impl Drop {
+    use tracing_forest::ForestLayer;
     use tracing_subscriber::EnvFilter;
     use tracing_subscriber::layer::SubscriberExt;
 
     let filter = EnvFilter::from_env("BOOTSTRAP_TRACING");
-    // cf. <https://docs.rs/tracing-tree/latest/tracing_tree/struct.HierarchicalLayer.html>.
-    let layer = tracing_tree::HierarchicalLayer::default().with_targets(true).with_indent_amount(2);
 
     let mut chrome_layer = tracing_chrome::ChromeLayerBuilder::new().include_args(true);
 
@@ -233,7 +232,8 @@ fn setup_tracing() -> impl Drop {
 
     let (chrome_layer, _guard) = chrome_layer.build();
 
-    let registry = tracing_subscriber::registry().with(filter).with(layer).with(chrome_layer);
+    let registry =
+        tracing_subscriber::registry().with(filter).with(ForestLayer::default()).with(chrome_layer);
 
     tracing::subscriber::set_global_default(registry).unwrap();
     _guard
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 8200e154169..84064150738 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -2241,7 +2241,7 @@ impl Step for Assemble {
         debug!("copying codegen backends to sysroot");
         copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
 
-        if builder.config.lld_enabled && !builder.config.is_system_llvm(target_compiler.host) {
+        if builder.config.lld_enabled {
             builder.ensure(crate::core::build_steps::tool::LldWrapper {
                 build_compiler,
                 target_compiler,
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index d1ffdf24acd..0cdfbbdaf75 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1003,9 +1003,7 @@ impl Config {
         }
 
         if config.lld_enabled && config.is_system_llvm(config.host_target) {
-            eprintln!(
-                "Warning: LLD is enabled when using external llvm-config. LLD will not be built and copied to the sysroot."
-            );
+            panic!("Cannot enable LLD with `rust.lld = true` when using external llvm-config.");
         }
 
         config.optimized_compiler_builtins =
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 7c588cfea8c..006c294d445 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -431,4 +431,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Warning,
         summary: "It is no longer possible to `x build` with stage 0. All build commands have to be on stage 1+.",
     },
+    ChangeInfo {
+        change_id: 143175,
+        severity: ChangeSeverity::Info,
+        summary: "It is no longer possible to combine `rust.lld = true` with configuring external LLVM using `llvm.llvm-config`.",
+    },
 ];
diff --git a/src/doc/book b/src/doc/book
-Subproject 8a6d44e45b7b564eeb6bae30507e1fbac439d72
+Subproject ef1ce8f87a8b18feb1b6a9cf9a4939a79bde679
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject 10fa1e084365f23f24ad0000df541923385b73b
+Subproject 41f688a598a5022b749e23d37f3c524f6a0b28e
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 50fc1628f36563958399123829c73755fa7a842
+Subproject e9fc99f107840813916f62e16b3f6d9556e1f2d
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 05c7d8bae65f23a1837430c5a19be129d414f5e
+Subproject 288b4e4948add43f387cad35adc7b1c54ca6fe1
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 3b544d8b828..cdada5a2230 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -6,6 +6,10 @@ edition = "2024"
 [lib]
 doctest = false
 
+[[bin]]
+name = "compiletest"
+path = "src/bin/main.rs"
+
 [dependencies]
 # tidy-alphabetical-start
 anstyle-svg = "0.1.3"
diff --git a/src/tools/compiletest/src/bin/main.rs b/src/tools/compiletest/src/bin/main.rs
new file mode 100644
index 00000000000..1f777e71cf9
--- /dev/null
+++ b/src/tools/compiletest/src/bin/main.rs
@@ -0,0 +1,24 @@
+use std::env;
+use std::io::IsTerminal;
+use std::sync::Arc;
+
+use compiletest::{early_config_check, log_config, parse_config, run_tests};
+
+fn main() {
+    tracing_subscriber::fmt::init();
+
+    // colored checks stdout by default, but for some reason only stderr is a terminal.
+    // compiletest *does* print many things to stdout, but it doesn't really matter.
+    if std::io::stderr().is_terminal()
+        && matches!(std::env::var("NO_COLOR").as_deref(), Err(_) | Ok("0"))
+    {
+        colored::control::set_override(true);
+    }
+
+    let config = Arc::new(parse_config(env::args().collect()));
+
+    early_config_check(&config);
+
+    log_config(&config);
+    run_tests(config);
+}
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 0db4d3f6a41..23a4dd73796 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -51,12 +51,6 @@ use crate::util::logv;
 /// some code here that inspects environment variables or even runs executables
 /// (e.g. when discovering debugger versions).
 pub fn parse_config(args: Vec<String>) -> Config {
-    if env::var("RUST_TEST_NOCAPTURE").is_ok() {
-        eprintln!(
-            "WARNING: RUST_TEST_NOCAPTURE is not supported. Use the `--no-capture` flag instead."
-        );
-    }
-
     let mut opts = Options::new();
     opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
         .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
@@ -1111,3 +1105,25 @@ fn check_for_overlapping_test_paths(found_path_stems: &HashSet<Utf8PathBuf>) {
         );
     }
 }
+
+pub fn early_config_check(config: &Config) {
+    if !config.has_html_tidy && config.mode == Mode::Rustdoc {
+        eprintln!("warning: `tidy` (html-tidy.org) is not installed; diffs will not be generated");
+    }
+
+    if !config.profiler_runtime && config.mode == Mode::CoverageRun {
+        let actioned = if config.bless { "blessed" } else { "checked" };
+        eprintln!(
+            r#"
+WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned}
+help: try setting `profiler = true` in the `[build]` section of `bootstrap.toml`"#
+        );
+    }
+
+    // `RUST_TEST_NOCAPTURE` is a libtest env var, but we don't callout to libtest.
+    if env::var("RUST_TEST_NOCAPTURE").is_ok() {
+        eprintln!(
+            "WARNING: RUST_TEST_NOCAPTURE is not supported. Use the `--no-capture` flag instead."
+        );
+    }
+}
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
deleted file mode 100644
index b9ae583581e..00000000000
--- a/src/tools/compiletest/src/main.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use std::env;
-use std::io::IsTerminal;
-use std::sync::Arc;
-
-use compiletest::common::Mode;
-use compiletest::{log_config, parse_config, run_tests};
-
-fn main() {
-    tracing_subscriber::fmt::init();
-
-    // colored checks stdout by default, but for some reason only stderr is a terminal.
-    // compiletest *does* print many things to stdout, but it doesn't really matter.
-    if std::io::stderr().is_terminal()
-        && matches!(std::env::var("NO_COLOR").as_deref(), Err(_) | Ok("0"))
-    {
-        colored::control::set_override(true);
-    }
-
-    let config = Arc::new(parse_config(env::args().collect()));
-
-    if !config.has_html_tidy && config.mode == Mode::Rustdoc {
-        eprintln!("warning: `tidy` (html-tidy.org) is not installed; diffs will not be generated");
-    }
-
-    if !config.profiler_runtime && config.mode == Mode::CoverageRun {
-        let actioned = if config.bless { "blessed" } else { "checked" };
-        eprintln!(
-            r#"
-WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned}
-help: try setting `profiler = true` in the `[build]` section of `bootstrap.toml`"#
-        );
-    }
-
-    log_config(&config);
-    run_tests(config);
-}
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 4a038fe6487..1796120cf8a 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -390,7 +390,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     ) -> InterpResult<'tcx, interpret::Pointer<Provenance>> {
         let this = self.eval_context_ref();
 
-        let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance)
+        let (prov, offset) = ptr.prov_and_relative_offset();
         let alloc_id = prov.alloc_id();
 
         // Get a pointer to the beginning of this allocation.
@@ -447,7 +447,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     ) -> Option<(AllocId, Size)> {
         let this = self.eval_context_ref();
 
-        let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance)
+        let (tag, addr) = ptr.into_raw_parts(); // addr is absolute (Miri provenance)
 
         let alloc_id = if let Provenance::Concrete { alloc_id, .. } = tag {
             alloc_id
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 3a748c4c687..17c13a9e33c 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -285,7 +285,7 @@ impl interpret::Provenance for Provenance {
     }
 
     fn fmt(ptr: &interpret::Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let (prov, addr) = ptr.into_parts(); // address is absolute
+        let (prov, addr) = ptr.into_raw_parts(); // offset is absolute address
         write!(f, "{:#x}", addr.bytes())?;
         if f.alternate() {
             write!(f, "{prov:#?}")?;
diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs
index b3d715db9cd..6adf1448648 100644
--- a/src/tools/miri/src/provenance_gc.rs
+++ b/src/tools/miri/src/provenance_gc.rs
@@ -68,15 +68,13 @@ impl VisitProvenance for Provenance {
 
 impl VisitProvenance for StrictPointer {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
-        let (prov, _offset) = self.into_parts();
-        prov.visit_provenance(visit);
+        self.provenance.visit_provenance(visit);
     }
 }
 
 impl VisitProvenance for Pointer {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
-        let (prov, _offset) = self.into_parts();
-        prov.visit_provenance(visit);
+        self.provenance.visit_provenance(visit);
     }
 }
 
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 416cb1ab55e..97070eb742f 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -411,7 +411,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                         AlignFromBytesError::TooLarge(_) => Align::MAX,
                     }
                 });
-                let (_, addr) = ptr.into_parts(); // we know the offset is absolute
+                let addr = ptr.addr();
                 // Cannot panic since `align` is a power of 2 and hence non-zero.
                 if addr.bytes().strict_rem(align.bytes()) != 0 {
                     throw_unsup_format!(
diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs
index 4bbbbc69c08..1738de4dd4f 100644
--- a/src/tools/miri/src/shims/unix/mem.rs
+++ b/src/tools/miri/src/shims/unix/mem.rs
@@ -49,7 +49,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             && matches!(&*this.tcx.sess.target.os, "macos" | "solaris" | "illumos")
             && (flags & map_fixed) != 0
         {
-            return interp_ok(Scalar::from_maybe_pointer(Pointer::from_addr_invalid(addr), this));
+            return interp_ok(Scalar::from_maybe_pointer(Pointer::without_provenance(addr), this));
         }
 
         let prot_read = this.eval_libc_i32("PROT_READ");
diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs
index 53ce772fa77..705a1750ae8 100644
--- a/src/tools/opt-dist/src/tests.rs
+++ b/src/tools/opt-dist/src/tests.rs
@@ -72,6 +72,8 @@ change-id = 115898
 [rust]
 channel = "{channel}"
 verbose-tests = true
+# rust-lld cannot be combined with an external LLVM
+lld = false
 
 [build]
 rustc = "{rustc}"
diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 79fb7a2d2ea..770652494f4 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -17,6 +17,10 @@ env:
   RUST_BACKTRACE: short
   RUSTUP_MAX_RETRIES: 10
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   changes:
     runs-on: ubuntu-latest
@@ -80,6 +84,7 @@ jobs:
       CC: deny_c
 
     strategy:
+      fail-fast: false
       matrix:
         os: [ubuntu-latest, windows-latest, macos-latest]
 
@@ -99,7 +104,7 @@ jobs:
           rustup toolchain install nightly --profile minimal --component rustfmt
       # https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/rust.json
       - name: Install Rust Problem Matcher
-        if: matrix.os == 'ubuntu-latest'
+        if: matrix.os == 'macos-latest'
         run: echo "::add-matcher::.github/rust.json"
 
       # - name: Cache Dependencies
@@ -116,23 +121,9 @@ jobs:
         if: matrix.os == 'ubuntu-latest'
         run: cargo codegen --check
 
-      - name: Compile tests
-        run: cargo test --no-run
-
       - name: Run tests
         run: cargo nextest run --no-fail-fast --hide-progress-bar --status-level fail
 
-      - name: Cancel parallel jobs
-        if: failure()
-        run: |
-          # https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#cancel-a-workflow-run
-          curl -L \
-          -X POST \
-          -H "Accept: application/vnd.github.v3+json" \
-          -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
-          -H "X-GitHub-Api-Version: 2022-11-28" \
-          https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
-
       - name: Run Clippy
         if: matrix.os == 'macos-latest'
         run: cargo clippy --all-targets -- -D clippy::disallowed_macros -D clippy::dbg_macro -D clippy::todo -D clippy::print_stdout -D clippy::print_stderr
@@ -333,3 +324,21 @@ jobs:
           jq -C <<< '${{ toJson(needs) }}'
           # Check if all jobs that we depend on (in the needs array) were successful (or have been skipped).
           jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'
+
+  cancel-if-matrix-failed:
+    needs: rust
+    if: ${{ always() }}
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cancel parallel jobs
+        run: |
+          if jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'; then
+            exit 0
+          fi
+          # https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#cancel-a-workflow-run
+          curl -L \
+          -X POST \
+          -H "Accept: application/vnd.github.v3+json" \
+          -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
+          -H "X-GitHub-Api-Version: 2022-11-28" \
+          https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
diff --git a/src/tools/rust-analyzer/.github/workflows/release.yaml b/src/tools/rust-analyzer/.github/workflows/release.yaml
index a758ecfd467..5bd90130f4c 100644
--- a/src/tools/rust-analyzer/.github/workflows/release.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/release.yaml
@@ -134,13 +134,13 @@ jobs:
 
       - name: Run analysis-stats on rust-analyzer
         if: matrix.target == 'x86_64-unknown-linux-gnu'
-        run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats .
+        run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats . -q
 
       - name: Run analysis-stats on rust std library
         if: matrix.target == 'x86_64-unknown-linux-gnu'
         env:
           RUSTC_BOOTSTRAP: 1
-        run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std
+        run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std -q
 
       - name: Upload artifacts
         uses: actions/upload-artifact@v4
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 2c7b4641641..caa8f28d8e2 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -1458,7 +1458,7 @@ dependencies = [
  "edition",
  "expect-test",
  "ra-ap-rustc_lexer",
- "rustc-literal-escaper 0.0.3",
+ "rustc-literal-escaper 0.0.4",
  "stdx",
  "tracing",
 ]
@@ -1927,9 +1927,9 @@ checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04"
 
 [[package]]
 name = "rustc-literal-escaper"
-version = "0.0.3"
+version = "0.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78744cd17f5d01c75b709e49807d1363e02a940ccee2e9e72435843fdb0d076e"
+checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
 
 [[package]]
 name = "rustc-stable-hash"
@@ -2207,7 +2207,7 @@ dependencies = [
  "rayon",
  "rowan",
  "rustc-hash 2.1.1",
- "rustc-literal-escaper 0.0.3",
+ "rustc-literal-escaper 0.0.4",
  "rustc_apfloat",
  "smol_str",
  "stdx",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 449c75859cf..0a8e6feb46e 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -143,7 +143,7 @@ serde = { version = "1.0.219" }
 serde_derive = { version = "1.0.219" }
 serde_json = "1.0.140"
 rustc-hash = "2.1.1"
-rustc-literal-escaper = "0.0.3"
+rustc-literal-escaper = "0.0.4"
 smallvec = { version = "1.15.1", features = [
   "const_new",
   "union",
diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
index 3b423a86f97..ea06fd9c48f 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 la-arena.workspace = true
diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
index d7764a16c04..ba349666145 100644
--- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
index c6922eca49f..abb4819a767 100644
--- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 arrayvec.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index 00408e95ae6..c67bb2422ac 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -25,11 +25,10 @@ use crate::{
     import_map::ImportMap,
     item_tree::{ItemTree, file_item_tree_query},
     lang_item::{self, LangItem},
-    nameres::{assoc::TraitItems, crate_def_map, diagnostics::DefDiagnostics},
+    nameres::crate_def_map,
     signatures::{
         ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
         StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature, UnionSignature,
-        VariantFields,
     },
     tt,
     visibility::{self, Visibility},
@@ -113,24 +112,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
 
     // region:data
 
-    #[salsa::invoke(VariantFields::query)]
-    fn variant_fields_with_source_map(
-        &self,
-        id: VariantId,
-    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>);
-
-    #[salsa::transparent]
-    #[salsa::invoke(TraitItems::trait_items_query)]
-    fn trait_items(&self, e: TraitId) -> Arc<TraitItems>;
-
-    #[salsa::invoke(TraitItems::trait_items_with_diagnostics_query)]
-    fn trait_items_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitItems>, DefDiagnostics);
-
-    #[salsa::tracked]
-    fn variant_fields(&self, id: VariantId) -> Arc<VariantFields> {
-        self.variant_fields_with_source_map(id).0
-    }
-
     #[salsa::tracked]
     fn trait_signature(&self, trait_: TraitId) -> Arc<TraitSignature> {
         self.trait_signature_with_source_map(trait_).0
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs
index f617c3225ae..85bd193223f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs
@@ -9,7 +9,10 @@ pub mod scope;
 #[cfg(test)]
 mod tests;
 
-use std::ops::{Deref, Index};
+use std::{
+    ops::{Deref, Index},
+    sync::LazyLock,
+};
 
 use cfg::{CfgExpr, CfgOptions};
 use either::Either;
@@ -19,6 +22,7 @@ use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::{Edition, SyntaxContext};
 use syntax::{AstPtr, SyntaxNodePtr, ast};
+use triomphe::Arc;
 use tt::TextRange;
 
 use crate::{
@@ -220,6 +224,12 @@ impl ExpressionStoreBuilder {
 }
 
 impl ExpressionStore {
+    pub fn empty_singleton() -> Arc<Self> {
+        static EMPTY: LazyLock<Arc<ExpressionStore>> =
+            LazyLock::new(|| Arc::new(ExpressionStoreBuilder::default().finish()));
+        EMPTY.clone()
+    }
+
     /// Returns an iterator over all block expressions in this store that define inner items.
     pub fn blocks<'a>(
         &'a self,
@@ -636,6 +646,12 @@ impl Index<PathId> for ExpressionStore {
 // FIXME: Change `node_` prefix to something more reasonable.
 // Perhaps `expr_syntax` and `expr_id`?
 impl ExpressionStoreSourceMap {
+    pub fn empty_singleton() -> Arc<Self> {
+        static EMPTY: LazyLock<Arc<ExpressionStoreSourceMap>> =
+            LazyLock::new(|| Arc::new(ExpressionStoreSourceMap::default()));
+        EMPTY.clone()
+    }
+
     pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
         match id {
             ExprOrPatId::ExprId(id) => self.expr_syntax(id),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
index efa1374a446..c0e51b338b4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
@@ -2250,7 +2250,7 @@ impl ExprCollector<'_> {
                         Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
                         Some(ModuleDefId::EnumVariantId(variant))
                         // FIXME: This can cause a cycle if the user is writing invalid code
-                            if self.db.variant_fields(variant.into()).shape != FieldsShape::Record =>
+                            if variant.fields(self.db).shape != FieldsShape::Record =>
                         {
                             (None, Pat::Path(name.into()))
                         }
@@ -2825,14 +2825,7 @@ impl ExprCollector<'_> {
         let use_format_args_since_1_89_0 = fmt_args().is_some() && fmt_unsafe_arg().is_none();
 
         let idx = if use_format_args_since_1_89_0 {
-            self.collect_format_args_impl(
-                syntax_ptr,
-                fmt,
-                hygiene,
-                argmap,
-                lit_pieces,
-                format_options,
-            )
+            self.collect_format_args_impl(syntax_ptr, fmt, argmap, lit_pieces, format_options)
         } else {
             self.collect_format_args_before_1_89_0_impl(
                 syntax_ptr,
@@ -2962,7 +2955,6 @@ impl ExprCollector<'_> {
         &mut self,
         syntax_ptr: AstPtr<ast::Expr>,
         fmt: FormatArgs,
-        hygiene: HygieneId,
         argmap: FxIndexSet<(usize, ArgumentType)>,
         lit_pieces: ExprId,
         format_options: ExprId,
@@ -2997,8 +2989,11 @@ impl ExprCollector<'_> {
             let args =
                 self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
             let args_name = Name::new_symbol_root(sym::args);
-            let args_binding =
-                self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
+            let args_binding = self.alloc_binding(
+                args_name.clone(),
+                BindingAnnotation::Unannotated,
+                HygieneId::ROOT,
+            );
             let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
             self.add_definition_to_binding(args_binding, args_pat);
             // TODO: We don't have `super let` yet.
@@ -3008,13 +3003,16 @@ impl ExprCollector<'_> {
                 initializer: Some(args),
                 else_branch: None,
             };
-            (vec![let_stmt], self.alloc_expr_desugared(Expr::Path(Path::from(args_name))))
+            (vec![let_stmt], self.alloc_expr_desugared(Expr::Path(args_name.into())))
         } else {
             // Generate:
             //     super let args = (&arg0, &arg1, &...);
             let args_name = Name::new_symbol_root(sym::args);
-            let args_binding =
-                self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
+            let args_binding = self.alloc_binding(
+                args_name.clone(),
+                BindingAnnotation::Unannotated,
+                HygieneId::ROOT,
+            );
             let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
             self.add_definition_to_binding(args_binding, args_pat);
             let elements = arguments
@@ -3057,8 +3055,11 @@ impl ExprCollector<'_> {
                 .collect();
             let array =
                 self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
-            let args_binding =
-                self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
+            let args_binding = self.alloc_binding(
+                args_name.clone(),
+                BindingAnnotation::Unannotated,
+                HygieneId::ROOT,
+            );
             let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
             self.add_definition_to_binding(args_binding, args_pat);
             let let_stmt2 = Statement::Let {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
index 56c7655f9ea..87bcd33ed7b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs
@@ -121,7 +121,7 @@ pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: E
         VariantId::UnionId(it) => format!("union {}", item_name(db, it, "<missing>")),
     };
 
-    let fields = db.variant_fields(owner);
+    let fields = owner.fields(db);
 
     let mut p = Printer {
         db,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
index a9a0e36312c..94e683cb0f8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
@@ -331,13 +331,13 @@ impl GenericParams {
     }
 
     #[inline]
-    pub fn no_predicates(&self) -> bool {
+    pub fn has_no_predicates(&self) -> bool {
         self.where_predicates.is_empty()
     }
 
     #[inline]
-    pub fn where_predicates(&self) -> std::slice::Iter<'_, WherePredicate> {
-        self.where_predicates.iter()
+    pub fn where_predicates(&self) -> &[WherePredicate] {
+        &self.where_predicates
     }
 
     /// Iterator of type_or_consts field
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
index a6138fb6821..f31f355cfa5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
@@ -16,7 +16,7 @@ use crate::{
     AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId,
     db::DefDatabase,
     item_scope::{ImportOrExternCrate, ItemInNs},
-    nameres::{DefMap, crate_def_map},
+    nameres::{DefMap, assoc::TraitItems, crate_def_map},
     visibility::Visibility,
 };
 
@@ -221,7 +221,7 @@ impl ImportMap {
         trait_import_info: &ImportInfo,
     ) {
         let _p = tracing::info_span!("collect_trait_assoc_items").entered();
-        for &(ref assoc_item_name, item) in &db.trait_items(tr).items {
+        for &(ref assoc_item_name, item) in &TraitItems::query(db, tr).items {
             let module_def_id = match item {
                 AssocItemId::FunctionId(f) => ModuleDefId::from(f),
                 AssocItemId::ConstId(c) => ModuleDefId::from(c),
@@ -482,7 +482,7 @@ mod tests {
     use expect_test::{Expect, expect};
     use test_fixture::WithFixture;
 
-    use crate::{ItemContainerId, Lookup, test_db::TestDB};
+    use crate::{ItemContainerId, Lookup, nameres::assoc::TraitItems, test_db::TestDB};
 
     use super::*;
 
@@ -580,7 +580,7 @@ mod tests {
 
         let trait_info = dependency_imports.import_info_for(ItemInNs::Types(trait_id.into()))?;
 
-        let trait_items = db.trait_items(trait_id);
+        let trait_items = TraitItems::query(db, trait_id);
         let (assoc_item_name, _) = trait_items
             .items
             .iter()
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index faff7d036a2..750308026ee 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -9,8 +9,10 @@ use triomphe::Arc;
 
 use crate::{
     AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId,
-    StaticId, StructId, TraitId, TypeAliasId, UnionId, db::DefDatabase, expr_store::path::Path,
-    nameres::crate_def_map,
+    StaticId, StructId, TraitId, TypeAliasId, UnionId,
+    db::DefDatabase,
+    expr_store::path::Path,
+    nameres::{assoc::TraitItems, crate_def_map},
 };
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -113,14 +115,16 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
             match def {
                 ModuleDefId::TraitId(trait_) => {
                     lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
-                    db.trait_items(trait_).items.iter().for_each(|&(_, assoc_id)| match assoc_id {
-                        AssocItemId::FunctionId(f) => {
-                            lang_items.collect_lang_item(db, f, LangItemTarget::Function);
+                    TraitItems::query(db, trait_).items.iter().for_each(|&(_, assoc_id)| {
+                        match assoc_id {
+                            AssocItemId::FunctionId(f) => {
+                                lang_items.collect_lang_item(db, f, LangItemTarget::Function);
+                            }
+                            AssocItemId::TypeAliasId(alias) => {
+                                lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
+                            }
+                            AssocItemId::ConstId(_) => {}
                         }
-                        AssocItemId::TypeAliasId(alias) => {
-                            lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
-                        }
-                        AssocItemId::ConstId(_) => {}
                     });
                 }
                 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
@@ -304,6 +308,8 @@ impl LangItem {
 language_item_table! {
 //  Variant name,            Name,                     Getter method name,         Target                  Generic requirements;
     Sized,                   sym::sized,               sized_trait,                Target::Trait,          GenericRequirement::Exact(0);
+    MetaSized,               sym::meta_sized,          sized_trait,                Target::Trait,          GenericRequirement::Exact(0);
+    PointeeSized,            sym::pointee_sized,       sized_trait,                Target::Trait,          GenericRequirement::Exact(0);
     Unsize,                  sym::unsize,              unsize_trait,               Target::Trait,          GenericRequirement::Minimum(1);
     /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
     StructuralPeq,           sym::structural_peq,      structural_peq_trait,       Target::Trait,          GenericRequirement::None;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index a562f2d0af2..bdf8b453e2d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -87,9 +87,12 @@ use crate::{
     attr::Attrs,
     builtin_type::BuiltinType,
     db::DefDatabase,
+    expr_store::ExpressionStoreSourceMap,
     hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId},
     nameres::{
-        LocalDefMap, assoc::ImplItems, block_def_map, crate_def_map, crate_local_def_map,
+        LocalDefMap,
+        assoc::{ImplItems, TraitItems},
+        block_def_map, crate_def_map, crate_local_def_map,
         diagnostics::DefDiagnostics,
     },
     signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields},
@@ -252,9 +255,35 @@ impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
 type StructLoc = ItemLoc<ast::Struct>;
 impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
 
+impl StructId {
+    pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
+        VariantFields::firewall(db, self.into())
+    }
+
+    pub fn fields_with_source_map(
+        self,
+        db: &dyn DefDatabase,
+    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
+        VariantFields::query(db, self.into())
+    }
+}
+
 pub type UnionLoc = ItemLoc<ast::Union>;
 impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
 
+impl UnionId {
+    pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
+        VariantFields::firewall(db, self.into())
+    }
+
+    pub fn fields_with_source_map(
+        self,
+        db: &dyn DefDatabase,
+    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
+        VariantFields::query(db, self.into())
+    }
+}
+
 pub type EnumLoc = ItemLoc<ast::Enum>;
 impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
 
@@ -282,6 +311,13 @@ impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
 pub type TraitLoc = ItemLoc<ast::Trait>;
 impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
 
+impl TraitId {
+    #[inline]
+    pub fn trait_items(self, db: &dyn DefDatabase) -> &TraitItems {
+        TraitItems::query(db, self)
+    }
+}
+
 pub type TraitAliasLoc = ItemLoc<ast::TraitAlias>;
 impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
 
@@ -328,6 +364,20 @@ pub struct EnumVariantLoc {
 }
 impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
 impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
+
+impl EnumVariantId {
+    pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
+        VariantFields::firewall(db, self.into())
+    }
+
+    pub fn fields_with_source_map(
+        self,
+        db: &dyn DefDatabase,
+    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
+        VariantFields::query(db, self.into())
+    }
+}
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct Macro2Loc {
     pub container: ModuleId,
@@ -1015,8 +1065,15 @@ pub enum VariantId {
 impl_from!(EnumVariantId, StructId, UnionId for VariantId);
 
 impl VariantId {
-    pub fn variant_data(self, db: &dyn DefDatabase) -> Arc<VariantFields> {
-        db.variant_fields(self)
+    pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
+        VariantFields::firewall(db, self)
+    }
+
+    pub fn fields_with_source_map(
+        self,
+        db: &dyn DefDatabase,
+    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
+        VariantFields::query(db, self)
     }
 
     pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
index 7aaa918d1c9..07210df8873 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
@@ -38,16 +38,18 @@ pub struct TraitItems {
     pub macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>,
 }
 
+#[salsa::tracked]
 impl TraitItems {
     #[inline]
-    pub(crate) fn trait_items_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitItems> {
-        db.trait_items_with_diagnostics(tr).0
+    pub(crate) fn query(db: &dyn DefDatabase, tr: TraitId) -> &TraitItems {
+        &Self::query_with_diagnostics(db, tr).0
     }
 
-    pub(crate) fn trait_items_with_diagnostics_query(
+    #[salsa::tracked(returns(ref))]
+    pub fn query_with_diagnostics(
         db: &dyn DefDatabase,
         tr: TraitId,
-    ) -> (Arc<TraitItems>, DefDiagnostics) {
+    ) -> (TraitItems, DefDiagnostics) {
         let ItemLoc { container: module_id, id: ast_id } = tr.lookup(db);
 
         let collector =
@@ -55,7 +57,7 @@ impl TraitItems {
         let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db);
         let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list());
 
-        (Arc::new(TraitItems { macro_calls, items }), DefDiagnostics::new(diagnostics))
+        (TraitItems { macro_calls, items }, DefDiagnostics::new(diagnostics))
     }
 
     pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 78fdc275606..0c3274d849a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -41,6 +41,7 @@ use crate::{
     macro_call_as_call_id,
     nameres::{
         BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
+        assoc::TraitItems,
         attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
         crate_def_map,
         diagnostics::DefDiagnostic,
@@ -1020,8 +1021,7 @@ impl<'db> DefCollector<'db> {
                         let resolutions = if true {
                             vec![]
                         } else {
-                            self.db
-                                .trait_items(it)
+                            TraitItems::query(self.db, it)
                                 .items
                                 .iter()
                                 .map(|&(ref name, variant)| {
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 e8235b1c96f..4641b220daa 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
@@ -24,8 +24,8 @@ use crate::{
     item_scope::{BUILTIN_SCOPE, ImportOrExternCrate},
     item_tree::FieldsShape,
     nameres::{
-        BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, crate_def_map,
-        sub_namespace_match,
+        BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, assoc::TraitItems,
+        crate_def_map, sub_namespace_match,
     },
     per_ns::PerNs,
     visibility::{RawVisibility, Visibility},
@@ -584,8 +584,11 @@ impl DefMap {
                     // now resulting in a cycle.
                     // To properly implement this, trait item collection needs to be done in def map
                     // collection...
-                    let item =
-                        if true { None } else { db.trait_items(t).assoc_item_by_name(segment) };
+                    let item = if true {
+                        None
+                    } else {
+                        TraitItems::query(db, t).assoc_item_by_name(segment)
+                    };
                     return match item {
                         Some(item) => ResolvePathResult::new(
                             match item {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
index 377a545ebf4..1958eb6c6a1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
@@ -1,6 +1,6 @@
 //! Item signature IR definitions
 
-use std::ops::Not as _;
+use std::{cell::LazyCell, ops::Not as _};
 
 use bitflags::bitflags;
 use cfg::{CfgExpr, CfgOptions};
@@ -731,29 +731,26 @@ pub struct VariantFields {
     pub store: Arc<ExpressionStore>,
     pub shape: FieldsShape,
 }
+
+#[salsa::tracked]
 impl VariantFields {
-    #[inline]
+    #[salsa::tracked(returns(clone))]
     pub(crate) fn query(
         db: &dyn DefDatabase,
         id: VariantId,
     ) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
-        let (shape, (fields, store, source_map)) = match id {
+        let (shape, result) = match id {
             VariantId::EnumVariantId(id) => {
                 let loc = id.lookup(db);
                 let parent = loc.parent.lookup(db);
                 let source = loc.source(db);
                 let shape = adt_shape(source.value.kind());
-                let span_map = db.span_map(source.file_id);
-                let override_visibility = visibility_from_ast(
-                    db,
-                    source.value.parent_enum().visibility(),
-                    &mut |range| span_map.span_for_range(range).ctx,
-                );
+                let enum_vis = Some(source.value.parent_enum().visibility());
                 let fields = lower_field_list(
                     db,
                     parent.container,
                     source.map(|src| src.field_list()),
-                    Some(override_visibility),
+                    enum_vis,
                 );
                 (shape, fields)
             }
@@ -777,10 +774,29 @@ impl VariantFields {
                 (FieldsShape::Record, fields)
             }
         };
+        match result {
+            Some((fields, store, source_map)) => (
+                Arc::new(VariantFields { fields, store: Arc::new(store), shape }),
+                Arc::new(source_map),
+            ),
+            None => (
+                Arc::new(VariantFields {
+                    fields: Arena::default(),
+                    store: ExpressionStore::empty_singleton(),
+                    shape,
+                }),
+                ExpressionStoreSourceMap::empty_singleton(),
+            ),
+        }
+    }
 
-        (Arc::new(VariantFields { fields, store: Arc::new(store), shape }), Arc::new(source_map))
+    #[salsa::tracked(returns(deref))]
+    pub(crate) fn firewall(db: &dyn DefDatabase, id: VariantId) -> Arc<Self> {
+        Self::query(db, id).0
     }
+}
 
+impl VariantFields {
     pub fn len(&self) -> usize {
         self.fields.len()
     }
@@ -798,31 +814,24 @@ fn lower_field_list(
     db: &dyn DefDatabase,
     module: ModuleId,
     fields: InFile<Option<ast::FieldList>>,
-    override_visibility: Option<RawVisibility>,
-) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) {
+    override_visibility: Option<Option<ast::Visibility>>,
+) -> Option<(Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap)> {
     let file_id = fields.file_id;
-    match fields.value {
-        Some(ast::FieldList::RecordFieldList(fields)) => lower_fields(
+    match fields.value? {
+        ast::FieldList::RecordFieldList(fields) => lower_fields(
             db,
             module,
             InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))),
             |_, field| as_name_opt(field.name()),
             override_visibility,
         ),
-        Some(ast::FieldList::TupleFieldList(fields)) => lower_fields(
+        ast::FieldList::TupleFieldList(fields) => lower_fields(
             db,
             module,
             InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))),
             |idx, _| Name::new_tuple_field(idx),
             override_visibility,
         ),
-        None => lower_fields(
-            db,
-            module,
-            InFile::new(file_id, std::iter::empty::<(Option<ast::Type>, ast::RecordField)>()),
-            |_, _| Name::missing(),
-            None,
-        ),
     }
 }
 
@@ -831,22 +840,34 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
     module: ModuleId,
     fields: InFile<impl Iterator<Item = (Option<ast::Type>, Field)>>,
     mut field_name: impl FnMut(usize, &Field) -> Name,
-    override_visibility: Option<RawVisibility>,
-) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) {
-    let mut arena = Arena::new();
+    override_visibility: Option<Option<ast::Visibility>>,
+) -> Option<(Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap)> {
     let cfg_options = module.krate.cfg_options(db);
     let mut col = ExprCollector::new(db, module, fields.file_id);
+    let override_visibility = override_visibility.map(|vis| {
+        LazyCell::new(|| {
+            let span_map = db.span_map(fields.file_id);
+            visibility_from_ast(db, vis, &mut |range| span_map.span_for_range(range).ctx)
+        })
+    });
+
+    let mut arena = Arena::new();
     let mut idx = 0;
+    let mut has_fields = false;
     for (ty, field) in fields.value {
+        has_fields = true;
         match Attrs::is_cfg_enabled_for(db, &field, col.span_map(), cfg_options) {
             Ok(()) => {
                 let type_ref =
                     col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator);
-                let visibility = override_visibility.clone().unwrap_or_else(|| {
-                    visibility_from_ast(db, field.visibility(), &mut |range| {
-                        col.span_map().span_for_range(range).ctx
-                    })
-                });
+                let visibility = override_visibility.as_ref().map_or_else(
+                    || {
+                        visibility_from_ast(db, field.visibility(), &mut |range| {
+                            col.span_map().span_for_range(range).ctx
+                        })
+                    },
+                    |it| RawVisibility::clone(it),
+                );
                 let is_unsafe = field
                     .syntax()
                     .children_with_tokens()
@@ -867,9 +888,12 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
             }
         }
     }
+    if !has_fields {
+        return None;
+    }
     let store = col.store.finish();
     arena.shrink_to_fit();
-    (arena, store, col.source_map)
+    Some((arena, store, col.source_map))
 }
 
 #[derive(Debug, PartialEq, Eq)]
@@ -948,7 +972,7 @@ impl EnumVariants {
         self.variants.iter().all(|&(v, _, _)| {
             // The condition check order is slightly modified from rustc
             // to improve performance by early returning with relatively fast checks
-            let variant = &db.variant_fields(v.into());
+            let variant = v.fields(db);
             if !variant.fields().is_empty() {
                 return false;
             }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
index 2514e88864f..b5eb84c25f2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
@@ -273,7 +273,7 @@ pub(crate) fn field_visibilities_query(
     db: &dyn DefDatabase,
     variant_id: VariantId,
 ) -> Arc<ArenaMap<LocalFieldId, Visibility>> {
-    let variant_fields = db.variant_fields(variant_id);
+    let variant_fields = variant_id.fields(db);
     let fields = variant_fields.fields();
     if fields.is_empty() {
         return Arc::default();
diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
index ed818c5be3f..80a3c084865 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
index 94c97713f06..986f8764f5c 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -433,20 +433,19 @@ fn unescape(s: &str) -> Option<Cow<'_, str>> {
     let mut buf = String::new();
     let mut prev_end = 0;
     let mut has_error = false;
-    unescape::unescape_unicode(s, unescape::Mode::Str, &mut |char_range, unescaped_char| match (
-        unescaped_char,
-        buf.capacity() == 0,
-    ) {
-        (Ok(c), false) => buf.push(c),
-        (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
-            prev_end = char_range.end
-        }
-        (Ok(c), true) => {
-            buf.reserve_exact(s.len());
-            buf.push_str(&s[..prev_end]);
-            buf.push(c);
+    unescape::unescape_str(s, |char_range, unescaped_char| {
+        match (unescaped_char, buf.capacity() == 0) {
+            (Ok(c), false) => buf.push(c),
+            (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
+                prev_end = char_range.end
+            }
+            (Ok(c), true) => {
+                buf.reserve_exact(s.len());
+                buf.push_str(&s[..prev_end]);
+                buf.push(c);
+            }
+            (Err(_), _) => has_error = true,
         }
-        (Err(_), _) => has_error = true,
     });
 
     match (has_error, buf.capacity() == 0) {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index 3180b8dae10..f9abe4f5566 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -12,7 +12,7 @@ use span::{Edition, FileId, Span};
 use stdx::format_to;
 use syntax::{
     format_smolstr,
-    unescape::{Mode, unescape_byte, unescape_char, unescape_unicode},
+    unescape::{unescape_byte, unescape_char, unescape_str},
 };
 use syntax_bridge::syntax_node_to_token_tree;
 
@@ -430,7 +430,7 @@ fn compile_error_expand(
                 kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
                 suffix: _,
             })),
-        ] => ExpandError::other(span, Box::from(unescape_str(text).as_str())),
+        ] => ExpandError::other(span, Box::from(unescape_symbol(text).as_str())),
         _ => ExpandError::other(span, "`compile_error!` argument must be a string"),
     };
 
@@ -481,7 +481,7 @@ fn concat_expand(
                         format_to!(text, "{}", it.symbol.as_str())
                     }
                     tt::LitKind::Str => {
-                        text.push_str(unescape_str(&it.symbol).as_str());
+                        text.push_str(unescape_symbol(&it.symbol).as_str());
                         record_span(it.span);
                     }
                     tt::LitKind::StrRaw(_) => {
@@ -691,7 +691,7 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
                 span,
                 kind: tt::LitKind::Str,
                 suffix: _,
-            })) => Ok((unescape_str(text), *span)),
+            })) => Ok((unescape_symbol(text), *span)),
             TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                 symbol: text,
                 span,
@@ -712,7 +712,7 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
                             span,
                             kind: tt::LitKind::Str,
                             suffix: _,
-                        })) => Some((unescape_str(text), *span)),
+                        })) => Some((unescape_symbol(text), *span)),
                         TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                             symbol: text,
                             span,
@@ -897,11 +897,11 @@ fn quote_expand(
     )
 }
 
-fn unescape_str(s: &Symbol) -> Symbol {
+fn unescape_symbol(s: &Symbol) -> Symbol {
     if s.as_str().contains('\\') {
         let s = s.as_str();
         let mut buf = String::with_capacity(s.len());
-        unescape_unicode(s, Mode::Str, &mut |_, c| {
+        unescape_str(s, |_, c| {
             if let Ok(c) = c {
                 buf.push(c)
             }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index 8b65126e7b7..7cc0a26d37c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
index 7acc9456ec9..cc8f7bf04a5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -208,7 +208,7 @@ pub(crate) fn deref_by_trait(
     };
     let trait_id = trait_id()?;
     let target =
-        db.trait_items(trait_id).associated_type_by_name(&Name::new_symbol_root(sym::Target))?;
+        trait_id.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Target))?;
 
     let projection = {
         let b = TyBuilder::subst_for_def(db, trait_id, None);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 79454428112..26b635298a6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -315,9 +315,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
             crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
                 if let Some((future_trait, future_output)) =
                     LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| {
-                        let alias = self
-                            .db
-                            .trait_items(trait_)
+                        let alias = trait_
+                            .trait_items(self.db)
                             .associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
                         Some((trait_, alias))
                     })
@@ -711,7 +710,7 @@ pub(crate) fn trait_datum_query(
     };
     let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
     let associated_ty_ids =
-        db.trait_items(trait_).associated_types().map(to_assoc_type_id).collect();
+        trait_.trait_items(db).associated_types().map(to_assoc_type_id).collect();
     let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
     let well_known = db.lang_attr(trait_.into()).and_then(well_known_trait_from_lang_item);
     let trait_datum = TraitDatum {
@@ -802,7 +801,7 @@ pub(crate) fn adt_datum_query(
 
     // this slows down rust-analyzer by quite a bit unfortunately, so enabling this is currently not worth it
     let _variant_id_to_fields = |id: VariantId| {
-        let variant_data = &id.variant_data(db);
+        let variant_data = &id.fields(db);
         let fields = if variant_data.fields().is_empty() {
             vec![]
         } else {
@@ -879,7 +878,7 @@ fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId)
     let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
 
     let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses };
-    let trait_data = db.trait_items(trait_);
+    let trait_data = trait_.trait_items(db);
     let associated_ty_value_ids = impl_id
         .impl_items(db)
         .items
@@ -931,8 +930,9 @@ fn type_alias_associated_ty_value(
         .into_value_and_skipped_binders()
         .0; // we don't return any assoc ty values if the impl'd trait can't be resolved
 
-    let assoc_ty = db
-        .trait_items(trait_ref.hir_trait_id())
+    let assoc_ty = trait_ref
+        .hir_trait_id()
+        .trait_items(db)
         .associated_type_by_name(&type_alias_data.name)
         .expect("assoc ty value should not exist"); // validated when building the impl data as well
     let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
index 1873f12fb7c..9c0f8f40080 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -307,7 +307,7 @@ impl<'a> DeclValidator<'a> {
 
     /// Check incorrect names for struct fields.
     fn validate_struct_fields(&mut self, struct_id: StructId) {
-        let data = self.db.variant_fields(struct_id.into());
+        let data = struct_id.fields(self.db);
         if data.shape != FieldsShape::Record {
             return;
         };
@@ -468,7 +468,7 @@ impl<'a> DeclValidator<'a> {
 
     /// Check incorrect names for fields of enum variant.
     fn validate_enum_variant_fields(&mut self, variant_id: EnumVariantId) {
-        let variant_data = self.db.variant_fields(variant_id.into());
+        let variant_data = variant_id.fields(self.db);
         if variant_data.shape != FieldsShape::Record {
             return;
         };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index df2eb410b99..5d56957be6d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -494,7 +494,7 @@ impl FilterMapNextChecker {
                 Some(next_function_id),
                 match next_function_id.lookup(db).container {
                     ItemContainerId::TraitId(iterator_trait_id) => {
-                        let iterator_trait_items = &db.trait_items(iterator_trait_id).items;
+                        let iterator_trait_items = &iterator_trait_id.trait_items(db).items;
                         iterator_trait_items.iter().find_map(|(name, it)| match it {
                             &AssocItemId::FunctionId(id) if *name == sym::filter_map => Some(id),
                             _ => None,
@@ -558,7 +558,7 @@ pub fn record_literal_missing_fields(
         return None;
     }
 
-    let variant_data = variant_def.variant_data(db);
+    let variant_data = variant_def.fields(db);
 
     let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
     let missed_fields: Vec<LocalFieldId> = variant_data
@@ -588,7 +588,7 @@ pub fn record_pattern_missing_fields(
         return None;
     }
 
-    let variant_data = variant_def.variant_data(db);
+    let variant_data = variant_def.fields(db);
 
     let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
     let missed_fields: Vec<LocalFieldId> = variant_data
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs
index 916876d4ac9..0bce32a6778 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs
@@ -169,13 +169,13 @@ impl<'a> PatCtxt<'a> {
             }
 
             hir_def::hir::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => {
-                let expected_len = variant.unwrap().variant_data(self.db).fields().len();
+                let expected_len = variant.unwrap().fields(self.db).fields().len();
                 let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis);
                 self.lower_variant_or_leaf(pat, ty, subpatterns)
             }
 
             hir_def::hir::Pat::Record { ref args, .. } if variant.is_some() => {
-                let variant_data = variant.unwrap().variant_data(self.db);
+                let variant_data = variant.unwrap().fields(self.db);
                 let subpatterns = args
                     .iter()
                     .map(|field| {
@@ -345,7 +345,7 @@ impl HirDisplay for Pat {
                         )?,
                     };
 
-                    let variant_data = variant.variant_data(f.db);
+                    let variant_data = variant.fields(f.db);
                     if variant_data.shape == FieldsShape::Record {
                         write!(f, " {{ ")?;
 
@@ -377,7 +377,7 @@ impl HirDisplay for Pat {
                 }
 
                 let num_fields =
-                    variant.map_or(subpatterns.len(), |v| v.variant_data(f.db).fields().len());
+                    variant.map_or(subpatterns.len(), |v| v.fields(f.db).fields().len());
                 if num_fields != 0 || variant.is_none() {
                     write!(f, "(")?;
                     let subpats = (0..num_fields).map(|i| {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 2873a3e09e7..7cf22c64d0f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -6,7 +6,7 @@ use std::fmt;
 use hir_def::{DefWithBodyId, EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId};
 use intern::sym;
 use rustc_pattern_analysis::{
-    Captures, IndexVec, PatCx, PrivateUninhabitedField,
+    IndexVec, PatCx, PrivateUninhabitedField,
     constructor::{Constructor, ConstructorSet, VariantVisibility},
     usefulness::{PlaceValidity, UsefulnessReport, compute_match_usefulness},
 };
@@ -138,15 +138,15 @@ impl<'db> MatchCheckCtx<'db> {
     }
 
     // This lists the fields of a variant along with their types.
-    fn list_variant_fields<'a>(
-        &'a self,
-        ty: &'a Ty,
+    fn list_variant_fields(
+        &self,
+        ty: &Ty,
         variant: VariantId,
-    ) -> impl Iterator<Item = (LocalFieldId, Ty)> + Captures<'a> + Captures<'db> {
+    ) -> impl Iterator<Item = (LocalFieldId, Ty)> {
         let (_, substs) = ty.as_adt().unwrap();
 
         let field_tys = self.db.field_types(variant);
-        let fields_len = variant.variant_data(self.db).fields().len() as u32;
+        let fields_len = variant.fields(self.db).fields().len() as u32;
 
         (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| {
             let ty = field_tys[fid].clone().substitute(Interner, substs);
@@ -229,7 +229,7 @@ impl<'db> MatchCheckCtx<'db> {
                             }
                         };
                         let variant = Self::variant_id_for_adt(self.db, &ctor, adt).unwrap();
-                        arity = variant.variant_data(self.db).fields().len();
+                        arity = variant.fields(self.db).fields().len();
                     }
                     _ => {
                         never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
@@ -349,7 +349,7 @@ impl PatCx for MatchCheckCtx<'_> {
                         1
                     } else {
                         let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
-                        variant.variant_data(self.db).fields().len()
+                        variant.fields(self.db).fields().len()
                     }
                 }
                 _ => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 1aa7e0fcf88..507bab29208 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -888,7 +888,7 @@ fn render_const_scalar(
                     write!(f, "{}", data.name.display(f.db, f.edition()))?;
                     let field_types = f.db.field_types(s.into());
                     render_variant_after_name(
-                        &f.db.variant_fields(s.into()),
+                        s.fields(f.db),
                         f,
                         &field_types,
                         f.db.trait_environment(adt.0.into()),
@@ -920,7 +920,7 @@ fn render_const_scalar(
                     )?;
                     let field_types = f.db.field_types(var_id.into());
                     render_variant_after_name(
-                        &f.db.variant_fields(var_id.into()),
+                        var_id.fields(f.db),
                         f,
                         &field_types,
                         f.db.trait_environment(adt.0.into()),
@@ -1394,7 +1394,7 @@ impl HirDisplay for Ty {
                         let future_trait =
                             LangItem::Future.resolve_trait(db, body.module(db).krate());
                         let output = future_trait.and_then(|t| {
-                            db.trait_items(t)
+                            t.trait_items(db)
                                 .associated_type_by_name(&Name::new_symbol_root(sym::Output))
                         });
                         write!(f, "impl ")?;
@@ -2178,6 +2178,7 @@ impl HirDisplayWithExpressionStore for TypeRefId {
                         f.write_joined(
                             generic_params
                                 .where_predicates()
+                                .iter()
                                 .filter_map(|it| match it {
                                     WherePredicate::TypeBound { target, bound }
                                     | WherePredicate::ForLifetime { lifetimes: _, target, bound }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index 48094945c11..30949c83bfa 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -101,7 +101,7 @@ where
 
     // rustc checks for non-lifetime binders here, but we don't support HRTB yet
 
-    let trait_data = db.trait_items(trait_);
+    let trait_data = trait_.trait_items(db);
     for (_, assoc_item) in &trait_data.items {
         dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
     }
@@ -164,7 +164,7 @@ fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
 
 // Same as the above, `predicates_reference_self`
 fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
-    let trait_data = db.trait_items(trait_);
+    let trait_data = trait_.trait_items(db);
     trait_data
         .items
         .iter()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
index a3ed39934cd..f14872e68c3 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -60,7 +60,16 @@ impl Generics {
     }
 
     pub(crate) fn where_predicates(&self) -> impl Iterator<Item = &WherePredicate> {
-        self.params.where_predicates()
+        self.params.where_predicates().iter()
+    }
+
+    pub(crate) fn has_no_predicates(&self) -> bool {
+        self.params.has_no_predicates()
+            && self.parent_generics.as_ref().is_none_or(|g| g.params.has_no_predicates())
+    }
+
+    pub(crate) fn is_empty(&self) -> bool {
+        self.params.is_empty() && self.parent_generics.as_ref().is_none_or(|g| g.params.is_empty())
     }
 
     pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 80478f19371..ce53198e966 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -1813,7 +1813,7 @@ impl<'db> InferenceContext<'db> {
     }
 
     fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
-        self.db.trait_items(trait_).associated_type_by_name(&Name::new_symbol_root(sym::Output))
+        trait_.trait_items(self.db).associated_type_by_name(&Name::new_symbol_root(sym::Output))
     }
 
     fn resolve_lang_trait(&self, lang: LangItem) -> Option<TraitId> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs
index 8d345defdc1..4e95eca3f94 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs
@@ -382,7 +382,7 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result<Option<Pointe
                 return Err(());
             };
 
-            let struct_data = table.db.variant_fields(id.into());
+            let struct_data = id.fields(table.db);
             if let Some((last_field, _)) = struct_data.fields().iter().last() {
                 let last_field_ty =
                     table.db.field_types(id.into())[last_field].clone().substitute(Interner, subst);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index b756bb859d3..65a273cdf8d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -677,7 +677,7 @@ impl CapturedItem {
             match proj {
                 ProjectionElem::Deref => {}
                 ProjectionElem::Field(Either::Left(f)) => {
-                    let variant_data = f.parent.variant_data(db);
+                    let variant_data = f.parent.fields(db);
                     match variant_data.shape {
                         FieldsShape::Record => {
                             result.push('_');
@@ -720,7 +720,7 @@ impl CapturedItem {
                 // In source code autoderef kicks in.
                 ProjectionElem::Deref => {}
                 ProjectionElem::Field(Either::Left(f)) => {
-                    let variant_data = f.parent.variant_data(db);
+                    let variant_data = f.parent.fields(db);
                     match variant_data.shape {
                         FieldsShape::Record => format_to!(
                             result,
@@ -782,7 +782,7 @@ impl CapturedItem {
                     if field_need_paren {
                         result = format!("({result})");
                     }
-                    let variant_data = f.parent.variant_data(db);
+                    let variant_data = f.parent.fields(db);
                     let field = match variant_data.shape {
                         FieldsShape::Record => {
                             variant_data.fields()[f.local_id].name.as_str().to_owned()
@@ -1210,9 +1210,8 @@ impl InferenceContext<'_> {
                         if let Some(deref_trait) =
                             self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait())
                         {
-                            if let Some(deref_fn) = self
-                                .db
-                                .trait_items(deref_trait)
+                            if let Some(deref_fn) = deref_trait
+                                .trait_items(self.db)
                                 .method_by_name(&Name::new_symbol_root(sym::deref_mut))
                             {
                                 break 'b deref_fn == f;
@@ -1560,7 +1559,7 @@ impl InferenceContext<'_> {
                             self.consume_place(place)
                         }
                         VariantId::StructId(s) => {
-                            let vd = &*self.db.variant_fields(s.into());
+                            let vd = s.fields(self.db);
                             for field_pat in args.iter() {
                                 let arg = field_pat.pat;
                                 let Some(local_id) = vd.field(&field_pat.name) else {
@@ -1612,7 +1611,7 @@ impl InferenceContext<'_> {
                             self.consume_place(place)
                         }
                         VariantId::StructId(s) => {
-                            let vd = &*self.db.variant_fields(s.into());
+                            let vd = s.fields(self.db);
                             let (al, ar) =
                                 args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
                             let fields = vd.fields().iter();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 64031279296..d40d52c134d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -542,7 +542,7 @@ impl InferenceContext<'_> {
                     _ if fields.is_empty() => {}
                     Some(def) => {
                         let field_types = self.db.field_types(def);
-                        let variant_data = def.variant_data(self.db);
+                        let variant_data = def.fields(self.db);
                         let visibilities = self.db.field_visibilities(def);
                         for field in fields.iter() {
                             let field_def = {
@@ -654,9 +654,8 @@ impl InferenceContext<'_> {
                 match op {
                     UnaryOp::Deref => {
                         if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
-                            if let Some(deref_fn) = self
-                                .db
-                                .trait_items(deref_trait)
+                            if let Some(deref_fn) = deref_trait
+                                .trait_items(self.db)
                                 .method_by_name(&Name::new_symbol_root(sym::deref))
                             {
                                 // FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
@@ -813,9 +812,8 @@ impl InferenceContext<'_> {
                         self.table.new_lifetime_var(),
                     ));
                     self.write_expr_adj(*base, adj.into_boxed_slice());
-                    if let Some(func) = self
-                        .db
-                        .trait_items(index_trait)
+                    if let Some(func) = index_trait
+                        .trait_items(self.db)
                         .method_by_name(&Name::new_symbol_root(sym::index))
                     {
                         let subst = TyBuilder::subst_for_def(self.db, index_trait, None);
@@ -1148,7 +1146,7 @@ impl InferenceContext<'_> {
         let Some(trait_) = fn_x.get_id(self.db, self.table.trait_env.krate) else {
             return;
         };
-        let trait_data = self.db.trait_items(trait_);
+        let trait_data = trait_.trait_items(self.db);
         if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) {
             let subst = TyBuilder::subst_for_def(self.db, trait_, None)
                 .push(callee_ty.clone())
@@ -1316,7 +1314,7 @@ impl InferenceContext<'_> {
 
         let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
             let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
-            let func = self.db.trait_items(trait_id).method_by_name(&name)?;
+            let func = trait_id.trait_items(self.db).method_by_name(&name)?;
             Some((trait_id, func))
         });
         let (trait_, func) = match trait_func {
@@ -1568,12 +1566,12 @@ impl InferenceContext<'_> {
                     });
                 }
                 &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref parameters) => {
-                    let local_id = self.db.variant_fields(s.into()).field(name)?;
+                    let local_id = s.fields(self.db).field(name)?;
                     let field = FieldId { parent: s.into(), local_id };
                     (field, parameters.clone())
                 }
                 &TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), ref parameters) => {
-                    let local_id = self.db.variant_fields(u.into()).field(name)?;
+                    let local_id = u.fields(self.db).field(name)?;
                     let field = FieldId { parent: u.into(), local_id };
                     (field, parameters.clone())
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs
index ac450c0b559..d2eaf212365 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs
@@ -129,9 +129,8 @@ impl InferenceContext<'_> {
                         if let Some(index_trait) =
                             LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
                         {
-                            if let Some(index_fn) = self
-                                .db
-                                .trait_items(index_trait)
+                            if let Some(index_fn) = index_trait
+                                .trait_items(self.db)
                                 .method_by_name(&Name::new_symbol_root(sym::index_mut))
                             {
                                 *f = index_fn;
@@ -194,9 +193,8 @@ impl InferenceContext<'_> {
                             });
                             if is_mut_ptr {
                                 mutability = Mutability::Not;
-                            } else if let Some(deref_fn) = self
-                                .db
-                                .trait_items(deref_trait)
+                            } else if let Some(deref_fn) = deref_trait
+                                .trait_items(self.db)
                                 .method_by_name(&Name::new_symbol_root(sym::deref_mut))
                             {
                                 *f = deref_fn;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
index 4bc3e167ebf..99d3b5c7a84 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
@@ -38,7 +38,7 @@ impl InferenceContext<'_> {
         decl: Option<DeclContext>,
     ) -> Ty {
         let (ty, def) = self.resolve_variant(id.into(), path, true);
-        let var_data = def.map(|it| it.variant_data(self.db));
+        let var_data = def.map(|it| it.fields(self.db));
         if let Some(variant) = def {
             self.write_variant_resolution(id.into(), variant);
         }
@@ -60,7 +60,7 @@ impl InferenceContext<'_> {
             _ if subs.is_empty() => {}
             Some(def) => {
                 let field_types = self.db.field_types(def);
-                let variant_data = def.variant_data(self.db);
+                let variant_data = def.fields(self.db);
                 let visibilities = self.db.field_visibilities(def);
 
                 let (pre, post) = match ellipsis {
@@ -129,7 +129,7 @@ impl InferenceContext<'_> {
             _ if subs.len() == 0 => {}
             Some(def) => {
                 let field_types = self.db.field_types(def);
-                let variant_data = def.variant_data(self.db);
+                let variant_data = def.fields(self.db);
                 let visibilities = self.db.field_visibilities(def);
 
                 let substs = ty.as_adt().map(TupleExt::tail);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index c327c13b664..bc8648ecdd9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -278,7 +278,7 @@ impl InferenceContext<'_> {
     ) -> Option<(ValueNs, Substitution)> {
         let trait_ = trait_ref.hir_trait_id();
         let item =
-            self.db.trait_items(trait_).items.iter().map(|(_name, id)| *id).find_map(|item| {
+            trait_.trait_items(self.db).items.iter().map(|(_name, id)| *id).find_map(|item| {
                 match item {
                     AssocItemId::FunctionId(func) => {
                         if segment.name == &self.db.function_signature(func).name {
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 631b571465f..c07755535f2 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
@@ -859,7 +859,7 @@ impl<'a> InferenceTable<'a> {
         ] {
             let krate = self.trait_env.krate;
             let fn_trait = fn_trait_name.get_id(self.db, krate)?;
-            let trait_data = self.db.trait_items(fn_trait);
+            let trait_data = fn_trait.trait_items(self.db);
             let output_assoc_type =
                 trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
 
@@ -1001,7 +1001,7 @@ impl<'a> InferenceTable<'a> {
             // Must use a loop here and not recursion because otherwise users will conduct completely
             // artificial examples of structs that have themselves as the tail field and complain r-a crashes.
             while let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
-                let struct_data = self.db.variant_fields(id.into());
+                let struct_data = id.fields(self.db);
                 if let Some((last_field, _)) = struct_data.fields().iter().next_back() {
                     let last_field_ty = self.db.field_types(id.into())[last_field]
                         .clone()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
index 79a99321f10..b16b6a11784 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
@@ -132,7 +132,7 @@ impl UninhabitedFrom<'_> {
         variant: VariantId,
         subst: &Substitution,
     ) -> ControlFlow<VisiblyUninhabited> {
-        let variant_data = self.db.variant_fields(variant);
+        let variant_data = variant.fields(self.db);
         let fields = variant_data.fields();
         if fields.is_empty() {
             return CONTINUE_OPAQUELY_INHABITED;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index c58bd1b773e..3fa2bfbd1b7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -375,7 +375,7 @@ pub(crate) fn layout_of_ty_cycle_result(
 fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
     match pointee.kind(Interner) {
         &TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), ref subst) => {
-            let data = db.variant_fields(i.into());
+            let data = i.fields(db);
             let mut it = data.fields().iter().rev();
             match it.next() {
                 Some((f, _)) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
index dff986fec3c..236f316366d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
@@ -42,7 +42,7 @@ pub fn layout_of_adt_query(
         AdtId::StructId(s) => {
             let sig = db.struct_signature(s);
             let mut r = SmallVec::<[_; 1]>::new();
-            r.push(handle_variant(s.into(), &db.variant_fields(s.into()))?);
+            r.push(handle_variant(s.into(), s.fields(db))?);
             (
                 r,
                 sig.repr.unwrap_or_default(),
@@ -52,7 +52,7 @@ pub fn layout_of_adt_query(
         AdtId::UnionId(id) => {
             let data = db.union_signature(id);
             let mut r = SmallVec::new();
-            r.push(handle_variant(id.into(), &db.variant_fields(id.into()))?);
+            r.push(handle_variant(id.into(), id.fields(db))?);
             (r, data.repr.unwrap_or_default(), false)
         }
         AdtId::EnumId(e) => {
@@ -60,7 +60,7 @@ pub fn layout_of_adt_query(
             let r = variants
                 .variants
                 .iter()
-                .map(|&(v, _, _)| handle_variant(v.into(), &db.variant_fields(v.into())))
+                .map(|&(v, _, _)| handle_variant(v.into(), v.fields(db)))
                 .collect::<Result<SmallVec<_>, _>>()?;
             (r, db.enum_signature(e).repr.unwrap_or_default(), false)
         }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 148f2a41e7d..e787fd9b1e5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -891,8 +891,8 @@ pub fn callable_sig_from_fn_trait(
 ) -> Option<(FnTrait, CallableSig)> {
     let krate = trait_env.krate;
     let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
-    let output_assoc_type = db
-        .trait_items(fn_once_trait)
+    let output_assoc_type = fn_once_trait
+        .trait_items(db)
         .associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
 
     let mut table = InferenceTable::new(db, trait_env.clone());
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 0a546768dab..f32b6af4d85 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -581,11 +581,28 @@ impl<'a> TyLoweringContext<'a> {
         match bound {
             &TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
                 // FIXME Don't silently drop the hrtb lifetimes here
-                if let Some((trait_ref, ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
-                    if !ignore_bindings {
-                        assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref.clone());
+                if let Some((trait_ref, mut ctx)) =
+                    self.lower_trait_ref_from_path(path, self_ty.clone())
+                {
+                    // FIXME(sized-hierarchy): Remove this bound modifications once we have implemented
+                    // sized-hierarchy correctly.
+                    let meta_sized = LangItem::MetaSized
+                        .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
+                    let pointee_sized = LangItem::PointeeSized
+                        .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
+                    if meta_sized.is_some_and(|it| it == trait_ref.hir_trait_id()) {
+                        // Ignore this bound
+                    } else if pointee_sized.is_some_and(|it| it == trait_ref.hir_trait_id()) {
+                        // Regard this as `?Sized` bound
+                        ctx.ty_ctx().unsized_types.insert(self_ty);
+                    } else {
+                        if !ignore_bindings {
+                            assoc_bounds =
+                                ctx.assoc_type_bindings_from_type_bound(trait_ref.clone());
+                        }
+                        clause =
+                            Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref)));
                     }
-                    clause = Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref)));
                 }
             }
             &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
@@ -711,7 +728,7 @@ impl<'a> TyLoweringContext<'a> {
                             .unwrap_or(it),
                         None => it,
                     },
-                    None => static_lifetime(),
+                    None => error_lifetime(),
                 },
             })
             .intern(Interner)
@@ -805,7 +822,7 @@ fn named_associated_type_shorthand_candidates<R>(
 ) -> Option<R> {
     let mut search = |t| {
         all_super_trait_refs(db, t, |t| {
-            let data = db.trait_items(t.hir_trait_id());
+            let data = t.hir_trait_id().trait_items(db);
 
             for (name, assoc_id) in &data.items {
                 if let AssocItemId::TypeAliasId(alias) = assoc_id {
@@ -883,7 +900,12 @@ pub(crate) fn field_types_with_diagnostics_query(
     db: &dyn HirDatabase,
     variant_id: VariantId,
 ) -> (Arc<ArenaMap<LocalFieldId, Binders<Ty>>>, Diagnostics) {
-    let var_data = db.variant_fields(variant_id);
+    let var_data = variant_id.fields(db);
+    let fields = var_data.fields();
+    if fields.is_empty() {
+        return (Arc::new(ArenaMap::default()), None);
+    }
+
     let (resolver, def): (_, GenericDefId) = match variant_id {
         VariantId::StructId(it) => (it.resolver(db), it.into()),
         VariantId::UnionId(it) => (it.resolver(db), it.into()),
@@ -899,7 +921,7 @@ pub(crate) fn field_types_with_diagnostics_query(
         LifetimeElisionKind::AnonymousReportError,
     )
     .with_type_param_mode(ParamLoweringMode::Variable);
-    for (field_id, field_data) in var_data.fields().iter() {
+    for (field_id, field_data) in fields.iter() {
         res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
     }
     (Arc::new(res), create_diagnostics(ctx.diagnostics))
@@ -920,6 +942,10 @@ pub(crate) fn generic_predicates_for_param_query(
     assoc_name: Option<Name>,
 ) -> GenericPredicates {
     let generics = generics(db, def);
+    if generics.has_no_predicates() && generics.is_empty() {
+        return GenericPredicates(None);
+    }
+
     let resolver = def.resolver(db);
     let mut ctx = TyLoweringContext::new(
         db,
@@ -936,8 +962,32 @@ pub(crate) fn generic_predicates_for_param_query(
         | WherePredicate::TypeBound { target, bound, .. } => {
             let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
             if invalid_target {
-                // If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
-                if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
+                // FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented
+                // sized-hierarchy correctly.
+                // If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into
+                // `ctx.unsized_types`
+                let lower = || -> bool {
+                    match bound {
+                        TypeBound::Path(_, TraitBoundModifier::Maybe) => true,
+                        TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
+                            let TypeRef::Path(path) = &ctx.store[path.type_ref()] else {
+                                return false;
+                            };
+                            let Some(pointee_sized) =
+                                LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate())
+                            else {
+                                return false;
+                            };
+                            // Lower the path directly with `Resolver` instead of PathLoweringContext`
+                            // to prevent diagnostics duplications.
+                            ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and(
+                                |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized),
+                            )
+                        }
+                        _ => false,
+                    }
+                }();
+                if lower {
                     ctx.lower_where_predicate(pred, true).for_each(drop);
                 }
                 return false;
@@ -957,7 +1007,7 @@ pub(crate) fn generic_predicates_for_param_query(
                     };
 
                     all_super_traits(db, tr).iter().any(|tr| {
-                        db.trait_items(*tr).items.iter().any(|(name, item)| {
+                        tr.trait_items(db).items.iter().any(|(name, item)| {
                             matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
                         })
                     })
@@ -1025,6 +1075,10 @@ pub(crate) fn trait_environment_query(
     def: GenericDefId,
 ) -> Arc<TraitEnvironment> {
     let generics = generics(db, def);
+    if generics.has_no_predicates() && generics.is_empty() {
+        return TraitEnvironment::empty(def.krate(db));
+    }
+
     let resolver = def.resolver(db);
     let mut ctx = TyLoweringContext::new(
         db,
@@ -1128,6 +1182,10 @@ where
     F: Fn(&WherePredicate, GenericDefId) -> bool,
 {
     let generics = generics(db, def);
+    if generics.has_no_predicates() && generics.is_empty() {
+        return (GenericPredicates(None), None);
+    }
+
     let resolver = def.resolver(db);
     let mut ctx = TyLoweringContext::new(
         db,
@@ -1154,7 +1212,7 @@ where
         }
     }
 
-    if generics.len() > 0 {
+    if !generics.is_empty() {
         let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
         let explicitly_unsized_tys = ctx.unsized_types;
         if let Some(implicitly_sized_predicates) =
@@ -1229,7 +1287,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
     def: GenericDefId,
 ) -> (GenericDefaults, Diagnostics) {
     let generic_params = generics(db, def);
-    if generic_params.len() == 0 {
+    if generic_params.is_empty() {
         return (GenericDefaults(None), None);
     }
     let resolver = def.resolver(db);
@@ -1418,7 +1476,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
 
 /// Build the type of a tuple struct constructor.
 fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option<Binders<Ty>> {
-    let struct_data = db.variant_fields(def.into());
+    let struct_data = def.fields(db);
     match struct_data.shape {
         FieldsShape::Record => None,
         FieldsShape::Unit => Some(type_for_adt(db, def.into())),
@@ -1451,7 +1509,7 @@ fn type_for_enum_variant_constructor(
     def: EnumVariantId,
 ) -> Option<Binders<Ty>> {
     let e = def.lookup(db).parent;
-    match db.variant_fields(def.into()).shape {
+    match def.fields(db).shape {
         FieldsShape::Record => None,
         FieldsShape::Unit => Some(type_for_adt(db, e.into())),
         FieldsShape::Tuple => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs
index 726eaf8b0a1..06686b6a164 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs
@@ -173,7 +173,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
                         self.skip_resolved_segment();
                         let segment = self.current_or_prev_segment;
                         let found =
-                            self.ctx.db.trait_items(trait_).associated_type_by_name(segment.name);
+                            trait_.trait_items(self.ctx.db).associated_type_by_name(segment.name);
 
                         match found {
                             Some(associated_ty) => {
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 25f1782bdd8..a6150a9bc17 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
@@ -1302,7 +1302,7 @@ fn iterate_trait_method_candidates(
         // trait, but if we find out it doesn't, we'll skip the rest of the
         // iteration
         let mut known_implemented = false;
-        for &(_, item) in db.trait_items(t).items.iter() {
+        for &(_, item) in t.trait_items(db).items.iter() {
             // Don't pass a `visible_from_module` down to `is_valid_candidate`,
             // since only inherent methods should be included into visibility checking.
             let visible =
@@ -1429,7 +1429,7 @@ fn iterate_inherent_methods(
     ) -> ControlFlow<()> {
         let db = table.db;
         for t in traits {
-            let data = db.trait_items(t);
+            let data = t.trait_items(db);
             for &(_, item) in data.items.iter() {
                 // We don't pass `visible_from_module` as all trait items should be visible.
                 let visible = match is_valid_trait_method_candidate(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index a8156ec375b..1ec55a82092 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -657,12 +657,12 @@ impl Evaluator<'_> {
             cached_ptr_size,
             cached_fn_trait_func: LangItem::Fn
                 .resolve_trait(db, crate_id)
-                .and_then(|x| db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call))),
+                .and_then(|x| x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call))),
             cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| {
-                db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut))
+                x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_mut))
             }),
             cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| {
-                db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once))
+                x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once))
             }),
         })
     }
@@ -1749,8 +1749,7 @@ impl Evaluator<'_> {
                         AdtId::UnionId(_) => not_supported!("unsizing unions"),
                         AdtId::EnumId(_) => not_supported!("unsizing enums"),
                     };
-                    let Some((last_field, _)) =
-                        self.db.variant_fields(id.into()).fields().iter().next_back()
+                    let Some((last_field, _)) = id.fields(self.db).fields().iter().next_back()
                     else {
                         not_supported!("unsizing struct without field");
                     };
@@ -2232,7 +2231,7 @@ impl Evaluator<'_> {
                 }
                 chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
                     AdtId::StructId(s) => {
-                        let data = this.db.variant_fields(s.into());
+                        let data = s.fields(this.db);
                         let layout = this.layout(ty)?;
                         let field_types = this.db.field_types(s.into());
                         for (f, _) in data.fields().iter() {
@@ -2261,7 +2260,7 @@ impl Evaluator<'_> {
                             bytes,
                             e,
                         ) {
-                            let data = &this.db.variant_fields(v.into());
+                            let data = v.fields(this.db);
                             let field_types = this.db.field_types(v.into());
                             for (f, _) in data.fields().iter() {
                                 let offset =
@@ -2808,7 +2807,7 @@ impl Evaluator<'_> {
     ) -> Result<()> {
         let Some(drop_fn) = (|| {
             let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?;
-            self.db.trait_items(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop))
+            drop_trait.trait_items(self.db).method_by_name(&Name::new_symbol_root(sym::drop))
         })() else {
             // in some tests we don't have drop trait in minicore, and
             // we can ignore drop in them.
@@ -2838,7 +2837,7 @@ impl Evaluator<'_> {
                             return Ok(());
                         }
                         let layout = self.layout_adt(id.0, subst.clone())?;
-                        let variant_fields = self.db.variant_fields(s.into());
+                        let variant_fields = s.fields(self.db);
                         match variant_fields.shape {
                             FieldsShape::Record | FieldsShape::Tuple => {
                                 let field_types = self.db.field_types(s.into());
@@ -2918,7 +2917,7 @@ pub fn render_const_using_debug_impl(
         not_supported!("core::fmt::Debug not found");
     };
     let Some(debug_fmt_fn) =
-        db.trait_items(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt))
+        debug_trait.trait_items(db).method_by_name(&Name::new_symbol_root(sym::fmt))
     else {
         not_supported!("core::fmt::Debug::fmt not found");
     };
@@ -3045,7 +3044,10 @@ impl IntValue {
             (8, true) => Self::I64(i64::from_le_bytes(bytes.try_into().unwrap())),
             (16, false) => Self::U128(u128::from_le_bytes(bytes.try_into().unwrap())),
             (16, true) => Self::I128(i128::from_le_bytes(bytes.try_into().unwrap())),
-            _ => panic!("invalid integer size"),
+            (len, is_signed) => {
+                never!("invalid integer size: {len}, signed: {is_signed}");
+                Self::I32(0)
+            }
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index 6ebde013344..e9665d5ae9c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -1257,9 +1257,8 @@ impl Evaluator<'_> {
                     args.push(IntervalAndTy::new(addr, field, self, locals)?);
                 }
                 if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
-                    if let Some(def) = self
-                        .db
-                        .trait_items(target)
+                    if let Some(def) = target
+                        .trait_items(self.db)
                         .method_by_name(&Name::new_symbol_root(sym::call_once))
                     {
                         self.exec_fn_trait(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs
index 984648cfec3..bc331a23d98 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs
@@ -31,7 +31,7 @@ impl Evaluator<'_> {
                     Some(len) => len,
                     _ => {
                         if let AdtId::StructId(id) = id.0 {
-                            let struct_data = self.db.variant_fields(id.into());
+                            let struct_data = id.fields(self.db);
                             let fields = struct_data.fields();
                             let Some((first_field, _)) = fields.iter().next() else {
                                 not_supported!("simd type with no field");
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
index 3abbbe45e6f..c1f86960e15 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
@@ -984,3 +984,17 @@ fn main<'a, T: Foo + Bar + Baz>(
         |e| matches!(e, MirEvalError::MirLowerError(_, MirLowerError::GenericArgNotProvided(..))),
     );
 }
+
+#[test]
+fn format_args_pass() {
+    check_pass(
+        r#"
+//- minicore: fmt
+fn main() {
+    let x1 = format_args!("");
+    let x2 = format_args!("{}", x1);
+    let x3 = format_args!("{} {}", x1, x2);
+}
+"#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 71e038b92f0..845d6b8eae1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -503,7 +503,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         Ok(Some(current))
                     }
                     ValueNs::EnumVariantId(variant_id) => {
-                        let variant_fields = &self.db.variant_fields(variant_id.into());
+                        let variant_fields = variant_id.fields(self.db);
                         if variant_fields.shape == FieldsShape::Unit {
                             let ty = self.infer.type_of_expr[expr_id].clone();
                             current = self.lower_enum_variant(
@@ -856,7 +856,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     TyKind::Adt(_, s) => s.clone(),
                     _ => not_supported!("Non ADT record literal"),
                 };
-                let variant_fields = self.db.variant_fields(variant_id);
+                let variant_fields = variant_id.fields(self.db);
                 match variant_id {
                     VariantId::EnumVariantId(_) | VariantId::StructId(_) => {
                         let mut operands = vec![None; variant_fields.fields().len()];
@@ -1176,8 +1176,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     place,
                     Rvalue::Aggregate(
                         AggregateKind::Adt(st.into(), subst.clone()),
-                        self.db
-                            .variant_fields(st.into())
+                        st.fields(self.db)
                             .fields()
                             .iter()
                             .map(|it| {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs
index ad664693e29..e7bffead931 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs
@@ -193,9 +193,8 @@ impl MirLowerCtx<'_> {
                                 if let Some(deref_trait) =
                                     self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
                                 {
-                                    if let Some(deref_fn) = self
-                                        .db
-                                        .trait_items(deref_trait)
+                                    if let Some(deref_fn) = deref_trait
+                                        .trait_items(self.db)
                                         .method_by_name(&Name::new_symbol_root(sym::deref_mut))
                                     {
                                         break 'b deref_fn == f;
@@ -347,9 +346,8 @@ impl MirLowerCtx<'_> {
             .resolve_lang_item(trait_lang_item)?
             .as_trait()
             .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
-        let deref_fn = self
-            .db
-            .trait_items(deref_trait)
+        let deref_fn = deref_trait
+            .trait_items(self.db)
             .method_by_name(&trait_method_name)
             .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
         let deref_fn_op = Operand::const_zst(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
index b3c1f6f387f..61c0685c48a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -609,7 +609,7 @@ impl MirLowerCtx<'_> {
                 }
                 self.pattern_matching_variant_fields(
                     shape,
-                    &self.db.variant_fields(v.into()),
+                    v.fields(self.db),
                     variant,
                     current,
                     current_else,
@@ -619,7 +619,7 @@ impl MirLowerCtx<'_> {
             }
             VariantId::StructId(s) => self.pattern_matching_variant_fields(
                 shape,
-                &self.db.variant_fields(s.into()),
+                s.fields(self.db),
                 variant,
                 current,
                 current_else,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
index 8764e48b538..78a69cf4509 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
@@ -326,7 +326,7 @@ impl<'a> MirPrettyCtx<'a> {
                     w!(this, ")");
                 }
                 ProjectionElem::Field(Either::Left(field)) => {
-                    let variant_fields = this.db.variant_fields(field.parent);
+                    let variant_fields = field.parent.fields(this.db);
                     let name = &variant_fields.fields()[field.local_id].name;
                     match field.parent {
                         hir_def::VariantId::EnumVariantId(e) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
index 9ca6ee476c6..79754bc8a09 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -486,7 +486,7 @@ pub(crate) fn visit_module(
                     });
                 }
                 ModuleDefId::TraitId(it) => {
-                    let trait_data = db.trait_items(it);
+                    let trait_data = it.trait_items(db);
                     for &(_, item) in trait_data.items.iter() {
                         match item {
                             AssocItemId::FunctionId(it) => cb(it.into()),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
index ddc5b715194..3894b4b6f7b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
@@ -561,7 +561,7 @@ trait Foo {}
 fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
     let _: &dyn Foo = &f;
     let _: &dyn Foo = g;
-                    //^ expected &'? (dyn Foo + 'static), got &'? impl Foo + ?Sized
+                    //^ expected &'? (dyn Foo + '?), got &'? impl Foo + ?Sized
 }
         "#,
     );
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
index a986b54a7b0..6e3faa05a62 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
@@ -67,11 +67,11 @@ trait B: A {}
 
 fn test<'a>(
     _: &(dyn A<Assoc = ()> + Send),
-  //^ &(dyn A<Assoc = ()> + Send + 'static)
+  //^ &(dyn A<Assoc = ()> + Send)
     _: &'a (dyn Send + A<Assoc = ()>),
-  //^ &'a (dyn A<Assoc = ()> + Send + 'static)
+  //^ &'a (dyn A<Assoc = ()> + Send)
     _: &dyn B<Assoc = ()>,
-  //^ &(dyn B<Assoc = ()> + 'static)
+  //^ &(dyn B<Assoc = ()>)
 ) {}
         "#,
     );
@@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
 trait Foo<'a> {}
 
 fn foo(foo: &dyn for<'a> Foo<'a>) {}
-    // ^^^ &(dyn Foo<'?> + 'static)
+    // ^^^ &dyn Foo<'?>
 "#,
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
index 905fd8a3bca..0377ce95f19 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
@@ -567,7 +567,7 @@ fn main() {
                 "ast_id_map_shim",
                 "parse_shim",
                 "real_span_map_shim",
-                "trait_items_with_diagnostics_shim",
+                "query_with_diagnostics_",
                 "body_shim",
                 "body_with_source_map_shim",
                 "attrs_shim",
@@ -596,8 +596,8 @@ fn main() {
                 "struct_signature_with_source_map_shim",
                 "generic_predicates_shim",
                 "value_ty_shim",
-                "variant_fields_shim",
-                "variant_fields_with_source_map_shim",
+                "firewall_",
+                "query_",
                 "lang_item",
                 "inherent_impls_in_crate_shim",
                 "impl_signature_shim",
@@ -674,7 +674,7 @@ fn main() {
                 "file_item_tree_query",
                 "real_span_map_shim",
                 "crate_local_def_map",
-                "trait_items_with_diagnostics_shim",
+                "query_with_diagnostics_",
                 "body_with_source_map_shim",
                 "attrs_shim",
                 "body_shim",
@@ -695,11 +695,9 @@ fn main() {
                 "return_type_impl_traits_shim",
                 "infer_shim",
                 "function_signature_with_source_map_shim",
-                "trait_environment_shim",
                 "expr_scopes_shim",
                 "struct_signature_with_source_map_shim",
-                "generic_predicates_shim",
-                "variant_fields_with_source_map_shim",
+                "query_",
                 "inherent_impls_in_crate_shim",
                 "impl_signature_with_source_map_shim",
                 "impl_signature_shim",
@@ -709,7 +707,6 @@ fn main() {
                 "impl_trait_with_diagnostics_shim",
                 "impl_self_ty_with_diagnostics_shim",
                 "generic_predicates_shim",
-                "generic_predicates_shim",
             ]
         "#]],
     );
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
index 94826acca30..c58ca6c67a8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
@@ -1153,9 +1153,9 @@ fn dyn_trait_super_trait_not_in_scope() {
             51..55 'self': &'? Self
             64..69 '{ 0 }': u32
             66..67 '0': u32
-            176..177 'd': &'? (dyn Trait + 'static)
+            176..177 'd': &'? (dyn Trait + '?)
             191..207 '{     ...o(); }': ()
-            197..198 'd': &'? (dyn Trait + 'static)
+            197..198 'd': &'? (dyn Trait + '?)
             197..204 'd.foo()': u32
         "#]],
     );
@@ -2019,10 +2019,10 @@ impl dyn Error + Send {
     /// Attempts to downcast the box to a concrete type.
     pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
         let err: Box<dyn Error> = self;
-                               // ^^^^ expected Box<dyn Error + 'static>, got Box<dyn Error + Send + 'static>
+                               // ^^^^ expected Box<dyn Error + '?>, got Box<dyn Error + Send + '?>
                                // FIXME, type mismatch should not occur
         <dyn Error>::downcast(err).map_err(|_| loop {})
-      //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + 'static>) -> Result<Box<{unknown}>, Box<dyn Error + 'static>>
+      //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + '?>) -> Result<Box<{unknown}>, Box<dyn Error + '?>>
     }
 }
 "#,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
index ff8adeef1db..238753e12e4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
@@ -629,7 +629,7 @@ fn issue_4053_diesel_where_clauses() {
             488..522 '{     ...     }': ()
             498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
             498..508 'self.order': O
-            498..515 'self.o...into()': dyn QueryFragment<DB> + 'static
+            498..515 'self.o...into()': dyn QueryFragment<DB> + '?
         "#]],
     );
 }
@@ -773,7 +773,7 @@ fn issue_4800() {
         "#,
         expect![[r#"
             379..383 'self': &'? mut PeerSet<D>
-            401..424 '{     ...     }': dyn Future<Output = ()> + 'static
+            401..424 '{     ...     }': dyn Future<Output = ()> + '?
             411..418 'loop {}': !
             416..418 '{}': ()
             575..579 'self': &'? mut Self
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
index cf51671afb2..43e8f3747ab 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
@@ -2741,11 +2741,11 @@ impl B for Astruct {}
             715..744 '#[rust...1i32])': Box<[i32; 1], Global>
             737..743 '[1i32]': [i32; 1]
             738..742 '1i32': i32
-            755..756 'v': Vec<Box<dyn B + 'static, Global>, Global>
-            776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B + 'static, Global>, Global>(Box<[Box<dyn B + 'static, Global>], Global>) -> Vec<Box<dyn B + 'static, Global>, Global>
-            776..850 '<[_]> ...ct)]))': Vec<Box<dyn B + 'static, Global>, Global>
-            794..849 '#[rust...uct)])': Box<[Box<dyn B + 'static, Global>; 1], Global>
-            816..848 '[#[rus...ruct)]': [Box<dyn B + 'static, Global>; 1]
+            755..756 'v': Vec<Box<dyn B + '?, Global>, Global>
+            776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B + '?, Global>, Global>(Box<[Box<dyn B + '?, Global>], Global>) -> Vec<Box<dyn B + '?, Global>, Global>
+            776..850 '<[_]> ...ct)]))': Vec<Box<dyn B + '?, Global>, Global>
+            794..849 '#[rust...uct)])': Box<[Box<dyn B + '?, Global>; 1], Global>
+            816..848 '[#[rus...ruct)]': [Box<dyn B + '?, Global>; 1]
             817..847 '#[rust...truct)': Box<Astruct, Global>
             839..846 'Astruct': Astruct
         "#]],
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 e5d1fbe9def..56e31a1af1b 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
@@ -1475,26 +1475,26 @@ fn test(x: Box<dyn Trait<u64>>, y: &dyn Trait<u64>) {
         expect![[r#"
             29..33 'self': &'? Self
             54..58 'self': &'? Self
-            198..200 '{}': Box<dyn Trait<u64> + 'static>
-            210..211 'x': Box<dyn Trait<u64> + 'static>
-            234..235 'y': &'? (dyn Trait<u64> + 'static)
+            198..200 '{}': Box<dyn Trait<u64> + '?>
+            210..211 'x': Box<dyn Trait<u64> + '?>
+            234..235 'y': &'? (dyn Trait<u64> + '?)
             254..371 '{     ...2(); }': ()
-            260..261 'x': Box<dyn Trait<u64> + 'static>
-            267..268 'y': &'? (dyn Trait<u64> + 'static)
-            278..279 'z': Box<dyn Trait<u64> + 'static>
-            282..285 'bar': fn bar() -> Box<dyn Trait<u64> + 'static>
-            282..287 'bar()': Box<dyn Trait<u64> + 'static>
-            293..294 'x': Box<dyn Trait<u64> + 'static>
+            260..261 'x': Box<dyn Trait<u64> + '?>
+            267..268 'y': &'? (dyn Trait<u64> + '?)
+            278..279 'z': Box<dyn Trait<u64> + '?>
+            282..285 'bar': fn bar() -> Box<dyn Trait<u64> + '?>
+            282..287 'bar()': Box<dyn Trait<u64> + '?>
+            293..294 'x': Box<dyn Trait<u64> + '?>
             293..300 'x.foo()': u64
-            306..307 'y': &'? (dyn Trait<u64> + 'static)
+            306..307 'y': &'? (dyn Trait<u64> + '?)
             306..313 'y.foo()': u64
-            319..320 'z': Box<dyn Trait<u64> + 'static>
+            319..320 'z': Box<dyn Trait<u64> + '?>
             319..326 'z.foo()': u64
-            332..333 'x': Box<dyn Trait<u64> + 'static>
+            332..333 'x': Box<dyn Trait<u64> + '?>
             332..340 'x.foo2()': i64
-            346..347 'y': &'? (dyn Trait<u64> + 'static)
+            346..347 'y': &'? (dyn Trait<u64> + '?)
             346..354 'y.foo2()': i64
-            360..361 'z': Box<dyn Trait<u64> + 'static>
+            360..361 'z': Box<dyn Trait<u64> + '?>
             360..368 'z.foo2()': i64
         "#]],
     );
@@ -1523,14 +1523,14 @@ fn test(s: S<u32, i32>) {
         expect![[r#"
             32..36 'self': &'? Self
             102..106 'self': &'? S<T, U>
-            128..139 '{ loop {} }': &'? (dyn Trait<T, U> + 'static)
+            128..139 '{ loop {} }': &'? (dyn Trait<T, U> + '?)
             130..137 'loop {}': !
             135..137 '{}': ()
             175..179 'self': &'? Self
             251..252 's': S<u32, i32>
             267..289 '{     ...z(); }': ()
             273..274 's': S<u32, i32>
-            273..280 's.bar()': &'? (dyn Trait<u32, i32> + 'static)
+            273..280 's.bar()': &'? (dyn Trait<u32, i32> + '?)
             273..286 's.bar().baz()': (u32, i32)
         "#]],
     );
@@ -1556,20 +1556,20 @@ fn test(x: Trait, y: &Trait) -> u64 {
 }"#,
         expect![[r#"
             26..30 'self': &'? Self
-            60..62 '{}': dyn Trait + 'static
-            72..73 'x': dyn Trait + 'static
-            82..83 'y': &'? (dyn Trait + 'static)
+            60..62 '{}': dyn Trait + '?
+            72..73 'x': dyn Trait + '?
+            82..83 'y': &'? (dyn Trait + '?)
             100..175 '{     ...o(); }': u64
-            106..107 'x': dyn Trait + 'static
-            113..114 'y': &'? (dyn Trait + 'static)
-            124..125 'z': dyn Trait + 'static
-            128..131 'bar': fn bar() -> dyn Trait + 'static
-            128..133 'bar()': dyn Trait + 'static
-            139..140 'x': dyn Trait + 'static
+            106..107 'x': dyn Trait + '?
+            113..114 'y': &'? (dyn Trait + '?)
+            124..125 'z': dyn Trait + '?
+            128..131 'bar': fn bar() -> dyn Trait + '?
+            128..133 'bar()': dyn Trait + '?
+            139..140 'x': dyn Trait + '?
             139..146 'x.foo()': u64
-            152..153 'y': &'? (dyn Trait + 'static)
+            152..153 'y': &'? (dyn Trait + '?)
             152..159 'y.foo()': u64
-            165..166 'z': dyn Trait + 'static
+            165..166 'z': dyn Trait + '?
             165..172 'z.foo()': u64
         "#]],
     );
@@ -1589,10 +1589,10 @@ fn main() {
         expect![[r#"
             31..35 'self': &'? S
             37..39 '{}': ()
-            47..48 '_': &'? (dyn Fn(S) + 'static)
+            47..48 '_': &'? (dyn Fn(S) + '?)
             58..60 '{}': ()
             71..105 '{     ...()); }': ()
-            77..78 'f': fn f(&'? (dyn Fn(S) + 'static))
+            77..78 'f': fn f(&'? (dyn Fn(S) + '?))
             77..102 'f(&|nu...foo())': ()
             79..101 '&|numb....foo()': &'? impl Fn(S)
             80..101 '|numbe....foo()': impl Fn(S)
@@ -2927,13 +2927,13 @@ fn test(x: &dyn Foo) {
     foo(x);
 }"#,
         expect![[r#"
-            21..22 'x': &'? (dyn Foo + 'static)
+            21..22 'x': &'? (dyn Foo + '?)
             34..36 '{}': ()
-            46..47 'x': &'? (dyn Foo + 'static)
+            46..47 'x': &'? (dyn Foo + '?)
             59..74 '{     foo(x); }': ()
-            65..68 'foo': fn foo(&'? (dyn Foo + 'static))
+            65..68 'foo': fn foo(&'? (dyn Foo + '?))
             65..71 'foo(x)': ()
-            69..70 'x': &'? (dyn Foo + 'static)
+            69..70 'x': &'? (dyn Foo + '?)
         "#]],
     );
 }
@@ -3210,13 +3210,13 @@ fn foo() {
             218..324 '{     ...&s); }': ()
             228..229 's': Option<i32>
             232..236 'None': Option<i32>
-            246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static>
-            281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + 'static>
+            246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + '?>
+            281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + '?>
             294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option<i32>)
             300..307 '|ps| {}': impl FnOnce(&'? Option<i32>)
             301..303 'ps': &'? Option<i32>
             305..307 '{}': ()
-            316..317 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static>
+            316..317 'f': Box<dyn FnOnce(&'? Option<i32>) + '?>
             316..321 'f(&s)': ()
             318..320 '&s': &'? Option<i32>
             319..320 's': Option<i32>
@@ -4252,9 +4252,9 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
     "#,
         expect![[r#"
             90..94 'self': &'? Self
-            127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
+            127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
             164..195 '{     ...f(); }': ()
-            170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
+            170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
             170..184 'v.get::<i32>()': &'? i32
             170..192 'v.get:...eref()': &'? i32
         "#]],
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 4c8e635eff9..d07c1aa33b4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -1,7 +1,7 @@
 //! Helper functions for working with def, which don't need to be a separate
 //! query, but can't be computed directly from `*Data` (ie, which need a `db`).
 
-use std::iter;
+use std::{cell::LazyCell, iter};
 
 use base_db::Crate;
 use chalk_ir::{
@@ -161,11 +161,12 @@ impl Iterator for ClauseElaborator<'_> {
 }
 
 fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
-    let resolver = trait_.resolver(db);
+    let resolver = LazyCell::new(|| trait_.resolver(db));
     let (generic_params, store) = db.generic_params_and_store(trait_.into());
     let trait_self = generic_params.trait_self_param();
     generic_params
         .where_predicates()
+        .iter()
         .filter_map(|pred| match pred {
             WherePredicate::ForLifetime { target, bound, .. }
             | WherePredicate::TypeBound { target, bound } => {
@@ -218,7 +219,7 @@ pub(super) fn associated_type_by_name_including_super_traits(
     name: &Name,
 ) -> Option<(TraitRef, TypeAliasId)> {
     all_super_trait_refs(db, trait_ref, |t| {
-        let assoc_type = db.trait_items(t.hir_trait_id()).associated_type_by_name(name)?;
+        let assoc_type = t.hir_trait_id().trait_items(db).associated_type_by_name(name)?;
         Some((t, assoc_type))
     })
 }
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml
index 2af3c2e4c35..c68ff706e48 100644
--- a/src/tools/rust-analyzer/crates/hir/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
index 0bce69a179b..c8645b62823 100644
--- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
@@ -207,7 +207,7 @@ fn resolve_assoc_or_field(
             // Doc paths in this context may only resolve to an item of this trait
             // (i.e. no items of its supertraits), so we need to handle them here
             // independently of others.
-            return db.trait_items(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| {
+            return id.trait_items(db).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| {
                 let def = match *assoc_id {
                     AssocItemId::FunctionId(it) => ModuleDef::Function(it.into()),
                     AssocItemId::ConstId(it) => ModuleDef::Const(it.into()),
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index 074bde91fb6..aba2e032b32 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -490,7 +490,7 @@ impl<'db> AnyDiagnostic<'db> {
     ) -> Option<AnyDiagnostic<'db>> {
         match diagnostic {
             BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => {
-                let variant_data = variant.variant_data(db);
+                let variant_data = variant.fields(db);
                 let missed_fields = missed_fields
                     .into_iter()
                     .map(|idx| variant_data.fields()[idx].name.clone())
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 112558bdd04..2960ebedf38 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -404,7 +404,7 @@ impl HirDisplay for TupleField {
 impl HirDisplay for Variant {
     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
         write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
-        let data = f.db.variant_fields(self.id.into());
+        let data = self.id.fields(f.db);
         match data.shape {
             FieldsShape::Unit => {}
             FieldsShape::Tuple => {
@@ -633,7 +633,7 @@ fn has_disaplayable_predicates(
     params: &GenericParams,
     store: &ExpressionStore,
 ) -> bool {
-    params.where_predicates().any(|pred| {
+    params.where_predicates().iter().any(|pred| {
         !matches!(
             pred,
             WherePredicate::TypeBound { target, .. }
@@ -668,7 +668,7 @@ fn write_where_predicates(
         _ => false,
     };
 
-    let mut iter = params.where_predicates().peekable();
+    let mut iter = params.where_predicates().iter().peekable();
     while let Some(pred) = iter.next() {
         if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(*target)) {
             continue;
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 3b39707cf60..e8a18169712 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -54,7 +54,7 @@ use hir_def::{
     },
     item_tree::ImportAlias,
     layout::{self, ReprOptions, TargetDataLayout},
-    nameres::{self, diagnostics::DefDiagnostic},
+    nameres::{self, assoc::TraitItems, diagnostics::DefDiagnostic},
     per_ns::PerNs,
     resolver::{HasResolver, Resolver},
     signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields},
@@ -649,7 +649,7 @@ impl Module {
                     acc.extend(def.diagnostics(db, style_lints))
                 }
                 ModuleDef::Trait(t) => {
-                    for diag in db.trait_items_with_diagnostics(t.id).1.iter() {
+                    for diag in TraitItems::query_with_diagnostics(db, t.id).1.iter() {
                         emit_def_diagnostic(db, acc, diag, edition);
                     }
 
@@ -668,25 +668,25 @@ impl Module {
                         Adt::Struct(s) => {
                             let source_map = db.struct_signature_with_source_map(s.id).1;
                             expr_store_diagnostics(db, acc, &source_map);
-                            let source_map = db.variant_fields_with_source_map(s.id.into()).1;
-                            expr_store_diagnostics(db, acc, &source_map);
+                            let source_map = &s.id.fields_with_source_map(db).1;
+                            expr_store_diagnostics(db, acc, source_map);
                             push_ty_diagnostics(
                                 db,
                                 acc,
                                 db.field_types_with_diagnostics(s.id.into()).1,
-                                &source_map,
+                                source_map,
                             );
                         }
                         Adt::Union(u) => {
                             let source_map = db.union_signature_with_source_map(u.id).1;
                             expr_store_diagnostics(db, acc, &source_map);
-                            let source_map = db.variant_fields_with_source_map(u.id.into()).1;
-                            expr_store_diagnostics(db, acc, &source_map);
+                            let source_map = &u.id.fields_with_source_map(db).1;
+                            expr_store_diagnostics(db, acc, source_map);
                             push_ty_diagnostics(
                                 db,
                                 acc,
                                 db.field_types_with_diagnostics(u.id.into()).1,
-                                &source_map,
+                                source_map,
                             );
                         }
                         Adt::Enum(e) => {
@@ -711,14 +711,14 @@ impl Module {
                                 }
                             }
                             for &(v, _, _) in &variants.variants {
-                                let source_map = db.variant_fields_with_source_map(v.into()).1;
+                                let source_map = &v.fields_with_source_map(db).1;
                                 push_ty_diagnostics(
                                     db,
                                     acc,
                                     db.field_types_with_diagnostics(v.into()).1,
-                                    &source_map,
+                                    source_map,
                                 );
-                                expr_store_diagnostics(db, acc, &source_map);
+                                expr_store_diagnostics(db, acc, source_map);
                             }
                         }
                     }
@@ -822,7 +822,7 @@ impl Module {
 
             // Negative impls can't have items, don't emit missing items diagnostic for them
             if let (false, Some(trait_)) = (impl_is_negative, trait_) {
-                let items = &db.trait_items(trait_.into()).items;
+                let items = &trait_.id.trait_items(db).items;
                 let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
                     AssocItemId::FunctionId(it) => !db.function_signature(it).has_body(),
                     AssocItemId::ConstId(id) => !db.const_signature(id).has_body(),
@@ -1311,7 +1311,7 @@ impl AstNode for FieldSource {
 
 impl Field {
     pub fn name(&self, db: &dyn HirDatabase) -> Name {
-        db.variant_fields(self.parent.into()).fields()[self.id].name.clone()
+        VariantId::from(self.parent).fields(db).fields()[self.id].name.clone()
     }
 
     pub fn index(&self) -> usize {
@@ -1380,7 +1380,7 @@ impl Field {
 
 impl HasVisibility for Field {
     fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
-        let variant_data = db.variant_fields(self.parent.into());
+        let variant_data = VariantId::from(self.parent).fields(db);
         let visibility = &variant_data.fields()[self.id].visibility;
         let parent_id: hir_def::VariantId = self.parent.into();
         // FIXME: RawVisibility::Public doesn't need to construct a resolver
@@ -1403,7 +1403,8 @@ impl Struct {
     }
 
     pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
-        db.variant_fields(self.id.into())
+        self.id
+            .fields(db)
             .fields()
             .iter()
             .map(|(id, _)| Field { parent: self.into(), id })
@@ -1434,8 +1435,8 @@ impl Struct {
         }
     }
 
-    fn variant_fields(self, db: &dyn HirDatabase) -> Arc<VariantFields> {
-        db.variant_fields(self.id.into())
+    fn variant_fields(self, db: &dyn HirDatabase) -> &VariantFields {
+        self.id.fields(db)
     }
 
     pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
@@ -1478,7 +1479,7 @@ impl Union {
     }
 
     pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
-        match db.variant_fields(self.id.into()).shape {
+        match self.id.fields(db).shape {
             hir_def::item_tree::FieldsShape::Record => StructKind::Record,
             hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
             hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
@@ -1486,7 +1487,8 @@ impl Union {
     }
 
     pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
-        db.variant_fields(self.id.into())
+        self.id
+            .fields(db)
             .fields()
             .iter()
             .map(|(id, _)| Field { parent: self.into(), id })
@@ -1626,7 +1628,8 @@ impl Variant {
     }
 
     pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
-        db.variant_fields(self.id.into())
+        self.id
+            .fields(db)
             .fields()
             .iter()
             .map(|(id, _)| Field { parent: self.into(), id })
@@ -1634,7 +1637,7 @@ impl Variant {
     }
 
     pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
-        match db.variant_fields(self.id.into()).shape {
+        match self.id.fields(db).shape {
             hir_def::item_tree::FieldsShape::Record => StructKind::Record,
             hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
             hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
@@ -1727,10 +1730,10 @@ impl Adt {
     pub fn ty_with_args<'db>(
         self,
         db: &'db dyn HirDatabase,
-        args: impl Iterator<Item = Type<'db>>,
+        args: impl IntoIterator<Item = Type<'db>>,
     ) -> Type<'db> {
         let id = AdtId::from(self);
-        let mut it = args.map(|t| t.ty);
+        let mut it = args.into_iter().map(|t| t.ty);
         let ty = TyBuilder::def_ty(db, id.into(), None)
             .fill(|x| {
                 let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
@@ -2883,7 +2886,7 @@ impl Trait {
     }
 
     pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq<Name>) -> Option<Function> {
-        db.trait_items(self.id).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
+        self.id.trait_items(db).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
         {
             AssocItemId::FunctionId(id) => Some(Function { id }),
             _ => None,
@@ -2891,7 +2894,7 @@ impl Trait {
     }
 
     pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
-        db.trait_items(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
+        self.id.trait_items(db).items.iter().map(|(_name, it)| (*it).into()).collect()
     }
 
     pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
@@ -2939,7 +2942,7 @@ impl Trait {
     }
 
     fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
-        db.trait_items(self.id).macro_calls.to_vec().into_boxed_slice()
+        self.id.trait_items(db).macro_calls.to_vec().into_boxed_slice()
     }
 
     /// `#[rust_analyzer::completions(...)]` mode.
@@ -3043,10 +3046,17 @@ pub struct BuiltinType {
 }
 
 impl BuiltinType {
+    // Constructors are added on demand, feel free to add more.
     pub fn str() -> BuiltinType {
         BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
     }
 
+    pub fn i32() -> BuiltinType {
+        BuiltinType {
+            inner: hir_def::builtin_type::BuiltinType::Int(hir_ty::primitive::BuiltinInt::I32),
+        }
+    }
+
     pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
         let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]);
         Type::new_for_crate(core, TyBuilder::builtin(self.inner))
@@ -3667,7 +3677,7 @@ impl GenericDef {
 
         let generics = db.generic_params(def);
 
-        if generics.is_empty() && generics.no_predicates() {
+        if generics.is_empty() && generics.has_no_predicates() {
             return;
         }
 
@@ -5000,7 +5010,7 @@ impl<'db> Type<'db> {
         }
 
         let output_assoc_type =
-            db.trait_items(trait_).associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
+            trait_.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
         self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
     }
 
@@ -5013,8 +5023,8 @@ impl<'db> Type<'db> {
     /// This does **not** resolve `IntoIterator`, only `Iterator`.
     pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
         let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
-        let iterator_item = db
-            .trait_items(iterator_trait)
+        let iterator_item = iterator_trait
+            .trait_items(db)
             .associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
         self.normalize_trait_assoc_type(db, &[], iterator_item.into())
     }
@@ -5044,8 +5054,8 @@ impl<'db> Type<'db> {
             return None;
         }
 
-        let into_iter_assoc_type = db
-            .trait_items(trait_)
+        let into_iter_assoc_type = trait_
+            .trait_items(db)
             .associated_type_by_name(&Name::new_symbol_root(sym::IntoIter))?;
         self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index d96975831e0..247bb693983 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -2199,6 +2199,10 @@ pub struct SemanticsScope<'db> {
 }
 
 impl<'db> SemanticsScope<'db> {
+    pub fn file_id(&self) -> HirFileId {
+        self.file_id
+    }
+
     pub fn module(&self) -> Module {
         Module { id: self.resolver.module() }
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
index fedd8239d03..e7db93d375d 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
@@ -35,7 +35,7 @@ pub(crate) trait ChildBySource {
 
 impl ChildBySource for TraitId {
     fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
-        let data = db.trait_items(*self);
+        let data = self.trait_items(db);
 
         data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
             |(ast_id, call_id)| {
@@ -191,7 +191,7 @@ impl ChildBySource for VariantId {
                 Either::Right(source) => res[keys::RECORD_FIELD].insert(AstPtr::new(&source), id),
             }
         }
-        let (_, sm) = db.variant_fields_with_source_map(*self);
+        let (_, sm) = self.fields_with_source_map(db);
         sm.expansions().for_each(|(ast, &exp_id)| res[keys::MACRO_CALL].insert(ast.value, exp_id));
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 48543ca581f..f18ca7cb201 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -156,14 +156,14 @@ impl<'db> SourceAnalyzer<'db> {
         InFile { file_id, .. }: InFile<&SyntaxNode>,
         _offset: Option<TextSize>,
     ) -> SourceAnalyzer<'db> {
-        let (fields, source_map) = db.variant_fields_with_source_map(def);
+        let (fields, source_map) = def.fields_with_source_map(db);
         let resolver = def.resolver(db);
         SourceAnalyzer {
             resolver,
             body_or_sig: Some(BodyOrSig::VariantFields {
                 def,
                 store: fields.store.clone(),
-                source_map,
+                source_map: source_map.clone(),
             }),
             file_id,
         }
@@ -713,7 +713,7 @@ impl<'db> SourceAnalyzer<'db> {
         };
         let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
         let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?;
-        let variant_data = variant.variant_data(db);
+        let variant_data = variant.fields(db);
         let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
         let field_ty =
             db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
@@ -734,7 +734,7 @@ impl<'db> SourceAnalyzer<'db> {
         let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
         let pat_id = self.pat_id(&record_pat.into())?;
         let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;
-        let variant_data = variant.variant_data(db);
+        let variant_data = variant.fields(db);
         let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
         let (adt, subst) = self.infer()?.type_of_pat.get(pat_id.as_pat()?)?.as_adt()?;
         let field_ty =
@@ -803,8 +803,8 @@ impl<'db> SourceAnalyzer<'db> {
                 };
                 container = Either::Right(db.normalize_projection(projection, trait_env.clone()));
             }
-            let handle_variants = |variant, subst: &Substitution, container: &mut _| {
-                let fields = db.variant_fields(variant);
+            let handle_variants = |variant: VariantId, subst: &Substitution, container: &mut _| {
+                let fields = variant.fields(db);
                 let field = fields.field(&field_name.as_name())?;
                 let field_types = db.field_types(variant);
                 *container = Either::Right(field_types[field].clone().substitute(Interner, subst));
@@ -1423,7 +1423,7 @@ impl<'db> SourceAnalyzer<'db> {
         method_name: &Name,
     ) -> Option<(TraitId, FunctionId)> {
         let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?;
-        let fn_id = db.trait_items(trait_id).method_by_name(method_name)?;
+        let fn_id = trait_id.trait_items(db).method_by_name(method_name)?;
         Some((trait_id, fn_id))
     }
 
@@ -1580,7 +1580,7 @@ fn resolve_hir_path_(
         // within the trait's associated types.
         if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
             if let Some(type_alias_id) =
-                db.trait_items(trait_id).associated_type_by_name(unresolved.name)
+                trait_id.trait_items(db).associated_type_by_name(unresolved.name)
             {
                 return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
             }
@@ -1731,7 +1731,7 @@ fn resolve_hir_path_qualifier(
         // within the trait's associated types.
         if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
             if let Some(type_alias_id) =
-                db.trait_items(trait_id).associated_type_by_name(unresolved.name)
+                trait_id.trait_items(db).associated_type_by_name(unresolved.name)
             {
                 return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
             }
diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
index 64f2a910bd1..756650891d4 100644
--- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
@@ -334,7 +334,7 @@ impl<'a> SymbolCollector<'a> {
     fn collect_from_trait(&mut self, trait_id: TraitId, trait_do_not_complete: Complete) {
         let trait_data = self.db.trait_signature(trait_id);
         self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
-            for &(ref name, assoc_item_id) in &self.db.trait_items(trait_id).items {
+            for &(ref name, assoc_item_id) in &trait_id.trait_items(self.db).items {
                 s.push_assoc_item(assoc_item_id, name, Some(trait_do_not_complete));
             }
         });
diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
index 53af980c194..385b0e1eb7c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
index 3e6d0bec68a..517906b429a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
@@ -1,3 +1,5 @@
+use std::slice;
+
 use ide_db::assists::GroupLabel;
 use stdx::to_lower_snake_case;
 use syntax::ast::HasVisibility;
@@ -52,7 +54,7 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_>
     let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text()));
 
     // Return early if we've found an existing new fn
-    let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?;
+    let impl_def = find_struct_impl(ctx, &parent_enum, slice::from_ref(&fn_name))?;
 
     let target = variant.syntax().text_range();
     acc.add_group(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
index 3974bcf6187..e4b0f830497 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
@@ -1,3 +1,5 @@
+use std::slice;
+
 use ide_db::assists::GroupLabel;
 use itertools::Itertools;
 use stdx::to_lower_snake_case;
@@ -148,7 +150,7 @@ fn generate_enum_projection_method(
     let fn_name = format!("{fn_name_prefix}_{}", &to_lower_snake_case(&variant_name.text()));
 
     // Return early if we've found an existing new fn
-    let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?;
+    let impl_def = find_struct_impl(ctx, &parent_enum, slice::from_ref(&fn_name))?;
 
     let target = variant.syntax().text_range();
     acc.add_group(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
index 019ddaf1441..6527d3706e2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
@@ -100,9 +100,7 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!() }"#,
     fn test_complete_todo_with_msg() {
         check_assist(
             term_search,
-            // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure.
-            // Should implement super let and remove `fmt_before_1_89_0`
-            r#"//- minicore: todo, unimplemented, fmt_before_1_89_0
+            r#"//- minicore: todo, unimplemented
 fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
             r#"fn f() { let a: u128 = 1; let b: u128 = a }"#,
         )
@@ -112,10 +110,8 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
     fn test_complete_unimplemented_with_msg() {
         check_assist(
             term_search,
-            // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure.
-            // Should implement super let and remove `fmt_before_1_89_0`
-            r#"//- minicore: todo, unimplemented, fmt_before_1_89_0
-fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
+            r#"//- minicore: todo, unimplemented
+fn f() { let a: u128 = 1; let b: u128 = unimplemented$0!("asd") }"#,
             r#"fn f() { let a: u128 = 1; let b: u128 = a }"#,
         )
     }
@@ -124,10 +120,8 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
     fn test_complete_unimplemented() {
         check_assist(
             term_search,
-            // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure.
-            // Should implement super let and remove `fmt_before_1_89_0`
-            r#"//- minicore: todo, unimplemented, fmt_before_1_89_0
-fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
+            r#"//- minicore: todo, unimplemented
+fn f() { let a: u128 = 1; let b: u128 = unimplemented$0!() }"#,
             r#"fn f() { let a: u128 = 1; let b: u128 = a }"#,
         )
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs
index 9ea78719b20..d7189aa5dbb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs
@@ -56,7 +56,8 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
     };
 
     let type_ref = &ret_type.ty()?;
-    let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
+    let ty = ctx.sema.resolve_type(type_ref)?;
+    let ty_adt = ty.as_adt();
     let famous_defs = FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate());
 
     for kind in WrapperKind::ALL {
@@ -64,7 +65,7 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
             continue;
         };
 
-        if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == core_wrapper) {
+        if matches!(ty_adt, Some(hir::Adt::Enum(ret_type)) if ret_type == core_wrapper) {
             // The return type is already wrapped
             cov_mark::hit!(wrap_return_type_simple_return_type_already_wrapped);
             continue;
@@ -78,10 +79,23 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
             |builder| {
                 let mut editor = builder.make_editor(&parent);
                 let make = SyntaxFactory::with_mappings();
-                let alias = wrapper_alias(ctx, &make, &core_wrapper, type_ref, kind.symbol());
-                let new_return_ty = alias.unwrap_or_else(|| match kind {
-                    WrapperKind::Option => make.ty_option(type_ref.clone()),
-                    WrapperKind::Result => make.ty_result(type_ref.clone(), make.ty_infer().into()),
+                let alias = wrapper_alias(ctx, &make, core_wrapper, type_ref, &ty, kind.symbol());
+                let (ast_new_return_ty, semantic_new_return_ty) = alias.unwrap_or_else(|| {
+                    let (ast_ty, ty_constructor) = match kind {
+                        WrapperKind::Option => {
+                            (make.ty_option(type_ref.clone()), famous_defs.core_option_Option())
+                        }
+                        WrapperKind::Result => (
+                            make.ty_result(type_ref.clone(), make.ty_infer().into()),
+                            famous_defs.core_result_Result(),
+                        ),
+                    };
+                    let semantic_ty = ty_constructor
+                        .map(|ty_constructor| {
+                            hir::Adt::from(ty_constructor).ty_with_args(ctx.db(), [ty.clone()])
+                        })
+                        .unwrap_or_else(|| ty.clone());
+                    (ast_ty, semantic_ty)
                 });
 
                 let mut exprs_to_wrap = Vec::new();
@@ -96,6 +110,17 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                 for_each_tail_expr(&body_expr, tail_cb);
 
                 for ret_expr_arg in exprs_to_wrap {
+                    if let Some(ty) = ctx.sema.type_of_expr(&ret_expr_arg) {
+                        if ty.adjusted().could_unify_with(ctx.db(), &semantic_new_return_ty) {
+                            // The type is already correct, don't wrap it.
+                            // We deliberately don't use `could_unify_with_deeply()`, because as long as the outer
+                            // enum matches it's okay for us, as we don't trigger the assist if the return type
+                            // is already `Option`/`Result`, so mismatched exact type is more likely a mistake
+                            // than something intended.
+                            continue;
+                        }
+                    }
+
                     let happy_wrapped = make.expr_call(
                         make.expr_path(make.ident_path(kind.happy_ident())),
                         make.arg_list(iter::once(ret_expr_arg.clone())),
@@ -103,12 +128,12 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
                     editor.replace(ret_expr_arg.syntax(), happy_wrapped.syntax());
                 }
 
-                editor.replace(type_ref.syntax(), new_return_ty.syntax());
+                editor.replace(type_ref.syntax(), ast_new_return_ty.syntax());
 
                 if let WrapperKind::Result = kind {
                     // Add a placeholder snippet at the first generic argument that doesn't equal the return type.
                     // This is normally the error type, but that may not be the case when we inserted a type alias.
-                    let args = new_return_ty
+                    let args = ast_new_return_ty
                         .path()
                         .unwrap()
                         .segment()
@@ -188,27 +213,28 @@ impl WrapperKind {
 }
 
 // Try to find an wrapper type alias in the current scope (shadowing the default).
-fn wrapper_alias(
-    ctx: &AssistContext<'_>,
+fn wrapper_alias<'db>(
+    ctx: &AssistContext<'db>,
     make: &SyntaxFactory,
-    core_wrapper: &hir::Enum,
-    ret_type: &ast::Type,
+    core_wrapper: hir::Enum,
+    ast_ret_type: &ast::Type,
+    semantic_ret_type: &hir::Type<'db>,
     wrapper: hir::Symbol,
-) -> Option<ast::PathType> {
+) -> Option<(ast::PathType, hir::Type<'db>)> {
     let wrapper_path = hir::ModPath::from_segments(
         hir::PathKind::Plain,
         iter::once(hir::Name::new_symbol_root(wrapper)),
     );
 
-    ctx.sema.resolve_mod_path(ret_type.syntax(), &wrapper_path).and_then(|def| {
+    ctx.sema.resolve_mod_path(ast_ret_type.syntax(), &wrapper_path).and_then(|def| {
         def.filter_map(|def| match def.into_module_def() {
             hir::ModuleDef::TypeAlias(alias) => {
                 let enum_ty = alias.ty(ctx.db()).as_adt()?.as_enum()?;
-                (&enum_ty == core_wrapper).then_some(alias)
+                (enum_ty == core_wrapper).then_some((alias, enum_ty))
             }
             _ => None,
         })
-        .find_map(|alias| {
+        .find_map(|(alias, enum_ty)| {
             let mut inserted_ret_type = false;
             let generic_args =
                 alias.source(ctx.db())?.value.generic_param_list()?.generic_params().map(|param| {
@@ -216,7 +242,7 @@ fn wrapper_alias(
                         // Replace the very first type parameter with the function's return type.
                         ast::GenericParam::TypeParam(_) if !inserted_ret_type => {
                             inserted_ret_type = true;
-                            make.type_arg(ret_type.clone()).into()
+                            make.type_arg(ast_ret_type.clone()).into()
                         }
                         ast::GenericParam::LifetimeParam(_) => {
                             make.lifetime_arg(make.lifetime("'_")).into()
@@ -231,7 +257,10 @@ fn wrapper_alias(
                 make.path_segment_generics(make.name_ref(name.as_str()), generic_arg_list),
             );
 
-            Some(make.ty_path(path))
+            let new_ty =
+                hir::Adt::from(enum_ty).ty_with_args(ctx.db(), [semantic_ret_type.clone()]);
+
+            Some((make.ty_path(path), new_ty))
         })
     })
 }
@@ -605,29 +634,39 @@ fn foo() -> Option<i32> {
         check_assist_by_label(
             wrap_return_type,
             r#"
-//- minicore: option
+//- minicore: option, future
+struct F(i32);
+impl core::future::Future for F {
+    type Output = i32;
+    fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> { 0 }
+}
 async fn foo() -> i$032 {
     if true {
         if false {
-            1.await
+            F(1).await
         } else {
-            2.await
+            F(2).await
         }
     } else {
-        24i32.await
+        F(24i32).await
     }
 }
 "#,
             r#"
+struct F(i32);
+impl core::future::Future for F {
+    type Output = i32;
+    fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> { 0 }
+}
 async fn foo() -> Option<i32> {
     if true {
         if false {
-            Some(1.await)
+            Some(F(1).await)
         } else {
-            Some(2.await)
+            Some(F(2).await)
         }
     } else {
-        Some(24i32.await)
+        Some(F(24i32).await)
     }
 }
 "#,
@@ -1666,29 +1705,39 @@ fn foo() -> Result<i32, ${0:_}> {
         check_assist_by_label(
             wrap_return_type,
             r#"
-//- minicore: result
+//- minicore: result, future
+struct F(i32);
+impl core::future::Future for F {
+    type Output = i32;
+    fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> { 0 }
+}
 async fn foo() -> i$032 {
     if true {
         if false {
-            1.await
+            F(1).await
         } else {
-            2.await
+            F(2).await
         }
     } else {
-        24i32.await
+        F(24i32).await
     }
 }
 "#,
             r#"
+struct F(i32);
+impl core::future::Future for F {
+    type Output = i32;
+    fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll<Self::Output> { 0 }
+}
 async fn foo() -> Result<i32, ${0:_}> {
     if true {
         if false {
-            Ok(1.await)
+            Ok(F(1).await)
         } else {
-            Ok(2.await)
+            Ok(F(2).await)
         }
     } else {
-        Ok(24i32.await)
+        Ok(F(24i32).await)
     }
 }
 "#,
@@ -2460,4 +2509,54 @@ fn foo() -> Result<i32, ${0:_}> {
             WrapperKind::Result.label(),
         );
     }
+
+    #[test]
+    fn already_wrapped() {
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: option
+fn foo() -> i32$0 {
+    if false {
+        0
+    } else {
+        Some(1)
+    }
+}
+            "#,
+            r#"
+fn foo() -> Option<i32> {
+    if false {
+        Some(0)
+    } else {
+        Some(1)
+    }
+}
+            "#,
+            WrapperKind::Option.label(),
+        );
+        check_assist_by_label(
+            wrap_return_type,
+            r#"
+//- minicore: result
+fn foo() -> i32$0 {
+    if false {
+        0
+    } else {
+        Ok(1)
+    }
+}
+            "#,
+            r#"
+fn foo() -> Result<i32, ${0:_}> {
+    if false {
+        Ok(0)
+    } else {
+        Ok(1)
+    }
+}
+            "#,
+            WrapperKind::Result.label(),
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
index 94c01e333ed..9bad21fc8e9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
index 6d1e973dc4c..809e71cc119 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
@@ -195,5 +195,5 @@ fn comma_wrapper(ctx: &CompletionContext<'_>) -> Option<(impl Fn(&str) -> String
         matches!(prev_token_kind, SyntaxKind::COMMA | SyntaxKind::L_PAREN | SyntaxKind::PIPE);
     let leading = if has_leading_comma { "" } else { ", " };
 
-    Some((move |label: &_| (format!("{leading}{label}{trailing}")), param.text_range()))
+    Some((move |label: &_| format!("{leading}{label}{trailing}"), param.text_range()))
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 6e3a76f346a..ea5fb39338b 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -4,6 +4,7 @@ use std::iter;
 use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant};
 use ide_db::{RootDatabase, active_parameter::ActiveParameter};
 use itertools::Either;
+use stdx::always;
 use syntax::{
     AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
     T, TextRange, TextSize,
@@ -869,8 +870,15 @@ fn classify_name_ref<'db>(
                     return None;
                 }
 
+                let mut receiver_ty = receiver.as_ref().and_then(|it| sema.type_of_expr(it));
+                if receiver_is_ambiguous_float_literal {
+                    // `123.|` is parsed as a float but should actually be an integer.
+                    always!(receiver_ty.as_ref().is_none_or(|receiver_ty| receiver_ty.original.is_float()));
+                    receiver_ty = Some(TypeInfo { original: hir::BuiltinType::i32().ty(sema.db), adjusted: None });
+                }
+
                 let kind = NameRefKind::DotAccess(DotAccess {
-                    receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
+                    receiver_ty,
                     kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
                     receiver,
                     ctx: DotAccessExprCtx { in_block_expr: is_in_block(field.syntax()), in_breakable: is_in_breakable(field.syntax()) }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index b2d18b796f1..33f729f0166 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -2241,3 +2241,37 @@ fn main() {
     "#,
     );
 }
+
+#[test]
+fn ambiguous_float_literal() {
+    check(
+        r#"
+#![rustc_coherence_is_core]
+
+impl i32 {
+    pub fn int_method(self) {}
+}
+impl f64 {
+    pub fn float_method(self) {}
+}
+
+fn foo() {
+    1.$0
+}
+    "#,
+        expect![[r#"
+            me int_method() fn(self)
+            sn box    Box::new(expr)
+            sn call   function(expr)
+            sn const        const {}
+            sn dbg        dbg!(expr)
+            sn dbgr      dbg!(&expr)
+            sn deref           *expr
+            sn match   match expr {}
+            sn ref             &expr
+            sn refm        &mut expr
+            sn return    return expr
+            sn unsafe      unsafe {}
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
index fcdf10c8561..179d6693602 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
@@ -550,3 +550,30 @@ fn inside_extern_blocks() {
         "#]],
     )
 }
+
+#[test]
+fn tokens_from_macro() {
+    check_edit(
+        "fn as_ref",
+        r#"
+//- proc_macros: identity
+//- minicore: as_ref
+struct Foo;
+
+#[proc_macros::identity]
+impl<'a> AsRef<&'a i32> for Foo {
+    $0
+}
+    "#,
+        r#"
+struct Foo;
+
+#[proc_macros::identity]
+impl<'a> AsRef<&'a i32> for Foo {
+    fn as_ref(&self) -> &&'a i32 {
+    $0
+}
+}
+    "#,
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
index 125e11e9e35..c7e2d058257 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
@@ -429,18 +429,18 @@ trait Tr<T> {
 impl Tr<$0
     "#,
         expect![[r#"
-            en Enum                        Enum
-            ma makro!(…)     macro_rules! makro
+            en Enum                    Enum
+            ma makro!(…) macro_rules! makro
             md module
-            sp Self dyn Tr<{unknown}> + 'static
-            st Record                    Record
-            st S                              S
-            st Tuple                      Tuple
-            st Unit                        Unit
+            sp Self       dyn Tr<{unknown}>
+            st Record                Record
+            st S                          S
+            st Tuple                  Tuple
+            st Unit                    Unit
             tt Tr
             tt Trait
-            un Union                      Union
-            bt u32                          u32
+            un Union                  Union
+            bt u32                      u32
             kw crate::
             kw self::
         "#]],
diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
index acde1d665da..e065adb0f0b 100644
--- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index 232648af661..0ab880bcfe7 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -2,7 +2,10 @@
 
 use crate::helpers::mod_path_to_ast;
 use either::Either;
-use hir::{AsAssocItem, HirDisplay, ImportPathConfig, ModuleDef, SemanticsScope};
+use hir::{
+    AsAssocItem, HirDisplay, HirFileId, ImportPathConfig, ModuleDef, SemanticsScope,
+    prettify_macro_expansion,
+};
 use itertools::Itertools;
 use rustc_hash::FxHashMap;
 use span::Edition;
@@ -136,6 +139,25 @@ impl<'a> PathTransform<'a> {
         }
     }
 
+    fn prettify_target_node(&self, node: SyntaxNode) -> SyntaxNode {
+        match self.target_scope.file_id() {
+            HirFileId::FileId(_) => node,
+            HirFileId::MacroFile(file_id) => {
+                let db = self.target_scope.db;
+                prettify_macro_expansion(
+                    db,
+                    node,
+                    &db.expansion_span_map(file_id),
+                    self.target_scope.module().krate().into(),
+                )
+            }
+        }
+    }
+
+    fn prettify_target_ast<N: AstNode>(&self, node: N) -> N {
+        N::cast(self.prettify_target_node(node.syntax().clone())).unwrap()
+    }
+
     fn build_ctx(&self) -> Ctx<'a> {
         let db = self.source_scope.db;
         let target_module = self.target_scope.module();
@@ -163,7 +185,7 @@ impl<'a> PathTransform<'a> {
             .for_each(|(k, v)| match (k.split(db), v) {
                 (Either::Right(k), Some(TypeOrConst::Either(v))) => {
                     if let Some(ty) = v.ty() {
-                        type_substs.insert(k, ty);
+                        type_substs.insert(k, self.prettify_target_ast(ty));
                     }
                 }
                 (Either::Right(k), None) => {
@@ -178,7 +200,7 @@ impl<'a> PathTransform<'a> {
                 }
                 (Either::Left(k), Some(TypeOrConst::Either(v))) => {
                     if let Some(ty) = v.ty() {
-                        const_substs.insert(k, ty.syntax().clone());
+                        const_substs.insert(k, self.prettify_target_node(ty.syntax().clone()));
                     }
                 }
                 (Either::Left(k), Some(TypeOrConst::Const(v))) => {
@@ -189,7 +211,7 @@ impl<'a> PathTransform<'a> {
                         // and sometimes require slight modifications; see
                         // https://doc.rust-lang.org/reference/statements.html#expression-statements
                         // (default values in curly brackets can cause the same problem)
-                        const_substs.insert(k, expr.syntax().clone());
+                        const_substs.insert(k, self.prettify_target_node(expr.syntax().clone()));
                     }
                 }
                 (Either::Left(k), None) => {
@@ -204,6 +226,7 @@ impl<'a> PathTransform<'a> {
                 }
                 _ => (), // ignore mismatching params
             });
+        // No need to prettify lifetimes, there's nothing to prettify.
         let lifetime_substs: FxHashMap<_, _> = self
             .generic_def
             .into_iter()
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
index 96be51e1b26..6f1e66948f4 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index e2957fcaefb..ac54ac0950f 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -1171,7 +1171,7 @@ trait B {}
 
 fn test(a: &dyn A) -> &dyn B {
     a
-  //^ error: expected &(dyn B + 'static), found &(dyn A + 'static)
+  //^ error: expected &dyn B, found &dyn A
 }
 "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
index 1212fa9f9c6..0620bd26fef 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml
index 2f8ed88fbb5..06d2776ebe8 100644
--- a/src/tools/rust-analyzer/crates/ide/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
index 194e8c968f7..9bd8504733a 100755
--- a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
@@ -2,7 +2,7 @@ use ide_db::{FxHashSet, syntax_helpers::node_ext::vis_eq};
 use syntax::{
     Direction, NodeOrToken, SourceFile,
     SyntaxKind::{self, *},
-    TextRange, TextSize,
+    SyntaxNode, TextRange, TextSize,
     ast::{self, AstNode, AstToken},
     match_ast,
 };
@@ -16,16 +16,21 @@ const REGION_END: &str = "// endregion";
 pub enum FoldKind {
     Comment,
     Imports,
-    Mods,
+    Region,
     Block,
     ArgList,
-    Region,
-    Consts,
-    Statics,
     Array,
     WhereClause,
     ReturnType,
     MatchArm,
+    // region: item runs
+    Modules,
+    Consts,
+    Statics,
+    TypeAliases,
+    TraitAliases,
+    ExternCrates,
+    // endregion: item runs
 }
 
 #[derive(Debug)]
@@ -41,10 +46,7 @@ pub struct Fold {
 pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
     let mut res = vec![];
     let mut visited_comments = FxHashSet::default();
-    let mut visited_imports = FxHashSet::default();
-    let mut visited_mods = FxHashSet::default();
-    let mut visited_consts = FxHashSet::default();
-    let mut visited_statics = FxHashSet::default();
+    let mut visited_nodes = FxHashSet::default();
 
     // regions can be nested, here is a LIFO buffer
     let mut region_starts: Vec<TextSize> = vec![];
@@ -93,30 +95,40 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
                             if module.item_list().is_none() {
                                 if let Some(range) = contiguous_range_for_item_group(
                                     module,
-                                    &mut visited_mods,
+                                    &mut visited_nodes,
                                 ) {
-                                    res.push(Fold { range, kind: FoldKind::Mods })
+                                    res.push(Fold { range, kind: FoldKind::Modules })
                                 }
                             }
                         },
                         ast::Use(use_) => {
-                            if let Some(range) = contiguous_range_for_item_group(use_, &mut visited_imports) {
+                            if let Some(range) = contiguous_range_for_item_group(use_, &mut visited_nodes) {
                                 res.push(Fold { range, kind: FoldKind::Imports })
                             }
                         },
                         ast::Const(konst) => {
-                            if let Some(range) = contiguous_range_for_item_group(konst, &mut visited_consts) {
+                            if let Some(range) = contiguous_range_for_item_group(konst, &mut visited_nodes) {
                                 res.push(Fold { range, kind: FoldKind::Consts })
                             }
                         },
                         ast::Static(statik) => {
-                            if let Some(range) = contiguous_range_for_item_group(statik, &mut visited_statics) {
+                            if let Some(range) = contiguous_range_for_item_group(statik, &mut visited_nodes) {
                                 res.push(Fold { range, kind: FoldKind::Statics })
                             }
                         },
-                        ast::WhereClause(where_clause) => {
-                            if let Some(range) = fold_range_for_where_clause(where_clause) {
-                                res.push(Fold { range, kind: FoldKind::WhereClause })
+                        ast::TypeAlias(alias) => {
+                            if let Some(range) = contiguous_range_for_item_group(alias, &mut visited_nodes) {
+                                res.push(Fold { range, kind: FoldKind::TypeAliases })
+                            }
+                        },
+                        ast::TraitAlias(alias) => {
+                            if let Some(range) = contiguous_range_for_item_group(alias, &mut visited_nodes) {
+                                res.push(Fold { range, kind: FoldKind::TraitAliases })
+                            }
+                        },
+                        ast::ExternCrate(extern_crate) => {
+                            if let Some(range) = contiguous_range_for_item_group(extern_crate, &mut visited_nodes) {
+                                res.push(Fold { range, kind: FoldKind::ExternCrates })
                             }
                         },
                         ast::MatchArm(match_arm) => {
@@ -137,9 +149,10 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
 fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
     match kind {
         COMMENT => Some(FoldKind::Comment),
-        ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList),
+        ARG_LIST | PARAM_LIST | GENERIC_ARG_LIST | GENERIC_PARAM_LIST => Some(FoldKind::ArgList),
         ARRAY_EXPR => Some(FoldKind::Array),
         RET_TYPE => Some(FoldKind::ReturnType),
+        WHERE_CLAUSE => Some(FoldKind::WhereClause),
         ASSOC_ITEM_LIST
         | RECORD_FIELD_LIST
         | RECORD_PAT_FIELD_LIST
@@ -155,11 +168,14 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
     }
 }
 
-fn contiguous_range_for_item_group<N>(first: N, visited: &mut FxHashSet<N>) -> Option<TextRange>
+fn contiguous_range_for_item_group<N>(
+    first: N,
+    visited: &mut FxHashSet<SyntaxNode>,
+) -> Option<TextRange>
 where
     N: ast::HasVisibility + Clone + Hash + Eq,
 {
-    if !visited.insert(first.clone()) {
+    if !visited.insert(first.syntax().clone()) {
         return None;
     }
 
@@ -183,7 +199,7 @@ where
         if let Some(next) = N::cast(node) {
             let next_vis = next.visibility();
             if eq_visibility(next_vis.clone(), last_vis) {
-                visited.insert(next.clone());
+                visited.insert(next.syntax().clone());
                 last_vis = next_vis;
                 last = next;
                 continue;
@@ -259,18 +275,6 @@ fn contiguous_range_for_comment(
     }
 }
 
-fn fold_range_for_where_clause(where_clause: ast::WhereClause) -> Option<TextRange> {
-    let first_where_pred = where_clause.predicates().next();
-    let last_where_pred = where_clause.predicates().last();
-
-    if first_where_pred != last_where_pred {
-        let start = where_clause.where_token()?.text_range().end();
-        let end = where_clause.syntax().text_range().end();
-        return Some(TextRange::new(start, end));
-    }
-    None
-}
-
 fn fold_range_for_multiline_match_arm(match_arm: ast::MatchArm) -> Option<TextRange> {
     if fold_kind(match_arm.expr()?.syntax().kind()).is_some() {
         None
@@ -307,16 +311,19 @@ mod tests {
             let kind = match fold.kind {
                 FoldKind::Comment => "comment",
                 FoldKind::Imports => "imports",
-                FoldKind::Mods => "mods",
+                FoldKind::Modules => "mods",
                 FoldKind::Block => "block",
                 FoldKind::ArgList => "arglist",
                 FoldKind::Region => "region",
                 FoldKind::Consts => "consts",
                 FoldKind::Statics => "statics",
+                FoldKind::TypeAliases => "typealiases",
                 FoldKind::Array => "array",
                 FoldKind::WhereClause => "whereclause",
                 FoldKind::ReturnType => "returntype",
                 FoldKind::MatchArm => "matcharm",
+                FoldKind::TraitAliases => "traitaliases",
+                FoldKind::ExternCrates => "externcrates",
             };
             assert_eq!(kind, &attr.unwrap());
         }
@@ -594,19 +601,18 @@ static SECOND_STATIC: &str = "second";</fold>
 
     #[test]
     fn fold_where_clause() {
-        // fold multi-line and don't fold single line.
         check(
             r#"
 fn foo()
-where<fold whereclause>
+<fold whereclause>where
     A: Foo,
     B: Foo,
     C: Foo,
     D: Foo,</fold> {}
 
 fn bar()
-where
-    A: Bar, {}
+<fold whereclause>where
+    A: Bar,</fold> {}
 "#,
         )
     }
@@ -624,4 +630,16 @@ fn bar() -> (bool, bool) { (true, true) }
 "#,
         )
     }
+
+    #[test]
+    fn fold_generics() {
+        check(
+            r#"
+type Foo<T, U> = foo<fold arglist><
+    T,
+    U,
+></fold>;
+"#,
+        )
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index 574803fb9e8..fd465f31d43 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -291,13 +291,14 @@ fn handle_control_flow_keywords(
     token: &SyntaxToken,
 ) -> Option<Vec<NavigationTarget>> {
     match token.kind() {
-        // For `fn` / `loop` / `while` / `for` / `async`, return the keyword it self,
+        // For `fn` / `loop` / `while` / `for` / `async` / `match`, return the keyword it self,
         // so that VSCode will find the references when using `ctrl + click`
         T![fn] | T![async] | T![try] | T![return] => nav_for_exit_points(sema, token),
         T![loop] | T![while] | T![break] | T![continue] => nav_for_break_points(sema, token),
         T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {
             nav_for_break_points(sema, token)
         }
+        T![match] | T![=>] | T![if] => nav_for_branch_exit_points(sema, token),
         _ => None,
     }
 }
@@ -407,6 +408,91 @@ fn nav_for_exit_points(
     Some(navs)
 }
 
+pub(crate) fn find_branch_root(
+    sema: &Semantics<'_, RootDatabase>,
+    token: &SyntaxToken,
+) -> Vec<SyntaxNode> {
+    let find_nodes = |node_filter: fn(SyntaxNode) -> Option<SyntaxNode>| {
+        sema.descend_into_macros(token.clone())
+            .into_iter()
+            .filter_map(|token| node_filter(token.parent()?))
+            .collect_vec()
+    };
+
+    match token.kind() {
+        T![match] => find_nodes(|node| Some(ast::MatchExpr::cast(node)?.syntax().clone())),
+        T![=>] => find_nodes(|node| Some(ast::MatchArm::cast(node)?.syntax().clone())),
+        T![if] => find_nodes(|node| {
+            let if_expr = ast::IfExpr::cast(node)?;
+
+            let root_if = iter::successors(Some(if_expr.clone()), |if_expr| {
+                let parent_if = if_expr.syntax().parent().and_then(ast::IfExpr::cast)?;
+                let ast::ElseBranch::IfExpr(else_branch) = parent_if.else_branch()? else {
+                    return None;
+                };
+
+                (else_branch.syntax() == if_expr.syntax()).then_some(parent_if)
+            })
+            .last()?;
+
+            Some(root_if.syntax().clone())
+        }),
+        _ => vec![],
+    }
+}
+
+fn nav_for_branch_exit_points(
+    sema: &Semantics<'_, RootDatabase>,
+    token: &SyntaxToken,
+) -> Option<Vec<NavigationTarget>> {
+    let db = sema.db;
+
+    let navs = match token.kind() {
+        T![match] => find_branch_root(sema, token)
+            .into_iter()
+            .filter_map(|node| {
+                let file_id = sema.hir_file_for(&node);
+                let match_expr = ast::MatchExpr::cast(node)?;
+                let focus_range = match_expr.match_token()?.text_range();
+                let match_expr_in_file = InFile::new(file_id, match_expr.into());
+                Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))
+            })
+            .flatten()
+            .collect_vec(),
+
+        T![=>] => find_branch_root(sema, token)
+            .into_iter()
+            .filter_map(|node| {
+                let match_arm = ast::MatchArm::cast(node)?;
+                let match_expr = sema
+                    .ancestors_with_macros(match_arm.syntax().clone())
+                    .find_map(ast::MatchExpr::cast)?;
+                let file_id = sema.hir_file_for(match_expr.syntax());
+                let focus_range = match_arm.fat_arrow_token()?.text_range();
+                let match_expr_in_file = InFile::new(file_id, match_expr.into());
+                Some(expr_to_nav(db, match_expr_in_file, Some(focus_range)))
+            })
+            .flatten()
+            .collect_vec(),
+
+        T![if] => find_branch_root(sema, token)
+            .into_iter()
+            .filter_map(|node| {
+                let file_id = sema.hir_file_for(&node);
+                let if_expr = ast::IfExpr::cast(node)?;
+                let focus_range = if_expr.if_token()?.text_range();
+                let if_expr_in_file = InFile::new(file_id, if_expr.into());
+                Some(expr_to_nav(db, if_expr_in_file, Some(focus_range)))
+            })
+            .flatten()
+            .collect_vec(),
+
+        _ => return Some(Vec::new()),
+    };
+
+    Some(navs)
+}
+
 pub(crate) fn find_loops(
     sema: &Semantics<'_, RootDatabase>,
     token: &SyntaxToken,
@@ -3614,4 +3700,155 @@ fn foo() {
         "#,
         );
     }
+
+    #[test]
+    fn goto_def_for_match_keyword() {
+        check(
+            r#"
+fn main() {
+    match$0 0 {
+ // ^^^^^
+        0 => {},
+        _ => {},
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_match_arm_fat_arrow() {
+        check(
+            r#"
+fn main() {
+    match 0 {
+        0 =>$0 {},
+       // ^^
+        _ => {},
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_if_keyword() {
+        check(
+            r#"
+fn main() {
+    if$0 true {
+ // ^^
+        ()
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_match_nested_in_if() {
+        check(
+            r#"
+fn main() {
+    if true {
+        match$0 0 {
+     // ^^^^^
+            0 => {},
+            _ => {},
+        }
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_multiple_match_expressions() {
+        check(
+            r#"
+fn main() {
+    match 0 {
+        0 => {},
+        _ => {},
+    };
+
+    match$0 1 {
+ // ^^^^^
+        1 => {},
+        _ => {},
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_nested_match_expressions() {
+        check(
+            r#"
+fn main() {
+    match 0 {
+        0 => match$0 1 {
+          // ^^^^^
+            1 => {},
+            _ => {},
+        },
+        _ => {},
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_if_else_chains() {
+        check(
+            r#"
+fn main() {
+    if true {
+ // ^^
+        ()
+    } else if$0 false {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_match_with_guards() {
+        check(
+            r#"
+fn main() {
+    match 42 {
+        x if x > 0 =>$0 {},
+                // ^^
+        _ => {},
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_match_with_macro_arm() {
+        check(
+            r#"
+macro_rules! arm {
+    () => { 0 => {} };
+}
+
+fn main() {
+    match$0 0 {
+ // ^^^^^
+        arm!(),
+        _ => {},
+    }
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
index 86d72fefe05..b80e81d39c6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
@@ -70,11 +70,10 @@ pub(crate) fn goto_type_definition(
     }
 
     let range = token.text_range();
-    sema.descend_into_macros_no_opaque(token,false)
+    sema.descend_into_macros_no_opaque(token, false)
         .into_iter()
         .filter_map(|token| {
-            sema
-                .token_ancestors_with_macros(token.value)
+            sema.token_ancestors_with_macros(token.value)
                 // When `token` is within a macro call, we can't determine its type. Don't continue
                 // this traversal because otherwise we'll end up returning the type of *that* macro
                 // call, which is not what we want in general.
@@ -103,7 +102,6 @@ pub(crate) fn goto_type_definition(
                             _ => return None,
                         }
                     };
-
                     Some(ty)
                 })
         })
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 aa947921a9b..356bd69aa44 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -37,8 +37,11 @@ pub struct HighlightRelatedConfig {
     pub break_points: bool,
     pub closure_captures: bool,
     pub yield_points: bool,
+    pub branch_exit_points: bool,
 }
 
+type HighlightMap = FxHashMap<EditionedFileId, FxHashSet<HighlightedRange>>;
+
 // Feature: Highlight Related
 //
 // Highlights constructs related to the thing under the cursor:
@@ -64,7 +67,7 @@ pub(crate) fn highlight_related(
 
     let token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind {
         T![?] => 4, // prefer `?` when the cursor is sandwiched like in `await$0?`
-        T![->] => 4,
+        T![->] | T![=>] => 4,
         kind if kind.is_keyword(file_id.edition(sema.db)) => 3,
         IDENT | INT_NUMBER => 2,
         T![|] => 1,
@@ -78,6 +81,9 @@ pub(crate) fn highlight_related(
         T![fn] | T![return] | T![->] if config.exit_points => {
             highlight_exit_points(sema, token).remove(&file_id)
         }
+        T![match] | T![=>] | T![if] if config.branch_exit_points => {
+            highlight_branch_exit_points(sema, token).remove(&file_id)
+        }
         T![await] | T![async] if config.yield_points => {
             highlight_yield_points(sema, token).remove(&file_id)
         }
@@ -300,11 +306,93 @@ fn highlight_references(
     if res.is_empty() { None } else { Some(res.into_iter().collect()) }
 }
 
+pub(crate) fn highlight_branch_exit_points(
+    sema: &Semantics<'_, RootDatabase>,
+    token: SyntaxToken,
+) -> FxHashMap<EditionedFileId, Vec<HighlightedRange>> {
+    let mut highlights: HighlightMap = FxHashMap::default();
+
+    let push_to_highlights = |file_id, range, highlights: &mut HighlightMap| {
+        if let Some(FileRange { file_id, range }) = original_frange(sema.db, file_id, range) {
+            let hrange = HighlightedRange { category: ReferenceCategory::empty(), range };
+            highlights.entry(file_id).or_default().insert(hrange);
+        }
+    };
+
+    let push_tail_expr = |tail: Option<ast::Expr>, highlights: &mut HighlightMap| {
+        let Some(tail) = tail else {
+            return;
+        };
+
+        for_each_tail_expr(&tail, &mut |tail| {
+            let file_id = sema.hir_file_for(tail.syntax());
+            let range = tail.syntax().text_range();
+            push_to_highlights(file_id, Some(range), highlights);
+        });
+    };
+
+    let nodes = goto_definition::find_branch_root(sema, &token).into_iter();
+    match token.kind() {
+        T![match] => {
+            for match_expr in nodes.filter_map(ast::MatchExpr::cast) {
+                let file_id = sema.hir_file_for(match_expr.syntax());
+                let range = match_expr.match_token().map(|token| token.text_range());
+                push_to_highlights(file_id, range, &mut highlights);
+
+                let Some(arm_list) = match_expr.match_arm_list() else {
+                    continue;
+                };
+                for arm in arm_list.arms() {
+                    push_tail_expr(arm.expr(), &mut highlights);
+                }
+            }
+        }
+        T![=>] => {
+            for arm in nodes.filter_map(ast::MatchArm::cast) {
+                let file_id = sema.hir_file_for(arm.syntax());
+                let range = arm.fat_arrow_token().map(|token| token.text_range());
+                push_to_highlights(file_id, range, &mut highlights);
+
+                push_tail_expr(arm.expr(), &mut highlights);
+            }
+        }
+        T![if] => {
+            for mut if_to_process in nodes.map(ast::IfExpr::cast) {
+                while let Some(cur_if) = if_to_process.take() {
+                    let file_id = sema.hir_file_for(cur_if.syntax());
+
+                    let if_kw_range = cur_if.if_token().map(|token| token.text_range());
+                    push_to_highlights(file_id, if_kw_range, &mut highlights);
+
+                    if let Some(then_block) = cur_if.then_branch() {
+                        push_tail_expr(Some(then_block.into()), &mut highlights);
+                    }
+
+                    match cur_if.else_branch() {
+                        Some(ast::ElseBranch::Block(else_block)) => {
+                            push_tail_expr(Some(else_block.into()), &mut highlights);
+                            if_to_process = None;
+                        }
+                        Some(ast::ElseBranch::IfExpr(nested_if)) => if_to_process = Some(nested_if),
+                        None => if_to_process = None,
+                    }
+                }
+            }
+        }
+        _ => {}
+    }
+
+    highlights
+        .into_iter()
+        .map(|(file_id, ranges)| (file_id, ranges.into_iter().collect()))
+        .collect()
+}
+
 fn hl_exit_points(
     sema: &Semantics<'_, RootDatabase>,
     def_token: Option<SyntaxToken>,
     body: ast::Expr,
-) -> Option<FxHashMap<EditionedFileId, FxHashSet<HighlightedRange>>> {
+) -> Option<HighlightMap> {
     let mut highlights: FxHashMap<EditionedFileId, FxHashSet<_>> = FxHashMap::default();
 
     let mut push_to_highlights = |file_id, range| {
@@ -411,7 +499,7 @@ pub(crate) fn highlight_break_points(
         loop_token: Option<SyntaxToken>,
         label: Option<ast::Label>,
         expr: ast::Expr,
-    ) -> Option<FxHashMap<EditionedFileId, FxHashSet<HighlightedRange>>> {
+    ) -> Option<HighlightMap> {
         let mut highlights: FxHashMap<EditionedFileId, FxHashSet<_>> = FxHashMap::default();
 
         let mut push_to_highlights = |file_id, range| {
@@ -504,7 +592,7 @@ pub(crate) fn highlight_yield_points(
         sema: &Semantics<'_, RootDatabase>,
         async_token: Option<SyntaxToken>,
         body: Option<ast::Expr>,
-    ) -> Option<FxHashMap<EditionedFileId, FxHashSet<HighlightedRange>>> {
+    ) -> Option<HighlightMap> {
         let mut highlights: FxHashMap<EditionedFileId, FxHashSet<_>> = FxHashMap::default();
 
         let mut push_to_highlights = |file_id, range| {
@@ -597,10 +685,7 @@ fn original_frange(
     InFile::new(file_id, text_range?).original_node_file_range_opt(db).map(|(frange, _)| frange)
 }
 
-fn merge_map(
-    res: &mut FxHashMap<EditionedFileId, FxHashSet<HighlightedRange>>,
-    new: Option<FxHashMap<EditionedFileId, FxHashSet<HighlightedRange>>>,
-) {
+fn merge_map(res: &mut HighlightMap, new: Option<HighlightMap>) {
     let Some(new) = new else {
         return;
     };
@@ -750,6 +835,7 @@ mod tests {
         references: true,
         closure_captures: true,
         yield_points: true,
+        branch_exit_points: true,
     };
 
     #[track_caller]
@@ -2135,6 +2221,62 @@ fn main() {
     }
 
     #[test]
+    fn nested_match() {
+        check(
+            r#"
+fn main() {
+    match$0 0 {
+ // ^^^^^
+        0 => match 1 {
+            1 => 2,
+              // ^
+            _ => 3,
+              // ^
+        },
+        _ => 4,
+          // ^
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn single_arm_highlight() {
+        check(
+            r#"
+fn main() {
+    match 0 {
+        0 =>$0 {
+       // ^^
+            let x = 1;
+            x
+         // ^
+        }
+        _ => 2,
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn no_branches_when_disabled() {
+        let config = HighlightRelatedConfig { branch_exit_points: false, ..ENABLED_CONFIG };
+        check_with_config(
+            r#"
+fn main() {
+    match$0 0 {
+        0 => 1,
+        _ => 2,
+    }
+}
+"#,
+            config,
+        );
+    }
+
+    #[test]
     fn asm() {
         check(
             r#"
@@ -2165,6 +2307,200 @@ pub unsafe fn bootstrap() -> ! {
     }
 
     #[test]
+    fn complex_arms_highlight() {
+        check(
+            r#"
+fn calculate(n: i32) -> i32 { n * 2 }
+
+fn main() {
+    match$0 Some(1) {
+ // ^^^^^
+        Some(x) => match x {
+            0 => { let y = x; y },
+                           // ^
+            1 => calculate(x),
+               //^^^^^^^^^^^^
+            _ => (|| 6)(),
+              // ^^^^^^^^
+        },
+        None => loop {
+            break 5;
+         // ^^^^^^^
+        },
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn match_in_macro_highlight() {
+        check(
+            r#"
+macro_rules! M {
+    ($e:expr) => { $e };
+}
+
+fn main() {
+    M!{
+        match$0 Some(1) {
+     // ^^^^^
+            Some(x) => x,
+                    // ^
+            None => 0,
+                 // ^
+        }
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn match_in_macro_highlight_2() {
+        check(
+            r#"
+macro_rules! match_ast {
+    (match $node:ident { $($tt:tt)* }) => { $crate::match_ast!(match ($node) { $($tt)* }) };
+
+    (match ($node:expr) {
+        $( $( $path:ident )::+ ($it:pat) => $res:expr, )*
+        _ => $catch_all:expr $(,)?
+    }) => {{
+        $( if let Some($it) = $($path::)+cast($node.clone()) { $res } else )*
+        { $catch_all }
+    }};
+}
+
+fn main() {
+    match_ast! {
+        match$0 Some(1) {
+            Some(x) => x,
+        }
+    }
+}
+            "#,
+        );
+    }
+
+    #[test]
+    fn nested_if_else() {
+        check(
+            r#"
+fn main() {
+    if$0 true {
+ // ^^
+        if false {
+            1
+         // ^
+        } else {
+            2
+         // ^
+        }
+    } else {
+        3
+     // ^
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn if_else_if_highlight() {
+        check(
+            r#"
+fn main() {
+    if$0 true {
+ // ^^
+        1
+     // ^
+    } else if false {
+        // ^^
+        2
+     // ^
+    } else {
+        3
+     // ^
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn complex_if_branches() {
+        check(
+            r#"
+fn calculate(n: i32) -> i32 { n * 2 }
+
+fn main() {
+    if$0 true {
+ // ^^
+        let x = 5;
+        calculate(x)
+     // ^^^^^^^^^^^^
+    } else if false {
+        // ^^
+        (|| 10)()
+     // ^^^^^^^^^
+    } else {
+        loop {
+            break 15;
+         // ^^^^^^^^
+        }
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn if_in_macro_highlight() {
+        check(
+            r#"
+macro_rules! M {
+    ($e:expr) => { $e };
+}
+
+fn main() {
+    M!{
+        if$0 true {
+     // ^^
+            5
+         // ^
+        } else {
+            10
+         // ^^
+        }
+    }
+}
+"#,
+        )
+    }
+
+    #[test]
+    fn match_in_macro() {
+        // We should not highlight the outer `match` expression.
+        check(
+            r#"
+macro_rules! M {
+    (match) => { 1 };
+}
+
+fn main() {
+    match Some(1) {
+        Some(x) => x,
+        None => {
+            M!(match$0)
+        }
+    }
+}
+            "#,
+        )
+    }
+
+    #[test]
     fn labeled_block_tail_expr() {
         check(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
index 36fdd90e8ae..729349365e6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
@@ -380,9 +380,9 @@ fn main() {
     let foo = foo3();
      // ^^^ impl Fn(f64, f64) -> u32
     let foo = foo4();
-     // ^^^ &'static (dyn Fn(f64, f64) -> u32 + 'static)
+     // ^^^ &'static dyn Fn(f64, f64) -> u32
     let foo = foo5();
-     // ^^^ &'static (dyn Fn(&(dyn Fn(f64, f64) -> u32 + 'static), f64) -> u32 + 'static)
+     // ^^^ &'static dyn Fn(&dyn Fn(f64, f64) -> u32, f64) -> u32
     let foo = foo6();
      // ^^^ impl Fn(f64, f64) -> u32
     let foo = foo7();
@@ -413,7 +413,7 @@ fn main() {
     let foo = foo3();
      // ^^^ impl Fn(f64, f64) -> u32
     let foo = foo4();
-     // ^^^ &'static (dyn Fn(f64, f64) -> u32 + 'static)
+     // ^^^ &'static dyn Fn(f64, f64) -> u32
     let foo = foo5();
     let foo = foo6();
     let foo = foo7();
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs
index b9a98f88be7..f0003dae3f3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs
@@ -143,7 +143,7 @@ fn foo<T>() {}
                                             file_id: FileId(
                                                 1,
                                             ),
-                                            range: 135..140,
+                                            range: 446..451,
                                         },
                                     ),
                                 ),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
index ca3a982760f..d2216e66ccb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
@@ -193,7 +193,7 @@ impl Tr for () {
 //^ impl Tr for ()
 impl dyn Tr {
   }
-//^ impl dyn Tr + 'static
+//^ impl dyn Tr
 
 static S0: () = 0;
 static S1: () = {};
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index c6a323d4081..fe874bc99b4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -21,6 +21,7 @@ use hir::{PathResolution, Semantics};
 use ide_db::{
     FileId, RootDatabase,
     defs::{Definition, NameClass, NameRefClass},
+    helpers::pick_best_token,
     search::{ReferenceCategory, SearchScope, UsageSearchResult},
 };
 use itertools::Itertools;
@@ -397,7 +398,11 @@ fn handle_control_flow_keywords(
         .attach_first_edition(file_id)
         .map(|it| it.edition(sema.db))
         .unwrap_or(Edition::CURRENT);
-    let token = file.syntax().token_at_offset(offset).find(|t| t.kind().is_keyword(edition))?;
+    let token = pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {
+        _ if kind.is_keyword(edition) => 4,
+        T![=>] => 3,
+        _ => 1,
+    })?;
 
     let references = match token.kind() {
         T![fn] | T![return] | T![try] => highlight_related::highlight_exit_points(sema, token),
@@ -408,6 +413,7 @@ fn handle_control_flow_keywords(
         T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {
             highlight_related::highlight_break_points(sema, token)
         }
+        T![if] | T![=>] | T![match] => highlight_related::highlight_branch_exit_points(sema, token),
         _ => return None,
     }
     .into_iter()
@@ -1344,6 +1350,159 @@ impl Foo {
         );
     }
 
+    #[test]
+    fn test_highlight_if_branches() {
+        check(
+            r#"
+fn main() {
+    let x = if$0 true {
+        1
+    } else if false {
+        2
+    } else {
+        3
+    };
+
+    println!("x: {}", x);
+}
+"#,
+            expect![[r#"
+                FileId(0) 24..26
+                FileId(0) 42..43
+                FileId(0) 55..57
+                FileId(0) 74..75
+                FileId(0) 97..98
+            "#]],
+        );
+    }
+
+    #[test]
+    fn test_highlight_match_branches() {
+        check(
+            r#"
+fn main() {
+    $0match Some(42) {
+        Some(x) if x > 0 => println!("positive"),
+        Some(0) => println!("zero"),
+        Some(_) => println!("negative"),
+        None => println!("none"),
+    };
+}
+"#,
+            expect![[r#"
+                FileId(0) 16..21
+                FileId(0) 61..81
+                FileId(0) 102..118
+                FileId(0) 139..159
+                FileId(0) 177..193
+            "#]],
+        );
+    }
+
+    #[test]
+    fn test_highlight_match_arm_arrow() {
+        check(
+            r#"
+fn main() {
+    match Some(42) {
+        Some(x) if x > 0 $0=> println!("positive"),
+        Some(0) => println!("zero"),
+        Some(_) => println!("negative"),
+        None => println!("none"),
+    }
+}
+"#,
+            expect![[r#"
+                FileId(0) 58..60
+                FileId(0) 61..81
+            "#]],
+        );
+    }
+
+    #[test]
+    fn test_highlight_nested_branches() {
+        check(
+            r#"
+fn main() {
+    let x = $0if true {
+        if false {
+            1
+        } else {
+            match Some(42) {
+                Some(_) => 2,
+                None => 3,
+            }
+        }
+    } else {
+        4
+    };
+
+    println!("x: {}", x);
+}
+"#,
+            expect![[r#"
+                FileId(0) 24..26
+                FileId(0) 65..66
+                FileId(0) 140..141
+                FileId(0) 167..168
+                FileId(0) 215..216
+            "#]],
+        );
+    }
+
+    #[test]
+    fn test_highlight_match_with_complex_guards() {
+        check(
+            r#"
+fn main() {
+    let x = $0match (x, y) {
+        (a, b) if a > b && a % 2 == 0 => 1,
+        (a, b) if a < b || b % 2 == 1 => 2,
+        (a, _) if a > 40 => 3,
+        _ => 4,
+    };
+
+    println!("x: {}", x);
+}
+"#,
+            expect![[r#"
+                FileId(0) 24..29
+                FileId(0) 80..81
+                FileId(0) 124..125
+                FileId(0) 155..156
+                FileId(0) 171..172
+            "#]],
+        );
+    }
+
+    #[test]
+    fn test_highlight_mixed_if_match_expressions() {
+        check(
+            r#"
+fn main() {
+    let x = $0if let Some(x) = Some(42) {
+        1
+    } else if let None = None {
+        2
+    } else {
+        match 42 {
+            0 => 3,
+            _ => 4,
+        }
+    };
+}
+"#,
+            expect![[r#"
+                FileId(0) 24..26
+                FileId(0) 60..61
+                FileId(0) 73..75
+                FileId(0) 102..103
+                FileId(0) 153..154
+                FileId(0) 173..174
+            "#]],
+        );
+    }
+
     fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
         check_with_scope(ra_fixture, None, expect)
     }
@@ -2867,4 +3026,66 @@ const FOO$0: i32 = 0;
             "#]],
         );
     }
+
+    #[test]
+    fn test_highlight_if_let_match_combined() {
+        check(
+            r#"
+enum MyEnum { A(i32), B(String), C }
+
+fn main() {
+    let val = MyEnum::A(42);
+
+    let x = $0if let MyEnum::A(x) = val {
+        1
+    } else if let MyEnum::B(s) = val {
+        2
+    } else {
+        match val {
+            MyEnum::C => 3,
+            _ => 4,
+        }
+    };
+}
+"#,
+            expect![[r#"
+                FileId(0) 92..94
+                FileId(0) 128..129
+                FileId(0) 141..143
+                FileId(0) 177..178
+                FileId(0) 237..238
+                FileId(0) 257..258
+            "#]],
+        );
+    }
+
+    #[test]
+    fn test_highlight_nested_match_expressions() {
+        check(
+            r#"
+enum Outer { A(Inner), B }
+enum Inner { X, Y(i32) }
+
+fn main() {
+    let val = Outer::A(Inner::Y(42));
+
+    $0match val {
+        Outer::A(inner) => match inner {
+            Inner::X => println!("Inner::X"),
+            Inner::Y(n) if n > 0 => println!("Inner::Y positive: {}", n),
+            Inner::Y(_) => println!("Inner::Y non-positive"),
+        },
+        Outer::B => println!("Outer::B"),
+    }
+}
+"#,
+            expect![[r#"
+                FileId(0) 108..113
+                FileId(0) 185..205
+                FileId(0) 243..279
+                FileId(0) 308..341
+                FileId(0) 374..394
+            "#]],
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/intern/Cargo.toml b/src/tools/rust-analyzer/crates/intern/Cargo.toml
index 9ff656cb744..81b6703deef 100644
--- a/src/tools/rust-analyzer/crates/intern/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/intern/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 
 [dependencies]
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index adc581309d1..1ccd20c25e9 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -438,6 +438,8 @@ define_symbols! {
     shr,
     simd,
     sized,
+    meta_sized,
+    pointee_sized,
     skip,
     slice_len_fn,
     Some,
diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
index f3ab093bae0..eef718b7062 100644
--- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml
index c80510eedfb..c7da654de6d 100644
--- a/src/tools/rust-analyzer/crates/parser/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 drop_bomb = "0.1.5"
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
index ea5a3bc8593..55c5dc400b9 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
@@ -122,7 +122,7 @@ fn lifetime_bounds(p: &mut Parser<'_>) {
 }
 
 // test type_param_bounds
-// struct S<T: 'a + ?Sized + (Copy) + ~const Drop>;
+// struct S<T: 'a + ?Sized + (Copy) + [const] Drop>;
 pub(super) fn bounds(p: &mut Parser<'_>) {
     p.expect(T![:]);
     bounds_without_colon(p);
@@ -187,6 +187,11 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
                     p.bump_any();
                     p.expect(T![const]);
                 }
+                T!['['] => {
+                    p.bump_any();
+                    p.expect(T![const]);
+                    p.expect(T![']']);
+                }
                 // test const_trait_bound
                 // const fn foo(_: impl const Trait) {}
                 T![const] => {
diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
index 0fa9a264545..e6c92dec681 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
@@ -11,7 +11,8 @@
 use std::ops;
 
 use rustc_literal_escaper::{
-    EscapeError, Mode, unescape_byte, unescape_char, unescape_mixed, unescape_unicode,
+    EscapeError, Mode, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char,
+    unescape_str,
 };
 
 use crate::{
@@ -151,14 +152,14 @@ impl<'a> Converter<'a> {
         self.res
     }
 
-    fn push(&mut self, kind: SyntaxKind, len: usize, err: Option<&str>) {
+    fn push(&mut self, kind: SyntaxKind, len: usize, errors: Vec<String>) {
         self.res.push(kind, self.offset);
         self.offset += len;
 
-        if let Some(err) = err {
-            let token = self.res.len() as u32;
-            let msg = err.to_owned();
-            self.res.error.push(LexError { msg, token });
+        for msg in errors {
+            if !msg.is_empty() {
+                self.res.error.push(LexError { msg, token: self.res.len() as u32 });
+            }
         }
     }
 
@@ -167,14 +168,16 @@ impl<'a> Converter<'a> {
         // We drop some useful information here (see patterns with double dots `..`)
         // Storing that info in `SyntaxKind` is not possible due to its layout requirements of
         // being `u16` that come from `rowan::SyntaxKind`.
-        let mut err = "";
+        let mut errors: Vec<String> = vec![];
 
         let syntax_kind = {
             match kind {
                 rustc_lexer::TokenKind::LineComment { doc_style: _ } => COMMENT,
                 rustc_lexer::TokenKind::BlockComment { doc_style: _, terminated } => {
                     if !terminated {
-                        err = "Missing trailing `*/` symbols to terminate the block comment";
+                        errors.push(
+                            "Missing trailing `*/` symbols to terminate the block comment".into(),
+                        );
                     }
                     COMMENT
                 }
@@ -184,9 +187,9 @@ impl<'a> Converter<'a> {
                     invalid_infostring,
                 } => {
                     if *has_invalid_preceding_whitespace {
-                        err = "invalid preceding whitespace for frontmatter opening"
+                        errors.push("invalid preceding whitespace for frontmatter opening".into());
                     } else if *invalid_infostring {
-                        err = "invalid infostring for frontmatter"
+                        errors.push("invalid infostring for frontmatter".into());
                     }
                     FRONTMATTER
                 }
@@ -198,7 +201,7 @@ impl<'a> Converter<'a> {
                     SyntaxKind::from_keyword(token_text, self.edition).unwrap_or(IDENT)
                 }
                 rustc_lexer::TokenKind::InvalidIdent => {
-                    err = "Ident contains invalid characters";
+                    errors.push("Ident contains invalid characters".into());
                     IDENT
                 }
 
@@ -206,7 +209,7 @@ impl<'a> Converter<'a> {
 
                 rustc_lexer::TokenKind::GuardedStrPrefix if self.edition.at_least_2024() => {
                     // FIXME: rustc does something better for recovery.
-                    err = "Invalid string literal (reserved syntax)";
+                    errors.push("Invalid string literal (reserved syntax)".into());
                     ERROR
                 }
                 rustc_lexer::TokenKind::GuardedStrPrefix => {
@@ -222,12 +225,12 @@ impl<'a> Converter<'a> {
 
                 rustc_lexer::TokenKind::Lifetime { starts_with_number } => {
                     if *starts_with_number {
-                        err = "Lifetime name cannot start with a number";
+                        errors.push("Lifetime name cannot start with a number".into());
                     }
                     LIFETIME_IDENT
                 }
                 rustc_lexer::TokenKind::UnknownPrefixLifetime => {
-                    err = "Unknown lifetime prefix";
+                    errors.push("Unknown lifetime prefix".into());
                     LIFETIME_IDENT
                 }
                 rustc_lexer::TokenKind::RawLifetime => LIFETIME_IDENT,
@@ -262,119 +265,128 @@ impl<'a> Converter<'a> {
                 rustc_lexer::TokenKind::Unknown => ERROR,
                 rustc_lexer::TokenKind::UnknownPrefix if token_text == "builtin" => IDENT,
                 rustc_lexer::TokenKind::UnknownPrefix => {
-                    err = "unknown literal prefix";
+                    errors.push("unknown literal prefix".into());
                     IDENT
                 }
                 rustc_lexer::TokenKind::Eof => EOF,
             }
         };
 
-        let err = if err.is_empty() { None } else { Some(err) };
-        self.push(syntax_kind, token_text.len(), err);
+        self.push(syntax_kind, token_text.len(), errors);
     }
 
     fn extend_literal(&mut self, len: usize, kind: &rustc_lexer::LiteralKind) {
-        let mut err = "";
+        let invalid_raw_msg = String::from("Invalid raw string literal");
+
+        let mut errors = vec![];
+        let mut no_end_quote = |c: char, kind: &str| {
+            errors.push(format!("Missing trailing `{c}` symbol to terminate the {kind} literal"));
+        };
 
         let syntax_kind = match *kind {
             rustc_lexer::LiteralKind::Int { empty_int, base: _ } => {
                 if empty_int {
-                    err = "Missing digits after the integer base prefix";
+                    errors.push("Missing digits after the integer base prefix".into());
                 }
                 INT_NUMBER
             }
             rustc_lexer::LiteralKind::Float { empty_exponent, base: _ } => {
                 if empty_exponent {
-                    err = "Missing digits after the exponent symbol";
+                    errors.push("Missing digits after the exponent symbol".into());
                 }
                 FLOAT_NUMBER
             }
             rustc_lexer::LiteralKind::Char { terminated } => {
                 if !terminated {
-                    err = "Missing trailing `'` symbol to terminate the character literal";
+                    no_end_quote('\'', "character");
                 } else {
                     let text = &self.res.text[self.offset + 1..][..len - 1];
-                    let i = text.rfind('\'').unwrap();
-                    let text = &text[..i];
+                    let text = &text[..text.rfind('\'').unwrap()];
                     if let Err(e) = unescape_char(text) {
-                        err = error_to_diagnostic_message(e, Mode::Char);
+                        errors.push(err_to_msg(e, Mode::Char));
                     }
                 }
                 CHAR
             }
             rustc_lexer::LiteralKind::Byte { terminated } => {
                 if !terminated {
-                    err = "Missing trailing `'` symbol to terminate the byte literal";
+                    no_end_quote('\'', "byte");
                 } else {
                     let text = &self.res.text[self.offset + 2..][..len - 2];
-                    let i = text.rfind('\'').unwrap();
-                    let text = &text[..i];
+                    let text = &text[..text.rfind('\'').unwrap()];
                     if let Err(e) = unescape_byte(text) {
-                        err = error_to_diagnostic_message(e, Mode::Byte);
+                        errors.push(err_to_msg(e, Mode::Byte));
                     }
                 }
-
                 BYTE
             }
             rustc_lexer::LiteralKind::Str { terminated } => {
                 if !terminated {
-                    err = "Missing trailing `\"` symbol to terminate the string literal";
+                    no_end_quote('"', "string");
                 } else {
                     let text = &self.res.text[self.offset + 1..][..len - 1];
-                    let i = text.rfind('"').unwrap();
-                    let text = &text[..i];
-                    err = unescape_string_error_message(text, Mode::Str);
+                    let text = &text[..text.rfind('"').unwrap()];
+                    unescape_str(text, |_, res| {
+                        if let Err(e) = res {
+                            errors.push(err_to_msg(e, Mode::Str));
+                        }
+                    });
                 }
                 STRING
             }
             rustc_lexer::LiteralKind::ByteStr { terminated } => {
                 if !terminated {
-                    err = "Missing trailing `\"` symbol to terminate the byte string literal";
+                    no_end_quote('"', "byte string");
                 } else {
                     let text = &self.res.text[self.offset + 2..][..len - 2];
-                    let i = text.rfind('"').unwrap();
-                    let text = &text[..i];
-                    err = unescape_string_error_message(text, Mode::ByteStr);
+                    let text = &text[..text.rfind('"').unwrap()];
+                    unescape_byte_str(text, |_, res| {
+                        if let Err(e) = res {
+                            errors.push(err_to_msg(e, Mode::ByteStr));
+                        }
+                    });
                 }
                 BYTE_STRING
             }
             rustc_lexer::LiteralKind::CStr { terminated } => {
                 if !terminated {
-                    err = "Missing trailing `\"` symbol to terminate the string literal";
+                    no_end_quote('"', "C string")
                 } else {
                     let text = &self.res.text[self.offset + 2..][..len - 2];
-                    let i = text.rfind('"').unwrap();
-                    let text = &text[..i];
-                    err = unescape_string_error_message(text, Mode::CStr);
+                    let text = &text[..text.rfind('"').unwrap()];
+                    unescape_c_str(text, |_, res| {
+                        if let Err(e) = res {
+                            errors.push(err_to_msg(e, Mode::CStr));
+                        }
+                    });
                 }
                 C_STRING
             }
             rustc_lexer::LiteralKind::RawStr { n_hashes } => {
                 if n_hashes.is_none() {
-                    err = "Invalid raw string literal";
+                    errors.push(invalid_raw_msg);
                 }
                 STRING
             }
             rustc_lexer::LiteralKind::RawByteStr { n_hashes } => {
                 if n_hashes.is_none() {
-                    err = "Invalid raw string literal";
+                    errors.push(invalid_raw_msg);
                 }
                 BYTE_STRING
             }
             rustc_lexer::LiteralKind::RawCStr { n_hashes } => {
                 if n_hashes.is_none() {
-                    err = "Invalid raw string literal";
+                    errors.push(invalid_raw_msg);
                 }
                 C_STRING
             }
         };
 
-        let err = if err.is_empty() { None } else { Some(err) };
-        self.push(syntax_kind, len, err);
+        self.push(syntax_kind, len, errors);
     }
 }
 
-fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str {
+fn err_to_msg(error: EscapeError, mode: Mode) -> String {
     match error {
         EscapeError::ZeroChars => "empty character literal",
         EscapeError::MoreThanOneChar => "character literal may only contain one codepoint",
@@ -410,28 +422,5 @@ fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str {
         EscapeError::UnskippedWhitespaceWarning => "",
         EscapeError::MultipleSkippedLinesWarning => "",
     }
-}
-
-fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str {
-    let mut error_message = "";
-    match mode {
-        Mode::CStr => {
-            unescape_mixed(text, mode, &mut |_, res| {
-                if let Err(e) = res {
-                    error_message = error_to_diagnostic_message(e, mode);
-                }
-            });
-        }
-        Mode::ByteStr | Mode::Str => {
-            unescape_unicode(text, mode, &mut |_, res| {
-                if let Err(e) = res {
-                    error_message = error_to_diagnostic_message(e, mode);
-                }
-            });
-        }
-        _ => {
-            // Other Modes are not supported yet or do not apply
-        }
-    }
-    error_message
+    .into()
 }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rast
index dee860c2418..259637c898a 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rast
@@ -40,8 +40,9 @@ SOURCE_FILE
           PLUS "+"
           WHITESPACE " "
           TYPE_BOUND
-            TILDE "~"
+            L_BRACK "["
             CONST_KW "const"
+            R_BRACK "]"
             WHITESPACE " "
             PATH_TYPE
               PATH
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rs
index 5da3083b9c5..8f37af78e9f 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/type_param_bounds.rs
@@ -1 +1 @@
-struct S<T: 'a + ?Sized + (Copy) + ~const Drop>;
+struct S<T: 'a + ?Sized + (Copy) + [const] Drop>;
diff --git a/src/tools/rust-analyzer/crates/paths/Cargo.toml b/src/tools/rust-analyzer/crates/paths/Cargo.toml
index 4cc70726da0..f0dafab70c1 100644
--- a/src/tools/rust-analyzer/crates/paths/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/paths/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 camino.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
index f5ba40a994b..dac8e094357 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 serde.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
index 8fd675d0d31..4034f244393 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 object.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
index c416d997a89..bc04482273e 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2024"
 license = "MIT OR Apache-2.0"
 
 [lib]
+doctest = false
 
 [build-dependencies]
 cargo_metadata = "0.20.0"
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
index b97569d4dbd..b9e84a474dd 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
@@ -109,13 +109,11 @@ fn main() {
 
     let mut artifact_path = None;
     for message in Message::parse_stream(output.stdout.as_slice()) {
-        if let Message::CompilerArtifact(artifact) = message.unwrap() {
-            if artifact.target.kind.contains(&cargo_metadata::TargetKind::ProcMacro)
-                && (artifact.package_id.repr.starts_with(&repr)
-                    || artifact.package_id.repr == pkgid)
-            {
-                artifact_path = Some(PathBuf::from(&artifact.filenames[0]));
-            }
+        if let Message::CompilerArtifact(artifact) = message.unwrap()
+            && artifact.target.kind.contains(&cargo_metadata::TargetKind::ProcMacro)
+            && (artifact.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid)
+        {
+            artifact_path = Some(PathBuf::from(&artifact.filenames[0]));
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml
index 33b7c2bb0ad..e1678bddff8 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2024"
 publish = false
 
 [lib]
+doctest = false
 proc-macro = true
 
 [dependencies]
diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml
index bae891c1984..4828419003a 100644
--- a/src/tools/rust-analyzer/crates/profile/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 cfg-if = "1.0.1"
diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
index 64ea75922fb..27fe9f79bbc 100644
--- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 anyhow.workspace = true
diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs
index 4435376eab6..bbaa8f4f292 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs
@@ -20,9 +20,7 @@ use toolchain::Tool;
 
 use crate::{
     CargoConfig, CargoFeatures, CargoWorkspace, InvocationStrategy, ManifestPath, Package, Sysroot,
-    TargetKind,
-    toolchain_info::{QueryConfig, version},
-    utf8_stdout,
+    TargetKind, utf8_stdout,
 };
 
 /// Output of the build script and proc-macro building steps for a workspace.
@@ -64,6 +62,7 @@ impl WorkspaceBuildScripts {
         workspace: &CargoWorkspace,
         progress: &dyn Fn(String),
         sysroot: &Sysroot,
+        toolchain: Option<&semver::Version>,
     ) -> io::Result<WorkspaceBuildScripts> {
         let current_dir = workspace.workspace_root();
 
@@ -74,6 +73,7 @@ impl WorkspaceBuildScripts {
             workspace.manifest_path(),
             current_dir,
             sysroot,
+            toolchain,
         )?;
         Self::run_per_ws(cmd, workspace, progress)
     }
@@ -95,6 +95,7 @@ impl WorkspaceBuildScripts {
             &ManifestPath::try_from(working_directory.clone()).unwrap(),
             working_directory,
             &Sysroot::empty(),
+            None,
         )?;
         // NB: Cargo.toml could have been modified between `cargo metadata` and
         // `cargo check`. We shouldn't assume that package ids we see here are
@@ -356,7 +357,7 @@ impl WorkspaceBuildScripts {
                         });
                     }
                     Message::CompilerMessage(message) => {
-                        progress(message.target.name);
+                        progress(format!("received compiler message for: {}", message.target.name));
 
                         if let Some(diag) = message.message.rendered.as_deref() {
                             push_err(diag);
@@ -387,12 +388,13 @@ impl WorkspaceBuildScripts {
         manifest_path: &ManifestPath,
         current_dir: &AbsPath,
         sysroot: &Sysroot,
+        toolchain: Option<&semver::Version>,
     ) -> io::Result<Command> {
-        let mut cmd = match config.run_build_script_command.as_deref() {
+        match config.run_build_script_command.as_deref() {
             Some([program, args @ ..]) => {
                 let mut cmd = toolchain::command(program, current_dir, &config.extra_env);
                 cmd.args(args);
-                cmd
+                Ok(cmd)
             }
             _ => {
                 let mut cmd = sysroot.tool(Tool::Cargo, current_dir, &config.extra_env);
@@ -444,40 +446,35 @@ impl WorkspaceBuildScripts {
 
                 cmd.arg("--keep-going");
 
-                cmd
+                // If [`--compile-time-deps` flag](https://github.com/rust-lang/cargo/issues/14434) is
+                // available in current toolchain's cargo, use it to build compile time deps only.
+                const COMP_TIME_DEPS_MIN_TOOLCHAIN_VERSION: semver::Version = semver::Version {
+                    major: 1,
+                    minor: 89,
+                    patch: 0,
+                    pre: semver::Prerelease::EMPTY,
+                    build: semver::BuildMetadata::EMPTY,
+                };
+
+                let cargo_comp_time_deps_available =
+                    toolchain.is_some_and(|v| *v >= COMP_TIME_DEPS_MIN_TOOLCHAIN_VERSION);
+
+                if cargo_comp_time_deps_available {
+                    cmd.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly");
+                    cmd.arg("-Zunstable-options");
+                    cmd.arg("--compile-time-deps");
+                } else if config.wrap_rustc_in_build_scripts {
+                    // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
+                    // that to compile only proc macros and build scripts during the initial
+                    // `cargo check`.
+                    // We don't need this if we are using `--compile-time-deps` flag.
+                    let myself = std::env::current_exe()?;
+                    cmd.env("RUSTC_WRAPPER", myself);
+                    cmd.env("RA_RUSTC_WRAPPER", "1");
+                }
+                Ok(cmd)
             }
-        };
-
-        // If [`--compile-time-deps` flag](https://github.com/rust-lang/cargo/issues/14434) is
-        // available in current toolchain's cargo, use it to build compile time deps only.
-        const COMP_TIME_DEPS_MIN_TOOLCHAIN_VERSION: semver::Version = semver::Version {
-            major: 1,
-            minor: 90,
-            patch: 0,
-            pre: semver::Prerelease::EMPTY,
-            build: semver::BuildMetadata::EMPTY,
-        };
-
-        let query_config = QueryConfig::Cargo(sysroot, manifest_path);
-        let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
-        let cargo_comp_time_deps_available =
-            toolchain.is_some_and(|v| v >= COMP_TIME_DEPS_MIN_TOOLCHAIN_VERSION);
-
-        if cargo_comp_time_deps_available {
-            cmd.env("__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS", "nightly");
-            cmd.arg("-Zunstable-options");
-            cmd.arg("--compile-time-deps");
-        } else if config.wrap_rustc_in_build_scripts {
-            // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
-            // that to compile only proc macros and build scripts during the initial
-            // `cargo check`.
-            // We don't need this if we are using `--compile-time-deps` flag.
-            let myself = std::env::current_exe()?;
-            cmd.env("RUSTC_WRAPPER", myself);
-            cmd.env("RA_RUSTC_WRAPPER", "1");
         }
-
-        Ok(cmd)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
index 58507418e4d..4bacc904174 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
@@ -48,6 +48,7 @@ pub struct CargoWorkspace {
     is_sysroot: bool,
     /// Environment variables set in the `.cargo/config` file.
     config_env: Env,
+    requires_rustc_private: bool,
 }
 
 impl ops::Index<Package> for CargoWorkspace {
@@ -513,6 +514,7 @@ impl CargoWorkspace {
         let workspace_root = AbsPathBuf::assert(meta.workspace_root);
         let target_directory = AbsPathBuf::assert(meta.target_directory);
         let mut is_virtual_workspace = true;
+        let mut requires_rustc_private = false;
 
         meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
         for meta_pkg in meta.packages {
@@ -577,6 +579,7 @@ impl CargoWorkspace {
                 metadata: meta.rust_analyzer.unwrap_or_default(),
             });
             let pkg_data = &mut packages[pkg];
+            requires_rustc_private |= pkg_data.metadata.rustc_private;
             pkg_by_id.insert(id, pkg);
             for meta_tgt in meta_targets {
                 let cargo_metadata::Target { name, kind, required_features, src_path, .. } =
@@ -626,6 +629,7 @@ impl CargoWorkspace {
             target_directory,
             manifest_path: ws_manifest_path,
             is_virtual_workspace,
+            requires_rustc_private,
             is_sysroot,
             config_env: cargo_config_env,
         }
@@ -724,4 +728,8 @@ impl CargoWorkspace {
     pub fn is_sysroot(&self) -> bool {
         self.is_sysroot
     }
+
+    pub fn requires_rustc_private(&self) -> bool {
+        self.requires_rustc_private
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs
index 450def5461d..9e0415c3b39 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/env.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs
@@ -1,6 +1,6 @@
 //! Cargo-like environment variables injection.
 use base_db::Env;
-use paths::Utf8Path;
+use paths::{Utf8Path, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use toolchain::Tool;
 
@@ -123,6 +123,26 @@ fn parse_output_cargo_config_env(manifest: &ManifestPath, stdout: &str) -> Env {
     env
 }
 
+pub(crate) fn cargo_config_build_target_dir(
+    manifest: &ManifestPath,
+    extra_env: &FxHashMap<String, Option<String>>,
+    sysroot: &Sysroot,
+) -> Option<Utf8PathBuf> {
+    let mut cargo_config = sysroot.tool(Tool::Cargo, manifest.parent(), extra_env);
+    cargo_config
+        .args(["-Z", "unstable-options", "config", "get", "build.target-dir"])
+        .env("RUSTC_BOOTSTRAP", "1");
+    if manifest.is_rust_manifest() {
+        cargo_config.arg("-Zscript");
+    }
+    utf8_stdout(&mut cargo_config)
+        .map(|stdout| {
+            Utf8Path::new(stdout.trim_start_matches("build.target-dir = ").trim_matches('"'))
+                .to_owned()
+        })
+        .ok()
+}
+
 #[test]
 fn parse_output_cargo_config_env_works() {
     let stdout = r#"
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 a6743a32b14..5bc64df535c 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -16,6 +16,7 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::{FxHashMap, FxHashSet};
 use semver::Version;
 use span::{Edition, FileId};
+use toolchain::Tool;
 use tracing::instrument;
 use triomphe::Arc;
 
@@ -25,10 +26,14 @@ use crate::{
     WorkspaceBuildScripts,
     build_dependencies::BuildScriptOutput,
     cargo_workspace::{CargoMetadataConfig, DepKind, PackageData, RustLibSource},
-    env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
+    env::{
+        cargo_config_build_target_dir, cargo_config_env, inject_cargo_env,
+        inject_cargo_package_env, inject_rustc_tool_env,
+    },
     project_json::{Crate, CrateArrayIdx},
     sysroot::RustLibSrcWorkspace,
     toolchain_info::{QueryConfig, rustc_cfg, target_data_layout, target_tuple, version},
+    utf8_stdout,
 };
 use tracing::{debug, error, info};
 
@@ -208,8 +213,7 @@ impl ProjectWorkspace {
         config: &CargoConfig,
         progress: &(dyn Fn(String) + Sync),
     ) -> Result<ProjectWorkspace, anyhow::Error> {
-        progress("Discovering sysroot".to_owned());
-        let workspace_dir = cargo_toml.parent();
+        progress("discovering sysroot".to_owned());
         let CargoConfig {
             features,
             rustc_source,
@@ -224,6 +228,7 @@ impl ProjectWorkspace {
             no_deps,
             ..
         } = config;
+        let workspace_dir = cargo_toml.parent();
         let mut sysroot = match (sysroot, sysroot_src) {
             (Some(RustLibSource::Discover), None) => Sysroot::discover(workspace_dir, extra_env),
             (Some(RustLibSource::Discover), Some(sysroot_src)) => {
@@ -238,8 +243,33 @@ impl ProjectWorkspace {
             (None, _) => Sysroot::empty(),
         };
 
+        // Resolve the Cargo.toml to the workspace root as we base the `target` dir off of it.
+        let mut cmd = sysroot.tool(Tool::Cargo, workspace_dir, extra_env);
+        cmd.args(["locate-project", "--workspace", "--manifest-path", cargo_toml.as_str()]);
+        let cargo_toml = &match utf8_stdout(&mut cmd) {
+            Ok(output) => {
+                #[derive(serde_derive::Deserialize)]
+                struct Root {
+                    root: Utf8PathBuf,
+                }
+                match serde_json::from_str::<Root>(&output) {
+                    Ok(object) => ManifestPath::try_from(AbsPathBuf::assert(object.root))
+                        .expect("manifest path should be absolute"),
+                    Err(e) => {
+                        tracing::error!(%e, %cargo_toml, "failed fetching cargo workspace root");
+                        cargo_toml.clone()
+                    }
+                }
+            }
+            Err(e) => {
+                tracing::error!(%e, %cargo_toml, "failed fetching cargo workspace root");
+                cargo_toml.clone()
+            }
+        };
+        let workspace_dir = cargo_toml.parent();
+
         tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot");
-        progress("Querying project metadata".to_owned());
+        progress("querying project metadata".to_owned());
         let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml);
         let targets =
             target_tuple::get(toolchain_config, target.as_deref(), extra_env).unwrap_or_default();
@@ -252,8 +282,11 @@ impl ProjectWorkspace {
             .ok()
             .flatten();
 
-        let target_dir =
-            config.target_dir.clone().unwrap_or_else(|| workspace_dir.join("target").into());
+        let target_dir = config
+            .target_dir
+            .clone()
+            .or_else(|| cargo_config_build_target_dir(cargo_toml, extra_env, &sysroot))
+            .unwrap_or_else(|| workspace_dir.join("target").into());
 
         // We spawn a bunch of processes to query various information about the workspace's
         // toolchain and sysroot
@@ -374,11 +407,17 @@ impl ProjectWorkspace {
             ))
         });
 
-        let (rustc_cfg, data_layout, rustc, loaded_sysroot, cargo_metadata, cargo_config_extra_env) =
-            match join {
-                Ok(it) => it,
-                Err(e) => std::panic::resume_unwind(e),
-            };
+        let (
+            rustc_cfg,
+            data_layout,
+            mut rustc,
+            loaded_sysroot,
+            cargo_metadata,
+            cargo_config_extra_env,
+        ) = match join {
+            Ok(it) => it,
+            Err(e) => std::panic::resume_unwind(e),
+        };
 
         let (meta, error) = cargo_metadata.with_context(|| {
             format!(
@@ -391,6 +430,14 @@ impl ProjectWorkspace {
             sysroot.set_workspace(loaded_sysroot);
         }
 
+        if !cargo.requires_rustc_private() {
+            if let Err(e) = &mut rustc {
+                // We don't need the rustc sources here,
+                // so just discard the error.
+                _ = e.take();
+            }
+        }
+
         Ok(ProjectWorkspace {
             kind: ProjectWorkspaceKind::Cargo {
                 cargo,
@@ -413,17 +460,25 @@ impl ProjectWorkspace {
         config: &CargoConfig,
         progress: &(dyn Fn(String) + Sync),
     ) -> ProjectWorkspace {
-        progress("Discovering sysroot".to_owned());
+        progress("discovering sysroot".to_owned());
         let mut sysroot =
             Sysroot::new(project_json.sysroot.clone(), project_json.sysroot_src.clone());
 
         tracing::info!(workspace = %project_json.manifest_or_root(), src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot");
-        progress("Querying project metadata".to_owned());
+        progress("querying project metadata".to_owned());
         let sysroot_project = project_json.sysroot_project.take();
         let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref());
         let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
             .unwrap_or_default();
         let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
+        let project_root = project_json.project_root();
+        let target_dir = config
+            .target_dir
+            .clone()
+            .or_else(|| {
+                cargo_config_build_target_dir(project_json.manifest()?, &config.extra_env, &sysroot)
+            })
+            .unwrap_or_else(|| project_root.join("target").into());
 
         // We spawn a bunch of processes to query various information about the workspace's
         // toolchain and sysroot
@@ -441,7 +496,6 @@ impl ProjectWorkspace {
                 )
             });
             let loaded_sysroot = s.spawn(|| {
-                let project_root = project_json.project_root();
                 if let Some(sysroot_project) = sysroot_project {
                     sysroot.load_workspace(
                         &RustSourceWorkspaceConfig::Json(*sysroot_project),
@@ -449,10 +503,6 @@ impl ProjectWorkspace {
                         progress,
                     )
                 } else {
-                    let target_dir = config
-                        .target_dir
-                        .clone()
-                        .unwrap_or_else(|| project_root.join("target").into());
                     sysroot.load_workspace(
                         &RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
                             config,
@@ -507,7 +557,12 @@ impl ProjectWorkspace {
             .unwrap_or_default();
         let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
         let data_layout = target_data_layout::get(query_config, None, &config.extra_env);
-        let target_dir = config.target_dir.clone().unwrap_or_else(|| dir.join("target").into());
+        let target_dir = config
+            .target_dir
+            .clone()
+            .or_else(|| cargo_config_build_target_dir(detached_file, &config.extra_env, &sysroot))
+            .unwrap_or_else(|| dir.join("target").into());
+
         let loaded_sysroot = sysroot.load_workspace(
             &RustSourceWorkspaceConfig::CargoMetadata(sysroot_metadata_config(
                 config,
@@ -581,10 +636,16 @@ impl ProjectWorkspace {
         match &self.kind {
             ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, _, None)), .. }
             | ProjectWorkspaceKind::Cargo { cargo, error: None, .. } => {
-                WorkspaceBuildScripts::run_for_workspace(config, cargo, progress, &self.sysroot)
-                    .with_context(|| {
-                        format!("Failed to run build scripts for {}", cargo.workspace_root())
-                    })
+                WorkspaceBuildScripts::run_for_workspace(
+                    config,
+                    cargo,
+                    progress,
+                    &self.sysroot,
+                    self.toolchain.as_ref(),
+                )
+                .with_context(|| {
+                    format!("Failed to run build scripts for {}", cargo.workspace_root())
+                })
             }
             _ => Ok(WorkspaceBuildScripts::default()),
         }
@@ -1166,14 +1227,10 @@ fn cargo_to_crate_graph(
     // Mapping of a package to its library target
     let mut pkg_to_lib_crate = FxHashMap::default();
     let mut pkg_crates = FxHashMap::default();
-    // Does any crate signal to rust-analyzer that they need the rustc_private crates?
-    let mut has_private = false;
     let workspace_proc_macro_cwd = Arc::new(cargo.workspace_root().to_path_buf());
 
     // Next, create crates for each package, target pair
     for pkg in cargo.packages() {
-        has_private |= cargo[pkg].metadata.rustc_private;
-
         let cfg_options = {
             let mut cfg_options = cfg_options.clone();
 
@@ -1318,7 +1375,7 @@ fn cargo_to_crate_graph(
         add_dep(crate_graph, from, name, to);
     }
 
-    if has_private {
+    if cargo.requires_rustc_private() {
         // If the user provided a path to rustc sources, we add all the rustc_private crates
         // and create dependencies on them for the crates which opt-in to that
         if let Some((rustc_workspace, rustc_build_scripts)) = rustc {
@@ -1588,7 +1645,7 @@ fn add_target_crate_root(
                     None => Err("proc-macro crate build data is missing dylib path".to_owned()),
                 }
             }
-            None => Err("proc-macro crate is missing its build data".to_owned()),
+            None => Err("build scripts have not been built".to_owned()),
         };
         proc_macros.insert(crate_id, proc_macro);
     }
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml
index 8b03d8f8cc7..5991120a30d 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 proc-macro = true
 
 [dependencies]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index 5e63521d747..b301a7189b3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -13,6 +13,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [[bin]]
 name = "rust-analyzer"
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 05e1b832cd1..e716d140752 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -94,6 +94,8 @@ config_data! {
 
 
 
+        /// Enables highlighting of related return values while the cursor is on any `match`, `if`, or match arm arrow (`=>`).
+        highlightRelated_branchExitPoints_enable: bool = true,
         /// Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords.
         highlightRelated_breakPoints_enable: bool = true,
         /// Enables highlighting of all captures of a closure while the cursor is on the `|` or move keyword of a closure.
@@ -1629,6 +1631,7 @@ impl Config {
             exit_points: self.highlightRelated_exitPoints_enable().to_owned(),
             yield_points: self.highlightRelated_yieldPoints_enable().to_owned(),
             closure_captures: self.highlightRelated_closureCaptures_enable().to_owned(),
+            branch_exit_points: self.highlightRelated_branchExitPoints_enable().to_owned(),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index afd9eff5264..a76a65220d3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -2433,17 +2433,14 @@ fn run_rustfmt(
             }
             _ => {
                 // Something else happened - e.g. `rustfmt` is missing or caught a signal
-                Err(LspError::new(
-                    -32900,
-                    format!(
-                        r#"rustfmt exited with:
-                           Status: {}
-                           stdout: {captured_stdout}
-                           stderr: {captured_stderr}"#,
-                        output.status,
-                    ),
-                )
-                .into())
+                tracing::error!(
+                    ?command,
+                    %output.status,
+                    %captured_stdout,
+                    %captured_stderr,
+                    "rustfmt failed"
+                );
+                Ok(None)
             }
         };
     }
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 4efe330f16a..8a848fb848c 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
@@ -900,14 +900,17 @@ pub(crate) fn folding_range(
         FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
         FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
         FoldKind::Region => Some(lsp_types::FoldingRangeKind::Region),
-        FoldKind::Mods
+        FoldKind::Modules
         | FoldKind::Block
         | FoldKind::ArgList
         | FoldKind::Consts
         | FoldKind::Statics
+        | FoldKind::TypeAliases
         | FoldKind::WhereClause
         | FoldKind::ReturnType
         | FoldKind::Array
+        | FoldKind::TraitAliases
+        | FoldKind::ExternCrates
         | FoldKind::MatchArm => None,
     };
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index 189d95ec7ed..133d5a6cf7a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -428,7 +428,7 @@ impl GlobalState {
                     let expansion_res = match client {
                         Ok(client) => match res {
                             Ok((crate_name, path)) => {
-                                progress(path.to_string());
+                                progress(format!("loading proc-macros: {path}"));
                                 let ignored_proc_macros = ignored_proc_macros
                                     .iter()
                                     .find_map(|(name, macros)| {
diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
index a6d57816608..2c19f00f082 100644
--- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 backtrace = { version = "0.3.75", optional = true }
diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml b/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml
index cccd41d5429..b0fd40ff59f 100644
--- a/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
index 9d3aaa8d4e3..1ee93013e3e 100644
--- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 either.workspace = true
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index c81da06682e..3f439472337 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -669,7 +669,7 @@ TypeBoundList =
 
 TypeBound =
   Lifetime
-| ('~' 'const' | 'const')? 'async'? '?'? Type
+| ('~' 'const' | '[' 'const' ']' | 'const')? 'async'? '?'? Type
 | 'use' UseBoundGenericArgs
 
 UseBoundGenericArgs =
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index 04c7e8a578c..79a9f4da338 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -1766,6 +1766,10 @@ impl TypeBound {
         support::child(&self.syntax)
     }
     #[inline]
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    #[inline]
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+    #[inline]
     pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
     #[inline]
     pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
index ced3b713d8d..4afdda78a0e 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
@@ -1,9 +1,11 @@
 //! There are many AstNodes, but only a few tokens, so we hand-write them here.
 
+use std::ops::Range;
 use std::{borrow::Cow, num::ParseIntError};
 
 use rustc_literal_escaper::{
-    EscapeError, MixedUnit, Mode, unescape_byte, unescape_char, unescape_mixed, unescape_unicode,
+    EscapeError, MixedUnit, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char,
+    unescape_str,
 };
 use stdx::always;
 
@@ -150,7 +152,7 @@ impl QuoteOffsets {
 
 pub trait IsString: AstToken {
     const RAW_PREFIX: &'static str;
-    const MODE: Mode;
+    fn unescape(s: &str, callback: impl FnMut(Range<usize>, Result<char, EscapeError>));
     fn is_raw(&self) -> bool {
         self.text().starts_with(Self::RAW_PREFIX)
     }
@@ -185,7 +187,7 @@ pub trait IsString: AstToken {
         let text = &self.text()[text_range_no_quotes - start];
         let offset = text_range_no_quotes.start() - start;
 
-        unescape_unicode(text, Self::MODE, &mut |range, unescaped_char| {
+        Self::unescape(text, &mut |range: Range<usize>, unescaped_char| {
             if let Some((s, e)) = range.start.try_into().ok().zip(range.end.try_into().ok()) {
                 cb(TextRange::new(s, e) + offset, unescaped_char);
             }
@@ -203,7 +205,9 @@ pub trait IsString: AstToken {
 
 impl IsString for ast::String {
     const RAW_PREFIX: &'static str = "r";
-    const MODE: Mode = Mode::Str;
+    fn unescape(s: &str, cb: impl FnMut(Range<usize>, Result<char, EscapeError>)) {
+        unescape_str(s, cb)
+    }
 }
 
 impl ast::String {
@@ -218,20 +222,19 @@ impl ast::String {
         let mut buf = String::new();
         let mut prev_end = 0;
         let mut has_error = None;
-        unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match (
-            unescaped_char,
-            buf.capacity() == 0,
-        ) {
-            (Ok(c), false) => buf.push(c),
-            (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
-                prev_end = char_range.end
-            }
-            (Ok(c), true) => {
-                buf.reserve_exact(text.len());
-                buf.push_str(&text[..prev_end]);
-                buf.push(c);
+        unescape_str(text, |char_range, unescaped_char| {
+            match (unescaped_char, buf.capacity() == 0) {
+                (Ok(c), false) => buf.push(c),
+                (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
+                    prev_end = char_range.end
+                }
+                (Ok(c), true) => {
+                    buf.reserve_exact(text.len());
+                    buf.push_str(&text[..prev_end]);
+                    buf.push(c);
+                }
+                (Err(e), _) => has_error = Some(e),
             }
-            (Err(e), _) => has_error = Some(e),
         });
 
         match (has_error, buf.capacity() == 0) {
@@ -244,7 +247,9 @@ impl ast::String {
 
 impl IsString for ast::ByteString {
     const RAW_PREFIX: &'static str = "br";
-    const MODE: Mode = Mode::ByteStr;
+    fn unescape(s: &str, mut callback: impl FnMut(Range<usize>, Result<char, EscapeError>)) {
+        unescape_byte_str(s, |range, res| callback(range, res.map(char::from)))
+    }
 }
 
 impl ast::ByteString {
@@ -259,20 +264,19 @@ impl ast::ByteString {
         let mut buf: Vec<u8> = Vec::new();
         let mut prev_end = 0;
         let mut has_error = None;
-        unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match (
-            unescaped_char,
-            buf.capacity() == 0,
-        ) {
-            (Ok(c), false) => buf.push(c as u8),
-            (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
-                prev_end = char_range.end
-            }
-            (Ok(c), true) => {
-                buf.reserve_exact(text.len());
-                buf.extend_from_slice(&text.as_bytes()[..prev_end]);
-                buf.push(c as u8);
+        unescape_byte_str(text, |char_range, unescaped_byte| {
+            match (unescaped_byte, buf.capacity() == 0) {
+                (Ok(b), false) => buf.push(b),
+                (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
+                    prev_end = char_range.end
+                }
+                (Ok(b), true) => {
+                    buf.reserve_exact(text.len());
+                    buf.extend_from_slice(&text.as_bytes()[..prev_end]);
+                    buf.push(b);
+                }
+                (Err(e), _) => has_error = Some(e),
             }
-            (Err(e), _) => has_error = Some(e),
         });
 
         match (has_error, buf.capacity() == 0) {
@@ -285,25 +289,10 @@ impl ast::ByteString {
 
 impl IsString for ast::CString {
     const RAW_PREFIX: &'static str = "cr";
-    const MODE: Mode = Mode::CStr;
-
-    fn escaped_char_ranges(&self, cb: &mut dyn FnMut(TextRange, Result<char, EscapeError>)) {
-        let text_range_no_quotes = match self.text_range_between_quotes() {
-            Some(it) => it,
-            None => return,
-        };
-
-        let start = self.syntax().text_range().start();
-        let text = &self.text()[text_range_no_quotes - start];
-        let offset = text_range_no_quotes.start() - start;
-
-        unescape_mixed(text, Self::MODE, &mut |range, unescaped_char| {
-            let text_range =
-                TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
-            // XXX: This method should only be used for highlighting ranges. The unescaped
-            // char/byte is not used. For simplicity, we return an arbitrary placeholder char.
-            cb(text_range + offset, unescaped_char.map(|_| ' '));
-        });
+    // NOTE: This method should only be used for highlighting ranges. The unescaped
+    // char/byte is not used. For simplicity, we return an arbitrary placeholder char.
+    fn unescape(s: &str, mut callback: impl FnMut(Range<usize>, Result<char, EscapeError>)) {
+        unescape_c_str(s, |range, _res| callback(range, Ok('_')))
     }
 }
 
@@ -323,10 +312,7 @@ impl ast::CString {
             MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()),
             MixedUnit::HighByte(b) => buf.push(b),
         };
-        unescape_mixed(text, Self::MODE, &mut |char_range, unescaped| match (
-            unescaped,
-            buf.capacity() == 0,
-        ) {
+        unescape_c_str(text, |char_range, unescaped| match (unescaped, buf.capacity() == 0) {
             (Ok(u), false) => extend_unit(&mut buf, u),
             (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
                 prev_end = char_range.end
diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
index 5bfeb3bff87..4180f9cd185 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
@@ -6,7 +6,9 @@ mod block;
 
 use itertools::Itertools;
 use rowan::Direction;
-use rustc_literal_escaper::{self, EscapeError, Mode, unescape_mixed, unescape_unicode};
+use rustc_literal_escaper::{
+    EscapeError, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str,
+};
 
 use crate::{
     AstNode, SyntaxError,
@@ -47,7 +49,7 @@ pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec<SyntaxError>) {
 }
 
 fn rustc_unescape_error_to_string(err: EscapeError) -> (&'static str, bool) {
-    use rustc_literal_escaper::EscapeError as EE;
+    use EscapeError as EE;
 
     #[rustfmt::skip]
     let err_message = match err {
@@ -142,7 +144,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         ast::LiteralKind::String(s) => {
             if !s.is_raw() {
                 if let Some(without_quotes) = unquote(text, 1, '"') {
-                    unescape_unicode(without_quotes, Mode::Str, &mut |range, char| {
+                    unescape_str(without_quotes, |range, char| {
                         if let Err(err) = char {
                             push_err(1, range.start, err);
                         }
@@ -153,7 +155,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         ast::LiteralKind::ByteString(s) => {
             if !s.is_raw() {
                 if let Some(without_quotes) = unquote(text, 2, '"') {
-                    unescape_unicode(without_quotes, Mode::ByteStr, &mut |range, char| {
+                    unescape_byte_str(without_quotes, |range, char| {
                         if let Err(err) = char {
                             push_err(1, range.start, err);
                         }
@@ -164,7 +166,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         ast::LiteralKind::CString(s) => {
             if !s.is_raw() {
                 if let Some(without_quotes) = unquote(text, 2, '"') {
-                    unescape_mixed(without_quotes, Mode::CStr, &mut |range, char| {
+                    unescape_c_str(without_quotes, |range, char| {
                         if let Err(err) = char {
                             push_err(1, range.start, err);
                         }
@@ -174,20 +176,16 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         }
         ast::LiteralKind::Char(_) => {
             if let Some(without_quotes) = unquote(text, 1, '\'') {
-                unescape_unicode(without_quotes, Mode::Char, &mut |range, char| {
-                    if let Err(err) = char {
-                        push_err(1, range.start, err);
-                    }
-                });
+                if let Err(err) = unescape_char(without_quotes) {
+                    push_err(1, 0, err);
+                }
             }
         }
         ast::LiteralKind::Byte(_) => {
             if let Some(without_quotes) = unquote(text, 2, '\'') {
-                unescape_unicode(without_quotes, Mode::Byte, &mut |range, char| {
-                    if let Err(err) = char {
-                        push_err(2, range.start, err);
-                    }
-                });
+                if let Err(err) = unescape_byte(without_quotes) {
+                    push_err(2, 0, err);
+                }
             }
         }
         ast::LiteralKind::IntNumber(_)
diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
index c27e850ce7f..6d1930aa268 100644
--- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 # Avoid adding deps here, this crate is widely used in tests it should compile fast!
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index d13a81d287f..d48063fb86f 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -26,7 +26,7 @@
 //!     deref: sized
 //!     derive:
 //!     discriminant:
-//!     drop:
+//!     drop: sized
 //!     env: option
 //!     eq: sized
 //!     error: fmt
@@ -37,7 +37,7 @@
 //!     future: pin
 //!     coroutine: pin
 //!     dispatch_from_dyn: unsize, pin
-//!     hash:
+//!     hash: sized
 //!     include:
 //!     index: sized
 //!     infallible:
@@ -77,33 +77,46 @@
 
 pub mod marker {
     // region:sized
+    #[lang = "pointee_sized"]
+    #[fundamental]
+    #[rustc_specialization_trait]
+    #[rustc_coinductive]
+    pub trait PointeeSized {}
+
+    #[lang = "meta_sized"]
+    #[fundamental]
+    #[rustc_specialization_trait]
+    #[rustc_coinductive]
+    pub trait MetaSized: PointeeSized {}
+
     #[lang = "sized"]
     #[fundamental]
     #[rustc_specialization_trait]
-    pub trait Sized {}
+    #[rustc_coinductive]
+    pub trait Sized: MetaSized {}
     // endregion:sized
 
     // region:send
     pub unsafe auto trait Send {}
 
-    impl<T: ?Sized> !Send for *const T {}
-    impl<T: ?Sized> !Send for *mut T {}
+    impl<T: PointeeSized> !Send for *const T {}
+    impl<T: PointeeSized> !Send for *mut T {}
     // region:sync
-    unsafe impl<T: Sync + ?Sized> Send for &T {}
-    unsafe impl<T: Send + ?Sized> Send for &mut T {}
+    unsafe impl<T: Sync + PointeeSized> Send for &T {}
+    unsafe impl<T: Send + PointeeSized> Send for &mut T {}
     // endregion:sync
     // endregion:send
 
     // region:sync
     pub unsafe auto trait Sync {}
 
-    impl<T: ?Sized> !Sync for *const T {}
-    impl<T: ?Sized> !Sync for *mut T {}
+    impl<T: PointeeSized> !Sync for *const T {}
+    impl<T: PointeeSized> !Sync for *mut T {}
     // endregion:sync
 
     // region:unsize
     #[lang = "unsize"]
-    pub trait Unsize<T: ?Sized> {}
+    pub trait Unsize<T: PointeeSized>: PointeeSized {}
     // endregion:unsize
 
     // region:unpin
@@ -120,7 +133,7 @@ pub mod marker {
     // endregion:derive
 
     mod copy_impls {
-        use super::Copy;
+        use super::{Copy, PointeeSized};
 
         macro_rules! impl_copy {
             ($($t:ty)*) => {
@@ -137,9 +150,9 @@ pub mod marker {
             bool char
         }
 
-        impl<T: ?Sized> Copy for *const T {}
-        impl<T: ?Sized> Copy for *mut T {}
-        impl<T: ?Sized> Copy for &T {}
+        impl<T: PointeeSized> Copy for *const T {}
+        impl<T: PointeeSized> Copy for *mut T {}
+        impl<T: PointeeSized> Copy for &T {}
         impl Copy for ! {}
     }
     // endregion:copy
@@ -151,7 +164,7 @@ pub mod marker {
 
     // region:phantom_data
     #[lang = "phantom_data"]
-    pub struct PhantomData<T: ?Sized>;
+    pub struct PhantomData<T: PointeeSized>;
     // endregion:phantom_data
 
     // region:discriminant
@@ -206,9 +219,11 @@ pub mod default {
 
 // region:hash
 pub mod hash {
+    use crate::marker::PointeeSized;
+
     pub trait Hasher {}
 
-    pub trait Hash {
+    pub trait Hash: PointeeSized {
         fn hash<H: Hasher>(&self, state: &mut H);
     }
 
@@ -221,10 +236,11 @@ pub mod hash {
 
 // region:cell
 pub mod cell {
+    use crate::marker::PointeeSized;
     use crate::mem;
 
     #[lang = "unsafe_cell"]
-    pub struct UnsafeCell<T: ?Sized> {
+    pub struct UnsafeCell<T: PointeeSized> {
         value: T,
     }
 
@@ -238,7 +254,7 @@ pub mod cell {
         }
     }
 
-    pub struct Cell<T: ?Sized> {
+    pub struct Cell<T: PointeeSized> {
         value: UnsafeCell<T>,
     }
 
@@ -357,7 +373,7 @@ pub mod convert {
     // endregion:from
 
     // region:as_ref
-    pub trait AsRef<T: ?Sized> {
+    pub trait AsRef<T: crate::marker::PointeeSized>: crate::marker::PointeeSized {
         fn as_ref(&self) -> &T;
     }
     // endregion:as_ref
@@ -368,9 +384,11 @@ pub mod convert {
 
 pub mod mem {
     // region:manually_drop
+    use crate::marker::PointeeSized;
+
     #[lang = "manually_drop"]
     #[repr(transparent)]
-    pub struct ManuallyDrop<T: ?Sized> {
+    pub struct ManuallyDrop<T: PointeeSized> {
         value: T,
     }
 
@@ -381,7 +399,7 @@ pub mod mem {
     }
 
     // region:deref
-    impl<T: ?Sized> crate::ops::Deref for ManuallyDrop<T> {
+    impl<T: PointeeSized> crate::ops::Deref for ManuallyDrop<T> {
         type Target = T;
         fn deref(&self) -> &T {
             &self.value
@@ -428,7 +446,7 @@ pub mod mem {
 pub mod ptr {
     // region:drop
     #[lang = "drop_in_place"]
-    pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+    pub unsafe fn drop_in_place<T: crate::marker::PointeeSized>(to_drop: *mut T) {
         unsafe { drop_in_place(to_drop) }
     }
     pub const unsafe fn read<T>(src: *const T) -> T {
@@ -444,7 +462,7 @@ pub mod ptr {
     // region:pointee
     #[lang = "pointee_trait"]
     #[rustc_deny_explicit_impl(implement_via_object = false)]
-    pub trait Pointee {
+    pub trait Pointee: crate::marker::PointeeSized {
         #[lang = "metadata_type"]
         type Metadata: Copy + Send + Sync + Ord + Hash + Unpin;
     }
@@ -452,12 +470,14 @@ pub mod ptr {
     // region:non_null
     #[rustc_layout_scalar_valid_range_start(1)]
     #[rustc_nonnull_optimization_guaranteed]
-    pub struct NonNull<T: ?Sized> {
+    pub struct NonNull<T: crate::marker::PointeeSized> {
         pointer: *const T,
     }
     // region:coerce_unsized
-    impl<T: ?Sized, U: ?Sized> crate::ops::CoerceUnsized<NonNull<U>> for NonNull<T> where
-        T: crate::marker::Unsize<U>
+    impl<T: crate::marker::PointeeSized, U: crate::marker::PointeeSized>
+        crate::ops::CoerceUnsized<NonNull<U>> for NonNull<T>
+    where
+        T: crate::marker::Unsize<U>,
     {
     }
     // endregion:coerce_unsized
@@ -478,42 +498,44 @@ pub mod ptr {
 pub mod ops {
     // region:coerce_unsized
     mod unsize {
-        use crate::marker::Unsize;
+        use crate::marker::{PointeeSized, Unsize};
 
         #[lang = "coerce_unsized"]
-        pub trait CoerceUnsized<T: ?Sized> {}
+        pub trait CoerceUnsized<T> {}
 
-        impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {}
-        impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b mut T {}
-        impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for &'a mut T {}
-        impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a mut T {}
+        impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T {}
+        impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b mut T {}
+        impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {}
+        impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T {}
 
-        impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
-        impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for &'a T {}
+        impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {}
+        impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for &'a T {}
 
-        impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
-        impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *mut T {}
-        impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*const U> for *const T {}
+        impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {}
+        impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *mut T {}
+        impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *const T {}
     }
     pub use self::unsize::CoerceUnsized;
     // endregion:coerce_unsized
 
     // region:deref
     mod deref {
+        use crate::marker::PointeeSized;
+
         #[lang = "deref"]
-        pub trait Deref {
+        pub trait Deref: PointeeSized {
             #[lang = "deref_target"]
             type Target: ?Sized;
             fn deref(&self) -> &Self::Target;
         }
 
-        impl<T: ?Sized> Deref for &T {
+        impl<T: PointeeSized> Deref for &T {
             type Target = T;
             fn deref(&self) -> &T {
                 loop {}
             }
         }
-        impl<T: ?Sized> Deref for &mut T {
+        impl<T: PointeeSized> Deref for &mut T {
             type Target = T;
             fn deref(&self) -> &T {
                 loop {}
@@ -521,19 +543,19 @@ pub mod ops {
         }
         // region:deref_mut
         #[lang = "deref_mut"]
-        pub trait DerefMut: Deref {
+        pub trait DerefMut: Deref + PointeeSized {
             fn deref_mut(&mut self) -> &mut Self::Target;
         }
         // endregion:deref_mut
 
         // region:receiver
         #[lang = "receiver"]
-        pub trait Receiver {
+        pub trait Receiver: PointeeSized {
             #[lang = "receiver_target"]
             type Target: ?Sized;
         }
 
-        impl<P: ?Sized, T: ?Sized> Receiver for P
+        impl<P: PointeeSized, T: PointeeSized> Receiver for P
         where
             P: Deref<Target = T>,
         {
@@ -686,7 +708,7 @@ pub mod ops {
             #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
             impl<A: Tuple, F: ?Sized> const Fn<A> for &F
             where
-                F: ~const Fn<A>,
+                F: [const] Fn<A>,
             {
                 extern "rust-call" fn call(&self, args: A) -> F::Output {
                     (**self).call(args)
@@ -697,7 +719,7 @@ pub mod ops {
             #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
             impl<A: Tuple, F: ?Sized> const FnMut<A> for &F
             where
-                F: ~const Fn<A>,
+                F: [const] Fn<A>,
             {
                 extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
                     (**self).call(args)
@@ -708,7 +730,7 @@ pub mod ops {
             #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
             impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F
             where
-                F: ~const Fn<A>,
+                F: [const] Fn<A>,
             {
                 type Output = F::Output;
 
@@ -721,7 +743,7 @@ pub mod ops {
             #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
             impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F
             where
-                F: ~const FnMut<A>,
+                F: [const] FnMut<A>,
             {
                 extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
                     (*self).call_mut(args)
@@ -732,7 +754,7 @@ pub mod ops {
             #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
             impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F
             where
-                F: ~const FnMut<A>,
+                F: [const] FnMut<A>,
             {
                 type Output = F::Output;
                 extern "rust-call" fn call_once(self, args: A) -> F::Output {
@@ -1006,18 +1028,18 @@ pub mod ops {
 
     // region:dispatch_from_dyn
     mod dispatch_from_dyn {
-        use crate::marker::Unsize;
+        use crate::marker::{PointeeSized, Unsize};
 
         #[lang = "dispatch_from_dyn"]
         pub trait DispatchFromDyn<T> {}
 
-        impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
+        impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {}
 
-        impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {}
+        impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a mut U> for &'a mut T {}
 
-        impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
+        impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*const U> for *const T {}
 
-        impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
+        impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T {}
     }
     pub use self::dispatch_from_dyn::DispatchFromDyn;
     // endregion:dispatch_from_dyn
@@ -1025,15 +1047,17 @@ pub mod ops {
 
 // region:eq
 pub mod cmp {
+    use crate::marker::PointeeSized;
+
     #[lang = "eq"]
-    pub trait PartialEq<Rhs: ?Sized = Self> {
+    pub trait PartialEq<Rhs: PointeeSized = Self>: PointeeSized {
         fn eq(&self, other: &Rhs) -> bool;
         fn ne(&self, other: &Rhs) -> bool {
             !self.eq(other)
         }
     }
 
-    pub trait Eq: PartialEq<Self> {}
+    pub trait Eq: PartialEq<Self> + PointeeSized {}
 
     // region:derive
     #[rustc_builtin_macro]
@@ -1044,11 +1068,11 @@ pub mod cmp {
 
     // region:ord
     #[lang = "partial_ord"]
-    pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
+    pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
         fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
     }
 
-    pub trait Ord: Eq + PartialOrd<Self> {
+    pub trait Ord: Eq + PartialOrd<Self> + PointeeSized {
         fn cmp(&self, other: &Self) -> Ordering;
     }
 
@@ -1071,6 +1095,8 @@ pub mod cmp {
 
 // region:fmt
 pub mod fmt {
+    use crate::marker::PointeeSized;
+
     pub struct Error;
     pub type Result = crate::result::Result<(), Error>;
     pub struct Formatter<'a>;
@@ -1106,10 +1132,10 @@ pub mod fmt {
         }
     }
 
-    pub trait Debug {
+    pub trait Debug: PointeeSized {
         fn fmt(&self, f: &mut Formatter<'_>) -> Result;
     }
-    pub trait Display {
+    pub trait Display: PointeeSized {
         fn fmt(&self, f: &mut Formatter<'_>) -> Result;
     }
 
@@ -1268,7 +1294,7 @@ pub mod fmt {
         }
     }
 
-    impl<T: Debug + ?Sized> Debug for &T {
+    impl<T: Debug + PointeeSized> Debug for &T {
         fn fmt(&self, f: &mut Formatter<'_>) -> Result {
             (&**self).fmt(f)
         }
@@ -1512,6 +1538,8 @@ pub mod iter {
 
     mod traits {
         mod iterator {
+            use crate::marker::PointeeSized;
+
             #[doc(notable_trait)]
             #[lang = "iterator"]
             pub trait Iterator {
@@ -1543,7 +1571,7 @@ pub mod iter {
                 }
                 // endregion:iterators
             }
-            impl<I: Iterator + ?Sized> Iterator for &mut I {
+            impl<I: Iterator + PointeeSized> Iterator for &mut I {
                 type Item = I::Item;
                 fn next(&mut self) -> Option<I::Item> {
                     (**self).next()
diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
index 315a3a2890f..f561c1c0e2b 100644
--- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 home = "0.5.11"
diff --git a/src/tools/rust-analyzer/crates/tt/Cargo.toml b/src/tools/rust-analyzer/crates/tt/Cargo.toml
index 529fad3244a..82e7c24668f 100644
--- a/src/tools/rust-analyzer/crates/tt/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/tt/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 arrayvec.workspace = true
diff --git a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
index 9b32ee17abc..bd6c8331e66 100644
--- a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 tracing.workspace = true
diff --git a/src/tools/rust-analyzer/crates/vfs/Cargo.toml b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
index 546195481c6..e8a6195036e 100644
--- a/src/tools/rust-analyzer/crates/vfs/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
+doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/docs/book/src/SUMMARY.md b/src/tools/rust-analyzer/docs/book/src/SUMMARY.md
index 1f211a97d78..dffdae94a6e 100644
--- a/src/tools/rust-analyzer/docs/book/src/SUMMARY.md
+++ b/src/tools/rust-analyzer/docs/book/src/SUMMARY.md
@@ -6,6 +6,7 @@
   - [rust-analyzer Binary](rust_analyzer_binary.md)
   - [Other Editors](other_editors.md)
 - [Troubleshooting](troubleshooting.md)
+  - [FAQ](faq.md)
 - [Configuration](configuration.md)
   - [Non-Cargo Based Projects](non_cargo_based_projects.md)
 - [Security](security.md)
diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
index 9404b1454a0..ebac26e1d60 100644
--- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
+++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
@@ -612,6 +612,13 @@ Default: `"client"`
 Controls file watching implementation.
 
 
+## rust-analyzer.highlightRelated.branchExitPoints.enable {#highlightRelated.branchExitPoints.enable}
+
+Default: `true`
+
+Enables highlighting of related return values while the cursor is on any `match`, `if`, or match arm arrow (`=>`).
+
+
 ## rust-analyzer.highlightRelated.breakPoints.enable {#highlightRelated.breakPoints.enable}
 
 Default: `true`
diff --git a/src/tools/rust-analyzer/docs/book/src/faq.md b/src/tools/rust-analyzer/docs/book/src/faq.md
new file mode 100644
index 00000000000..c8720330901
--- /dev/null
+++ b/src/tools/rust-analyzer/docs/book/src/faq.md
@@ -0,0 +1,7 @@
+# Troubleshooting FAQ
+
+### I see a warning "Variable `None` should have snake_case name, e.g. `none`"
+
+rust-analyzer fails to resolve `None`, and thinks you are binding to a variable
+named `None`. That's usually a sign of a corrupted sysroot. Try removing and re-installing
+it: `rustup component remove rust-src` then `rustup component install rust-src`.
diff --git a/src/tools/rust-analyzer/docs/book/src/non_cargo_based_projects.md b/src/tools/rust-analyzer/docs/book/src/non_cargo_based_projects.md
index bbdb48bbbc9..befb631ec03 100644
--- a/src/tools/rust-analyzer/docs/book/src/non_cargo_based_projects.md
+++ b/src/tools/rust-analyzer/docs/book/src/non_cargo_based_projects.md
@@ -40,6 +40,9 @@ interface ProjectJson {
     /// several different "sysroots" in one graph of
     /// crates.
     sysroot_src?: string;
+    /// A ProjectJson describing the crates of the sysroot.
+    sysroot_project?: ProjectJson;
+
     /// List of groups of common cfg values, to allow
     /// sharing them between crates.
     ///
diff --git a/src/tools/rust-analyzer/docs/book/src/troubleshooting.md b/src/tools/rust-analyzer/docs/book/src/troubleshooting.md
index 1b2841421a4..a357cbef415 100644
--- a/src/tools/rust-analyzer/docs/book/src/troubleshooting.md
+++ b/src/tools/rust-analyzer/docs/book/src/troubleshooting.md
@@ -1,5 +1,8 @@
 # Troubleshooting
 
+First, search the [troubleshooting FAQ](faq.html). If your problem appears
+there (and the proposed solution works for you), great! Otherwise, read on.
+
 Start with looking at the rust-analyzer version. Try **rust-analyzer:
 Show RA Version** in VS Code (using **Command Palette** feature
 typically activated by Ctrl+Shift+P) or `rust-analyzer --version` in the
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 26a21c1468d..3cb4c21ee1f 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -1532,6 +1532,16 @@
             {
                 "title": "highlightRelated",
                 "properties": {
+                    "rust-analyzer.highlightRelated.branchExitPoints.enable": {
+                        "markdownDescription": "Enables highlighting of related return values while the cursor is on any `match`, `if`, or match arm arrow (`=>`).",
+                        "default": true,
+                        "type": "boolean"
+                    }
+                }
+            },
+            {
+                "title": "highlightRelated",
+                "properties": {
                     "rust-analyzer.highlightRelated.breakPoints.enable": {
                         "markdownDescription": "Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords.",
                         "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 cdeea7333a6..073ff2f4703 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -3,7 +3,7 @@ import * as lc from "vscode-languageclient/node";
 import * as vscode from "vscode";
 import * as ra from "../src/lsp_ext";
 import * as Is from "vscode-languageclient/lib/common/utils/is";
-import { assert, unwrapUndefinable } from "./util";
+import { assert } from "./util";
 import * as diagnostics from "./diagnostics";
 import { WorkspaceEdit } from "vscode";
 import { type Config, prepareVSCodeConfig } from "./config";
@@ -188,11 +188,17 @@ export async function createClient(
                 context: await client.code2ProtocolConverter.asCodeActionContext(context, token),
             };
             const callback = async (
-                values: (lc.Command | lc.CodeAction)[] | null,
+                values: (lc.Command | lc.CodeAction | object)[] | null,
             ): Promise<(vscode.Command | vscode.CodeAction)[] | undefined> => {
                 if (values === null) return undefined;
                 const result: (vscode.CodeAction | vscode.Command)[] = [];
-                const groups = new Map<string, { index: number; items: vscode.CodeAction[] }>();
+                const groups = new Map<
+                    string,
+                    {
+                        primary: vscode.CodeAction;
+                        items: { label: string; arguments: lc.CodeAction }[];
+                    }
+                >();
                 for (const item of values) {
                     // In our case we expect to get code edits only from diagnostics
                     if (lc.CodeAction.is(item)) {
@@ -204,62 +210,55 @@ export async function createClient(
                         result.push(action);
                         continue;
                     }
-                    assert(
-                        isCodeActionWithoutEditsAndCommands(item),
-                        "We don't expect edits or commands here",
-                    );
-                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-                    const kind = client.protocol2CodeConverter.asCodeActionKind((item as any).kind);
-                    const action = new vscode.CodeAction(item.title, kind);
-                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-                    const group = (item as any).group;
-                    action.command = {
-                        command: "rust-analyzer.resolveCodeAction",
-                        title: item.title,
-                        arguments: [item],
-                    };
+                    assertIsCodeActionWithoutEditsAndCommands(item);
+                    const kind = client.protocol2CodeConverter.asCodeActionKind(item.kind);
+                    const group = item.group;
 
-                    // Set a dummy edit, so that VS Code doesn't try to resolve this.
-                    action.edit = new WorkspaceEdit();
+                    const mkAction = () => {
+                        const action = new vscode.CodeAction(item.title, kind);
+                        action.command = {
+                            command: "rust-analyzer.resolveCodeAction",
+                            title: item.title,
+                            arguments: [item],
+                        };
+                        // Set a dummy edit, so that VS Code doesn't try to resolve this.
+                        action.edit = new WorkspaceEdit();
+                        return action;
+                    };
 
                     if (group) {
                         let entry = groups.get(group);
                         if (!entry) {
-                            entry = { index: result.length, items: [] };
+                            entry = { primary: mkAction(), items: [] };
                             groups.set(group, entry);
-                            result.push(action);
+                        } else {
+                            entry.items.push({
+                                label: item.title,
+                                arguments: item,
+                            });
                         }
-                        entry.items.push(action);
                     } else {
-                        result.push(action);
+                        result.push(mkAction());
                     }
                 }
-                for (const [group, { index, items }] of groups) {
-                    if (items.length === 1) {
-                        const item = unwrapUndefinable(items[0]);
-                        result[index] = item;
-                    } else {
-                        const action = new vscode.CodeAction(group);
-                        const item = unwrapUndefinable(items[0]);
-                        action.kind = item.kind;
-                        action.command = {
+                for (const [group, { items, primary }] of groups) {
+                    // This group contains more than one item, so rewrite it to be a group action
+                    if (items.length !== 0) {
+                        const args = [
+                            {
+                                label: primary.title,
+                                arguments: primary.command!.arguments![0],
+                            },
+                            ...items,
+                        ];
+                        primary.title = group;
+                        primary.command = {
                             command: "rust-analyzer.applyActionGroup",
                             title: "",
-                            arguments: [
-                                items.map((item) => {
-                                    return {
-                                        label: item.title,
-                                        arguments: item.command!.arguments![0],
-                                    };
-                                }),
-                            ],
+                            arguments: [args],
                         };
-
-                        // Set a dummy edit, so that VS Code doesn't try to resolve this.
-                        action.edit = new WorkspaceEdit();
-
-                        result[index] = action;
                     }
+                    result.push(primary);
                 }
                 return result;
             };
@@ -363,17 +362,22 @@ class OverrideFeatures implements lc.StaticFeature {
     clear(): void {}
 }
 
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function isCodeActionWithoutEditsAndCommands(value: any): boolean {
-    const candidate: lc.CodeAction = value;
-    return (
+function assertIsCodeActionWithoutEditsAndCommands(
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    candidate: any,
+): asserts candidate is lc.CodeAction & {
+    group?: string;
+} {
+    assert(
         candidate &&
-        Is.string(candidate.title) &&
-        (candidate.diagnostics === void 0 ||
-            Is.typedArray(candidate.diagnostics, lc.Diagnostic.is)) &&
-        (candidate.kind === void 0 || Is.string(candidate.kind)) &&
-        candidate.edit === void 0 &&
-        candidate.command === void 0
+            Is.string(candidate.title) &&
+            (candidate.diagnostics === undefined ||
+                Is.typedArray(candidate.diagnostics, lc.Diagnostic.is)) &&
+            (candidate.group === undefined || Is.string(candidate.group)) &&
+            (candidate.kind === undefined || Is.string(candidate.kind)) &&
+            candidate.edit === undefined &&
+            candidate.command === undefined,
+        `Expected a CodeAction without edits or commands, got: ${JSON.stringify(candidate)}`,
     );
 }
 
diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts
index 3ac1a933d9e..25b30013fa1 100644
--- a/src/tools/rust-analyzer/editors/code/src/commands.ts
+++ b/src/tools/rust-analyzer/editors/code/src/commands.ts
@@ -1114,11 +1114,11 @@ export function applySnippetWorkspaceEditCommand(_ctx: CtxInit): Cmd {
     };
 }
 
-export function run(ctx: CtxInit): Cmd {
+export function run(ctx: CtxInit, mode?: "cursor"): Cmd {
     let prevRunnable: RunnableQuickPick | undefined;
 
     return async () => {
-        const item = await selectRunnable(ctx, prevRunnable);
+        const item = await selectRunnable(ctx, prevRunnable, false, true, mode);
         if (!item) return;
 
         item.detail = "rerun";
diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts
index 5e500730693..996298524f1 100644
--- a/src/tools/rust-analyzer/editors/code/src/main.ts
+++ b/src/tools/rust-analyzer/editors/code/src/main.ts
@@ -167,7 +167,7 @@ function createCommands(): Record<string, CommandFactory> {
         viewCrateGraph: { enabled: commands.viewCrateGraph },
         viewFullCrateGraph: { enabled: commands.viewFullCrateGraph },
         expandMacro: { enabled: commands.expandMacro },
-        run: { enabled: commands.run },
+        run: { enabled: (ctx) => (mode?: "cursor") => commands.run(ctx, mode)() },
         copyRunCommandLine: { enabled: commands.copyRunCommandLine },
         debug: { enabled: commands.debug },
         newDebugConfig: { enabled: commands.newDebugConfig },
diff --git a/src/tools/rust-analyzer/editors/code/src/run.ts b/src/tools/rust-analyzer/editors/code/src/run.ts
index 40027cc7c85..95166c427b2 100644
--- a/src/tools/rust-analyzer/editors/code/src/run.ts
+++ b/src/tools/rust-analyzer/editors/code/src/run.ts
@@ -18,10 +18,15 @@ export async function selectRunnable(
     prevRunnable?: RunnableQuickPick,
     debuggeeOnly = false,
     showButtons: boolean = true,
+    mode?: "cursor",
 ): Promise<RunnableQuickPick | undefined> {
     const editor = ctx.activeRustEditor ?? ctx.activeCargoTomlEditor;
     if (!editor) return;
 
+    if (mode === "cursor") {
+        return selectRunnableAtCursor(ctx, editor, prevRunnable);
+    }
+
     // show a placeholder while we get the runnables from the server
     const quickPick = vscode.window.createQuickPick();
     quickPick.title = "Select Runnable";
@@ -54,6 +59,58 @@ export async function selectRunnable(
     );
 }
 
+async function selectRunnableAtCursor(
+    ctx: CtxInit,
+    editor: RustEditor,
+    prevRunnable?: RunnableQuickPick,
+): Promise<RunnableQuickPick | undefined> {
+    const runnableQuickPicks = await getRunnables(ctx.client, editor, prevRunnable, false);
+    let runnableQuickPickAtCursor = null;
+    const cursorPosition = ctx.client.code2ProtocolConverter.asPosition(editor.selection.active);
+    for (const runnableQuickPick of runnableQuickPicks) {
+        if (!runnableQuickPick.runnable.location?.targetRange) {
+            continue;
+        }
+        const runnableQuickPickRange = runnableQuickPick.runnable.location.targetRange;
+        if (
+            runnableQuickPickAtCursor?.runnable?.location?.targetRange != null &&
+            rangeContainsOtherRange(
+                runnableQuickPickRange,
+                runnableQuickPickAtCursor.runnable.location.targetRange,
+            )
+        ) {
+            continue;
+        }
+        if (rangeContainsPosition(runnableQuickPickRange, cursorPosition)) {
+            runnableQuickPickAtCursor = runnableQuickPick;
+        }
+    }
+    if (runnableQuickPickAtCursor == null) {
+        return;
+    }
+    return Promise.resolve(runnableQuickPickAtCursor);
+}
+
+function rangeContainsPosition(range: lc.Range, position: lc.Position): boolean {
+    return (
+        (position.line > range.start.line ||
+            (position.line === range.start.line && position.character >= range.start.character)) &&
+        (position.line < range.end.line ||
+            (position.line === range.end.line && position.character <= range.end.character))
+    );
+}
+
+function rangeContainsOtherRange(range: lc.Range, otherRange: lc.Range) {
+    return (
+        (range.start.line < otherRange.start.line ||
+            (range.start.line === otherRange.start.line &&
+                range.start.character <= otherRange.start.character)) &&
+        (range.end.line > otherRange.end.line ||
+            (range.end.line === otherRange.end.line &&
+                range.end.character >= otherRange.end.character))
+    );
+}
+
 export class RunnableQuickPick implements vscode.QuickPickItem {
     public label: string;
     public description?: string | undefined;
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index a454087b0cd..902793225ea 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-27733d46d79f4eb92e240fbba502c43022665735
+ad3b7257615c28aaf8212a189ec032b8af75de51
diff --git a/tests/ui/stats/macro-stats.rs b/tests/ui/stats/macro-stats.rs
index ee265d682fd..d986904ddd6 100644
--- a/tests/ui/stats/macro-stats.rs
+++ b/tests/ui/stats/macro-stats.rs
@@ -49,12 +49,17 @@ fn opt(x: Option<u32>) {
     }
 }
 
-macro_rules! this_is_a_really_really_long_macro_name {
+macro_rules! long_name_that_fits_on_a_single_line {
+    () => {}
+}
+long_name_that_fits_on_a_single_line!();
+
+macro_rules! long_name_that_doesnt_fit_on_one_line {
     ($t:ty) => {
         fn f(_: $t) {}
     }
 }
-this_is_a_really_really_long_macro_name!(u32!()); // AstFragmentKind::{Items,Ty}
+long_name_that_doesnt_fit_on_one_line!(u32!()); // AstFragmentKind::{Items,Ty}
 
 macro_rules! trait_tys {
     () => {
diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr
index 00c6b55c6a2..8d0fdb8958a 100644
--- a/tests/ui/stats/macro-stats.stderr
+++ b/tests/ui/stats/macro-stats.stderr
@@ -15,12 +15,13 @@ macro-stats #[derive(Copy)]                       1          2        2.0
 macro-stats p!                                    1          3        3.0         32       32.0
 macro-stats trait_impl_tys!                       1          2        2.0         28       28.0
 macro-stats foreign_item!                         1          1        1.0         21       21.0
-macro-stats this_is_a_really_really_long_macro_name!
+macro-stats long_name_that_doesnt_fit_on_one_line!
 macro-stats                                       1          1        1.0         18       18.0
 macro-stats impl_const!                           1          1        1.0         17       17.0
 macro-stats trait_tys!                            1          2        2.0         15       15.0
 macro-stats n99!                                  2          2        1.0          4        2.0
 macro-stats none!                                 1          1        1.0          4        4.0
 macro-stats u32!                                  1          1        1.0          3        3.0
+macro-stats long_name_that_fits_on_a_single_line! 1          1        1.0          0        0.0
 macro-stats #[test]                               1          1        1.0          0        0.0
 macro-stats ===================================================================================