about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs13
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs35
-rw-r--r--compiler/rustc_hir/src/def.rs14
-rw-r--r--compiler/rustc_hir/src/definitions.rs85
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs34
-rw-r--r--compiler/rustc_middle/src/ty/context.rs18
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs3
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs12
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs3
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs37
-rw-r--r--compiler/rustc_resolve/src/lib.rs7
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs3
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs3
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs70
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs7
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs1
-rw-r--r--src/bootstrap/src/utils/cc_detect/tests.rs12
-rw-r--r--src/tools/rust-analyzer/Cargo.lock18
-rw-r--r--src/tools/rust-analyzer/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/crates/base-db/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs2
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs94
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs55
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs49
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs93
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs187
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs113
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs85
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs42
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/test_db.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs158
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/change.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs60
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/name.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs29
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs83
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/drop.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs72
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs22
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs43
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs75
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs47
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs31
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs27
-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.rs78
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/traits.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/variance.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs81
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/symbols.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs299
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs68
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_imports.rs (renamed from src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs)111
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs30
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs96
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs4
-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/assists.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs61
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs26
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs42
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs55
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs42
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs20
-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/lib.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/status.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs2
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol.rs34
-rw-r--r--src/tools/rust-analyzer/crates/load-cargo/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items.rs3
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs15
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/types.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast7
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast9
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast30
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast15
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/build.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/env.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs2
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs10
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs2
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs2
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs6
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs8
-rw-r--r--src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs13
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs12
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs14
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs18
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs18
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs7
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs5
-rw-r--r--src/tools/rust-analyzer/crates/span/src/hygiene.rs65
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/thread.rs15
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs5
-rw-r--r--src/tools/rust-analyzer/crates/syntax/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs35
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs124
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs50
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/grammar.rs2
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs4
-rw-r--r--src/tools/rust-analyzer/xtask/src/dist.rs109
-rw-r--r--src/tools/rust-analyzer/xtask/src/flags.rs52
-rw-r--r--src/tools/rust-analyzer/xtask/src/install.rs28
-rw-r--r--src/tools/rust-analyzer/xtask/src/main.rs1
-rw-r--r--src/tools/rust-analyzer/xtask/src/pgo.rs105
-rw-r--r--src/tools/rust-analyzer/xtask/src/util.rs12
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff14
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff14
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff14
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff14
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff16
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff16
-rw-r--r--tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff18
-rw-r--r--tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff24
-rw-r--r--tests/mir-opt/pre-codegen/matchbr.match1.PreCodegen.after.mir13
-rw-r--r--tests/mir-opt/pre-codegen/matchbr.rs10
-rw-r--r--tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff5
-rw-r--r--tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff5
-rw-r--r--tests/ui-fulldeps/stable-mir/check_assoc_items.rs24
-rw-r--r--tests/ui/delegation/unsupported.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr4
-rw-r--r--tests/ui/impl-trait/in-trait/dump.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/dump.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr4
-rw-r--r--tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr4
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr4
234 files changed, 2788 insertions, 1929 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 8e1a3cd1435..9f3aed9216c 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -492,9 +492,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let mut generic_args = ThinVec::new();
         for (idx, arg) in args.iter().cloned().enumerate() {
             if legacy_args_idx.contains(&idx) {
-                let parent_def_id = self.current_hir_id_owner.def_id;
                 let node_id = self.next_node_id();
-                self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, f.span);
+                self.create_def(node_id, None, DefKind::AnonConst, f.span);
                 let mut visitor = WillCreateDefIdsVisitor {};
                 let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) {
                     AstP(Expr {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 9f9d1f9a556..8597820073a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -500,12 +500,12 @@ enum GenericArgsMode {
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn create_def(
         &mut self,
-        parent: LocalDefId,
         node_id: ast::NodeId,
         name: Option<Symbol>,
         def_kind: DefKind,
         span: Span,
     ) -> LocalDefId {
+        let parent = self.current_hir_id_owner.def_id;
         debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
         assert!(
             self.opt_local_def_id(node_id).is_none(),
@@ -515,7 +515,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             self.tcx.hir_def_key(self.local_def_id(node_id)),
         );
 
-        let def_id = self.tcx.at(span).create_def(parent, name, def_kind).def_id();
+        let def_id = self
+            .tcx
+            .at(span)
+            .create_def(parent, name, def_kind, None, &mut self.resolver.disambiguator)
+            .def_id();
 
         debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
         self.resolver.node_id_to_def_id.insert(node_id, def_id);
@@ -787,7 +791,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             LifetimeRes::Fresh { param, kind, .. } => {
                 // Late resolution delegates to us the creation of the `LocalDefId`.
                 let _def_id = self.create_def(
-                    self.current_hir_id_owner.def_id,
                     param,
                     Some(kw::UnderscoreLifetime),
                     DefKind::LifetimeParam,
@@ -2113,8 +2116,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             hir::ConstArgKind::Path(qpath)
         } else {
             // Construct an AnonConst where the expr is the "ty"'s path.
-
-            let parent_def_id = self.current_hir_id_owner.def_id;
             let node_id = self.next_node_id();
             let span = self.lower_span(span);
 
@@ -2122,7 +2123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // We're lowering a const argument that was originally thought to be a type argument,
             // so the def collector didn't create the def ahead of time. That's why we have to do
             // it here.
-            let def_id = self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, span);
+            let def_id = self.create_def(node_id, None, DefKind::AnonConst, span);
             let hir_id = self.lower_node_id(node_id);
 
             let path_expr = Expr {
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 4a6929ef011..58dea472f1d 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -522,14 +522,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         span: Span,
         base_type: Span,
     ) -> &'hir hir::ConstArg<'hir> {
-        let parent_def_id = self.current_hir_id_owner.def_id;
         let node_id = self.next_node_id();
 
         // Add a definition for the in-band const def.
         // We're generating a range end that didn't exist in the AST,
         // so the def collector didn't create the def ahead of time. That's why we have to do
         // it here.
-        let def_id = self.create_def(parent_def_id, node_id, None, DefKind::AnonConst, span);
+        let def_id = self.create_def(node_id, None, DefKind::AnonConst, span);
         let hir_id = self.lower_node_id(node_id);
 
         let unstable_span = self.mark_span_with_reason(
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 8f0cb197c44..1dd96297d1f 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -17,13 +17,13 @@ use hir::def::DefKind;
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_hir as hir;
+use rustc_hir::definitions::{DefPathData, DisambiguatorState};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::span_bug;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::sym;
 use tracing::{instrument, trace};
 
 use super::{
@@ -66,6 +66,7 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
     ecx: &mut InterpCx<'tcx, M>,
     alloc_id: AllocId,
     mutability: Mutability,
+    disambiguator: Option<&mut DisambiguatorState>,
 ) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, ()> {
     trace!("intern_shallow {:?}", alloc_id);
     // remove allocation
@@ -88,7 +89,13 @@ fn intern_shallow<'tcx, T, M: CompileTimeMachine<'tcx, T>>(
     // link the alloc id to the actual allocation
     let alloc = ecx.tcx.mk_const_alloc(alloc);
     if let Some(static_id) = ecx.machine.static_def_id() {
-        intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc);
+        intern_as_new_static(
+            ecx.tcx,
+            static_id,
+            alloc_id,
+            alloc,
+            disambiguator.expect("disambiguator needed"),
+        );
     } else {
         ecx.tcx.set_alloc_id_memory(alloc_id, alloc);
     }
@@ -102,11 +109,18 @@ fn intern_as_new_static<'tcx>(
     static_id: LocalDefId,
     alloc_id: AllocId,
     alloc: ConstAllocation<'tcx>,
+    disambiguator: &mut DisambiguatorState,
 ) {
+    // `intern_const_alloc_recursive` is called once per static and it contains the `DisambiguatorState`.
+    //  The `<static_id>::{{nested}}` path is thus unique to `intern_const_alloc_recursive` and the
+    // `DisambiguatorState` ensures the generated path is unique for this call as we generate
+    // `<static_id>::{{nested#n}}` where `n` is the `n`th `intern_as_new_static` call.
     let feed = tcx.create_def(
         static_id,
-        Some(sym::nested),
+        None,
         DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true },
+        Some(DefPathData::NestedStatic),
+        disambiguator,
     );
     tcx.set_nested_alloc_id_static(alloc_id, feed.def_id());
 
@@ -154,6 +168,8 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
     intern_kind: InternKind,
     ret: &MPlaceTy<'tcx>,
 ) -> Result<(), InternResult> {
+    let mut disambiguator = DisambiguatorState::new();
+
     // We are interning recursively, and for mutability we are distinguishing the "root" allocation
     // that we are starting in, and all other allocations that we are encountering recursively.
     let (base_mutability, inner_mutability, is_static) = match intern_kind {
@@ -197,7 +213,9 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
         alloc.1.mutability = base_mutability;
         alloc.1.provenance().ptrs().iter().map(|&(_, prov)| prov).collect()
     } else {
-        intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().collect()
+        intern_shallow(ecx, base_alloc_id, base_mutability, Some(&mut disambiguator))
+            .unwrap()
+            .collect()
     };
     // We need to distinguish "has just been interned" from "was already in `tcx`",
     // so we track this in a separate set.
@@ -291,7 +309,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
         // okay with losing some potential for immutability here. This can anyway only affect
         // `static mut`.
         just_interned.insert(alloc_id);
-        match intern_shallow(ecx, alloc_id, inner_mutability) {
+        match intern_shallow(ecx, alloc_id, inner_mutability, Some(&mut disambiguator)) {
             Ok(nested) => todo.extend(nested),
             Err(()) => {
                 ecx.tcx.dcx().delayed_bug("found dangling pointer during const interning");
@@ -313,8 +331,9 @@ pub fn intern_const_alloc_for_constprop<'tcx, T, M: CompileTimeMachine<'tcx, T>>
         return interp_ok(());
     }
     // Move allocation to `tcx`.
-    if let Some(_) =
-        (intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))?).next()
+    if let Some(_) = intern_shallow(ecx, alloc_id, Mutability::Not, None)
+        .map_err(|()| err_ub!(DeadLocal))?
+        .next()
     {
         // We are not doing recursive interning, so we don't currently support provenance.
         // (If this assertion ever triggers, we should just implement a
@@ -340,7 +359,7 @@ impl<'tcx> InterpCx<'tcx, DummyMachine> {
         let dest = self.allocate(layout, MemoryKind::Stack)?;
         f(self, &dest.clone().into())?;
         let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance
-        for prov in intern_shallow(self, alloc_id, Mutability::Not).unwrap() {
+        for prov in intern_shallow(self, alloc_id, Mutability::Not, None).unwrap() {
             // We are not doing recursive interning, so we don't currently support provenance.
             // (If this assertion ever triggers, we should just implement a
             // proper recursive interning loop -- or just call `intern_const_alloc_recursive`.
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 9372ab532bf..507c94aca8b 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -269,18 +269,10 @@ impl DefKind {
             | DefKind::TyParam
             | DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),
 
-            // An associated type name will be missing for an RPITIT.
-            DefKind::AssocTy => {
-                if let Some(name) = name {
-                    DefPathData::TypeNs(name)
-                } else {
-                    DefPathData::AnonAssocTy
-                }
-            }
+            // An associated type name will be missing for an RPITIT (DefPathData::AnonAssocTy),
+            // but those provide their own DefPathData.
+            DefKind::AssocTy => DefPathData::TypeNs(name.unwrap()),
 
-            // It's not exactly an anon const, but wrt DefPathData, there
-            // is no difference.
-            DefKind::Static { nested: true, .. } => DefPathData::AnonConst,
             DefKind::Fn
             | DefKind::Const
             | DefKind::ConstParam
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index bf7b1eefcf6..98b41187f11 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -68,7 +68,7 @@ impl DefPathTable {
             //
             // See the documentation for DefPathHash for more information.
             panic!(
-                "found DefPathHash collision between {def_path1:?} and {def_path2:?}. \
+                "found DefPathHash collision between {def_path1:#?} and {def_path2:#?}. \
                     Compilation cannot continue."
             );
         }
@@ -97,13 +97,31 @@ impl DefPathTable {
     }
 }
 
+#[derive(Debug)]
+pub struct DisambiguatorState {
+    next: UnordMap<(LocalDefId, DefPathData), u32>,
+}
+
+impl DisambiguatorState {
+    pub fn new() -> Self {
+        Self { next: Default::default() }
+    }
+
+    /// Creates a `DisambiguatorState` where the next allocated `(LocalDefId, DefPathData)` pair
+    /// will have `index` as the disambiguator.
+    pub fn with(def_id: LocalDefId, data: DefPathData, index: u32) -> Self {
+        let mut this = Self::new();
+        this.next.insert((def_id, data), index);
+        this
+    }
+}
+
 /// The definition table containing node definitions.
 /// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s.
 /// It also stores mappings to convert `LocalDefId`s to/from `HirId`s.
 #[derive(Debug)]
 pub struct Definitions {
     table: DefPathTable,
-    next_disambiguator: UnordMap<(LocalDefId, DefPathData), u32>,
 }
 
 /// A unique identifier that we can use to lookup a definition
@@ -127,7 +145,7 @@ impl DefKey {
         let DisambiguatedDefPathData { ref data, disambiguator } = self.disambiguated_data;
 
         std::mem::discriminant(data).hash(&mut hasher);
-        if let Some(name) = data.get_opt_name() {
+        if let Some(name) = data.hashed_symbol() {
             // Get a stable hash by considering the symbol chars rather than
             // the symbol index.
             name.as_str().hash(&mut hasher);
@@ -173,7 +191,11 @@ impl DisambiguatedDefPathData {
                 }
             }
             DefPathDataName::Anon { namespace } => {
-                write!(writer, "{{{}#{}}}", namespace, self.disambiguator)
+                if let DefPathData::AnonAssocTy(method) = self.data {
+                    write!(writer, "{}::{{{}#{}}}", method, namespace, self.disambiguator)
+                } else {
+                    write!(writer, "{{{}#{}}}", namespace, self.disambiguator)
+                }
             }
         }
     }
@@ -287,10 +309,13 @@ pub enum DefPathData {
     /// An existential `impl Trait` type node.
     /// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
     OpaqueTy,
-    /// An anonymous associated type from an RPITIT.
-    AnonAssocTy,
+    /// An anonymous associated type from an RPITIT. The symbol refers to the name of the method
+    /// that defined the type.
+    AnonAssocTy(Symbol),
     /// A synthetic body for a coroutine's by-move body.
     SyntheticCoroutineBody,
+    /// Additional static data referred to by a static.
+    NestedStatic,
 }
 
 impl Definitions {
@@ -342,11 +367,20 @@ impl Definitions {
         let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
         assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
 
-        Definitions { table, next_disambiguator: Default::default() }
+        Definitions { table }
     }
 
-    /// Adds a definition with a parent definition.
-    pub fn create_def(&mut self, parent: LocalDefId, data: DefPathData) -> LocalDefId {
+    /// Creates a definition with a parent definition.
+    /// If there are multiple definitions with the same DefPathData and the same parent, use
+    /// `disambiguator` to differentiate them. Distinct `DisambiguatorState` instances are not
+    /// guaranteed to generate unique disambiguators and should instead ensure that the `parent`
+    /// and `data` pair is distinct from other instances.
+    pub fn create_def(
+        &mut self,
+        parent: LocalDefId,
+        data: DefPathData,
+        disambiguator: &mut DisambiguatorState,
+    ) -> LocalDefId {
         // We can't use `Debug` implementation for `LocalDefId` here, since it tries to acquire a
         // reference to `Definitions` and we're already holding a mutable reference.
         debug!(
@@ -354,12 +388,12 @@ impl Definitions {
             self.def_path(parent).to_string_no_crate_verbose(),
         );
 
-        // The root node must be created with `create_root_def()`.
+        // The root node must be created in `new()`.
         assert!(data != DefPathData::CrateRoot);
 
         // Find the next free disambiguator for this key.
         let disambiguator = {
-            let next_disamb = self.next_disambiguator.entry((parent, data)).or_insert(0);
+            let next_disamb = disambiguator.next.entry((parent, data)).or_insert(0);
             let disambiguator = *next_disamb;
             *next_disamb = next_disamb.checked_add(1).expect("disambiguator overflow");
             disambiguator
@@ -422,8 +456,30 @@ impl DefPathData {
             | Ctor
             | AnonConst
             | OpaqueTy
-            | AnonAssocTy
-            | SyntheticCoroutineBody => None,
+            | AnonAssocTy(..)
+            | SyntheticCoroutineBody
+            | NestedStatic => None,
+        }
+    }
+
+    fn hashed_symbol(&self) -> Option<Symbol> {
+        use self::DefPathData::*;
+        match *self {
+            TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | AnonAssocTy(name) => {
+                Some(name)
+            }
+
+            Impl
+            | ForeignMod
+            | CrateRoot
+            | Use
+            | GlobalAsm
+            | Closure
+            | Ctor
+            | AnonConst
+            | OpaqueTy
+            | SyntheticCoroutineBody
+            | NestedStatic => None,
         }
     }
 
@@ -443,8 +499,9 @@ impl DefPathData {
             Ctor => DefPathDataName::Anon { namespace: sym::constructor },
             AnonConst => DefPathDataName::Anon { namespace: sym::constant },
             OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
-            AnonAssocTy => DefPathDataName::Anon { namespace: sym::anon_assoc },
+            AnonAssocTy(..) => DefPathDataName::Anon { namespace: sym::anon_assoc },
             SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
+            NestedStatic => DefPathDataName::Anon { namespace: sym::nested },
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 59ab36d98fd..a89160785eb 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -14,6 +14,7 @@ use rustc_ast::visit::walk_list;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def::{DefKind, Res};
+use rustc_hir::definitions::DisambiguatorState;
 use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
 use rustc_hir::{
     self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, LifetimeKind, Node,
@@ -63,6 +64,7 @@ impl ResolvedArg {
 struct BoundVarContext<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     rbv: &'a mut ResolveBoundVars,
+    disambiguator: &'a mut DisambiguatorState,
     scope: ScopeRef<'a>,
 }
 
@@ -245,8 +247,12 @@ pub(crate) fn provide(providers: &mut Providers) {
 #[instrument(level = "debug", skip(tcx))]
 fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBoundVars {
     let mut rbv = ResolveBoundVars::default();
-    let mut visitor =
-        BoundVarContext { tcx, rbv: &mut rbv, scope: &Scope::Root { opt_parent_item: None } };
+    let mut visitor = BoundVarContext {
+        tcx,
+        rbv: &mut rbv,
+        scope: &Scope::Root { opt_parent_item: None },
+        disambiguator: &mut DisambiguatorState::new(),
+    };
     match tcx.hir_owner_node(local_def_id) {
         hir::OwnerNode::Item(item) => visitor.visit_item(item),
         hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
@@ -515,9 +521,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
 
         let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
         if capture_all_in_scope_lifetimes {
+            let tcx = self.tcx;
             let lifetime_ident = |def_id: LocalDefId| {
-                let name = self.tcx.item_name(def_id.to_def_id());
-                let span = self.tcx.def_span(def_id);
+                let name = tcx.item_name(def_id.to_def_id());
+                let span = tcx.def_span(def_id);
                 Ident::new(name, span)
             };
 
@@ -1091,8 +1098,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
     where
         F: for<'b> FnOnce(&mut BoundVarContext<'b, 'tcx>),
     {
-        let BoundVarContext { tcx, rbv, .. } = self;
-        let mut this = BoundVarContext { tcx: *tcx, rbv, scope: &wrap_scope };
+        let BoundVarContext { tcx, rbv, disambiguator, .. } = self;
+        let mut this = BoundVarContext { tcx: *tcx, rbv, disambiguator, scope: &wrap_scope };
         let span = debug_span!("scope", scope = ?this.scope.debug_truncated());
         {
             let _enter = span.enter();
@@ -1446,7 +1453,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
     #[instrument(level = "trace", skip(self, opaque_capture_scopes), ret)]
     fn remap_opaque_captures(
-        &self,
+        &mut self,
         opaque_capture_scopes: &Vec<(LocalDefId, &RefCell<FxIndexMap<ResolvedArg, LocalDefId>>)>,
         mut lifetime: ResolvedArg,
         ident: Ident,
@@ -1462,8 +1469,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         for &(opaque_def_id, captures) in opaque_capture_scopes.iter().rev() {
             let mut captures = captures.borrow_mut();
             let remapped = *captures.entry(lifetime).or_insert_with(|| {
-                let feed =
-                    self.tcx.create_def(opaque_def_id, Some(ident.name), DefKind::LifetimeParam);
+                // `opaque_def_id` is unique to the `BoundVarContext` pass which is executed once
+                // per `resolve_bound_vars` query. This is the only location that creates nested
+                // lifetime inside a opaque type. `<opaque_def_id>::LifetimeNs(..)` is thus unique
+                // to this query and duplicates within the query are handled by `self.disambiguator`.
+                let feed = self.tcx.create_def(
+                    opaque_def_id,
+                    Some(ident.name),
+                    DefKind::LifetimeParam,
+                    None,
+                    &mut self.disambiguator,
+                );
                 feed.def_span(ident.span);
                 feed.def_ident_span(Some(ident.span));
                 feed.def_id()
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index d660234618e..2c6c587f9f0 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -35,7 +35,7 @@ use rustc_errors::{
 };
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
-use rustc_hir::definitions::Definitions;
+use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState};
 use rustc_hir::intravisit::VisitorExt;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate};
@@ -1978,8 +1978,11 @@ impl<'tcx> TyCtxtAt<'tcx> {
         parent: LocalDefId,
         name: Option<Symbol>,
         def_kind: DefKind,
+        override_def_path_data: Option<DefPathData>,
+        disambiguator: &mut DisambiguatorState,
     ) -> TyCtxtFeed<'tcx, LocalDefId> {
-        let feed = self.tcx.create_def(parent, name, def_kind);
+        let feed =
+            self.tcx.create_def(parent, name, def_kind, override_def_path_data, disambiguator);
 
         feed.def_span(self.span);
         feed
@@ -1993,8 +1996,10 @@ impl<'tcx> TyCtxt<'tcx> {
         parent: LocalDefId,
         name: Option<Symbol>,
         def_kind: DefKind,
+        override_def_path_data: Option<DefPathData>,
+        disambiguator: &mut DisambiguatorState,
     ) -> TyCtxtFeed<'tcx, LocalDefId> {
-        let data = def_kind.def_path_data(name);
+        let data = override_def_path_data.unwrap_or_else(|| def_kind.def_path_data(name));
         // The following call has the side effect of modifying the tables inside `definitions`.
         // These very tables are relied on by the incr. comp. engine to decode DepNodes and to
         // decode the on-disk cache.
@@ -2004,12 +2009,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // - has been created by this call to `create_def`.
         // As a consequence, this LocalDefId is always re-created before it is needed by the incr.
         // comp. engine itself.
-        //
-        // This call also writes to the value of the `source_span` query.
-        // This is fine because:
-        // - that query is `eval_always` so we won't miss its result changing;
-        // - this write will have happened before that query is called.
-        let def_id = self.untracked.definitions.write().create_def(parent, data);
+        let def_id = self.untracked.definitions.write().create_def(parent, data, disambiguator);
 
         // This function modifies `self.definitions` using a side-effect.
         // We need to ensure that these side effects are re-run by the incr. comp. engine.
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index b4ef82f6d42..b8da97c42d4 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -38,6 +38,7 @@ use rustc_errors::{Diag, ErrorGuaranteed};
 use rustc_hir::LangItem;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
+use rustc_hir::definitions::DisambiguatorState;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::BitMatrix;
 use rustc_macros::{
@@ -209,6 +210,8 @@ pub struct ResolverAstLowering {
 
     pub node_id_to_def_id: NodeMap<LocalDefId>,
 
+    pub disambiguator: DisambiguatorState,
+
     pub trait_map: NodeMap<Vec<hir::TraitCandidate>>,
     /// List functions and methods for which lifetime elision was successful.
     pub lifetime_elision_allowed: FxHashSet<ast::NodeId>,
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index dd0e07f2218..0a839d91404 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -73,6 +73,7 @@ use rustc_data_structures::unord::UnordMap;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::definitions::DisambiguatorState;
 use rustc_middle::bug;
 use rustc_middle::hir::place::{Projection, ProjectionKind};
 use rustc_middle::mir::visit::MutVisitor;
@@ -213,8 +214,15 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
     let mut by_move_body = body.clone();
     MakeByMoveBody { tcx, field_remapping, by_move_coroutine_ty }.visit_body(&mut by_move_body);
 
-    // This will always be `{closure#1}`, since the original coroutine is `{closure#0}`.
-    let body_def = tcx.create_def(parent_def_id, None, DefKind::SyntheticCoroutineBody);
+    // This path is unique since we're in a query so we'll only be called once with `parent_def_id`
+    // and this is the only location creating `SyntheticCoroutineBody`.
+    let body_def = tcx.create_def(
+        parent_def_id,
+        None,
+        DefKind::SyntheticCoroutineBody,
+        None,
+        &mut DisambiguatorState::new(),
+    );
     by_move_body.source =
         mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id()));
     dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(()));
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 24f4c11a66d..dc0eacd3613 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -701,8 +701,6 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
             // Now, we need to shrink the generated MIR.
             &ref_prop::ReferencePropagation,
             &sroa::ScalarReplacementOfAggregates,
-            &match_branches::MatchBranchSimplification,
-            // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
             &multiple_return_terminators::MultipleReturnTerminators,
             // After simplifycfg, it allows us to discover new opportunities for peephole
             // optimizations.
@@ -711,6 +709,7 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
             &dead_store_elimination::DeadStoreElimination::Initial,
             &gvn::GVN,
             &simplify::SimplifyLocals::AfterGVN,
+            &match_branches::MatchBranchSimplification,
             &dataflow_const_prop::DataflowConstProp,
             &single_use_consts::SingleUseConsts,
             &o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index b37241185c9..8c0c3096899 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -19,30 +19,32 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let typing_env = body.typing_env(tcx);
-        let mut should_cleanup = false;
-        for bb_idx in body.basic_blocks.indices() {
-            match &body.basic_blocks[bb_idx].terminator().kind {
+        let mut apply_patch = false;
+        let mut patch = MirPatch::new(body);
+        for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
+            match &bb_data.terminator().kind {
                 TerminatorKind::SwitchInt {
                     discr: Operand::Copy(_) | Operand::Move(_),
                     targets,
                     ..
                     // We require that the possible target blocks don't contain this block.
-                } if !targets.all_targets().contains(&bb_idx) => {}
+                } if !targets.all_targets().contains(&bb) => {}
                 // Only optimize switch int statements
                 _ => continue,
             };
 
-            if SimplifyToIf.simplify(tcx, body, bb_idx, typing_env).is_some() {
-                should_cleanup = true;
+            if SimplifyToIf.simplify(tcx, body, &mut patch, bb, typing_env).is_some() {
+                apply_patch = true;
                 continue;
             }
-            if SimplifyToExp::default().simplify(tcx, body, bb_idx, typing_env).is_some() {
-                should_cleanup = true;
+            if SimplifyToExp::default().simplify(tcx, body, &mut patch, bb, typing_env).is_some() {
+                apply_patch = true;
                 continue;
             }
         }
 
-        if should_cleanup {
+        if apply_patch {
+            patch.apply(body);
             simplify_cfg(tcx, body);
         }
     }
@@ -59,7 +61,8 @@ trait SimplifyMatch<'tcx> {
     fn simplify(
         &mut self,
         tcx: TyCtxt<'tcx>,
-        body: &mut Body<'tcx>,
+        body: &Body<'tcx>,
+        patch: &mut MirPatch<'tcx>,
         switch_bb_idx: BasicBlock,
         typing_env: ty::TypingEnv<'tcx>,
     ) -> Option<()> {
@@ -73,8 +76,6 @@ trait SimplifyMatch<'tcx> {
         let discr_ty = discr.ty(body.local_decls(), tcx);
         self.can_simplify(tcx, targets, typing_env, bbs, discr_ty)?;
 
-        let mut patch = MirPatch::new(body);
-
         // Take ownership of items now that we know we can optimize.
         let discr = discr.clone();
 
@@ -87,19 +88,9 @@ trait SimplifyMatch<'tcx> {
         let parent_end = Location { block: switch_bb_idx, statement_index };
         patch.add_statement(parent_end, StatementKind::StorageLive(discr_local));
         patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr));
-        self.new_stmts(
-            tcx,
-            targets,
-            typing_env,
-            &mut patch,
-            parent_end,
-            bbs,
-            discr_local,
-            discr_ty,
-        );
+        self.new_stmts(tcx, targets, typing_env, patch, parent_end, bbs, discr_local, discr_ty);
         patch.add_statement(parent_end, StatementKind::StorageDead(discr_local));
         patch.patch_terminator(switch_bb_idx, bbs[first].terminator().kind.clone());
-        patch.apply(body);
         Some(())
     }
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index d23e588e2e3..d0549bae614 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -56,6 +56,7 @@ use rustc_hir::def::{
     self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS,
 };
 use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
+use rustc_hir::definitions::DisambiguatorState;
 use rustc_hir::{PrimTy, TraitCandidate};
 use rustc_metadata::creader::{CStore, CrateLoader};
 use rustc_middle::metadata::ModChild;
@@ -1179,6 +1180,8 @@ pub struct Resolver<'ra, 'tcx> {
 
     node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>,
 
+    disambiguator: DisambiguatorState,
+
     /// Indices of unnamed struct or variant fields with unresolved attributes.
     placeholder_field_indices: FxHashMap<NodeId, usize>,
     /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
@@ -1342,7 +1345,7 @@ impl<'tcx> Resolver<'_, 'tcx> {
         );
 
         // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()`
-        let feed = self.tcx.create_def(parent, name, def_kind);
+        let feed = self.tcx.create_def(parent, name, def_kind, None, &mut self.disambiguator);
         let def_id = feed.def_id();
 
         // Create the definition.
@@ -1556,6 +1559,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             lint_buffer: LintBuffer::default(),
             next_node_id: CRATE_NODE_ID,
             node_id_to_def_id,
+            disambiguator: DisambiguatorState::new(),
             placeholder_field_indices: Default::default(),
             invocation_parents,
             legacy_const_generic_args: Default::default(),
@@ -1685,6 +1689,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 .into_items()
                 .map(|(k, f)| (k, f.key()))
                 .collect(),
+            disambiguator: self.disambiguator,
             trait_map: self.trait_map,
             lifetime_elision_allowed: self.lifetime_elision_allowed,
             lint_buffer: Steal::new(self.lint_buffer),
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index 4b1b3903e40..f7f354d12e8 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -717,12 +717,13 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
             hir::definitions::DefPathData::AnonConst => "k",
             hir::definitions::DefPathData::OpaqueTy => "i",
             hir::definitions::DefPathData::SyntheticCoroutineBody => "s",
+            hir::definitions::DefPathData::NestedStatic => "n",
             hir::definitions::DefPathData::CrateRoot
             | hir::definitions::DefPathData::Use
             | hir::definitions::DefPathData::GlobalAsm
             | hir::definitions::DefPathData::MacroNs(..)
             | hir::definitions::DefPathData::LifetimeNs(..)
-            | hir::definitions::DefPathData::AnonAssocTy => {
+            | hir::definitions::DefPathData::AnonAssocTy(..) => {
                 bug!("encode_ty_name: unexpected `{:?}`", disambiguated_data.data);
             }
         });
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index ad391d56992..1f45440eecf 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -881,6 +881,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             DefPathData::AnonConst => 'k',
             DefPathData::OpaqueTy => 'i',
             DefPathData::SyntheticCoroutineBody => 's',
+            DefPathData::NestedStatic => 'n',
 
             // These should never show up as `path_append` arguments.
             DefPathData::CrateRoot
@@ -889,7 +890,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             | DefPathData::Impl
             | DefPathData::MacroNs(_)
             | DefPathData::LifetimeNs(_)
-            | DefPathData::AnonAssocTy => {
+            | DefPathData::AnonAssocTy(..) => {
                 bug!("symbol_names: unexpected DefPathData: {:?}", disambiguated_data.data)
             }
         };
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 6cb9fdc6f93..f14a45aa1e3 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -1,6 +1,7 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
+use rustc_hir::definitions::{DefPathData, DisambiguatorState};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir, AmbigArg};
 use rustc_middle::query::Providers;
@@ -159,6 +160,22 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
         container: ty::AssocItemContainer::Impl,
     }
 }
+struct RPITVisitor {
+    rpits: FxIndexSet<LocalDefId>,
+}
+
+impl<'tcx> Visitor<'tcx> for RPITVisitor {
+    fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
+        if let hir::TyKind::OpaqueDef(opaq) = ty.kind
+            && self.rpits.insert(opaq.def_id)
+        {
+            for bound in opaq.bounds {
+                intravisit::walk_param_bound(self, bound);
+            }
+        }
+        intravisit::walk_ty(self, ty)
+    }
+}
 
 /// Given an `fn_def_id` of a trait or a trait implementation:
 ///
@@ -177,23 +194,6 @@ fn associated_types_for_impl_traits_in_associated_fn(
 
     match tcx.def_kind(parent_def_id) {
         DefKind::Trait => {
-            struct RPITVisitor {
-                rpits: FxIndexSet<LocalDefId>,
-            }
-
-            impl<'tcx> Visitor<'tcx> for RPITVisitor {
-                fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
-                    if let hir::TyKind::OpaqueDef(opaq) = ty.kind
-                        && self.rpits.insert(opaq.def_id)
-                    {
-                        for bound in opaq.bounds {
-                            intravisit::walk_param_bound(self, bound);
-                        }
-                    }
-                    intravisit::walk_ty(self, ty)
-                }
-            }
-
             let mut visitor = RPITVisitor { rpits: FxIndexSet::default() };
 
             if let Some(output) = tcx.hir_get_fn_output(fn_def_id) {
@@ -246,9 +246,23 @@ fn associated_type_for_impl_trait_in_trait(
     let trait_def_id = tcx.local_parent(fn_def_id);
     assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
 
+    // Collect all opaque types in return position for the method and use
+    // the index as the disambiguator to make an unique def path.
+    let mut visitor = RPITVisitor { rpits: FxIndexSet::default() };
+    visitor.visit_fn_ret_ty(tcx.hir_get_fn_output(fn_def_id).unwrap());
+    let disambiguator = visitor.rpits.get_index_of(&opaque_ty_def_id).unwrap().try_into().unwrap();
+
     let span = tcx.def_span(opaque_ty_def_id);
-    // No name because this is an anonymous associated type.
-    let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, None, DefKind::AssocTy);
+    // Also use the method name to create an unique def path.
+    let data = DefPathData::AnonAssocTy(tcx.item_name(fn_def_id.to_def_id()));
+    let trait_assoc_ty = tcx.at(span).create_def(
+        trait_def_id,
+        // No name because this is an anonymous associated type.
+        None,
+        DefKind::AssocTy,
+        Some(data),
+        &mut DisambiguatorState::with(trait_def_id, data, disambiguator),
+    );
 
     let local_def_id = trait_assoc_ty.def_id();
     let def_id = local_def_id.to_def_id();
@@ -299,8 +313,22 @@ fn associated_type_for_impl_trait_in_impl(
         hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
         hir::FnRetTy::Return(ty) => ty.span,
     };
-    // No name because this is an anonymous associated type.
-    let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, None, DefKind::AssocTy);
+
+    // Use the same disambiguator and method name as the anon associated type in the trait.
+    let disambiguated_data = tcx.def_key(trait_assoc_def_id).disambiguated_data;
+    let DefPathData::AnonAssocTy(name) = disambiguated_data.data else {
+        bug!("expected anon associated type")
+    };
+    let data = DefPathData::AnonAssocTy(name);
+
+    let impl_assoc_ty = tcx.at(span).create_def(
+        impl_local_def_id,
+        // No name because this is an anonymous associated type.
+        None,
+        DefKind::AssocTy,
+        Some(data),
+        &mut DisambiguatorState::with(impl_local_def_id, data, disambiguated_data.disambiguator),
+    );
 
     let local_def_id = impl_assoc_ty.def_id();
     let def_id = local_def_id.to_def_id();
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 36b3c95d638..d625c2ef584 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -112,9 +112,8 @@ impl Cargo {
         let mut cargo = builder.cargo(compiler, mode, source_type, target, cmd_kind);
 
         match cmd_kind {
-            // No need to configure the target linker for these command types,
-            // as they don't invoke rustc at all.
-            Kind::Clean | Kind::Suggest | Kind::Format | Kind::Setup => {}
+            // No need to configure the target linker for these command types.
+            Kind::Clean | Kind::Check | Kind::Suggest | Kind::Format | Kind::Setup => {}
             _ => {
                 cargo.configure_linker(builder);
             }
@@ -205,6 +204,8 @@ impl Cargo {
         self
     }
 
+    // FIXME(onur-ozkan): Add coverage to make sure modifications to this function
+    // doesn't cause cache invalidations (e.g., #130108).
     fn configure_linker(&mut self, builder: &Builder<'_>) -> &mut Cargo {
         let target = self.target;
         let compiler = self.compiler;
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index 147b009d3f4..ceac24d4315 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -96,6 +96,7 @@ pub fn find(build: &Build) {
     let targets: HashSet<_> = match build.config.cmd {
         // We don't need to check cross targets for these commands.
         crate::Subcommand::Clean { .. }
+        | crate::Subcommand::Check { .. }
         | crate::Subcommand::Suggest { .. }
         | crate::Subcommand::Format { .. }
         | crate::Subcommand::Setup { .. } => {
diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs
index b4a1b52dd23..43d61ce02c5 100644
--- a/src/bootstrap/src/utils/cc_detect/tests.rs
+++ b/src/bootstrap/src/utils/cc_detect/tests.rs
@@ -181,7 +181,7 @@ fn test_language_clang() {
 
 #[test]
 fn test_new_cc_build() {
-    let build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
+    let build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) });
     let target = TargetSelection::from_user("x86_64-unknown-linux-gnu");
     let cfg = new_cc_build(&build, target.clone());
     let compiler = cfg.get_compiler();
@@ -190,7 +190,7 @@ fn test_new_cc_build() {
 
 #[test]
 fn test_default_compiler_wasi() {
-    let build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
+    let build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) });
     let target = TargetSelection::from_user("wasm32-wasi");
     let wasi_sdk = PathBuf::from("/wasi-sdk");
     // SAFETY: bootstrap tests run on a single thread
@@ -215,7 +215,7 @@ fn test_default_compiler_wasi() {
 
 #[test]
 fn test_default_compiler_fallback() {
-    let build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
+    let build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) });
     let target = TargetSelection::from_user("x86_64-unknown-linux-gnu");
     let mut cfg = cc::Build::new();
     let result = default_compiler(&mut cfg, Language::C, target, &build);
@@ -224,7 +224,7 @@ fn test_default_compiler_fallback() {
 
 #[test]
 fn test_find_target_with_config() {
-    let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
+    let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) });
     let target = TargetSelection::from_user("x86_64-unknown-linux-gnu");
     let mut target_config = Target::default();
     target_config.cc = Some(PathBuf::from("dummy-cc"));
@@ -249,7 +249,7 @@ fn test_find_target_with_config() {
 
 #[test]
 fn test_find_target_without_config() {
-    let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
+    let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) });
     let target = TargetSelection::from_user("x86_64-unknown-linux-gnu");
     build.config.target_config.clear();
     find_target(&build, target.clone());
@@ -262,7 +262,7 @@ fn test_find_target_without_config() {
 
 #[test]
 fn test_find() {
-    let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
+    let mut build = Build::new(Config { ..Config::parse(Flags::parse(&["build".to_owned()])) });
     let target1 = TargetSelection::from_user("x86_64-unknown-linux-gnu");
     let target2 = TargetSelection::from_user("x86_64-unknown-openbsd");
     build.targets.push(target1.clone());
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 9f6b80c6379..8d6c8284e44 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -85,6 +85,7 @@ dependencies = [
  "query-group-macro",
  "rustc-hash 2.1.1",
  "salsa",
+ "salsa-macros",
  "semver",
  "span",
  "syntax",
@@ -630,6 +631,7 @@ dependencies = [
  "rustc-hash 2.1.1",
  "rustc_apfloat",
  "salsa",
+ "salsa-macros",
  "smallvec",
  "span",
  "stdx",
@@ -660,6 +662,7 @@ dependencies = [
  "query-group-macro",
  "rustc-hash 2.1.1",
  "salsa",
+ "salsa-macros",
  "smallvec",
  "span",
  "stdx",
@@ -700,6 +703,7 @@ dependencies = [
  "rustc-hash 2.1.1",
  "rustc_apfloat",
  "salsa",
+ "salsa-macros",
  "scoped-tls",
  "smallvec",
  "span",
@@ -936,6 +940,7 @@ dependencies = [
  "rayon",
  "rustc-hash 2.1.1",
  "salsa",
+ "salsa-macros",
  "span",
  "stdx",
  "syntax",
@@ -1729,6 +1734,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "salsa",
+ "salsa-macros",
  "syn",
 ]
 
@@ -2033,9 +2039,9 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
 
 [[package]]
 name = "salsa"
-version = "0.20.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1be22155f8d9732518b2db2bf379fe6f0b2375e76b08b7c8fe6c1b887d548c24"
+checksum = "6f80d5cf3c3fcab2cef898012f242a670477a1baa609267376af9cb4409026c5"
 dependencies = [
  "boxcar",
  "crossbeam-queue",
@@ -2056,15 +2062,15 @@ dependencies = [
 
 [[package]]
 name = "salsa-macro-rules"
-version = "0.20.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f55a7ef0a84e336f7c5f0332d81727f5629fe042d2aa556c75307afebc9f78a5"
+checksum = "05303d72606fbf2b9c9523cda2039bb8ecb00304027a3cd7e52b02a65c7d9185"
 
 [[package]]
 name = "salsa-macros"
-version = "0.20.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d0e88a9c0c0d231a63f83dcd1a2c5e5d11044fac4b65bc9ad3b68ab48b0a0ab"
+checksum = "eb2f0e2a30c65cb3cd63440c491dde68d9af7e1be2b77832ac7057141107db50"
 dependencies = [
  "heck",
  "proc-macro2",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 6fa171702dd..c4c2fdf34ba 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -131,7 +131,9 @@ process-wrap = { version = "8.2.0", features = ["std"] }
 pulldown-cmark-to-cmark = "10.0.4"
 pulldown-cmark = { version = "0.9.6", default-features = false }
 rayon = "1.10.0"
-salsa = "0.20.0"
+rowan = "=0.15.15"
+salsa = { version = "0.21.1", default-features = false, features = ["rayon","salsa_unstable"] }
+salsa-macros = "0.21.1"
 semver = "1.0.26"
 serde = { version = "1.0.219" }
 serde_derive = { version = "1.0.219" }
diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
index 441434504c2..e2e3253773f 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -15,6 +15,7 @@ rust-version.workspace = true
 la-arena.workspace = true
 dashmap.workspace = true
 salsa.workspace = true
+salsa-macros.workspace = true
 query-group.workspace = true
 rustc-hash.workspace = true
 triomphe.workspace = true
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index 499c9b3716b..9660e6e87cc 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -392,7 +392,7 @@ impl BuiltDependency {
 
 pub type CratesIdMap = FxHashMap<CrateBuilderId, Crate>;
 
-#[salsa::input]
+#[salsa_macros::input]
 #[derive(Debug)]
 pub struct Crate {
     #[return_ref]
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index 7f7a712577e..a67fbf75c02 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -1,9 +1,13 @@
 //! base_db defines basic database traits. The concrete DB is defined by ide.
+
+pub use salsa;
+pub use salsa_macros;
+
 // FIXME: Rename this crate, base db is non descriptive
 mod change;
 mod input;
 
-use std::hash::BuildHasherDefault;
+use std::{cell::RefCell, hash::BuildHasherDefault, panic, sync::Once};
 
 pub use crate::{
     change::FileChange,
@@ -17,7 +21,6 @@ pub use crate::{
 use dashmap::{DashMap, mapref::entry::Entry};
 pub use query_group::{self};
 use rustc_hash::{FxHashSet, FxHasher};
-pub use salsa::{self};
 use salsa::{Durability, Setter};
 pub use semver::{BuildMetadata, Prerelease, Version, VersionReq};
 use span::Edition;
@@ -28,7 +31,7 @@ pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet}
 #[macro_export]
 macro_rules! impl_intern_key {
     ($id:ident, $loc:ident) => {
-        #[salsa::interned(no_lifetime)]
+        #[salsa_macros::interned(no_lifetime)]
         pub struct $id {
             pub loc: $loc,
         }
@@ -57,7 +60,12 @@ pub struct Files {
 
 impl Files {
     pub fn file_text(&self, file_id: vfs::FileId) -> FileText {
-        *self.files.get(&file_id).expect("Unable to fetch file; this is a bug")
+        match self.files.get(&file_id) {
+            Some(text) => *text,
+            None => {
+                panic!("Unable to fetch file text for `vfs::FileId`: {file_id:?}; this is a bug")
+            }
+        }
     }
 
     pub fn set_file_text(&self, db: &mut dyn SourceDatabase, file_id: vfs::FileId, text: &str) {
@@ -93,10 +101,12 @@ impl Files {
 
     /// Source root of the file.
     pub fn source_root(&self, source_root_id: SourceRootId) -> SourceRootInput {
-        let source_root = self
-            .source_roots
-            .get(&source_root_id)
-            .expect("Unable to fetch source root id; this is a bug");
+        let source_root = match self.source_roots.get(&source_root_id) {
+            Some(source_root) => source_root,
+            None => panic!(
+                "Unable to fetch `SourceRootInput` with `SourceRootId` ({source_root_id:?}); this is a bug"
+            ),
+        };
 
         *source_root
     }
@@ -121,10 +131,12 @@ impl Files {
     }
 
     pub fn file_source_root(&self, id: vfs::FileId) -> FileSourceRootInput {
-        let file_source_root = self
-            .file_source_roots
-            .get(&id)
-            .expect("Unable to fetch FileSourceRootInput; this is a bug");
+        let file_source_root = match self.file_source_roots.get(&id) {
+            Some(file_source_root) => file_source_root,
+            None => panic!(
+                "Unable to get `FileSourceRootInput` with `vfs::FileId` ({id:?}); this is a bug",
+            ),
+        };
         *file_source_root
     }
 
@@ -152,7 +164,7 @@ impl Files {
     }
 }
 
-#[salsa::interned(no_lifetime, debug, constructor=from_span)]
+#[salsa_macros::interned(no_lifetime, debug, constructor=from_span)]
 pub struct EditionedFileId {
     pub editioned_file_id: span::EditionedFileId,
 }
@@ -187,18 +199,18 @@ impl EditionedFileId {
     }
 }
 
-#[salsa::input(debug)]
+#[salsa_macros::input(debug)]
 pub struct FileText {
     pub text: Arc<str>,
     pub file_id: vfs::FileId,
 }
 
-#[salsa::input(debug)]
+#[salsa_macros::input(debug)]
 pub struct FileSourceRootInput {
     pub source_root_id: SourceRootId,
 }
 
-#[salsa::input(debug)]
+#[salsa_macros::input(debug)]
 pub struct SourceRootInput {
     pub source_root: Arc<SourceRoot>,
 }
@@ -265,7 +277,7 @@ pub fn transitive_deps(db: &dyn SourceDatabase, crate_id: Crate) -> FxHashSet<Cr
     deps
 }
 
-#[salsa::db]
+#[salsa_macros::db]
 pub trait SourceDatabase: salsa::Database {
     /// Text of the file.
     fn file_text(&self, file_id: vfs::FileId) -> FileText;
@@ -344,7 +356,7 @@ fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse<ast::SourceFil
 }
 
 fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<&[SyntaxError]> {
-    #[salsa::tracked(return_ref)]
+    #[salsa_macros::tracked(return_ref)]
     fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<Box<[SyntaxError]>> {
         let errors = db.parse(file_id).errors();
         match &*errors {
@@ -373,3 +385,49 @@ fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[Crate]> {
     let source_root = db.file_source_root(file_id);
     db.source_root_crates(source_root.source_root_id(db))
 }
+
+#[must_use]
+#[non_exhaustive]
+pub struct DbPanicContext;
+
+impl Drop for DbPanicContext {
+    fn drop(&mut self) {
+        Self::with_ctx(|ctx| assert!(ctx.pop().is_some()));
+    }
+}
+
+impl DbPanicContext {
+    pub fn enter(frame: String) -> DbPanicContext {
+        #[expect(clippy::print_stderr, reason = "already panicking anyway")]
+        fn set_hook() {
+            let default_hook = panic::take_hook();
+            panic::set_hook(Box::new(move |panic_info| {
+                default_hook(panic_info);
+                if let Some(backtrace) = salsa::Backtrace::capture() {
+                    eprintln!("{backtrace:#}");
+                }
+                DbPanicContext::with_ctx(|ctx| {
+                    if !ctx.is_empty() {
+                        eprintln!("additional context:");
+                        for (idx, frame) in ctx.iter().enumerate() {
+                            eprintln!("{idx:>4}: {frame}\n");
+                        }
+                    }
+                });
+            }));
+        }
+
+        static SET_HOOK: Once = Once::new();
+        SET_HOOK.call_once(set_hook);
+
+        Self::with_ctx(|ctx| ctx.push(frame));
+        DbPanicContext
+    }
+
+    fn with_ctx(f: impl FnOnce(&mut Vec<String>)) {
+        thread_local! {
+            static CTX: RefCell<Vec<String>> = const { RefCell::new(Vec::new()) };
+        }
+        CTX.with(|ctx| f(&mut ctx.borrow_mut()));
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
index f97597ffe5a..c1c89e8d1cc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
@@ -28,6 +28,7 @@ triomphe.workspace = true
 rustc_apfloat = "0.2.2"
 text-size.workspace = true
 salsa.workspace = true
+salsa-macros.workspace = true
 query-group.workspace = true
 
 ra-ap-rustc_parse_format.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index a80313aba3e..bb6222b1d46 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -1,6 +1,6 @@
 //! A higher level attributes based on TokenTree, with also some shortcuts.
 
-use std::{borrow::Cow, hash::Hash, ops};
+use std::{borrow::Cow, convert::identity, hash::Hash, ops};
 
 use base_db::Crate;
 use cfg::{CfgExpr, CfgOptions};
@@ -8,6 +8,7 @@ use either::Either;
 use hir_expand::{
     HirFileId, InFile,
     attrs::{Attr, AttrId, RawAttrs, collect_attrs},
+    span_map::SpanMapRef,
 };
 use intern::{Symbol, sym};
 use la_arena::{ArenaMap, Idx, RawIdx};
@@ -45,8 +46,27 @@ impl Attrs {
         (**self).iter().find(|attr| attr.id == id)
     }
 
-    pub(crate) fn filter(db: &dyn DefDatabase, krate: Crate, raw_attrs: RawAttrs) -> Attrs {
-        Attrs(raw_attrs.filter(db, krate))
+    pub(crate) fn expand_cfg_attr(
+        db: &dyn DefDatabase,
+        krate: Crate,
+        raw_attrs: RawAttrs,
+    ) -> Attrs {
+        Attrs(raw_attrs.expand_cfg_attr(db, krate))
+    }
+
+    pub(crate) fn is_cfg_enabled_for(
+        db: &dyn DefDatabase,
+        owner: &dyn ast::HasAttrs,
+        span_map: SpanMapRef<'_>,
+        cfg_options: &CfgOptions,
+    ) -> Result<(), CfgExpr> {
+        RawAttrs::attrs_iter_expanded::<false>(db, owner, span_map, cfg_options)
+            .filter_map(|attr| attr.cfg())
+            .find_map(|cfg| match cfg_options.check(&cfg).is_none_or(identity) {
+                true => None,
+                false => Some(cfg),
+            })
+            .map_or(Ok(()), Err)
     }
 }
 
@@ -522,38 +542,41 @@ impl AttrsWithOwner {
                 GenericParamId::ConstParamId(it) => {
                     let src = it.parent().child_source(db);
                     // FIXME: We should be never getting `None` here.
-                    match src.value.get(it.local_id()) {
-                        Some(val) => RawAttrs::from_attrs_owner(
+                    return Attrs(match src.value.get(it.local_id()) {
+                        Some(val) => RawAttrs::new_expanded(
                             db,
-                            src.with_value(val),
+                            val,
                             db.span_map(src.file_id).as_ref(),
+                            def.krate(db).cfg_options(db),
                         ),
                         None => RawAttrs::EMPTY,
-                    }
+                    });
                 }
                 GenericParamId::TypeParamId(it) => {
                     let src = it.parent().child_source(db);
                     // FIXME: We should be never getting `None` here.
-                    match src.value.get(it.local_id()) {
-                        Some(val) => RawAttrs::from_attrs_owner(
+                    return Attrs(match src.value.get(it.local_id()) {
+                        Some(val) => RawAttrs::new_expanded(
                             db,
-                            src.with_value(val),
+                            val,
                             db.span_map(src.file_id).as_ref(),
+                            def.krate(db).cfg_options(db),
                         ),
                         None => RawAttrs::EMPTY,
-                    }
+                    });
                 }
                 GenericParamId::LifetimeParamId(it) => {
                     let src = it.parent.child_source(db);
                     // FIXME: We should be never getting `None` here.
-                    match src.value.get(it.local_id) {
-                        Some(val) => RawAttrs::from_attrs_owner(
+                    return Attrs(match src.value.get(it.local_id) {
+                        Some(val) => RawAttrs::new_expanded(
                             db,
-                            src.with_value(val),
+                            val,
                             db.span_map(src.file_id).as_ref(),
+                            def.krate(db).cfg_options(db),
                         ),
                         None => RawAttrs::EMPTY,
-                    }
+                    });
                 }
             },
             AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it),
@@ -561,7 +584,7 @@ impl AttrsWithOwner {
             AttrDefId::UseId(it) => attrs_from_item_tree_loc(db, it),
         };
 
-        let attrs = raw_attrs.filter(db, def.krate(db));
+        let attrs = raw_attrs.expand_cfg_attr(db, def.krate(db));
         Attrs(attrs)
     }
 
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 34cf42d02bd..2cbdbe16f9b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -22,7 +22,7 @@ use crate::{
     hir::generics::GenericParams,
     import_map::ImportMap,
     item_tree::{AttrOwner, ItemTree},
-    lang_item::{self, LangItem, LangItemTarget, LangItems},
+    lang_item::{self, LangItem},
     nameres::{
         DefMap, LocalDefMap,
         assoc::{ImplItems, TraitItems},
@@ -325,9 +325,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
 
     // endregion:attrs
 
-    #[salsa::invoke(LangItems::lang_item_query)]
-    fn lang_item(&self, start_crate: Crate, item: LangItem) -> Option<LangItemTarget>;
-
     #[salsa::invoke(ImportMap::import_map_query)]
     fn import_map(&self, krate: Crate) -> Arc<ImportMap>;
 
@@ -349,9 +346,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
 
     // endregion:visibilities
 
-    #[salsa::invoke(LangItems::crate_lang_items_query)]
-    fn crate_lang_items(&self, krate: Crate) -> Option<Arc<LangItems>>;
-
     #[salsa::invoke(crate::lang_item::notable_traits_in_deps)]
     fn notable_traits_in_deps(&self, krate: Crate) -> Arc<[Arc<[TraitId]>]>;
     #[salsa::invoke(crate::lang_item::crate_notable_traits)]
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs
index 7eec913dd65..3823fb5a1e7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs
@@ -3,21 +3,24 @@
 use std::mem;
 
 use base_db::Crate;
+use cfg::CfgOptions;
 use drop_bomb::DropBomb;
+use hir_expand::AstId;
 use hir_expand::{
     ExpandError, ExpandErrorKind, ExpandResult, HirFileId, InFile, Lookup, MacroCallId,
-    attrs::RawAttrs, eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap,
+    eager::EagerCallBackFn, mod_path::ModPath, span_map::SpanMap,
 };
 use span::{AstIdMap, Edition, SyntaxContext};
 use syntax::ast::HasAttrs;
-use syntax::{Parse, ast};
+use syntax::{AstNode, Parse, ast};
 use triomphe::Arc;
 use tt::TextRange;
 
 use crate::attr::Attrs;
 use crate::expr_store::HygieneId;
+use crate::macro_call_as_call_id;
 use crate::nameres::DefMap;
-use crate::{AsMacroCall, MacroId, UnresolvedMacro, db::DefDatabase};
+use crate::{MacroId, UnresolvedMacro, db::DefDatabase};
 
 #[derive(Debug)]
 pub(super) struct Expander {
@@ -64,22 +67,13 @@ impl Expander {
         }
     }
 
-    pub(super) fn attrs(
-        &self,
-        db: &dyn DefDatabase,
-        krate: Crate,
-        has_attrs: &dyn HasAttrs,
-    ) -> Attrs {
-        Attrs::filter(db, krate, RawAttrs::new(db, has_attrs, self.span_map.as_ref()))
-    }
-
     pub(super) fn is_cfg_enabled(
         &self,
         db: &dyn DefDatabase,
-        krate: Crate,
         has_attrs: &dyn HasAttrs,
-    ) -> bool {
-        self.attrs(db, krate, has_attrs).is_cfg_enabled(krate.cfg_options(db))
+        cfg_options: &CfgOptions,
+    ) -> Result<(), cfg::CfgExpr> {
+        Attrs::is_cfg_enabled_for(db, has_attrs, self.span_map.as_ref(), cfg_options)
     }
 
     pub(super) fn call_syntax_ctx(&self) -> SyntaxContext {
@@ -100,8 +94,31 @@ impl Expander {
 
         let result = self.within_limit(db, |this| {
             let macro_call = this.in_file(&macro_call);
-            match macro_call.as_call_id_with_errors(
+
+            let expands_to = hir_expand::ExpandTo::from_call_site(macro_call.value);
+            let ast_id = AstId::new(macro_call.file_id, this.ast_id_map().ast_id(macro_call.value));
+            let path = macro_call.value.path().and_then(|path| {
+                let range = path.syntax().text_range();
+                let mod_path = ModPath::from_src(db, path, &mut |range| {
+                    this.span_map.span_for_range(range).ctx
+                })?;
+                let call_site = this.span_map.span_for_range(range);
+                Some((call_site, mod_path))
+            });
+
+            let Some((call_site, path)) = path else {
+                return ExpandResult::only_err(ExpandError::other(
+                    this.span_map.span_for_range(macro_call.value.syntax().text_range()),
+                    "malformed macro invocation",
+                ));
+            };
+
+            match macro_call_as_call_id(
                 db,
+                ast_id,
+                &path,
+                call_site.ctx,
+                expands_to,
                 krate,
                 |path| resolver(path).map(|it| db.macro_def(it)),
                 eager_callback,
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 7f907fdba8e..50505d54ba2 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
@@ -7,6 +7,7 @@ mod path;
 
 use std::mem;
 
+use cfg::CfgOptions;
 use either::Either;
 use hir_expand::{
     HirFileId, InFile, Lookup, MacroDefId,
@@ -81,8 +82,6 @@ pub(super) fn lower_body(
     // even though they should be the same. Also, when the body comes from multiple expansions, their
     // hygiene is different.
 
-    let krate = module.krate();
-
     let mut self_param = None;
     let mut source_map_self_param = None;
     let mut params = vec![];
@@ -100,9 +99,8 @@ pub(super) fn lower_body(
     // and skip the body.
     if skip_body {
         if let Some(param_list) = parameters {
-            if let Some(self_param_syn) = param_list
-                .self_param()
-                .filter(|self_param| collector.expander.is_cfg_enabled(db, krate, self_param))
+            if let Some(self_param_syn) =
+                param_list.self_param().filter(|self_param| collector.check_cfg(self_param))
             {
                 let is_mutable =
                     self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
@@ -119,10 +117,7 @@ pub(super) fn lower_body(
                 source_map_self_param =
                     Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
             }
-            let count = param_list
-                .params()
-                .filter(|it| collector.expander.is_cfg_enabled(db, krate, it))
-                .count();
+            let count = param_list.params().filter(|it| collector.check_cfg(it)).count();
             params = (0..count).map(|_| collector.missing_pat()).collect();
         };
         let body_expr = collector.missing_expr();
@@ -138,9 +133,7 @@ pub(super) fn lower_body(
     }
 
     if let Some(param_list) = parameters {
-        if let Some(self_param_syn) =
-            param_list.self_param().filter(|it| collector.expander.is_cfg_enabled(db, krate, it))
-        {
+        if let Some(self_param_syn) = param_list.self_param().filter(|it| collector.check_cfg(it)) {
             let is_mutable =
                 self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
             let hygiene = self_param_syn
@@ -157,7 +150,7 @@ pub(super) fn lower_body(
         }
 
         for param in param_list.params() {
-            if collector.expander.is_cfg_enabled(db, krate, &param) {
+            if collector.check_cfg(&param) {
                 let param_pat = collector.collect_pat_top(param.pat());
                 params.push(param_pat);
             }
@@ -346,7 +339,7 @@ pub(crate) fn lower_function(
     collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| {
         if let Some(param_list) = fn_.value.param_list() {
             if let Some(param) = param_list.self_param() {
-                let enabled = collector.expander.is_cfg_enabled(db, module.krate(), &param);
+                let enabled = collector.check_cfg(&param);
                 if enabled {
                     has_self_param = true;
                     params.push(match param.ty() {
@@ -381,7 +374,7 @@ pub(crate) fn lower_function(
             }
             let p = param_list
                 .params()
-                .filter(|param| collector.expander.is_cfg_enabled(db, module.krate(), param))
+                .filter(|param| collector.check_cfg(param))
                 .filter(|param| {
                     let is_variadic = param.dotdotdot_token().is_some();
                     has_variadic |= is_variadic;
@@ -441,6 +434,7 @@ pub(crate) fn lower_function(
 
 pub struct ExprCollector<'db> {
     db: &'db dyn DefDatabase,
+    cfg_options: &'db CfgOptions,
     expander: Expander,
     def_map: Arc<DefMap>,
     local_def_map: Arc<LocalDefMap>,
@@ -553,6 +547,7 @@ impl ExprCollector<'_> {
         let expander = Expander::new(db, current_file_id, &def_map);
         ExprCollector {
             db,
+            cfg_options: module.krate().cfg_options(db),
             module,
             def_map,
             local_def_map,
@@ -1026,7 +1021,9 @@ impl ExprCollector<'_> {
     /// Returns `None` if and only if the expression is `#[cfg]`d out.
     fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
         let syntax_ptr = AstPtr::new(&expr);
-        self.check_cfg(&expr)?;
+        if !self.check_cfg(&expr) {
+            return None;
+        }
 
         // FIXME: Move some of these arms out into separate methods for clarity
         Some(match expr {
@@ -1114,6 +1111,7 @@ impl ExprCollector<'_> {
             ast::Expr::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e),
             ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e),
             ast::Expr::CallExpr(e) => {
+                // FIXME: Remove this once we drop support for <1.86, https://github.com/rust-lang/rust/commit/ac9cb908ac4301dfc25e7a2edee574320022ae2c
                 let is_rustc_box = {
                     let attrs = e.attrs();
                     attrs.filter_map(|it| it.as_simple_atom()).any(|it| it == "rustc_box")
@@ -1156,13 +1154,17 @@ impl ExprCollector<'_> {
                     match_arm_list
                         .arms()
                         .filter_map(|arm| {
-                            self.check_cfg(&arm).map(|()| MatchArm {
-                                pat: self.collect_pat_top(arm.pat()),
-                                expr: self.collect_expr_opt(arm.expr()),
-                                guard: arm
-                                    .guard()
-                                    .map(|guard| self.collect_expr_opt(guard.condition())),
-                            })
+                            if self.check_cfg(&arm) {
+                                Some(MatchArm {
+                                    pat: self.collect_pat_top(arm.pat()),
+                                    expr: self.collect_expr_opt(arm.expr()),
+                                    guard: arm
+                                        .guard()
+                                        .map(|guard| self.collect_expr_opt(guard.condition())),
+                                })
+                            } else {
+                                None
+                            }
                         })
                         .collect()
                 } else {
@@ -1230,7 +1232,9 @@ impl ExprCollector<'_> {
                     let fields = nfl
                         .fields()
                         .filter_map(|field| {
-                            self.check_cfg(&field)?;
+                            if !self.check_cfg(&field) {
+                                return None;
+                            }
 
                             let name = field.field_name()?.as_name();
 
@@ -1483,7 +1487,9 @@ impl ExprCollector<'_> {
     }
 
     fn maybe_collect_expr_as_pat(&mut self, expr: &ast::Expr) -> Option<PatId> {
-        self.check_cfg(expr)?;
+        if !self.check_cfg(expr) {
+            return None;
+        }
         let syntax_ptr = AstPtr::new(expr);
 
         let result = match expr {
@@ -1558,7 +1564,9 @@ impl ExprCollector<'_> {
                 let args = record_field_list
                     .fields()
                     .filter_map(|f| {
-                        self.check_cfg(&f)?;
+                        if !self.check_cfg(&f) {
+                            return None;
+                        }
                         let field_expr = f.expr()?;
                         let pat = self.collect_expr_as_pat(field_expr);
                         let name = f.field_name()?.as_name();
@@ -2044,7 +2052,7 @@ impl ExprCollector<'_> {
     fn collect_stmt(&mut self, statements: &mut Vec<Statement>, s: ast::Stmt) {
         match s {
             ast::Stmt::LetStmt(stmt) => {
-                if self.check_cfg(&stmt).is_none() {
+                if !self.check_cfg(&stmt) {
                     return;
                 }
                 let pat = self.collect_pat_top(stmt.pat());
@@ -2059,7 +2067,7 @@ impl ExprCollector<'_> {
             ast::Stmt::ExprStmt(stmt) => {
                 let expr = stmt.expr();
                 match &expr {
-                    Some(expr) if self.check_cfg(expr).is_none() => return,
+                    Some(expr) if !self.check_cfg(expr) => return,
                     _ => (),
                 }
                 let has_semi = stmt.semicolon_token().is_some();
@@ -2074,7 +2082,7 @@ impl ExprCollector<'_> {
                 }
             }
             ast::Stmt::Item(ast::Item::MacroDef(macro_)) => {
-                if self.check_cfg(&macro_).is_none() {
+                if !self.check_cfg(&macro_) {
                     return;
                 }
                 let Some(name) = macro_.name() else {
@@ -2086,7 +2094,7 @@ impl ExprCollector<'_> {
                 self.collect_macro_def(statements, macro_id);
             }
             ast::Stmt::Item(ast::Item::MacroRules(macro_)) => {
-                if self.check_cfg(&macro_).is_none() {
+                if !self.check_cfg(&macro_) {
                     return;
                 }
                 let Some(name) = macro_.name() else {
@@ -2360,7 +2368,9 @@ impl ExprCollector<'_> {
                 let args = record_pat_field_list
                     .fields()
                     .filter_map(|f| {
-                        self.check_cfg(&f)?;
+                        if !self.check_cfg(&f) {
+                            return None;
+                        }
                         let ast_pat = f.pat()?;
                         let pat = self.collect_pat(ast_pat, binding_list);
                         let name = f.field_name()?.as_name();
@@ -2536,25 +2546,18 @@ impl ExprCollector<'_> {
 
     /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
     /// not.
-    fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> Option<()> {
-        let attrs = self.expander.attrs(self.db, self.module.krate(), owner);
-        match attrs.cfg() {
-            Some(cfg) => {
-                let cfg_options = self.module.krate().cfg_options(self.db);
-
-                if cfg_options.check(&cfg) != Some(false) {
-                    return Some(());
-                }
-
+    fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> bool {
+        let enabled = self.expander.is_cfg_enabled(self.db, owner, self.cfg_options);
+        match enabled {
+            Ok(()) => true,
+            Err(cfg) => {
                 self.source_map.diagnostics.push(ExpressionStoreDiagnostics::InactiveCode {
                     node: self.expander.in_file(SyntaxNodePtr::new(owner.syntax())),
                     cfg,
-                    opts: cfg_options.clone(),
+                    opts: self.cfg_options.clone(),
                 });
-
-                None
+                false
             }
-            None => Some(()),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs
index 9485e703d9c..02a1d274fb5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/generics.rs
@@ -110,7 +110,7 @@ impl GenericParamsCollector {
 
     fn lower_param_list(&mut self, ec: &mut ExprCollector<'_>, params: ast::GenericParamList) {
         for generic_param in params.generic_params() {
-            let enabled = ec.expander.is_cfg_enabled(ec.db, ec.module.krate(), &generic_param);
+            let enabled = ec.check_cfg(&generic_param);
             if !enabled {
                 continue;
             }
@@ -270,7 +270,7 @@ impl GenericParamsCollector {
         let self_ = Name::new_symbol_root(sym::Self_);
         let idx = self.type_or_consts.alloc(
             TypeParamData {
-                name: Some(self_.clone()),
+                name: Some(self_),
                 default: None,
                 provenance: TypeParamProvenance::TraitSelf,
             }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index bece940950d..5362c0588db 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -167,7 +167,7 @@ pub struct ItemScope {
     // the resolutions of the imports of this scope
     use_imports_types: FxHashMap<ImportOrExternCrate, ImportOrDef>,
     use_imports_values: FxHashMap<ImportOrGlob, ImportOrDef>,
-    use_imports_macros: FxHashMap<ImportOrGlob, ImportOrDef>,
+    use_imports_macros: FxHashMap<ImportOrExternCrate, ImportOrDef>,
 
     use_decls: Vec<UseId>,
     extern_crate_decls: Vec<ExternCrateId>,
@@ -242,7 +242,7 @@ impl ItemScope {
         self.types.iter().map(|(n, &i)| (n, i))
     }
 
-    pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportOrGlob>)> + '_ {
+    pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportOrExternCrate>)> + '_ {
         self.macros.iter().map(|(n, &i)| (n, i))
     }
 
@@ -250,9 +250,9 @@ impl ItemScope {
         self.use_imports_types
             .keys()
             .copied()
+            .chain(self.use_imports_macros.keys().copied())
             .filter_map(ImportOrExternCrate::import_or_glob)
             .chain(self.use_imports_values.keys().copied())
-            .chain(self.use_imports_macros.keys().copied())
             .filter_map(ImportOrGlob::into_import)
             .sorted()
             .dedup()
@@ -263,7 +263,7 @@ impl ItemScope {
 
         let mut def_map;
         let mut scope = self;
-        while let Some(&m) = scope.use_imports_macros.get(&ImportOrGlob::Import(import)) {
+        while let Some(&m) = scope.use_imports_macros.get(&ImportOrExternCrate::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
                     let module_id = i.use_.lookup(db).container;
@@ -682,7 +682,6 @@ impl ItemScope {
                         }
                         _ => _ = glob_imports.macros.remove(&lookup),
                     }
-                    let import = import.and_then(ImportOrExternCrate::import_or_glob);
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
                         self.use_imports_macros.insert(
@@ -698,7 +697,6 @@ impl ItemScope {
                 {
                     if glob_imports.macros.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
-                        let import = import.and_then(ImportOrExternCrate::import_or_glob);
                         let prev = std::mem::replace(&mut fld.import, import);
                         if let Some(import) = import {
                             self.use_imports_macros.insert(
@@ -783,8 +781,9 @@ impl ItemScope {
             if let Some(Item { import, .. }) = def.macros {
                 buf.push_str(" m");
                 match import {
-                    Some(ImportOrGlob::Import(_)) => buf.push('i'),
-                    Some(ImportOrGlob::Glob(_)) => buf.push('g'),
+                    Some(ImportOrExternCrate::Import(_)) => buf.push('i'),
+                    Some(ImportOrExternCrate::Glob(_)) => buf.push('g'),
+                    Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'),
                     None => (),
                 }
             }
@@ -893,9 +892,7 @@ impl PerNs {
             ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import),
             ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import),
             ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import),
-            ModuleDefId::MacroId(mac) => {
-                PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::import_or_glob))
-            }
+            ModuleDefId::MacroId(mac) => PerNs::macros(mac, v, import),
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index 01d340cea6d..1b97eb72b6f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -179,7 +179,7 @@ impl ItemTree {
 
     /// Returns the inner attributes of the source file.
     pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs {
-        Attrs::filter(
+        Attrs::expand_cfg_attr(
             db,
             krate,
             self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(),
@@ -191,7 +191,7 @@ impl ItemTree {
     }
 
     pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: Crate, of: AttrOwner) -> Attrs {
-        Attrs::filter(db, krate, self.raw_attrs(of).clone())
+        Attrs::expand_cfg_attr(db, krate, self.raw_attrs(of).clone())
     }
 
     /// Returns a count of a few, expensive items.
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 5431ec9679c..51a833b5f15 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
@@ -83,104 +83,99 @@ impl LangItemTarget {
     }
 }
 
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
-pub struct LangItems {
-    items: FxHashMap<LangItem, LangItemTarget>,
-}
+/// Salsa query. This will look for lang items in a specific crate.
+#[salsa_macros::tracked(return_ref)]
+pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangItems>> {
+    let _p = tracing::info_span!("crate_lang_items_query").entered();
 
-impl LangItems {
-    pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
-        self.items.get(&item).copied()
-    }
+    let mut lang_items = LangItems::default();
 
-    /// Salsa query. This will look for lang items in a specific crate.
-    pub(crate) fn crate_lang_items_query(
-        db: &dyn DefDatabase,
-        krate: Crate,
-    ) -> Option<Arc<LangItems>> {
-        let _p = tracing::info_span!("crate_lang_items_query").entered();
-
-        let mut lang_items = LangItems::default();
+    let crate_def_map = db.crate_def_map(krate);
 
-        let crate_def_map = db.crate_def_map(krate);
+    for (_, module_data) in crate_def_map.modules() {
+        for impl_def in module_data.scope.impls() {
+            lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
+            for &(_, assoc) in db.impl_items(impl_def).items.iter() {
+                match assoc {
+                    AssocItemId::FunctionId(f) => {
+                        lang_items.collect_lang_item(db, f, LangItemTarget::Function)
+                    }
+                    AssocItemId::TypeAliasId(t) => {
+                        lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
+                    }
+                    AssocItemId::ConstId(_) => (),
+                }
+            }
+        }
 
-        for (_, module_data) in crate_def_map.modules() {
-            for impl_def in module_data.scope.impls() {
-                lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
-                for &(_, assoc) in db.impl_items(impl_def).items.iter() {
-                    match assoc {
+        for def in module_data.scope.declarations() {
+            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)
+                            lang_items.collect_lang_item(db, f, LangItemTarget::Function);
                         }
-                        AssocItemId::TypeAliasId(t) => {
-                            lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
+                        AssocItemId::TypeAliasId(alias) => {
+                            lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
                         }
-                        AssocItemId::ConstId(_) => (),
-                    }
+                        AssocItemId::ConstId(_) => {}
+                    });
                 }
-            }
-
-            for def in module_data.scope.declarations() {
-                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);
-                                }
-                                AssocItemId::TypeAliasId(alias) => lang_items.collect_lang_item(
-                                    db,
-                                    alias,
-                                    LangItemTarget::TypeAlias,
-                                ),
-                                AssocItemId::ConstId(_) => {}
-                            },
-                        );
-                    }
-                    ModuleDefId::AdtId(AdtId::EnumId(e)) => {
-                        lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
-                        db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
-                            lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
-                        });
-                    }
-                    ModuleDefId::AdtId(AdtId::StructId(s)) => {
-                        lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
-                    }
-                    ModuleDefId::AdtId(AdtId::UnionId(u)) => {
-                        lang_items.collect_lang_item(db, u, LangItemTarget::Union);
-                    }
-                    ModuleDefId::FunctionId(f) => {
-                        lang_items.collect_lang_item(db, f, LangItemTarget::Function);
-                    }
-                    ModuleDefId::StaticId(s) => {
-                        lang_items.collect_lang_item(db, s, LangItemTarget::Static);
-                    }
-                    ModuleDefId::TypeAliasId(t) => {
-                        lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
-                    }
-                    _ => {}
+                ModuleDefId::AdtId(AdtId::EnumId(e)) => {
+                    lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
+                    db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
+                        lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
+                    });
+                }
+                ModuleDefId::AdtId(AdtId::StructId(s)) => {
+                    lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
+                }
+                ModuleDefId::AdtId(AdtId::UnionId(u)) => {
+                    lang_items.collect_lang_item(db, u, LangItemTarget::Union);
                 }
+                ModuleDefId::FunctionId(f) => {
+                    lang_items.collect_lang_item(db, f, LangItemTarget::Function);
+                }
+                ModuleDefId::StaticId(s) => {
+                    lang_items.collect_lang_item(db, s, LangItemTarget::Static);
+                }
+                ModuleDefId::TypeAliasId(t) => {
+                    lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
+                }
+                _ => {}
             }
         }
+    }
 
-        if lang_items.items.is_empty() { None } else { Some(Arc::new(lang_items)) }
+    if lang_items.items.is_empty() { None } else { Some(Box::new(lang_items)) }
+}
+
+/// Salsa query. Look for a lang item, starting from the specified crate and recursively
+/// traversing its dependencies.
+#[salsa_macros::tracked]
+pub fn lang_item(
+    db: &dyn DefDatabase,
+    start_crate: Crate,
+    item: LangItem,
+) -> Option<LangItemTarget> {
+    let _p = tracing::info_span!("lang_item_query").entered();
+    if let Some(target) =
+        crate_lang_items(db, start_crate).as_ref().and_then(|it| it.items.get(&item).copied())
+    {
+        return Some(target);
     }
+    start_crate.data(db).dependencies.iter().find_map(|dep| lang_item(db, dep.crate_id, item))
+}
 
-    /// Salsa query. Look for a lang item, starting from the specified crate and recursively
-    /// traversing its dependencies.
-    pub(crate) fn lang_item_query(
-        db: &dyn DefDatabase,
-        start_crate: Crate,
-        item: LangItem,
-    ) -> Option<LangItemTarget> {
-        let _p = tracing::info_span!("lang_item_query").entered();
-        if let Some(target) =
-            db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied())
-        {
-            return Some(target);
-        }
-        start_crate.data(db).dependencies.iter().find_map(|dep| db.lang_item(dep.crate_id, item))
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+pub struct LangItems {
+    items: FxHashMap<LangItem, LangItemTarget>,
+}
+
+impl LangItems {
+    pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
+        self.items.get(&item).copied()
     }
 
     fn collect_lang_item<T>(
@@ -269,18 +264,38 @@ macro_rules! language_item_table {
 }
 
 impl LangItem {
+    pub fn resolve_function(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<FunctionId> {
+        lang_item(db, start_crate, self).and_then(|t| t.as_function())
+    }
+
+    pub fn resolve_trait(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<TraitId> {
+        lang_item(db, start_crate, self).and_then(|t| t.as_trait())
+    }
+
+    pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<EnumId> {
+        lang_item(db, start_crate, self).and_then(|t| t.as_enum())
+    }
+
+    pub fn resolve_type_alias(
+        self,
+        db: &dyn DefDatabase,
+        start_crate: Crate,
+    ) -> Option<TypeAliasId> {
+        lang_item(db, start_crate, self).and_then(|t| t.as_type_alias())
+    }
+
     /// Opposite of [`LangItem::name`]
     pub fn from_name(name: &hir_expand::name::Name) -> Option<Self> {
         Self::from_symbol(name.symbol())
     }
 
     pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option<Path> {
-        let t = db.lang_item(start_crate, *self)?;
+        let t = lang_item(db, start_crate, *self)?;
         Some(Path::LangItem(t, None))
     }
 
     pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option<Path> {
-        let t = db.lang_item(start_crate, *self)?;
+        let t = lang_item(db, start_crate, *self)?;
         Some(Path::LangItem(t, Some(seg)))
     }
 }
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 737941dba07..28011bda7c5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -64,8 +64,8 @@ use std::hash::{Hash, Hasher};
 
 use base_db::{Crate, impl_intern_key};
 use hir_expand::{
-    AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind,
-    MacroDefId, MacroDefKind,
+    AstId, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
+    MacroDefKind,
     builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
     db::ExpandDatabase,
     eager::expand_eager_macro_input,
@@ -79,7 +79,7 @@ use la_arena::Idx;
 use nameres::DefMap;
 use span::{AstIdNode, Edition, FileAstId, SyntaxContext};
 use stdx::impl_from;
-use syntax::{AstNode, ast};
+use syntax::ast;
 
 pub use hir_expand::{Intern, Lookup, tt};
 
@@ -554,7 +554,7 @@ pub enum ItemContainerId {
 impl_from!(ModuleId for ItemContainerId);
 
 /// A Data Type
-#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum AdtId {
     StructId(StructId),
     UnionId(UnionId),
@@ -563,7 +563,7 @@ pub enum AdtId {
 impl_from!(StructId, UnionId, EnumId for AdtId);
 
 /// A macro
-#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum MacroId {
     Macro2Id(Macro2Id),
     MacroRulesId(MacroRulesId),
@@ -619,7 +619,7 @@ impl_from!(
 
 /// A constant, which might appears as a const item, an anonymous const block in expressions
 /// or patterns, or as a constant in types with const generics.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum GeneralConstId {
     ConstId(ConstId),
     StaticId(StaticId),
@@ -656,7 +656,7 @@ impl GeneralConstId {
 }
 
 /// The defs which have a body (have root expressions for type inference).
-#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum DefWithBodyId {
     FunctionId(FunctionId),
     StaticId(StaticId),
@@ -701,7 +701,7 @@ pub enum AssocItemId {
 // casting them, and somehow making the constructors private, which would be annoying.
 impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId);
 
-#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum GenericDefId {
     AdtId(AdtId),
     // consts can have type parameters from their parents (i.e. associated consts of traits)
@@ -790,7 +790,7 @@ impl From<AssocItemId> for GenericDefId {
     }
 }
 
-#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum CallableDefId {
     FunctionId(FunctionId),
     StructId(StructId),
@@ -906,7 +906,7 @@ impl From<VariantId> for AttrDefId {
     }
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum VariantId {
     EnumVariantId(EnumVariantId),
     StructId(StructId),
@@ -1166,66 +1166,6 @@ impl ModuleDefId {
         })
     }
 }
-
-// FIXME: Replace this with a plain function, it only has one impl
-/// A helper trait for converting to MacroCallId
-trait AsMacroCall {
-    fn as_call_id_with_errors(
-        &self,
-        db: &dyn ExpandDatabase,
-        krate: Crate,
-        resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
-        eager_callback: &mut dyn FnMut(
-            InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
-            MacroCallId,
-        ),
-    ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>;
-}
-
-impl AsMacroCall for InFile<&ast::MacroCall> {
-    fn as_call_id_with_errors(
-        &self,
-        db: &dyn ExpandDatabase,
-        krate: Crate,
-        resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
-        eager_callback: &mut dyn FnMut(
-            InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
-            MacroCallId,
-        ),
-    ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
-        let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
-        let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
-        let span_map = db.span_map(self.file_id);
-        let path = self.value.path().and_then(|path| {
-            let range = path.syntax().text_range();
-            let mod_path = ModPath::from_src(db, path, &mut |range| {
-                span_map.as_ref().span_for_range(range).ctx
-            })?;
-            let call_site = span_map.span_for_range(range);
-            Some((call_site, mod_path))
-        });
-
-        let Some((call_site, path)) = path else {
-            return Ok(ExpandResult::only_err(ExpandError::other(
-                span_map.span_for_range(self.value.syntax().text_range()),
-                "malformed macro invocation",
-            )));
-        };
-
-        macro_call_as_call_id_with_eager(
-            db,
-            ast_id,
-            &path,
-            call_site.ctx,
-            expands_to,
-            krate,
-            resolver,
-            resolver,
-            eager_callback,
-        )
-    }
-}
-
 /// Helper wrapper for `AstId` with `ModPath`
 #[derive(Clone, Debug, Eq, PartialEq)]
 struct AstIdWithPath<T: AstIdNode> {
@@ -1239,41 +1179,14 @@ impl<T: AstIdNode> AstIdWithPath<T> {
     }
 }
 
-fn macro_call_as_call_id(
-    db: &dyn ExpandDatabase,
-    call: &AstIdWithPath<ast::MacroCall>,
-    call_site: SyntaxContext,
-    expand_to: ExpandTo,
-    krate: Crate,
-    resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
-    eager_callback: &mut dyn FnMut(
-        InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
-        MacroCallId,
-    ),
-) -> Result<Option<MacroCallId>, UnresolvedMacro> {
-    macro_call_as_call_id_with_eager(
-        db,
-        call.ast_id,
-        &call.path,
-        call_site,
-        expand_to,
-        krate,
-        resolver,
-        resolver,
-        eager_callback,
-    )
-    .map(|res| res.value)
-}
-
-fn macro_call_as_call_id_with_eager(
+pub fn macro_call_as_call_id(
     db: &dyn ExpandDatabase,
     ast_id: AstId<ast::MacroCall>,
     path: &ModPath,
     call_site: SyntaxContext,
     expand_to: ExpandTo,
     krate: Crate,
-    resolver: impl FnOnce(&ModPath) -> Option<MacroDefId>,
-    eager_resolver: impl Fn(&ModPath) -> Option<MacroDefId>,
+    resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
     eager_callback: &mut dyn FnMut(
         InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
         MacroCallId,
@@ -1289,7 +1202,7 @@ fn macro_call_as_call_id_with_eager(
             ast_id,
             def,
             call_site,
-            &|path| eager_resolver(path).filter(MacroDefId::is_fn_like),
+            &|path| resolver(path).filter(MacroDefId::is_fn_like),
             eager_callback,
         ),
         _ if def.is_fn_like() => ExpandResult {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index a3b48831a0b..e21d1415aa2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -285,8 +285,6 @@ fn main() {
     /* parse error: expected expression */
 builtin #format_args (x = );
     /* parse error: expected expression */
-/* parse error: expected R_PAREN */
-/* parse error: expected expression, item or let statement */
 builtin #format_args (x = , x = 2);
     /* parse error: expected expression */
 builtin #format_args ("{}", x = );
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
index abb5bd5ed72..38fc4b3d118 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
@@ -2001,8 +2001,9 @@ macro_rules! bug {
         true
     };
 }
-
-let _ = bug!(a;;;test);
+fn f() {
+    let _ = bug!(a;;;test);
+}
     "#,
         expect![[r#"
 macro_rules! bug {
@@ -2022,8 +2023,9 @@ macro_rules! bug {
         true
     };
 }
-
-let _ = true;
+fn f() {
+    let _ = true;
+}
     "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
index 143b5df7730..800c96ebdae 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -19,7 +19,7 @@ use std::{iter, ops::Range, sync};
 use base_db::RootQueryDb;
 use expect_test::Expect;
 use hir_expand::{
-    InFile, MacroCallKind, MacroKind,
+    AstId, InFile, MacroCallId, MacroCallKind, MacroKind,
     db::ExpandDatabase,
     proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind},
     span_map::SpanMapRef,
@@ -29,7 +29,7 @@ use itertools::Itertools;
 use span::{Edition, Span};
 use stdx::{format_to, format_to_acc};
 use syntax::{
-    AstNode,
+    AstNode, AstPtr,
     SyntaxKind::{COMMENT, EOF, IDENT, LIFETIME_IDENT},
     SyntaxNode, T,
     ast::{self, edit::IndentLevel},
@@ -37,10 +37,9 @@ use syntax::{
 use test_fixture::WithFixture;
 
 use crate::{
-    AdtId, AsMacroCall, Lookup, ModuleDefId,
+    AdtId, Lookup, ModuleDefId,
     db::DefDatabase,
-    nameres::{DefMap, MacroSubNs, ModuleSource},
-    resolver::HasResolver,
+    nameres::{DefMap, ModuleSource},
     src::HasSource,
     test_db::TestDB,
     tt::TopSubtree,
@@ -78,7 +77,6 @@ fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect)
     expect.assert_eq(&errors);
 }
 
-#[track_caller]
 fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, mut expect: Expect) {
     let extra_proc_macros = vec![(
         r#"
@@ -95,54 +93,59 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
             disabled: false,
         },
     )];
+
+    fn resolve(
+        db: &dyn DefDatabase,
+        def_map: &DefMap,
+        ast_id: AstId<ast::MacroCall>,
+        ast_ptr: InFile<AstPtr<ast::MacroCall>>,
+    ) -> Option<MacroCallId> {
+        def_map.modules().find_map(|module| {
+            for decl in
+                module.1.scope.declarations().chain(module.1.scope.unnamed_consts().map(Into::into))
+            {
+                let body = match decl {
+                    ModuleDefId::FunctionId(it) => it.into(),
+                    ModuleDefId::ConstId(it) => it.into(),
+                    ModuleDefId::StaticId(it) => it.into(),
+                    _ => continue,
+                };
+
+                let (body, sm) = db.body_with_source_map(body);
+                if let Some(it) =
+                    body.blocks(db).find_map(|block| resolve(db, &block.1, ast_id, ast_ptr))
+                {
+                    return Some(it);
+                }
+                if let Some((_, res)) = sm.macro_calls().find(|it| it.0 == ast_ptr) {
+                    return Some(res);
+                }
+            }
+            module.1.scope.macro_invoc(ast_id)
+        })
+    }
+
     let db = TestDB::with_files_extra_proc_macros(ra_fixture, extra_proc_macros);
     let krate = db.fetch_test_crate();
     let def_map = db.crate_def_map(krate);
     let local_id = DefMap::ROOT;
-    let module = def_map.module_id(local_id);
-    let resolver = module.resolver(&db);
     let source = def_map[local_id].definition_source(&db);
     let source_file = match source.value {
         ModuleSource::SourceFile(it) => it,
         ModuleSource::Module(_) | ModuleSource::BlockExpr(_) => panic!(),
     };
 
-    // What we want to do is to replace all macros (fn-like, derive, attr) with
-    // their expansions. Turns out, we don't actually store enough information
-    // to do this precisely though! Specifically, if a macro expands to nothing,
-    // it leaves zero traces in def-map, so we can't get its expansion after the
-    // fact.
-    //
-    // This is the usual
-    // <https://github.com/rust-lang/rust-analyzer/issues/3407>
-    // resolve/record tension!
-    //
-    // So here we try to do a resolve, which is necessary a heuristic. For macro
-    // calls, we use `as_call_id_with_errors`. For derives, we look at the impls
-    // in the module and assume that, if impls's source is a different
-    // `HirFileId`, than it came from macro expansion.
-
     let mut text_edits = Vec::new();
     let mut expansions = Vec::new();
 
-    for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
-        let macro_call = InFile::new(source.file_id, &macro_call);
-        let res = macro_call
-            .as_call_id_with_errors(
-                &db,
-                krate,
-                |path| {
-                    resolver
-                        .resolve_path_as_macro(&db, path, Some(MacroSubNs::Bang))
-                        .map(|(it, _)| db.macro_def(it))
-                },
-                &mut |_, _| (),
-            )
-            .unwrap();
-        let macro_call_id = res.value.unwrap();
-        let mut expansion_result = db.parse_macro_expansion(macro_call_id);
-        expansion_result.err = expansion_result.err.or(res.err);
-        expansions.push((macro_call.value.clone(), expansion_result));
+    for macro_call_node in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {
+        let ast_id = db.ast_id_map(source.file_id).ast_id(&macro_call_node);
+        let ast_id = InFile::new(source.file_id, ast_id);
+        let ptr = InFile::new(source.file_id, AstPtr::new(&macro_call_node));
+        let macro_call_id = resolve(&db, &def_map, ast_id, ptr)
+            .unwrap_or_else(|| panic!("unable to find semantic macro call {macro_call_node}"));
+        let expansion_result = db.parse_macro_expansion(macro_call_id);
+        expansions.push((macro_call_node.clone(), expansion_result));
     }
 
     for (call, exp) in expansions.into_iter().rev() {
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 b0970655294..448b908936a 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
@@ -259,7 +259,8 @@ impl<'a> AssocItemCollector<'a> {
                 };
                 match macro_call_as_call_id(
                     self.db,
-                    &AstIdWithPath::new(tree_id.file_id(), ast_id, Clone::clone(path)),
+                    InFile::new(tree_id.file_id(), ast_id),
+                    path,
                     ctxt,
                     expand_to,
                     self.module_id.krate(),
@@ -268,12 +269,15 @@ impl<'a> AssocItemCollector<'a> {
                         self.macro_calls.push((ptr.map(|(_, it)| it.upcast()), call_id))
                     },
                 ) {
-                    Ok(Some(call_id)) => {
-                        self.macro_calls
-                            .push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id));
-                        self.collect_macro_items(call_id);
-                    }
-                    Ok(None) => (),
+                    // FIXME: Expansion error?
+                    Ok(call_id) => match call_id.value {
+                        Some(call_id) => {
+                            self.macro_calls
+                                .push((InFile::new(tree_id.file_id(), ast_id.upcast()), call_id));
+                            self.collect_macro_items(call_id);
+                        }
+                        None => (),
+                    },
                     Err(_) => {
                         self.diagnostics.push(DefDiagnostic::unresolved_macro_call(
                             self.module_id.local_id,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 77effbcc880..8df0f092cd0 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
@@ -39,7 +39,7 @@ use crate::{
         ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
         UseTreeKind,
     },
-    macro_call_as_call_id, macro_call_as_call_id_with_eager,
+    macro_call_as_call_id,
     nameres::{
         BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
         attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
@@ -1256,7 +1256,8 @@ impl DefCollector<'_> {
                 MacroDirectiveKind::FnLike { ast_id, expand_to, ctxt: call_site } => {
                     let call_id = macro_call_as_call_id(
                         self.db,
-                        ast_id,
+                        ast_id.ast_id,
+                        &ast_id.path,
                         *call_site,
                         *expand_to,
                         self.def_map.krate,
@@ -1265,15 +1266,18 @@ impl DefCollector<'_> {
                             eager_callback_buffer.push((directive.module_id, ptr, call_id));
                         },
                     );
-                    if let Ok(Some(call_id)) = call_id {
-                        self.def_map.modules[directive.module_id]
-                            .scope
-                            .add_macro_invoc(ast_id.ast_id, call_id);
+                    if let Ok(call_id) = call_id {
+                        // FIXME: Expansion error
+                        if let Some(call_id) = call_id.value {
+                            self.def_map.modules[directive.module_id]
+                                .scope
+                                .add_macro_invoc(ast_id.ast_id, call_id);
 
-                        push_resolved(directive, call_id);
+                            push_resolved(directive, call_id);
 
-                        res = ReachedFixedPoint::No;
-                        return Resolved::Yes;
+                            res = ReachedFixedPoint::No;
+                            return Resolved::Yes;
+                        }
                     }
                 }
                 MacroDirectiveKind::Derive {
@@ -1542,7 +1546,8 @@ impl DefCollector<'_> {
                     // FIXME: we shouldn't need to re-resolve the macro here just to get the unresolved error!
                     let macro_call_as_call_id = macro_call_as_call_id(
                         self.db,
-                        ast_id,
+                        ast_id.ast_id,
+                        &ast_id.path,
                         *call_site,
                         *expand_to,
                         self.def_map.krate,
@@ -2420,7 +2425,7 @@ impl ModCollector<'_, '_> {
 
         let mut eager_callback_buffer = vec![];
         // Case 1: try to resolve macro calls with single-segment name and expand macro_rules
-        if let Ok(res) = macro_call_as_call_id_with_eager(
+        if let Ok(res) = macro_call_as_call_id(
             db,
             ast_id.ast_id,
             &ast_id.path,
@@ -2445,21 +2450,6 @@ impl ModCollector<'_, '_> {
                         .map(|it| self.def_collector.db.macro_def(it))
                 })
             },
-            |path| {
-                let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro(
-                    self.def_collector
-                        .crate_local_def_map
-                        .as_deref()
-                        .unwrap_or(&self.def_collector.local_def_map),
-                    db,
-                    ResolveMode::Other,
-                    self.module_id,
-                    path,
-                    BuiltinShadowMode::Module,
-                    Some(MacroSubNs::Bang),
-                );
-                resolved_res.resolved_def.take_macros().map(|it| db.macro_def(it))
-            },
             &mut |ptr, call_id| eager_callback_buffer.push((ptr, call_id)),
         ) {
             for (ptr, call_id) in eager_callback_buffer {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
index d6c9f5a00c9..0c50f13edfb 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
@@ -86,7 +86,7 @@ impl ModDir {
                 let dir_path = if root_dir_owner {
                     DirPath::empty()
                 } else {
-                    DirPath::new(format!("{}/", name))
+                    DirPath::new(format!("{name}/"))
                 };
                 if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
                     return Ok((
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 f8b2c73a8f6..a49155d878c 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
@@ -673,12 +673,11 @@ impl DefMap {
     }
 
     fn resolve_in_macro_use_prelude(&self, name: &Name) -> PerNs {
-        self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| {
+        self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
             PerNs::macros(
                 it,
                 Visibility::Public,
-                // FIXME?
-                None, // extern_crate.map(ImportOrExternCrate::ExternCrate),
+                extern_crate.map(ImportOrExternCrate::ExternCrate),
             )
         })
     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
index 1f7dd6f0c40..8721cd65dba 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
@@ -37,7 +37,8 @@ pub struct Item<Def, Import = ImportId> {
 
 pub type TypesItem = Item<ModuleDefId, ImportOrExternCrate>;
 pub type ValuesItem = Item<ModuleDefId, ImportOrGlob>;
-pub type MacrosItem = Item<MacroId, ImportOrGlob>;
+// May be Externcrate for `[macro_use]`'d macros
+pub type MacrosItem = Item<MacroId, ImportOrExternCrate>;
 
 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
 pub struct PerNs {
@@ -84,7 +85,7 @@ impl PerNs {
         }
     }
 
-    pub fn macros(def: MacroId, vis: Visibility, import: Option<ImportOrGlob>) -> PerNs {
+    pub fn macros(def: MacroId, vis: Visibility, import: Option<ImportOrExternCrate>) -> PerNs {
         PerNs { types: None, values: None, macros: Some(Item { def, vis, import }) }
     }
 
@@ -116,7 +117,7 @@ impl PerNs {
         self.macros.map(|it| it.def)
     }
 
-    pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportOrGlob>)> {
+    pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportOrExternCrate>)> {
         self.macros.map(|it| (it.def, it.import))
     }
 
@@ -158,9 +159,6 @@ impl PerNs {
                 self.values
                     .map(|it| (ItemInNs::Values(it.def), it.import.map(ImportOrExternCrate::from))),
             )
-            .chain(
-                self.macros
-                    .map(|it| (ItemInNs::Macros(it.def), it.import.map(ImportOrExternCrate::from))),
-            )
+            .chain(self.macros.map(|it| (ItemInNs::Macros(it.def), it.import)))
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index 46c12574fde..8a8d17018c1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -493,7 +493,7 @@ impl Resolver {
         db: &dyn DefDatabase,
         path: &ModPath,
         expected_macro_kind: Option<MacroSubNs>,
-    ) -> Option<(MacroId, Option<ImportOrGlob>)> {
+    ) -> Option<(MacroId, Option<ImportOrExternCrate>)> {
         let (item_map, item_local_map, module) = self.item_scope_();
         item_map
             .resolve_path(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
index 2f7675134ca..47097548295 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/test_db.rs
@@ -19,7 +19,7 @@ use crate::{
     src::HasSource,
 };
 
-#[salsa::db]
+#[salsa_macros::db]
 #[derive(Clone)]
 pub(crate) struct TestDB {
     storage: salsa::Storage<Self>,
@@ -44,7 +44,7 @@ impl Default for TestDB {
     }
 }
 
-#[salsa::db]
+#[salsa_macros::db]
 impl salsa::Database for TestDB {
     fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) {
         let mut events = self.events.lock().unwrap();
@@ -63,7 +63,7 @@ impl fmt::Debug for TestDB {
 
 impl panic::RefUnwindSafe for TestDB {}
 
-#[salsa::db]
+#[salsa_macros::db]
 impl SourceDatabase for TestDB {
     fn file_text(&self, file_id: base_db::FileId) -> FileText {
         self.files.file_text(file_id)
diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
index b83efca2552..ed818c5be3f 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
@@ -21,6 +21,7 @@ smallvec.workspace = true
 triomphe.workspace = true
 query-group.workspace = true
 salsa.workspace = true
+salsa-macros.workspace = true
 
 # local deps
 stdx.workspace = true
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 5dae27f7a16..bb17eb06276 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -2,7 +2,7 @@
 use std::{borrow::Cow, fmt, ops};
 
 use base_db::Crate;
-use cfg::CfgExpr;
+use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 use intern::{Interned, Symbol, sym};
 
@@ -14,11 +14,10 @@ use syntax::{AstNode, AstToken, SyntaxNode, ast, match_ast};
 use syntax_bridge::{DocCommentDesugarMode, desugar_doc_comment_text, syntax_node_to_token_tree};
 use triomphe::ThinArc;
 
-use crate::name::Name;
 use crate::{
-    InFile,
     db::ExpandDatabase,
     mod_path::ModPath,
+    name::Name,
     span_map::SpanMapRef,
     tt::{self, TopSubtree, token_to_literal},
 };
@@ -49,29 +48,7 @@ impl RawAttrs {
         owner: &dyn ast::HasAttrs,
         span_map: SpanMapRef<'_>,
     ) -> Self {
-        let entries: Vec<_> = collect_attrs(owner)
-            .filter_map(|(id, attr)| match attr {
-                Either::Left(attr) => {
-                    attr.meta().and_then(|meta| Attr::from_src(db, meta, span_map, id))
-                }
-                Either::Right(comment) => comment.doc_comment().map(|doc| {
-                    let span = span_map.span_for_range(comment.syntax().text_range());
-                    let (text, kind) =
-                        desugar_doc_comment_text(doc, DocCommentDesugarMode::ProcMacro);
-                    Attr {
-                        id,
-                        input: Some(Box::new(AttrInput::Literal(tt::Literal {
-                            symbol: text,
-                            span,
-                            kind,
-                            suffix: None,
-                        }))),
-                        path: Interned::new(ModPath::from(Name::new_symbol(sym::doc, span.ctx))),
-                        ctxt: span.ctx,
-                    }
-                }),
-            })
-            .collect();
+        let entries: Vec<_> = Self::attrs_iter::<true>(db, owner, span_map).collect();
 
         let entries = if entries.is_empty() {
             None
@@ -82,12 +59,61 @@ impl RawAttrs {
         RawAttrs { entries }
     }
 
-    pub fn from_attrs_owner(
+    /// A [`RawAttrs`] that has its `#[cfg_attr(...)]` attributes expanded.
+    pub fn new_expanded(
         db: &dyn ExpandDatabase,
-        owner: InFile<&dyn ast::HasAttrs>,
+        owner: &dyn ast::HasAttrs,
         span_map: SpanMapRef<'_>,
+        cfg_options: &CfgOptions,
     ) -> Self {
-        Self::new(db, owner.value, span_map)
+        let entries: Vec<_> =
+            Self::attrs_iter_expanded::<true>(db, owner, span_map, cfg_options).collect();
+
+        let entries = if entries.is_empty() {
+            None
+        } else {
+            Some(ThinArc::from_header_and_iter((), entries.into_iter()))
+        };
+
+        RawAttrs { entries }
+    }
+
+    pub fn attrs_iter<const DESUGAR_COMMENTS: bool>(
+        db: &dyn ExpandDatabase,
+        owner: &dyn ast::HasAttrs,
+        span_map: SpanMapRef<'_>,
+    ) -> impl Iterator<Item = Attr> {
+        collect_attrs(owner).filter_map(move |(id, attr)| match attr {
+            Either::Left(attr) => {
+                attr.meta().and_then(|meta| Attr::from_src(db, meta, span_map, id))
+            }
+            Either::Right(comment) if DESUGAR_COMMENTS => comment.doc_comment().map(|doc| {
+                let span = span_map.span_for_range(comment.syntax().text_range());
+                let (text, kind) = desugar_doc_comment_text(doc, DocCommentDesugarMode::ProcMacro);
+                Attr {
+                    id,
+                    input: Some(Box::new(AttrInput::Literal(tt::Literal {
+                        symbol: text,
+                        span,
+                        kind,
+                        suffix: None,
+                    }))),
+                    path: Interned::new(ModPath::from(Name::new_symbol(sym::doc, span.ctx))),
+                    ctxt: span.ctx,
+                }
+            }),
+            Either::Right(_) => None,
+        })
+    }
+
+    pub fn attrs_iter_expanded<const DESUGAR_COMMENTS: bool>(
+        db: &dyn ExpandDatabase,
+        owner: &dyn ast::HasAttrs,
+        span_map: SpanMapRef<'_>,
+        cfg_options: &CfgOptions,
+    ) -> impl Iterator<Item = Attr> {
+        Self::attrs_iter::<DESUGAR_COMMENTS>(db, owner, span_map)
+            .flat_map(|attr| attr.expand_cfg_attr(db, cfg_options))
     }
 
     pub fn merge(&self, other: Self) -> Self {
@@ -114,9 +140,8 @@ impl RawAttrs {
         }
     }
 
-    /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
-    // FIXME: This should return a different type, signaling it was filtered?
-    pub fn filter(self, db: &dyn ExpandDatabase, krate: Crate) -> RawAttrs {
+    /// Processes `cfg_attr`s
+    pub fn expand_cfg_attr(self, db: &dyn ExpandDatabase, krate: Crate) -> RawAttrs {
         let has_cfg_attrs =
             self.iter().any(|attr| attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr));
         if !has_cfg_attrs {
@@ -126,37 +151,8 @@ impl RawAttrs {
         let cfg_options = krate.cfg_options(db);
         let new_attrs = self
             .iter()
-            .flat_map(|attr| -> SmallVec<[_; 1]> {
-                let is_cfg_attr = attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr);
-                if !is_cfg_attr {
-                    return smallvec![attr.clone()];
-                }
-
-                let subtree = match attr.token_tree_value() {
-                    Some(it) => it,
-                    _ => return smallvec![attr.clone()],
-                };
-
-                let (cfg, parts) = match parse_cfg_attr_input(subtree) {
-                    Some(it) => it,
-                    None => return smallvec![attr.clone()],
-                };
-                let index = attr.id;
-                let attrs = parts
-                    .enumerate()
-                    .take(1 << AttrId::CFG_ATTR_BITS)
-                    .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)));
-
-                let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg);
-                let cfg = CfgExpr::parse(&cfg);
-                if cfg_options.check(&cfg) == Some(false) {
-                    smallvec![]
-                } else {
-                    cov_mark::hit!(cfg_attr_active);
-
-                    attrs.collect()
-                }
-            })
+            .cloned()
+            .flat_map(|attr| attr.expand_cfg_attr(db, cfg_options))
             .collect::<Vec<_>>();
         let entries = if new_attrs.is_empty() {
             None
@@ -316,6 +312,42 @@ impl Attr {
     pub fn path(&self) -> &ModPath {
         &self.path
     }
+
+    pub fn expand_cfg_attr(
+        self,
+        db: &dyn ExpandDatabase,
+        cfg_options: &CfgOptions,
+    ) -> impl IntoIterator<Item = Self> {
+        let is_cfg_attr = self.path.as_ident().is_some_and(|name| *name == sym::cfg_attr);
+        if !is_cfg_attr {
+            return smallvec![self];
+        }
+
+        let subtree = match self.token_tree_value() {
+            Some(it) => it,
+            _ => return smallvec![self.clone()],
+        };
+
+        let (cfg, parts) = match parse_cfg_attr_input(subtree) {
+            Some(it) => it,
+            None => return smallvec![self.clone()],
+        };
+        let index = self.id;
+        let attrs = parts
+            .enumerate()
+            .take(1 << AttrId::CFG_ATTR_BITS)
+            .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)));
+
+        let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg);
+        let cfg = CfgExpr::parse(&cfg);
+        if cfg_options.check(&cfg) == Some(false) {
+            smallvec![]
+        } else {
+            cov_mark::hit!(cfg_attr_active);
+
+            attrs.collect::<SmallVec<[_; 1]>>()
+        }
+    }
 }
 
 impl Attr {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
index 6873cb7eaf9..3959741e6f1 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
@@ -1,7 +1,6 @@
 //! Defines a unit of change that can applied to the database to get the next
 //! state. Changes are transactional.
-use base_db::{CrateGraphBuilder, FileChange, SourceRoot};
-use salsa::Durability;
+use base_db::{CrateGraphBuilder, FileChange, SourceRoot, salsa::Durability};
 use span::FileId;
 use triomphe::Arc;
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index 29b7b33fd0f..7cb1b6c0207 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -18,10 +18,7 @@ use crate::{
     cfg_process,
     declarative::DeclarativeMacroExpander,
     fixup::{self, SyntaxFixupUndoInfo},
-    hygiene::{
-        SyntaxContextExt as _, span_with_call_site_ctxt, span_with_def_site_ctxt,
-        span_with_mixed_site_ctxt,
-    },
+    hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt},
     proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros},
     span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef},
     tt,
@@ -147,7 +144,7 @@ pub trait ExpandDatabase: RootQueryDb {
     fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext;
 }
 
-#[salsa::interned(no_lifetime, id = span::SyntaxContext)]
+#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext)]
 pub struct SyntaxContextWrapper {
     pub data: SyntaxContext,
 }
@@ -752,8 +749,7 @@ fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
             err: Some(ExpandError::other(
                 tt.delimiter.open,
                 format!(
-                    "macro invocation exceeds token limit: produced {} tokens, limit is {}",
-                    count, TOKEN_LIMIT,
+                    "macro invocation exceeds token limit: produced {count} tokens, limit is {TOKEN_LIMIT}",
                 ),
             )),
         })
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
index 1fa682ce3a2..0d100c1364a 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
@@ -82,7 +82,7 @@ impl DeclarativeMacroExpander {
 
         let transparency = |node| {
             // ... would be nice to have the item tree here
-            let attrs = RawAttrs::new(db, node, map.as_ref()).filter(db, def_crate);
+            let attrs = RawAttrs::new_expanded(db, node, map.as_ref(), def_crate.cfg_options(db));
             match attrs
                 .iter()
                 .find(|it| {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs
index e7856920bc4..28800c6fabd 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs
@@ -22,7 +22,7 @@
 // FIXME: Move this into the span crate? Not quite possible today as that depends on `MacroCallLoc`
 // which contains a bunch of unrelated things
 
-use std::{convert::identity, iter};
+use std::convert::identity;
 
 use span::{Edition, MacroCallId, Span, SyntaxContext};
 
@@ -141,61 +141,3 @@ fn apply_mark_internal(
         |_| opaque_and_semitransparent,
     )
 }
-
-pub trait SyntaxContextExt {
-    fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContext;
-    fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContext;
-    fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContext;
-    fn remove_mark(&mut self, db: &dyn ExpandDatabase)
-    -> (Option<span::MacroCallId>, Transparency);
-    fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option<span::MacroCallId>, Transparency);
-    fn marks(self, db: &dyn ExpandDatabase) -> Vec<(span::MacroCallId, Transparency)>;
-    fn is_opaque(self, db: &dyn ExpandDatabase) -> bool;
-}
-
-impl SyntaxContextExt for SyntaxContext {
-    fn normalize_to_macro_rules(self, db: &dyn ExpandDatabase) -> span::SyntaxContext {
-        self.opaque_and_semitransparent(db)
-    }
-    fn normalize_to_macros_2_0(self, db: &dyn ExpandDatabase) -> span::SyntaxContext {
-        self.opaque(db)
-    }
-    fn parent_ctxt(self, db: &dyn ExpandDatabase) -> span::SyntaxContext {
-        self.parent(db)
-    }
-    fn outer_mark(self, db: &dyn ExpandDatabase) -> (Option<span::MacroCallId>, Transparency) {
-        let data = self;
-        (data.outer_expn(db), data.outer_transparency(db))
-    }
-    fn remove_mark(
-        &mut self,
-        db: &dyn ExpandDatabase,
-    ) -> (Option<span::MacroCallId>, Transparency) {
-        let data = *self;
-        *self = data.parent(db);
-        (data.outer_expn(db), data.outer_transparency(db))
-    }
-    fn marks(self, db: &dyn ExpandDatabase) -> Vec<(span::MacroCallId, Transparency)> {
-        let mut marks = marks_rev(self, db).collect::<Vec<_>>();
-        marks.reverse();
-        marks
-    }
-    fn is_opaque(self, db: &dyn ExpandDatabase) -> bool {
-        !self.is_root() && self.outer_transparency(db).is_opaque()
-    }
-}
-
-// FIXME: Make this a SyntaxContextExt method once we have RPIT
-pub fn marks_rev(
-    ctxt: SyntaxContext,
-    db: &dyn ExpandDatabase,
-) -> impl Iterator<Item = (span::MacroCallId, Transparency)> + '_ {
-    iter::successors(Some(ctxt), move |&mark| Some(mark.parent_ctxt(db)))
-        .take_while(|&it| !it.is_root())
-        .map(|ctx| {
-            let mark = ctx.outer_mark(db);
-            // We stop before taking the root expansion, as such we cannot encounter a `None` outer
-            // expansion, as only the ROOT has it.
-            (mark.0.unwrap(), mark.1)
-        })
-}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index f0a9a2ad52c..d844d8f41ee 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -206,8 +206,7 @@ impl ExpandErrorKind {
                     },
                     None => RenderedExpandError {
                         message: format!(
-                            "internal error: proc-macro map is missing error entry for crate {:?}",
-                            def_crate
+                            "internal error: proc-macro map is missing error entry for crate {def_crate:?}"
                         ),
                         error: true,
                         kind: RenderedExpandError::GENERAL_KIND,
@@ -1051,7 +1050,7 @@ impl ExpandTo {
 
 intern::impl_internable!(ModPath, attrs::AttrInput);
 
-#[salsa::interned(no_lifetime, debug)]
+#[salsa_macros::interned(no_lifetime, debug)]
 #[doc(alias = "MacroFileId")]
 pub struct MacroCallId {
     pub loc: MacroCallLoc,
@@ -1071,7 +1070,7 @@ impl From<MacroCallId> for span::MacroCallId {
     }
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum HirFileId {
     FileId(EditionedFileId),
     MacroFile(MacroCallId),
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
index 72a5627636b..9f1e3879e1e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
@@ -7,7 +7,7 @@ use std::{
 
 use crate::{
     db::ExpandDatabase,
-    hygiene::{SyntaxContextExt, Transparency, marks_rev},
+    hygiene::Transparency,
     name::{AsName, Name},
     tt,
 };
@@ -340,7 +340,7 @@ pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContext) -> O
     // definitions actually produced by `macro` and `macro` definitions produced by
     // `macro_rules!`, but at least such configurations are not stable yet.
     ctxt = ctxt.normalize_to_macro_rules(db);
-    let mut iter = marks_rev(ctxt, db).peekable();
+    let mut iter = ctxt.marks_rev(db).peekable();
     let mut result_mark = None;
     // Find the last opaque mark from the end if it exists.
     while let Some(&(mark, Transparency::Opaque)) = iter.peek() {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
index d43ef38f291..217d991d110 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
@@ -191,7 +191,7 @@ impl Name {
     // FIXME: Remove this in favor of `display`, see fixme on `as_str`
     #[doc(hidden)]
     pub fn display_no_db(&self, edition: Edition) -> impl fmt::Display + '_ {
-        Display { name: self, needs_escaping: is_raw_identifier(self.symbol.as_str(), edition) }
+        Display { name: self, edition }
     }
 
     pub fn symbol(&self) -> &Symbol {
@@ -201,15 +201,28 @@ impl Name {
 
 struct Display<'a> {
     name: &'a Name,
-    needs_escaping: bool,
+    edition: Edition,
 }
 
 impl fmt::Display for Display<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.needs_escaping {
-            write!(f, "r#")?;
+        let mut symbol = self.name.symbol.as_str();
+
+        if symbol == "'static" {
+            // FIXME: '`static` can also be a label, and there it does need escaping.
+            // But knowing where it is will require adding a parameter to `display()`,
+            // and that is an infectious change.
+            return f.write_str(symbol);
+        }
+
+        if let Some(s) = symbol.strip_prefix('\'') {
+            f.write_str("'")?;
+            symbol = s;
+        }
+        if is_raw_identifier(symbol, self.edition) {
+            f.write_str("r#")?;
         }
-        fmt::Display::fmt(self.name.symbol.as_str(), f)
+        f.write_str(symbol)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index 69ad7703c2c..efa544cf396 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -34,6 +34,7 @@ indexmap.workspace = true
 rustc_apfloat = "0.2.2"
 query-group.workspace = true
 salsa.workspace = true
+salsa-macros.workspace = true
 
 ra-ap-rustc_abi.workspace = true
 ra-ap-rustc_index.workspace = true
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 71154454568..7acc9456ec9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -198,15 +198,13 @@ pub(crate) fn deref_by_trait(
         // blanked impl on `Deref`.
         #[expect(clippy::overly_complex_bool_expr)]
         if use_receiver_trait && false {
-            if let Some(receiver) =
-                db.lang_item(table.trait_env.krate, LangItem::Receiver).and_then(|l| l.as_trait())
-            {
+            if let Some(receiver) = LangItem::Receiver.resolve_trait(db, table.trait_env.krate) {
                 return Some(receiver);
             }
         }
         // Old rustc versions might not have `Receiver` trait.
         // Fallback to `Deref` if they don't
-        db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())
+        LangItem::Deref.resolve_trait(db, table.trait_env.krate)
     };
     let trait_id = trait_id()?;
     let target =
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 2aa9401eefa..cd799c03ddf 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
@@ -16,7 +16,7 @@ use hir_def::{
     AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
     TypeAliasId, VariantId,
     hir::Movability,
-    lang_item::{LangItem, LangItemTarget},
+    lang_item::LangItem,
     signatures::{ImplFlags, StructFlags, TraitFlags},
 };
 
@@ -262,10 +262,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
         well_known_trait: rust_ir::WellKnownTrait,
     ) -> Option<chalk_ir::TraitId<Interner>> {
         let lang_attr = lang_item_from_well_known_trait(well_known_trait);
-        let trait_ = match self.db.lang_item(self.krate, lang_attr) {
-            Some(LangItemTarget::Trait(trait_)) => trait_,
-            _ => return None,
-        };
+        let trait_ = lang_attr.resolve_trait(self.db, self.krate)?;
         Some(to_chalk_trait_id(trait_))
     }
 
@@ -306,11 +303,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
                 chalk_ir::Binders::new(binders, bound)
             }
             crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
-                if let Some((future_trait, future_output)) = self
-                    .db
-                    .lang_item(self.krate, LangItem::Future)
-                    .and_then(|item| item.as_trait())
-                    .and_then(|trait_| {
+                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_)
@@ -338,10 +332,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
                     });
                     let mut binder = vec![];
                     binder.push(crate::wrap_empty_binders(impl_bound));
-                    let sized_trait = self
-                        .db
-                        .lang_item(self.krate, LangItem::Sized)
-                        .and_then(|item| item.as_trait());
+                    let sized_trait = LangItem::Sized.resolve_trait(self.db, self.krate);
                     if let Some(sized_trait_) = sized_trait {
                         let sized_bound = WhereClause::Implemented(TraitRef {
                             trait_id: to_chalk_trait_id(sized_trait_),
@@ -646,7 +637,10 @@ pub(crate) fn associated_ty_data_query(
         .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0)
         .build();
     let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst))
-        .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self())
+        .fill_with_bound_vars(
+            crate::DebruijnIndex::INNERMOST,
+            generic_params.parent_generics().map_or(0, |it| it.len()),
+        )
         .build();
     let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner);
 
@@ -660,9 +654,8 @@ pub(crate) fn associated_ty_data_query(
     }
 
     if !ctx.unsized_types.contains(&self_ty) {
-        let sized_trait = db
-            .lang_item(resolver.krate(), LangItem::Sized)
-            .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
+        let sized_trait =
+            LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id);
         let sized_bound = sized_trait.into_iter().map(|sized_trait| {
             let trait_bound =
                 rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
index 0f0cf6ae7ae..aabc4c4234d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
@@ -251,9 +251,7 @@ impl TyExt for Ty {
                 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
                     ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
                         let krate = def.module(db).krate();
-                        if let Some(future_trait) =
-                            db.lang_item(krate, LangItem::Future).and_then(|item| item.as_trait())
-                        {
+                        if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
                             // This is only used by type walking.
                             // Parameters will be walked outside, and projection predicate is not used.
                             // So just provide the Future trait.
@@ -364,8 +362,7 @@ impl TyExt for Ty {
 
     fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool {
         let crate_id = owner.module(db).krate();
-        let Some(copy_trait) = db.lang_item(crate_id, LangItem::Copy).and_then(|it| it.as_trait())
-        else {
+        let Some(copy_trait) = LangItem::Copy.resolve_trait(db, crate_id) else {
             return false;
         };
         let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index c24ef16b496..980ee264b02 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -283,8 +283,9 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
 
     #[salsa::invoke(crate::variance::variances_of)]
     #[salsa::cycle(
-        cycle_fn = crate::variance::variances_of_cycle_fn,
-        cycle_initial = crate::variance::variances_of_cycle_initial,
+        // cycle_fn = crate::variance::variances_of_cycle_fn,
+        // cycle_initial = crate::variance::variances_of_cycle_initial,
+        cycle_result = crate::variance::variances_of_cycle_initial,
     )]
     fn variances_of(&self, def: GenericDefId) -> Option<Arc<[crate::variance::Variance]>>;
 
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 5e3d8805896..57106412765 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
@@ -482,9 +482,8 @@ struct FilterMapNextChecker {
 impl FilterMapNextChecker {
     fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self {
         // Find and store the FunctionIds for Iterator::filter_map and Iterator::next
-        let (next_function_id, filter_map_function_id) = match db
-            .lang_item(resolver.krate(), LangItem::IteratorNext)
-            .and_then(|it| it.as_function())
+        let (next_function_id, filter_map_function_id) = match LangItem::IteratorNext
+            .resolve_function(db, resolver.krate())
         {
             Some(next_function_id) => (
                 Some(next_function_id),
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 f62e4bb4f80..f0989d9de91 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -19,7 +19,7 @@ use hir_def::{
     hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
     item_scope::ItemInNs,
     item_tree::FieldsShape,
-    lang_item::{LangItem, LangItemTarget},
+    lang_item::LangItem,
     nameres::DefMap,
     signatures::VariantFields,
     type_ref::{
@@ -90,11 +90,26 @@ pub struct HirFormatter<'a> {
     show_container_bounds: bool,
     omit_verbose_types: bool,
     closure_style: ClosureStyle,
+    display_lifetimes: DisplayLifetime,
     display_kind: DisplayKind,
     display_target: DisplayTarget,
     bounds_formatting_ctx: BoundsFormattingCtx,
 }
 
+// FIXME: To consider, ref and dyn trait lifetimes can be omitted if they are `'_`, path args should
+// not be when in signatures
+// So this enum does not encode this well enough
+// Also 'static can be omitted for ref and dyn trait lifetimes in static/const item types
+// FIXME: Also named lifetimes may be rendered in places where their name is not in scope?
+#[derive(Copy, Clone)]
+pub enum DisplayLifetime {
+    Always,
+    OnlyStatic,
+    OnlyNamed,
+    OnlyNamedOrStatic,
+    Never,
+}
+
 #[derive(Default)]
 enum BoundsFormattingCtx {
     Entered {
@@ -155,6 +170,21 @@ impl HirFormatter<'_> {
             }
         }
     }
+
+    fn render_lifetime(&self, lifetime: &Lifetime) -> bool {
+        match self.display_lifetimes {
+            DisplayLifetime::Always => true,
+            DisplayLifetime::OnlyStatic => matches!(***lifetime.interned(), LifetimeData::Static),
+            DisplayLifetime::OnlyNamed => {
+                matches!(***lifetime.interned(), LifetimeData::Placeholder(_))
+            }
+            DisplayLifetime::OnlyNamedOrStatic => matches!(
+                ***lifetime.interned(),
+                LifetimeData::Static | LifetimeData::Placeholder(_)
+            ),
+            DisplayLifetime::Never => false,
+        }
+    }
 }
 
 pub trait HirDisplay {
@@ -189,6 +219,7 @@ pub trait HirDisplay {
             display_kind,
             closure_style,
             show_container_bounds,
+            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
         }
     }
 
@@ -212,6 +243,7 @@ pub trait HirDisplay {
             display_target,
             display_kind: DisplayKind::Diagnostics,
             show_container_bounds: false,
+            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
         }
     }
 
@@ -236,6 +268,7 @@ pub trait HirDisplay {
             display_target,
             display_kind: DisplayKind::Diagnostics,
             show_container_bounds: false,
+            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
         }
     }
 
@@ -260,6 +293,7 @@ pub trait HirDisplay {
             display_target,
             display_kind: DisplayKind::Diagnostics,
             show_container_bounds: false,
+            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
         }
     }
 
@@ -284,6 +318,7 @@ pub trait HirDisplay {
             display_target: DisplayTarget::from_crate(db, module_id.krate()),
             display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque },
             show_container_bounds: false,
+            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
             bounds_formatting_ctx: Default::default(),
         }) {
             Ok(()) => {}
@@ -312,6 +347,7 @@ pub trait HirDisplay {
             display_target,
             display_kind: DisplayKind::Test,
             show_container_bounds: false,
+            display_lifetimes: DisplayLifetime::Always,
         }
     }
 
@@ -336,6 +372,7 @@ pub trait HirDisplay {
             display_target,
             display_kind: DisplayKind::Diagnostics,
             show_container_bounds,
+            display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
         }
     }
 }
@@ -480,6 +517,7 @@ pub struct HirDisplayWrapper<'a, T> {
     display_kind: DisplayKind,
     display_target: DisplayTarget,
     show_container_bounds: bool,
+    display_lifetimes: DisplayLifetime,
 }
 
 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
@@ -502,7 +540,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
         self.t.hir_fmt(&mut HirFormatter {
             db: self.db,
             fmt: f,
-            buf: String::with_capacity(20),
+            buf: String::with_capacity(self.max_size.unwrap_or(20)),
             curr_size: 0,
             max_size: self.max_size,
             entity_limit: self.limited_size,
@@ -511,6 +549,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
             display_target: self.display_target,
             closure_style: self.closure_style,
             show_container_bounds: self.show_container_bounds,
+            display_lifetimes: self.display_lifetimes,
             bounds_formatting_ctx: Default::default(),
         })
     }
@@ -519,6 +558,11 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
         self.closure_style = c;
         self
     }
+
+    pub fn with_lifetime_display(mut self, l: DisplayLifetime) -> Self {
+        self.display_lifetimes = l;
+        self
+    }
 }
 
 impl<T> fmt::Display for HirDisplayWrapper<'_, T>
@@ -1022,9 +1066,7 @@ impl HirDisplay for Ty {
             kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => {
                 if let TyKind::Ref(_, l, _) = kind {
                     f.write_char('&')?;
-                    if cfg!(test) {
-                        // rendering these unconditionally is probably too much (at least for inlay
-                        // hints) so we gate it to testing only for the time being
+                    if f.render_lifetime(l) {
                         l.hir_fmt(f)?;
                         f.write_char(' ')?;
                     }
@@ -1055,9 +1097,10 @@ impl HirDisplay for Ty {
                     })
                 };
                 let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) {
-                    TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
+                    TyKind::Dyn(dyn_ty) => {
                         let bounds = dyn_ty.bounds.skip_binders().interned();
-                        (bounds.len(), contains_impl_fn(bounds))
+                        let render_lifetime = f.render_lifetime(&dyn_ty.lifetime);
+                        (bounds.len() + render_lifetime as usize, contains_impl_fn(bounds))
                     }
                     TyKind::Alias(AliasTy::Opaque(OpaqueTy {
                         opaque_ty_id,
@@ -1348,9 +1391,8 @@ impl HirDisplay for Ty {
                         )?;
                     }
                     ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
-                        let future_trait = db
-                            .lang_item(body.module(db).krate(), LangItem::Future)
-                            .and_then(LangItemTarget::as_trait);
+                        let future_trait =
+                            LangItem::Future.resolve_trait(db, body.module(db).krate());
                         let output = future_trait.and_then(|t| {
                             db.trait_items(t)
                                 .associated_type_by_name(&Name::new_symbol_root(sym::Output))
@@ -1480,7 +1522,7 @@ impl HirDisplay for Ty {
             TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
             TyKind::Dyn(dyn_ty) => {
                 // Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation.
-                // FIXME: `Iterator::partition_in_place()` or `Vec::drain_filter()` may make it
+                // FIXME: `Iterator::partition_in_place()` or `Vec::extract_if()` may make it
                 // more efficient when either of them hits stable.
                 let mut bounds: SmallVec<[_; 4]> =
                     dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect();
@@ -1489,6 +1531,17 @@ impl HirDisplay for Ty {
                 bounds.extend(others);
                 bounds.extend(auto_traits);
 
+                if f.render_lifetime(&dyn_ty.lifetime) {
+                    // we skip the binders in `write_bounds_like_dyn_trait_with_prefix`
+                    bounds.push(Binders::empty(
+                        Interner,
+                        chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
+                            ty: self.clone(),
+                            lifetime: dyn_ty.lifetime.clone(),
+                        }),
+                    ));
+                }
+
                 write_bounds_like_dyn_trait_with_prefix(
                     f,
                     "dyn",
@@ -1728,9 +1781,7 @@ impl SizedByDefault {
         match self {
             Self::NotSized => false,
             Self::Sized { anchor } => {
-                let sized_trait = db
-                    .lang_item(anchor, LangItem::Sized)
-                    .and_then(|lang_item| lang_item.as_trait());
+                let sized_trait = LangItem::Sized.resolve_trait(db, anchor);
                 Some(trait_) == sized_trait
             }
         }
@@ -1895,8 +1946,7 @@ fn write_bounds_like_dyn_trait(
         write!(f, ">")?;
     }
     if let SizedByDefault::Sized { anchor } = default_sized {
-        let sized_trait =
-            f.db.lang_item(anchor, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
+        let sized_trait = LangItem::Sized.resolve_trait(f.db, anchor);
         if !is_sized {
             if !first {
                 write!(f, " + ")?;
@@ -1993,7 +2043,6 @@ impl HirDisplay for LifetimeData {
                 write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
                 Ok(())
             }
-            _ if f.display_kind.is_source_code() => write!(f, "'_"),
             LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
             LifetimeData::InferenceVar(_) => write!(f, "_"),
             LifetimeData::Static => write!(f, "'static"),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
index 9823c854d5b..70763759ef0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
@@ -19,9 +19,7 @@ fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool {
         AdtId::StructId(id) => db.lookup_intern_struct(id).container,
         AdtId::UnionId(id) => db.lookup_intern_union(id).container,
     };
-    let Some(drop_trait) =
-        db.lang_item(module.krate(), LangItem::Drop).and_then(|it| it.as_trait())
-    else {
+    let Some(drop_trait) = LangItem::Drop.resolve_trait(db, module.krate()) else {
         return false;
     };
     let impls = match module.containing_block() {
@@ -181,8 +179,7 @@ fn projection_has_drop_glue(
 }
 
 fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironment>) -> bool {
-    let Some(copy_trait) = db.lang_item(env.krate, LangItem::Copy).and_then(|it| it.as_trait())
-    else {
+    let Some(copy_trait) = LangItem::Copy.resolve_trait(db, env.krate) else {
         return false;
     };
     let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(ty).build();
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 80b18473907..106b996b13e 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
@@ -124,7 +124,7 @@ pub fn dyn_compatibility_of_trait_query(
 
 fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
     let krate = def.module(db).krate();
-    let Some(sized) = db.lang_item(krate, LangItem::Sized).and_then(|l| l.as_trait()) else {
+    let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else {
         return false;
     };
 
@@ -491,8 +491,8 @@ fn receiver_is_dispatchable(
 
     let krate = func.module(db).krate();
     let traits = (
-        db.lang_item(krate, LangItem::Unsize).and_then(|it| it.as_trait()),
-        db.lang_item(krate, LangItem::DispatchFromDyn).and_then(|it| it.as_trait()),
+        LangItem::Unsize.resolve_trait(db, krate),
+        LangItem::DispatchFromDyn.resolve_trait(db, krate),
     );
     let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
         return false;
@@ -515,7 +515,7 @@ fn receiver_is_dispatchable(
         trait_id: to_chalk_trait_id(trait_),
         substitution: Substitution::from_iter(
             Interner,
-            std::iter::once(unsized_self_ty.clone().cast(Interner))
+            std::iter::once(unsized_self_ty.cast(Interner))
                 .chain(placeholder_subst.iter(Interner).skip(1).cloned()),
         ),
     });
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 790914fdaf2..f0ec31db8bb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -39,7 +39,7 @@ use hir_def::{
     builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
     expr_store::{Body, ExpressionStore, HygieneId, path::Path},
     hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
-    lang_item::{LangItem, LangItemTarget},
+    lang_item::{LangItem, LangItemTarget, lang_item},
     layout::Integer,
     resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
     signatures::{ConstSignature, StaticSignature},
@@ -1801,7 +1801,7 @@ impl<'a> InferenceContext<'a> {
 
     fn resolve_lang_item(&self, item: LangItem) -> Option<LangItemTarget> {
         let krate = self.resolver.krate();
-        self.db.lang_item(krate, item)
+        lang_item(self.db, krate, item)
     }
 
     fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
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 cf3b15d2a67..800897c6fc3 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
@@ -127,7 +127,7 @@ impl InferenceContext<'_> {
         let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
         let prev_closure = mem::replace(&mut self.current_closure, id);
         let prev_ret_ty = mem::replace(&mut self.return_ty, body_ret_ty.clone());
-        let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(body_ret_ty.clone()));
+        let prev_ret_coercion = self.return_coercion.replace(CoerceMany::new(body_ret_ty));
         let prev_resume_yield_tys = mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
 
         self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
index 847dd43a02d..39bd90849fe 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
@@ -8,10 +8,7 @@
 use std::iter;
 
 use chalk_ir::{BoundVar, Goal, Mutability, TyKind, TyVariableKind, cast::Cast};
-use hir_def::{
-    hir::ExprId,
-    lang_item::{LangItem, LangItemTarget},
-};
+use hir_def::{hir::ExprId, lang_item::LangItem};
 use stdx::always;
 use triomphe::Arc;
 
@@ -701,8 +698,8 @@ impl InferenceTable<'_> {
             reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
 
         let krate = self.trait_env.krate;
-        let coerce_unsized_trait = match self.db.lang_item(krate, LangItem::CoerceUnsized) {
-            Some(LangItemTarget::Trait(trait_)) => trait_,
+        let coerce_unsized_trait = match LangItem::CoerceUnsized.resolve_trait(self.db, krate) {
+            Some(trait_) => trait_,
             _ => return Err(TypeError),
         };
 
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 5468254ab91..8084b394d04 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
@@ -827,9 +827,9 @@ impl InferenceContext<'_> {
                     }
                     let assoc = self.resolve_ops_index_output();
                     self.resolve_associated_type_with_params(
-                        self_ty.clone(),
+                        self_ty,
                         assoc,
-                        &[index_ty.clone().cast(Interner)],
+                        &[index_ty.cast(Interner)],
                     )
                 } else {
                     self.err_ty()
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 cf0152ecd26..ac450c0b559 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
@@ -126,10 +126,8 @@ impl InferenceContext<'_> {
             &Expr::Index { base, index } => {
                 if mutability == Mutability::Mut {
                     if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
-                        if let Some(index_trait) = self
-                            .db
-                            .lang_item(self.table.trait_env.krate, LangItem::IndexMut)
-                            .and_then(|l| l.as_trait())
+                        if let Some(index_trait) =
+                            LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
                         {
                             if let Some(index_fn) = self
                                 .db
@@ -183,10 +181,8 @@ impl InferenceContext<'_> {
                 let mut mutability = mutability;
                 if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
                     if mutability == Mutability::Mut {
-                        if let Some(deref_trait) = self
-                            .db
-                            .lang_item(self.table.trait_env.krate, LangItem::DerefMut)
-                            .and_then(|l| l.as_trait())
+                        if let Some(deref_trait) =
+                            LangItem::DerefMut.resolve_trait(self.db, self.table.trait_env.krate)
                         {
                             let ty = self.result.type_of_expr.get(*expr);
                             let is_mut_ptr = ty.is_some_and(|ty| {
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 dc1de3b9e85..a9a3265858e 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
@@ -435,7 +435,7 @@ impl InferenceContext<'_> {
         decl: Option<DeclContext>,
     ) -> Ty {
         let (expectation_type, expectation_lt) = match expected.as_reference() {
-            Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime.clone()),
+            Some((inner_ty, lifetime, _exp_mut)) => (inner_ty.clone(), lifetime),
             None => {
                 let inner_ty = self.table.new_type_var();
                 let inner_lt = self.table.new_lifetime_var();
@@ -597,7 +597,7 @@ impl InferenceContext<'_> {
         let size = consteval::usize_const(self.db, Some(len as u128), self.owner.krate(self.db));
 
         let elem_ty = self.table.new_type_var();
-        let array_ty = TyKind::Array(elem_ty.clone(), size).intern(Interner);
+        let array_ty = TyKind::Array(elem_ty, size).intern(Interner);
         Some(array_ty)
     }
 
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 60aa9b5a17a..631b571465f 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
@@ -1024,16 +1024,12 @@ impl<'a> InferenceTable<'a> {
             }
         }
 
-        let Some(sized) = self
-            .db
-            .lang_item(self.trait_env.krate, LangItem::Sized)
-            .and_then(|sized| sized.as_trait())
-        else {
+        let Some(sized) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else {
             return false;
         };
         let sized_pred = WhereClause::Implemented(TraitRef {
             trait_id: to_chalk_trait_id(sized),
-            substitution: Substitution::from1(Interner, ty.clone()),
+            substitution: Substitution::from1(Interner, ty),
         });
         let goal = GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(sized_pred)).intern(Interner);
         matches!(self.try_obligation(goal), Some(Solution::Unique(_)))
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 e4688d044e9..9def39d5f97 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -590,10 +590,7 @@ impl<'a> TyLoweringContext<'a> {
                 }
             }
             &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
-                let sized_trait = self
-                    .db
-                    .lang_item(self.resolver.krate(), LangItem::Sized)
-                    .and_then(|lang_item| lang_item.as_trait());
+                let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate());
                 // Don't lower associated type bindings as the only possible relaxed trait bound
                 // `?Sized` has no of them.
                 // If we got another trait here ignore the bound completely.
@@ -736,10 +733,8 @@ impl<'a> TyLoweringContext<'a> {
             }
 
             if !ctx.unsized_types.contains(&self_ty) {
-                let sized_trait = ctx
-                    .db
-                    .lang_item(krate, LangItem::Sized)
-                    .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
+                let sized_trait =
+                    LangItem::Sized.resolve_trait(ctx.db, krate).map(to_chalk_trait_id);
                 let sized_clause = sized_trait.map(|trait_id| {
                     let clause = WhereClause::Implemented(TraitRef {
                         trait_id,
@@ -1188,9 +1183,7 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>(
     substitution: &'subst Substitution,
     resolver: &Resolver,
 ) -> Option<impl Iterator<Item = WhereClause> + Captures<'a> + Captures<'subst>> {
-    let sized_trait = db
-        .lang_item(resolver.krate(), LangItem::Sized)
-        .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id))?;
+    let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id)?;
 
     let trait_self_idx = trait_self_param_idx(db, def);
 
@@ -1475,7 +1468,7 @@ fn type_for_enum_variant_constructor(
     }
 }
 
-#[salsa::tracked(cycle_result = type_for_adt_cycle_result)]
+#[salsa_macros::tracked(cycle_result = type_for_adt_cycle_result)]
 fn type_for_adt_tracked(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
     type_for_adt(db, adt)
 }
@@ -1540,7 +1533,7 @@ pub enum TyDefId {
 }
 impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefId);
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Supertype)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum ValueTyDefId {
     FunctionId(FunctionId),
     StructId(StructId),
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 8f8e26eca2a..8e549ca0cbd 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
@@ -515,9 +515,15 @@ impl From<Option<BlockId>> for VisibleFromModule {
     }
 }
 
+#[derive(Debug, Clone)]
+pub enum AutorefOrPtrAdjustment {
+    Autoref(Mutability),
+    ToConstPtr,
+}
+
 #[derive(Debug, Clone, Default)]
 pub struct ReceiverAdjustments {
-    autoref: Option<Mutability>,
+    autoref: Option<AutorefOrPtrAdjustment>,
     autoderefs: usize,
     unsize_array: bool,
 }
@@ -535,10 +541,15 @@ impl ReceiverAdjustments {
                 }
                 Some((kind, new_ty)) => {
                     ty = new_ty.clone();
+                    let mutbl = match self.autoref {
+                        Some(AutorefOrPtrAdjustment::Autoref(m)) => Some(m),
+                        Some(AutorefOrPtrAdjustment::ToConstPtr) => Some(Mutability::Not),
+                        // FIXME should we know the mutability here, when autoref is `None`?
+                        None => None,
+                    };
                     adjust.push(Adjustment {
                         kind: Adjust::Deref(match kind {
-                            // FIXME should we know the mutability here, when autoref is `None`?
-                            AutoderefKind::Overloaded => Some(OverloadedDeref(self.autoref)),
+                            AutoderefKind::Overloaded => Some(OverloadedDeref(mutbl)),
                             AutoderefKind::Builtin => None,
                         }),
                         target: new_ty,
@@ -546,11 +557,27 @@ impl ReceiverAdjustments {
                 }
             }
         }
-        if let Some(m) = self.autoref {
+        if let Some(autoref) = &self.autoref {
             let lt = table.new_lifetime_var();
-            let a = Adjustment::borrow(m, ty, lt);
-            ty = a.target.clone();
-            adjust.push(a);
+            match autoref {
+                AutorefOrPtrAdjustment::Autoref(m) => {
+                    let a = Adjustment::borrow(*m, ty, lt);
+                    ty = a.target.clone();
+                    adjust.push(a);
+                }
+                AutorefOrPtrAdjustment::ToConstPtr => {
+                    if let TyKind::Raw(Mutability::Mut, pointee) = ty.kind(Interner) {
+                        let a = Adjustment {
+                            kind: Adjust::Pointer(PointerCast::MutToConstPointer),
+                            target: TyKind::Raw(Mutability::Not, pointee.clone()).intern(Interner),
+                        };
+                        ty = a.target.clone();
+                        adjust.push(a);
+                    } else {
+                        never!("`ToConstPtr` target is not a raw mutable pointer");
+                    }
+                }
+            };
         }
         if self.unsize_array {
             ty = 'it: {
@@ -575,8 +602,8 @@ impl ReceiverAdjustments {
         (ty, adjust)
     }
 
-    fn with_autoref(&self, m: Mutability) -> ReceiverAdjustments {
-        Self { autoref: Some(m), ..*self }
+    fn with_autoref(&self, a: AutorefOrPtrAdjustment) -> ReceiverAdjustments {
+        Self { autoref: Some(a), ..*self }
     }
 }
 
@@ -1051,7 +1078,7 @@ fn iterate_method_candidates_with_autoref(
     let mut maybe_reborrowed = first_adjustment.clone();
     if let Some((_, _, m)) = receiver_ty.value.as_reference() {
         // Prefer reborrow of references to move
-        maybe_reborrowed.autoref = Some(m);
+        maybe_reborrowed.autoref = Some(AutorefOrPtrAdjustment::Autoref(m));
         maybe_reborrowed.autoderefs += 1;
     }
 
@@ -1063,15 +1090,34 @@ fn iterate_method_candidates_with_autoref(
         binders: receiver_ty.binders.clone(),
     };
 
-    iterate_method_candidates_by_receiver(refed, first_adjustment.with_autoref(Mutability::Not))?;
+    iterate_method_candidates_by_receiver(
+        refed,
+        first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)),
+    )?;
 
     let ref_muted = Canonical {
         value: TyKind::Ref(Mutability::Mut, error_lifetime(), receiver_ty.value.clone())
             .intern(Interner),
-        binders: receiver_ty.binders,
+        binders: receiver_ty.binders.clone(),
     };
 
-    iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut))
+    iterate_method_candidates_by_receiver(
+        ref_muted,
+        first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)),
+    )?;
+
+    if let Some((ty, Mutability::Mut)) = receiver_ty.value.as_raw_ptr() {
+        let const_ptr_ty = Canonical {
+            value: TyKind::Raw(Mutability::Not, ty.clone()).intern(Interner),
+            binders: receiver_ty.binders,
+        };
+        iterate_method_candidates_by_receiver(
+            const_ptr_ty,
+            first_adjustment.with_autoref(AutorefOrPtrAdjustment::ToConstPtr),
+        )?;
+    }
+
+    ControlFlow::Continue(())
 }
 
 pub trait MethodCandidateCallback {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
index 6dc20203e0e..bf80ed7967a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
@@ -77,7 +77,14 @@ pub struct Local {
 /// currently implements it, but it seems like this may be something to check against in the
 /// validator.
 #[derive(Debug, PartialEq, Eq, Clone)]
-pub enum Operand {
+pub struct Operand {
+    kind: OperandKind,
+    // FIXME : This should actually just be of type `MirSpan`.
+    span: Option<MirSpan>,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum OperandKind {
     /// Creates a value by loading the given place.
     ///
     /// Before drop elaboration, the type of the place must be `Copy`. After drop elaboration there
@@ -101,7 +108,13 @@ pub enum Operand {
 
 impl Operand {
     fn from_concrete_const(data: Box<[u8]>, memory_map: MemoryMap, ty: Ty) -> Self {
-        Operand::Constant(intern_const_scalar(ConstScalar::Bytes(data, memory_map), ty))
+        Operand {
+            kind: OperandKind::Constant(intern_const_scalar(
+                ConstScalar::Bytes(data, memory_map),
+                ty,
+            )),
+            span: None,
+        }
     }
 
     fn from_bytes(data: Box<[u8]>, ty: Ty) -> Self {
@@ -1076,11 +1089,11 @@ impl MirBody {
             f: &mut impl FnMut(&mut Place, &mut ProjectionStore),
             store: &mut ProjectionStore,
         ) {
-            match op {
-                Operand::Copy(p) | Operand::Move(p) => {
+            match &mut op.kind {
+                OperandKind::Copy(p) | OperandKind::Move(p) => {
                     f(p, store);
                 }
-                Operand::Constant(_) | Operand::Static(_) => (),
+                OperandKind::Constant(_) | OperandKind::Static(_) => (),
             }
         }
         for (_, block) in self.basic_blocks.iter_mut() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
index eca6f4692a4..fb0c0dee095 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
@@ -15,13 +15,13 @@ use crate::{
     ClosureId, Interner, Substitution, Ty, TyExt, TypeFlags,
     db::{HirDatabase, InternedClosure},
     display::DisplayTarget,
-    mir::Operand,
+    mir::OperandKind,
     utils::ClosureSubst,
 };
 
 use super::{
-    BasicBlockId, BorrowKind, LocalId, MirBody, MirLowerError, MirSpan, MutBorrowKind, Place,
-    ProjectionElem, Rvalue, StatementKind, TerminatorKind,
+    BasicBlockId, BorrowKind, LocalId, MirBody, MirLowerError, MirSpan, MutBorrowKind, Operand,
+    Place, ProjectionElem, Rvalue, StatementKind, TerminatorKind,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -120,8 +120,8 @@ fn make_fetch_closure_field(
 
 fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef> {
     let mut result = vec![];
-    let mut for_operand = |op: &Operand, span: MirSpan| match op {
-        Operand::Copy(p) | Operand::Move(p) => {
+    let mut for_operand = |op: &Operand, span: MirSpan| match op.kind {
+        OperandKind::Copy(p) | OperandKind::Move(p) => {
             let mut ty: Ty = body.locals[p.local].ty.clone();
             let mut is_dereference_of_ref = false;
             for proj in p.projection.lookup(&body.projection_store) {
@@ -139,10 +139,10 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
                 && !ty.clone().is_copy(db, body.owner)
                 && !ty.data(Interner).flags.intersects(TypeFlags::HAS_ERROR)
             {
-                result.push(MovedOutOfRef { span, ty });
+                result.push(MovedOutOfRef { span: op.span.unwrap_or(span), ty });
             }
         }
-        Operand::Constant(_) | Operand::Static(_) => (),
+        OperandKind::Constant(_) | OperandKind::Static(_) => (),
     };
     for (_, block) in body.basic_blocks.iter() {
         db.unwind_if_revision_cancelled();
@@ -215,8 +215,8 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
 
 fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec<PartiallyMoved> {
     let mut result = vec![];
-    let mut for_operand = |op: &Operand, span: MirSpan| match op {
-        Operand::Copy(p) | Operand::Move(p) => {
+    let mut for_operand = |op: &Operand, span: MirSpan| match op.kind {
+        OperandKind::Copy(p) | OperandKind::Move(p) => {
             let mut ty: Ty = body.locals[p.local].ty.clone();
             for proj in p.projection.lookup(&body.projection_store) {
                 ty = proj.projected_ty(
@@ -232,7 +232,7 @@ fn partially_moved(db: &dyn HirDatabase, body: &MirBody) -> Vec<PartiallyMoved>
                 result.push(PartiallyMoved { span, ty, local: p.local });
             }
         }
-        Operand::Constant(_) | Operand::Static(_) => (),
+        OperandKind::Constant(_) | OperandKind::Static(_) => (),
     };
     for (_, block) in body.basic_blocks.iter() {
         db.unwind_if_revision_cancelled();
@@ -492,7 +492,7 @@ fn record_usage(local: LocalId, result: &mut ArenaMap<LocalId, MutabilityReason>
 }
 
 fn record_usage_for_operand(arg: &Operand, result: &mut ArenaMap<LocalId, MutabilityReason>) {
-    if let Operand::Copy(p) | Operand::Move(p) = arg {
+    if let OperandKind::Copy(p) | OperandKind::Move(p) = arg.kind {
         record_usage(p.local, result);
     }
 }
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 386226b16d5..21e5428520e 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
@@ -47,7 +47,7 @@ use crate::{
 
 use super::{
     AggregateKind, BasicBlockId, BinOp, CastKind, LocalId, MirBody, MirLowerError, MirSpan,
-    Operand, Place, PlaceElem, ProjectionElem, ProjectionStore, Rvalue, StatementKind,
+    Operand, OperandKind, Place, PlaceElem, ProjectionElem, ProjectionStore, Rvalue, StatementKind,
     TerminatorKind, UnOp, return_slot,
 };
 
@@ -655,22 +655,15 @@ impl Evaluator<'_> {
             mir_or_dyn_index_cache: RefCell::new(Default::default()),
             unused_locals_store: RefCell::new(Default::default()),
             cached_ptr_size,
-            cached_fn_trait_func: db
-                .lang_item(crate_id, LangItem::Fn)
-                .and_then(|x| x.as_trait())
+            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))),
-            cached_fn_mut_trait_func: db
-                .lang_item(crate_id, LangItem::FnMut)
-                .and_then(|x| x.as_trait())
-                .and_then(|x| {
-                    db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut))
-                }),
-            cached_fn_once_trait_func: db
-                .lang_item(crate_id, LangItem::FnOnce)
-                .and_then(|x| x.as_trait())
-                .and_then(|x| {
-                    db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once))
-                }),
+            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))
+            }),
+            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))
+            }),
         })
     }
 
@@ -863,10 +856,10 @@ impl Evaluator<'_> {
     }
 
     fn operand_ty(&self, o: &Operand, locals: &Locals) -> Result<Ty> {
-        Ok(match o {
-            Operand::Copy(p) | Operand::Move(p) => self.place_ty(p, locals)?,
-            Operand::Constant(c) => c.data(Interner).ty.clone(),
-            &Operand::Static(s) => {
+        Ok(match &o.kind {
+            OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?,
+            OperandKind::Constant(c) => c.data(Interner).ty.clone(),
+            &OperandKind::Static(s) => {
                 let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr].clone();
                 TyKind::Ref(Mutability::Not, static_lifetime(), ty).intern(Interner)
             }
@@ -1880,16 +1873,16 @@ impl Evaluator<'_> {
     }
 
     fn eval_operand(&mut self, it: &Operand, locals: &mut Locals) -> Result<Interval> {
-        Ok(match it {
-            Operand::Copy(p) | Operand::Move(p) => {
+        Ok(match &it.kind {
+            OperandKind::Copy(p) | OperandKind::Move(p) => {
                 locals.drop_flags.remove_place(p, &locals.body.projection_store);
                 self.eval_place(p, locals)?
             }
-            Operand::Static(st) => {
+            OperandKind::Static(st) => {
                 let addr = self.eval_static(*st, locals)?;
                 Interval::new(addr, self.ptr_size())
             }
-            Operand::Constant(konst) => self.allocate_const_in_heap(locals, konst)?,
+            OperandKind::Constant(konst) => self.allocate_const_in_heap(locals, konst)?,
         })
     }
 
@@ -2811,7 +2804,7 @@ impl Evaluator<'_> {
         span: MirSpan,
     ) -> Result<()> {
         let Some(drop_fn) = (|| {
-            let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?;
+            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))
         })() else {
             // in some tests we don't have drop trait in minicore, and
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 4de44cfd02e..26ef95d264b 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
@@ -6,7 +6,6 @@ use std::cmp::{self, Ordering};
 use chalk_ir::TyKind;
 use hir_def::{
     builtin_type::{BuiltinInt, BuiltinUint},
-    lang_item::LangItemTarget,
     resolver::HasResolver,
 };
 use hir_expand::name::Name;
@@ -156,8 +155,8 @@ impl Evaluator<'_> {
         if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
             let resolver = self.db.crate_def_map(self.crate_id).crate_root().resolver(self.db);
 
-            let Some(hir_def::lang_item::LangItemTarget::Function(const_panic_fmt)) =
-                self.db.lang_item(resolver.krate(), LangItem::ConstPanicFmt)
+            let Some(const_panic_fmt) =
+                LangItem::ConstPanicFmt.resolve_function(self.db, resolver.krate())
             else {
                 not_supported!("const_panic_fmt lang item not found or not a function");
             };
@@ -1257,12 +1256,12 @@ impl Evaluator<'_> {
                     let addr = tuple.interval.addr.offset(offset);
                     args.push(IntervalAndTy::new(addr, field, self, locals)?);
                 }
-                if let Some(target) = self.db.lang_item(self.crate_id, LangItem::FnOnce) {
-                    if let Some(def) = target.as_trait().and_then(|it| {
-                        self.db
-                            .trait_items(it)
-                            .method_by_name(&Name::new_symbol_root(sym::call_once))
-                    }) {
+                if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
+                    if let Some(def) = self
+                        .db
+                        .trait_items(target)
+                        .method_by_name(&Name::new_symbol_root(sym::call_once))
+                    {
                         self.exec_fn_trait(
                             def,
                             &args,
@@ -1376,9 +1375,7 @@ impl Evaluator<'_> {
                         }
                     }
                 }
-                if let Some(LangItemTarget::EnumId(e)) =
-                    self.db.lang_item(self.crate_id, LangItem::Ordering)
-                {
+                if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) {
                     let ty = self.db.ty(e.into());
                     let r = self
                         .compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?;
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 557027756f3..7b48b15d9ea 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
@@ -13,7 +13,7 @@ use hir_def::{
         Pat, PatId, RecordFieldPat, RecordLitField,
     },
     item_tree::FieldsShape,
-    lang_item::{LangItem, LangItemTarget},
+    lang_item::{LangItem, LangItemTarget, lang_item},
     resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
 };
 use hir_expand::name::Name;
@@ -48,6 +48,8 @@ use crate::{
     utils::ClosureSubst,
 };
 
+use super::OperandKind;
+
 mod as_place;
 mod pattern_matching;
 
@@ -324,7 +326,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
         let Some((p, current)) = self.lower_expr_as_place(current, expr_id, true)? else {
             return Ok(None);
         };
-        Ok(Some((Operand::Copy(p), current)))
+        Ok(Some((Operand { kind: OperandKind::Copy(p), span: Some(expr_id.into()) }, current)))
     }
 
     fn lower_expr_to_place_with_adjust(
@@ -347,7 +349,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     else {
                         return Ok(None);
                     };
-                    self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into());
+                    self.push_assignment(
+                        current,
+                        place,
+                        Operand { kind: OperandKind::Copy(p), span: None }.into(),
+                        expr_id.into(),
+                    );
                     Ok(Some(current))
                 }
                 Adjust::Borrow(AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m)) => {
@@ -371,7 +378,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         place,
                         Rvalue::Cast(
                             CastKind::PointerCoercion(*cast),
-                            Operand::Copy(p),
+                            Operand { kind: OperandKind::Copy(p), span: None },
                             last.target.clone(),
                         ),
                         expr_id.into(),
@@ -476,7 +483,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         self.push_assignment(
                             current,
                             place,
-                            Operand::Copy(temp).into(),
+                            Operand { kind: OperandKind::Copy(temp), span: None }.into(),
                             expr_id.into(),
                         );
                         Ok(Some(current))
@@ -517,21 +524,23 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         self.push_assignment(
                             current,
                             place,
-                            Operand::Constant(
-                                ConstData {
-                                    ty,
-                                    value: chalk_ir::ConstValue::BoundVar(BoundVar::new(
-                                        DebruijnIndex::INNERMOST,
-                                        generics.type_or_const_param_idx(p.into()).ok_or(
-                                            MirLowerError::TypeError(
-                                                "fail to lower const generic param",
-                                            ),
-                                        )?,
-                                    )),
-                                }
-                                .intern(Interner),
-                            )
-                            .into(),
+                            Rvalue::from(Operand {
+                                kind: OperandKind::Constant(
+                                    ConstData {
+                                        ty,
+                                        value: chalk_ir::ConstValue::BoundVar(BoundVar::new(
+                                            DebruijnIndex::INNERMOST,
+                                            generics.type_or_const_param_idx(p.into()).ok_or(
+                                                MirLowerError::TypeError(
+                                                    "fail to lower const generic param",
+                                                ),
+                                            )?,
+                                        )),
+                                    }
+                                    .intern(Interner),
+                                ),
+                                span: None,
+                            }),
                             expr_id.into(),
                         );
                         Ok(Some(current))
@@ -876,7 +885,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                                                 })),
                                                 &mut self.result.projection_store,
                                             );
-                                            Operand::Copy(p)
+                                            Operand { kind: OperandKind::Copy(p), span: None }
                                         }
                                     })
                                     .collect(),
@@ -979,7 +988,12 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 else {
                     return Ok(None);
                 };
-                self.push_assignment(current, place, Operand::Copy(p).into(), expr_id.into());
+                self.push_assignment(
+                    current,
+                    place,
+                    Operand { kind: OperandKind::Copy(p), span: None }.into(),
+                    expr_id.into(),
+                );
                 Ok(Some(current))
             }
             Expr::UnaryOp {
@@ -1056,8 +1070,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     else {
                         return Ok(None);
                     };
-                    let r_value =
-                        Rvalue::CheckedBinaryOp(op.into(), Operand::Copy(lhs_place), rhs_op);
+                    let r_value = Rvalue::CheckedBinaryOp(
+                        op.into(),
+                        Operand { kind: OperandKind::Copy(lhs_place), span: None },
+                        rhs_op,
+                    );
                     self.push_assignment(current, lhs_place, r_value, expr_id.into());
                     return Ok(Some(current));
                 }
@@ -1232,9 +1249,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
                                 Rvalue::Ref(*bk, p),
                                 capture_spans[0],
                             );
-                            operands.push(Operand::Move(tmp));
+                            operands.push(Operand { kind: OperandKind::Move(tmp), span: None });
+                        }
+                        CaptureKind::ByValue => {
+                            operands.push(Operand { kind: OperandKind::Move(p), span: None })
                         }
-                        CaptureKind::ByValue => operands.push(Operand::Move(p)),
                     }
                 }
                 self.push_assignment(
@@ -1476,7 +1495,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 .const_eval(const_id, subst, None)
                 .map_err(|e| MirLowerError::ConstEvalError(name.into(), Box::new(e)))?
         };
-        Ok(Operand::Constant(c))
+        Ok(Operand { kind: OperandKind::Constant(c), span: None })
     }
 
     fn write_bytes_to_place(
@@ -1727,7 +1746,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
 
     fn resolve_lang_item(&self, item: LangItem) -> Result<LangItemTarget> {
         let crate_id = self.owner.module(self.db).krate();
-        self.db.lang_item(crate_id, item).ok_or(MirLowerError::LangItemNotFound(item))
+        lang_item(self.db, crate_id, item).ok_or(MirLowerError::LangItemNotFound(item))
     }
 
     fn lower_block_to_place(
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 d3cd0099246..c22bada7a90 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
@@ -1,6 +1,6 @@
 //! MIR lowering for places
 
-use crate::mir::MutBorrowKind;
+use crate::mir::{MutBorrowKind, Operand, OperandKind};
 
 use super::*;
 use hir_def::FunctionId;
@@ -155,7 +155,7 @@ impl MirLowerCtx<'_> {
                         self.push_assignment(
                             current,
                             temp,
-                            Operand::Static(s).into(),
+                            Operand { kind: OperandKind::Static(s), span: None }.into(),
                             expr_id.into(),
                         );
                         Ok(Some((
@@ -305,7 +305,7 @@ impl MirLowerCtx<'_> {
         );
         let Some(current) = self.lower_call(
             index_fn_op,
-            Box::new([Operand::Copy(place), index_operand]),
+            Box::new([Operand { kind: OperandKind::Copy(place), span: None }, index_operand]),
             result,
             current,
             false,
@@ -365,7 +365,7 @@ impl MirLowerCtx<'_> {
         let mut result: Place = self.temp(target_ty_ref, current, span)?.into();
         let Some(current) = self.lower_call(
             deref_fn_op,
-            Box::new([Operand::Copy(ref_place)]),
+            Box::new([Operand { kind: OperandKind::Copy(ref_place), span: None }]),
             result,
             current,
             false,
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 abfa7aee04f..b3c1f6f387f 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
@@ -5,10 +5,10 @@ use hir_def::{AssocItemId, hir::ExprId, signatures::VariantFields};
 use crate::{
     BindingMode,
     mir::{
-        LocalId, MutBorrowKind,
+        LocalId, MutBorrowKind, Operand, OperandKind,
         lower::{
             BasicBlockId, BinOp, BindingId, BorrowKind, Either, Expr, FieldId, Idx, Interner,
-            MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Operand, Pat, PatId, Place,
+            MemoryMap, MirLowerCtx, MirLowerError, MirSpan, Mutability, Pat, PatId, Place,
             PlaceElem, ProjectionElem, RecordFieldPat, ResolveValueResult, Result, Rvalue,
             Substitution, SwitchTargets, TerminatorKind, TupleFieldId, TupleId, TyBuilder, TyKind,
             ValueNs, VariantId,
@@ -217,10 +217,14 @@ impl MirLowerCtx<'_> {
                     self.push_assignment(
                         current,
                         discr,
-                        Rvalue::CheckedBinaryOp(binop, lv, Operand::Copy(cond_place)),
+                        Rvalue::CheckedBinaryOp(
+                            binop,
+                            lv,
+                            Operand { kind: OperandKind::Copy(cond_place), span: None },
+                        ),
                         pattern.into(),
                     );
-                    let discr = Operand::Copy(discr);
+                    let discr = Operand { kind: OperandKind::Copy(discr), span: None };
                     self.set_terminator(
                         current,
                         TerminatorKind::SwitchInt {
@@ -262,7 +266,10 @@ impl MirLowerCtx<'_> {
                             self.set_terminator(
                                 current,
                                 TerminatorKind::SwitchInt {
-                                    discr: Operand::Copy(place_len),
+                                    discr: Operand {
+                                        kind: OperandKind::Copy(place_len),
+                                        span: None,
+                                    },
                                     targets: SwitchTargets::static_if(
                                         pattern_len as u128,
                                         next,
@@ -282,10 +289,14 @@ impl MirLowerCtx<'_> {
                             self.push_assignment(
                                 current,
                                 discr,
-                                Rvalue::CheckedBinaryOp(BinOp::Le, c, Operand::Copy(place_len)),
+                                Rvalue::CheckedBinaryOp(
+                                    BinOp::Le,
+                                    c,
+                                    Operand { kind: OperandKind::Copy(place_len), span: None },
+                                ),
                                 pattern.into(),
                             );
-                            let discr = Operand::Copy(discr);
+                            let discr = Operand { kind: OperandKind::Copy(discr), span: None };
                             self.set_terminator(
                                 current,
                                 TerminatorKind::SwitchInt {
@@ -407,8 +418,8 @@ impl MirLowerCtx<'_> {
                         tmp2,
                         Rvalue::CheckedBinaryOp(
                             BinOp::Eq,
-                            Operand::Copy(tmp),
-                            Operand::Copy(cond_place),
+                            Operand { kind: OperandKind::Copy(tmp), span: None },
+                            Operand { kind: OperandKind::Copy(cond_place), span: None },
                         ),
                         span,
                     );
@@ -417,7 +428,7 @@ impl MirLowerCtx<'_> {
                     self.set_terminator(
                         current,
                         TerminatorKind::SwitchInt {
-                            discr: Operand::Copy(tmp2),
+                            discr: Operand { kind: OperandKind::Copy(tmp2), span: None },
                             targets: SwitchTargets::static_if(1, next, else_target),
                         },
                         span,
@@ -486,7 +497,7 @@ impl MirLowerCtx<'_> {
                 self.push_assignment(
                     current,
                     lhs_place,
-                    Operand::Copy(cond_place).into(),
+                    Operand { kind: OperandKind::Copy(cond_place), span: None }.into(),
                     expr.into(),
                 );
                 (current, current_else)
@@ -523,7 +534,9 @@ impl MirLowerCtx<'_> {
             current,
             target_place.into(),
             match mode {
-                BindingMode::Move => Operand::Copy(cond_place).into(),
+                BindingMode::Move => {
+                    Operand { kind: OperandKind::Copy(cond_place), span: None }.into()
+                }
                 BindingMode::Ref(Mutability::Not) => Rvalue::Ref(BorrowKind::Shared, cond_place),
                 BindingMode::Ref(Mutability::Mut) => {
                     Rvalue::Ref(BorrowKind::Mut { kind: MutBorrowKind::Default }, cond_place)
@@ -547,10 +560,14 @@ impl MirLowerCtx<'_> {
         self.push_assignment(
             current,
             discr,
-            Rvalue::CheckedBinaryOp(BinOp::Eq, c, Operand::Copy(cond_place)),
+            Rvalue::CheckedBinaryOp(
+                BinOp::Eq,
+                c,
+                Operand { kind: OperandKind::Copy(cond_place), span: None },
+            ),
             pattern.into(),
         );
-        let discr = Operand::Copy(discr);
+        let discr = Operand { kind: OperandKind::Copy(discr), span: None };
         self.set_terminator(
             current,
             TerminatorKind::SwitchInt {
@@ -583,7 +600,7 @@ impl MirLowerCtx<'_> {
                     self.set_terminator(
                         current,
                         TerminatorKind::SwitchInt {
-                            discr: Operand::Copy(tmp),
+                            discr: Operand { kind: OperandKind::Copy(tmp), span: None },
                             targets: SwitchTargets::static_if(e, next, *else_target),
                         },
                         span,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
index d4f10c032cb..d8f443145ca 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
@@ -25,7 +25,7 @@ use crate::{
     infer::normalize,
 };
 
-use super::{MirBody, MirLowerError, Operand, Rvalue, StatementKind, TerminatorKind};
+use super::{MirBody, MirLowerError, Operand, OperandKind, Rvalue, StatementKind, TerminatorKind};
 
 macro_rules! not_supported {
     ($it: expr) => {
@@ -170,8 +170,8 @@ impl Filler<'_> {
     }
 
     fn fill_operand(&mut self, op: &mut Operand) -> Result<(), MirLowerError> {
-        match op {
-            Operand::Constant(c) => {
+        match &mut op.kind {
+            OperandKind::Constant(c) => {
                 match &c.data(Interner).value {
                     chalk_ir::ConstValue::BoundVar(b) => {
                         let resolved = self
@@ -215,7 +215,7 @@ impl Filler<'_> {
                 }
                 self.fill_const(c)?;
             }
-            Operand::Copy(_) | Operand::Move(_) | Operand::Static(_) => (),
+            OperandKind::Copy(_) | OperandKind::Move(_) | OperandKind::Static(_) => (),
         }
         Ok(())
     }
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 f71e2978976..7ae6e907e7a 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
@@ -18,8 +18,8 @@ use crate::{
 };
 
 use super::{
-    AggregateKind, BasicBlockId, BorrowKind, LocalId, MirBody, MutBorrowKind, Operand, Place,
-    Rvalue, UnOp,
+    AggregateKind, BasicBlockId, BorrowKind, LocalId, MirBody, MutBorrowKind, Operand, OperandKind,
+    Place, Rvalue, UnOp,
 };
 
 macro_rules! w {
@@ -374,14 +374,14 @@ impl<'a> MirPrettyCtx<'a> {
     }
 
     fn operand(&mut self, r: &Operand) {
-        match r {
-            Operand::Copy(p) | Operand::Move(p) => {
+        match &r.kind {
+            OperandKind::Copy(p) | OperandKind::Move(p) => {
                 // MIR at the time of writing doesn't have difference between move and copy, so we show them
                 // equally. Feel free to change it.
                 self.place(p);
             }
-            Operand::Constant(c) => w!(self, "Const({})", self.hir_display(c)),
-            Operand::Static(s) => w!(self, "Static({:?})", s),
+            OperandKind::Constant(c) => w!(self, "Const({})", self.hir_display(c)),
+            OperandKind::Static(s) => w!(self, "Static({:?})", s),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
index d2bba120b68..bcd8aa6c4e9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
@@ -16,7 +16,7 @@ use syntax::TextRange;
 use test_utils::extract_annotations;
 use triomphe::Arc;
 
-#[salsa::db]
+#[salsa_macros::db]
 #[derive(Clone)]
 pub(crate) struct TestDB {
     storage: salsa::Storage<Self>,
@@ -47,7 +47,7 @@ impl fmt::Debug for TestDB {
     }
 }
 
-#[salsa::db]
+#[salsa_macros::db]
 impl SourceDatabase for TestDB {
     fn file_text(&self, file_id: base_db::FileId) -> FileText {
         self.files.file_text(file_id)
@@ -102,7 +102,7 @@ impl SourceDatabase for TestDB {
     }
 }
 
-#[salsa::db]
+#[salsa_macros::db]
 impl salsa::Database for TestDB {
     fn salsa_event(&self, event: &dyn std::ops::Fn() -> salsa::Event) {
         let mut events = self.events.lock().unwrap();
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 eeaacbf12ea..ddc5b715194 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, got &'? impl Foo + ?Sized
+                    //^ expected &'? (dyn Foo + 'static), got &'? impl Foo + ?Sized
 }
         "#,
     );
@@ -827,11 +827,11 @@ struct V<T> { t: T }
 fn main() {
     let a: V<&dyn Tr>;
     (a,) = V { t: &S };
-  //^^^^expected V<&'? S>, got (V<&'? dyn Tr>,)
+  //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,)
 
     let mut a: V<&dyn Tr> = V { t: &S };
     (a,) = V { t: &S };
-  //^^^^expected V<&'? S>, got (V<&'? dyn Tr>,)
+  //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,)
 }
         "#,
     );
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 60c03b52246..a986b54a7b0 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
@@ -65,13 +65,13 @@ trait A {
 }
 trait B: A {}
 
-fn test(
+fn test<'a>(
     _: &(dyn A<Assoc = ()> + Send),
-  //^ &'_ (dyn A<Assoc = ()> + Send)
-    _: &(dyn Send + A<Assoc = ()>),
-  //^ &'_ (dyn A<Assoc = ()> + Send)
+  //^ &(dyn A<Assoc = ()> + Send + 'static)
+    _: &'a (dyn Send + A<Assoc = ()>),
+  //^ &'a (dyn A<Assoc = ()> + Send + 'static)
     _: &dyn B<Assoc = ()>,
-  //^ &'_ (dyn B<Assoc = ()>)
+  //^ &(dyn B<Assoc = ()> + 'static)
 ) {}
         "#,
     );
@@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
 trait Foo<'a> {}
 
 fn foo(foo: &dyn for<'a> Foo<'a>) {}
-    // ^^^ &'_ dyn Foo<'_>
+    // ^^^ &(dyn Foo<'?> + 'static)
 "#,
     );
 }
@@ -111,11 +111,11 @@ fn test(
     b;
   //^ impl Foo
     c;
-  //^ &'_ impl Foo + ?Sized
+  //^ &impl Foo + ?Sized
     d;
   //^ S<impl Foo>
     ref_any;
-  //^^^^^^^ &'_ impl ?Sized
+  //^^^^^^^ &impl ?Sized
     empty;
 } //^^^^^ impl Sized
 "#,
@@ -192,7 +192,7 @@ fn test(
     b;
   //^ fn(impl Foo) -> impl Foo
     c;
-} //^ fn(&'_ impl Foo + ?Sized) -> &'_ impl Foo + ?Sized
+} //^ fn(&impl Foo + ?Sized) -> &impl Foo + ?Sized
 "#,
     );
 }
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 3a258ecad10..94826acca30 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
+            176..177 'd': &'? (dyn Trait + 'static)
             191..207 '{     ...o(); }': ()
-            197..198 'd': &'? dyn Trait
+            197..198 'd': &'? (dyn Trait + 'static)
             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>, got Box<dyn Error + Send>
+                               // ^^^^ expected Box<dyn Error + 'static>, got Box<dyn Error + Send + 'static>
                                // FIXME, type mismatch should not occur
         <dyn Error>::downcast(err).map_err(|_| loop {})
-      //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error>) -> Result<Box<{unknown}>, Box<dyn Error>>
+      //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + 'static>) -> Result<Box<{unknown}>, Box<dyn Error + 'static>>
     }
 }
 "#,
@@ -2170,3 +2170,26 @@ fn main() {
 "#,
     );
 }
+
+#[test]
+fn mut_to_const_pointer() {
+    check(
+        r#"
+pub trait X {
+    fn perform(self) -> u64;
+}
+
+impl X for *const u8 {
+    fn perform(self) -> u64 {
+        42
+    }
+}
+
+fn test(x: *mut u8) {
+    let _v = x.perform();
+     //      ^ adjustments: Pointer(MutToConstPointer)
+     //      ^^^^^^^^^^^ type: u64
+}
+"#,
+    );
+}
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 638306054a9..47c695c6974 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>
+            498..515 'self.o...into()': dyn QueryFragment<DB> + 'static
         "#]],
     );
 }
@@ -773,7 +773,7 @@ fn issue_4800() {
         "#,
         expect![[r#"
             379..383 'self': &'? mut PeerSet<D>
-            401..424 '{     ...     }': dyn Future<Output = ()>
+            401..424 '{     ...     }': dyn Future<Output = ()> + 'static
             411..418 'loop {}': !
             416..418 '{}': ()
             575..579 'self': &'? mut Self
@@ -2278,3 +2278,26 @@ fn test(x: bool) {
         "#]],
     );
 }
+
+#[test]
+fn issue_19730() {
+    check_infer(
+        r#"
+trait Trait<T = Self> {}
+
+trait Foo {
+    type Bar<A, B>: Trait;
+
+    fn foo<A, B>(bar: Self::Bar<A, B>) {
+        let _ = bar;
+    }
+}
+"#,
+        expect![[r#"
+            83..86 'bar': Foo::Bar<Self, A, B>
+            105..133 '{     ...     }': ()
+            119..120 '_': Foo::Bar<Self, A, B>
+            123..126 'bar': Foo::Bar<Self, A, B>
+        "#]],
+    );
+}
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 0f5e44151de..eeebe38f182 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, 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]
+            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]
             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 2fb51acea87..14137605c9f 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>>
-            210..211 'x': Box<dyn Trait<u64>>
-            234..235 'y': &'? dyn Trait<u64>
+            198..200 '{}': Box<dyn Trait<u64> + 'static>
+            210..211 'x': Box<dyn Trait<u64> + 'static>
+            234..235 'y': &'? (dyn Trait<u64> + 'static)
             254..371 '{     ...2(); }': ()
-            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>>
+            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>
             293..300 'x.foo()': u64
-            306..307 'y': &'? dyn Trait<u64>
+            306..307 'y': &'? (dyn Trait<u64> + 'static)
             306..313 'y.foo()': u64
-            319..320 'z': Box<dyn Trait<u64>>
+            319..320 'z': Box<dyn Trait<u64> + 'static>
             319..326 'z.foo()': u64
-            332..333 'x': Box<dyn Trait<u64>>
+            332..333 'x': Box<dyn Trait<u64> + 'static>
             332..340 'x.foo2()': i64
-            346..347 'y': &'? dyn Trait<u64>
+            346..347 'y': &'? (dyn Trait<u64> + 'static)
             346..354 'y.foo2()': i64
-            360..361 'z': Box<dyn Trait<u64>>
+            360..361 'z': Box<dyn Trait<u64> + 'static>
             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>
+            128..139 '{ loop {} }': &'? (dyn Trait<T, U> + 'static)
             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>
+            273..280 's.bar()': &'? (dyn Trait<u32, i32> + 'static)
             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
-            72..73 'x': dyn Trait
-            82..83 'y': &'? dyn Trait
+            60..62 '{}': dyn Trait + 'static
+            72..73 'x': dyn Trait + 'static
+            82..83 'y': &'? (dyn Trait + 'static)
             100..175 '{     ...o(); }': u64
-            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
+            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
             139..146 'x.foo()': u64
-            152..153 'y': &'? dyn Trait
+            152..153 'y': &'? (dyn Trait + 'static)
             152..159 'y.foo()': u64
-            165..166 'z': dyn Trait
+            165..166 'z': dyn Trait + 'static
             165..172 'z.foo()': u64
         "#]],
     );
@@ -1589,10 +1589,10 @@ fn main() {
         expect![[r#"
             31..35 'self': &'? S
             37..39 '{}': ()
-            47..48 '_': &'? dyn Fn(S)
+            47..48 '_': &'? (dyn Fn(S) + 'static)
             58..60 '{}': ()
             71..105 '{     ...()); }': ()
-            77..78 'f': fn f(&'? dyn Fn(S))
+            77..78 'f': fn f(&'? (dyn Fn(S) + 'static))
             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
+            21..22 'x': &'? (dyn Foo + 'static)
             34..36 '{}': ()
-            46..47 'x': &'? dyn Foo
+            46..47 'x': &'? (dyn Foo + 'static)
             59..74 '{     foo(x); }': ()
-            65..68 'foo': fn foo(&'? dyn Foo)
+            65..68 'foo': fn foo(&'? (dyn Foo + 'static))
             65..71 'foo(x)': ()
-            69..70 'x': &'? dyn Foo
+            69..70 'x': &'? (dyn Foo + 'static)
         "#]],
     );
 }
@@ -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>)>
-            281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>)>
+            246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static>
+            281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + 'static>
             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>)>
+            316..317 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static>
             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>)
+            127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
             164..195 '{     ...f(); }': ()
-            170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32>)
+            170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
             170..184 'v.get::<i32>()': &'? i32
             170..192 'v.get:...eref()': &'? i32
         "#]],
@@ -4735,7 +4735,7 @@ pub async fn foo_async<'a>() -> Box<dyn Trait + 'a>  {
 
 fn foo() {
     foo_async();
-  //^^^^^^^^^^^impl Future<Output = Box<dyn Trait>> + ?Sized
+  //^^^^^^^^^^^impl Future<Output = Box<dyn Trait + '?>> + ?Sized
 }
 "#,
     )
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
index a5c195d4086..f9f8776cff7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
@@ -8,10 +8,7 @@ use chalk_recursive::Cache;
 use chalk_solve::{Solver, logging_db::LoggingRustIrDatabase, rust_ir};
 
 use base_db::Crate;
-use hir_def::{
-    BlockId, TraitId,
-    lang_item::{LangItem, LangItemTarget},
-};
+use hir_def::{BlockId, TraitId, lang_item::LangItem};
 use hir_expand::name::Name;
 use intern::sym;
 use span::Edition;
@@ -292,10 +289,6 @@ impl FnTrait {
     }
 
     pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<TraitId> {
-        let target = db.lang_item(krate, self.lang_item())?;
-        match target {
-            LangItemTarget::Trait(t) => Some(t),
-            _ => None,
-        }
+        self.lang_item().resolve_trait(db, krate)
     }
 }
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 198f715a6db..1e0ff423ded 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -36,8 +36,7 @@ use crate::{
 pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator<Item = TraitId> + '_ {
     [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]
         .into_iter()
-        .filter_map(move |lang| db.lang_item(krate, lang))
-        .flat_map(|it| it.as_trait())
+        .filter_map(move |lang| lang.resolve_trait(db, krate))
 }
 
 /// Returns an iterator over the direct super traits (including the trait itself).
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
index 4e9aa5610a5..6e1cd9a310f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
@@ -22,7 +22,6 @@ use crate::{
 use chalk_ir::Mutability;
 use hir_def::signatures::StructFlags;
 use hir_def::{AdtId, GenericDefId, GenericParamId, VariantId};
-use salsa::CycleRecoveryAction;
 use std::fmt;
 use std::ops::Not;
 use stdx::never;
@@ -55,14 +54,14 @@ pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Option<Ar
     variances.is_empty().not().then(|| Arc::from_iter(variances))
 }
 
-pub(crate) fn variances_of_cycle_fn(
-    _db: &dyn HirDatabase,
-    _result: &Option<Arc<[Variance]>>,
-    _count: u32,
-    _def: GenericDefId,
-) -> CycleRecoveryAction<Option<Arc<[Variance]>>> {
-    CycleRecoveryAction::Iterate
-}
+// pub(crate) fn variances_of_cycle_fn(
+//     _db: &dyn HirDatabase,
+//     _result: &Option<Arc<[Variance]>>,
+//     _count: u32,
+//     _def: GenericDefId,
+// ) -> salsa::CycleRecoveryAction<Option<Arc<[Variance]>>> {
+//     salsa::CycleRecoveryAction::Iterate
+// }
 
 pub(crate) fn variances_of_cycle_initial(
     db: &dyn HirDatabase,
@@ -966,7 +965,7 @@ struct S3<T>(S<T, T>);
 struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
 "#,
             expect![[r#"
-                FixedPoint[T: covariant, U: covariant, V: covariant]
+                FixedPoint[T: bivariant, U: bivariant, V: bivariant]
             "#]],
         );
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 53817f37aa6..124ab8e274a 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -516,8 +516,7 @@ impl HirDisplay for TypeParam {
             return Ok(());
         }
 
-        let sized_trait =
-            f.db.lang_item(krate, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
+        let sized_trait = LangItem::Sized.resolve_trait(f.db, krate);
         let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
             WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
             _ => false,
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 143c13069e4..3f1d5bb01f2 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -53,7 +53,6 @@ use hir_def::{
         generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
     },
     item_tree::{AttrOwner, FieldParent, ImportAlias, ItemTreeFieldId, ItemTreeNode},
-    lang_item::LangItemTarget,
     layout::{self, ReprOptions, TargetDataLayout},
     nameres::{self, diagnostics::DefDiagnostic},
     per_ns::PerNs,
@@ -137,7 +136,6 @@ pub use {
             HirFileRange, InFile, InFileWrapper, InMacroFile, InRealFile, MacroFilePosition,
             MacroFileRange,
         },
-        hygiene::{SyntaxContextExt, marks_rev},
         inert_attr_macro::AttributeTemplate,
         mod_path::{ModPath, PathKind, tool_path},
         name::Name,
@@ -781,7 +779,7 @@ impl Module {
             let drop_maybe_dangle = (|| {
                 // FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper
                 let trait_ = trait_?;
-                let drop_trait = db.lang_item(self.krate().into(), LangItem::Drop)?.as_trait()?;
+                let drop_trait = LangItem::Drop.resolve_trait(db, self.krate().into())?;
                 if drop_trait != trait_.into() {
                     return None;
                 }
@@ -2388,14 +2386,11 @@ impl Function {
         }
 
         let Some(impl_traits) = self.ret_type(db).as_impl_traits(db) else { return false };
-        let Some(future_trait_id) =
-            db.lang_item(self.ty(db).env.krate, LangItem::Future).and_then(|t| t.as_trait())
+        let Some(future_trait_id) = LangItem::Future.resolve_trait(db, self.ty(db).env.krate)
         else {
             return false;
         };
-        let Some(sized_trait_id) =
-            db.lang_item(self.ty(db).env.krate, LangItem::Sized).and_then(|t| t.as_trait())
-        else {
+        let Some(sized_trait_id) = LangItem::Sized.resolve_trait(db, self.ty(db).env.krate) else {
             return false;
         };
 
@@ -2861,9 +2856,7 @@ pub struct Trait {
 
 impl Trait {
     pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
-        db.lang_item(krate.into(), LangItem::from_name(name)?)
-            .and_then(LangItemTarget::as_trait)
-            .map(Into::into)
+        LangItem::from_name(name)?.resolve_trait(db, krate.into()).map(Into::into)
     }
 
     pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -3692,24 +3685,16 @@ impl GenericDef {
         }
 
         let source_map = match def {
-            GenericDefId::AdtId(AdtId::EnumId(it)) => {
-                db.enum_signature_with_source_map(it).1.clone()
-            }
-            GenericDefId::AdtId(AdtId::StructId(it)) => {
-                db.struct_signature_with_source_map(it).1.clone()
-            }
-            GenericDefId::AdtId(AdtId::UnionId(it)) => {
-                db.union_signature_with_source_map(it).1.clone()
-            }
+            GenericDefId::AdtId(AdtId::EnumId(it)) => db.enum_signature_with_source_map(it).1,
+            GenericDefId::AdtId(AdtId::StructId(it)) => db.struct_signature_with_source_map(it).1,
+            GenericDefId::AdtId(AdtId::UnionId(it)) => db.union_signature_with_source_map(it).1,
             GenericDefId::ConstId(_) => return,
-            GenericDefId::FunctionId(it) => db.function_signature_with_source_map(it).1.clone(),
-            GenericDefId::ImplId(it) => db.impl_signature_with_source_map(it).1.clone(),
+            GenericDefId::FunctionId(it) => db.function_signature_with_source_map(it).1,
+            GenericDefId::ImplId(it) => db.impl_signature_with_source_map(it).1,
             GenericDefId::StaticId(_) => return,
-            GenericDefId::TraitAliasId(it) => {
-                db.trait_alias_signature_with_source_map(it).1.clone()
-            }
-            GenericDefId::TraitId(it) => db.trait_signature_with_source_map(it).1.clone(),
-            GenericDefId::TypeAliasId(it) => db.type_alias_signature_with_source_map(it).1.clone(),
+            GenericDefId::TraitAliasId(it) => db.trait_alias_signature_with_source_map(it).1,
+            GenericDefId::TraitId(it) => db.trait_signature_with_source_map(it).1,
+            GenericDefId::TypeAliasId(it) => db.type_alias_signature_with_source_map(it).1,
         };
 
         expr_store_diagnostics(db, acc, &source_map);
@@ -3809,7 +3794,7 @@ impl GenericSubstitution {
         container_params
             .chain(self_params)
             .filter_map(|(ty, name)| {
-                Some((name?.symbol().clone(), Type { ty: ty.clone(), env: self.env.clone() }))
+                Some((name?.symbol().clone(), Type { ty, env: self.env.clone() }))
             })
             .collect()
     }
@@ -4989,18 +4974,14 @@ impl Type {
     /// `std::future::Future` and returns the `Output` associated type.
     /// This function is used in `.await` syntax completion.
     pub fn into_future_output(&self, db: &dyn HirDatabase) -> Option<Type> {
-        let trait_ = db
-            .lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
-            .and_then(|it| {
-                let into_future_fn = it.as_function()?;
+        let trait_ = LangItem::IntoFutureIntoFuture
+            .resolve_function(db, self.env.krate)
+            .and_then(|into_future_fn| {
                 let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
                 let into_future_trait = assoc_item.container_or_implemented_trait(db)?;
                 Some(into_future_trait.id)
             })
-            .or_else(|| {
-                let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
-                future_trait.as_trait()
-            })?;
+            .or_else(|| LangItem::Future.resolve_trait(db, self.env.krate))?;
 
         let canonical_ty =
             Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
@@ -5015,14 +4996,13 @@ impl Type {
 
     /// This does **not** resolve `IntoFuture`, only `Future`.
     pub fn future_output(self, db: &dyn HirDatabase) -> Option<Type> {
-        let future_output =
-            db.lang_item(self.env.krate, LangItem::FutureOutput)?.as_type_alias()?;
+        let future_output = LangItem::FutureOutput.resolve_type_alias(db, self.env.krate)?;
         self.normalize_trait_assoc_type(db, &[], future_output.into())
     }
 
     /// This does **not** resolve `IntoIterator`, only `Iterator`.
     pub fn iterator_item(self, db: &dyn HirDatabase) -> Option<Type> {
-        let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?;
+        let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
         let iterator_item = db
             .trait_items(iterator_trait)
             .associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
@@ -5030,9 +5010,7 @@ impl Type {
     }
 
     pub fn impls_iterator(self, db: &dyn HirDatabase) -> bool {
-        let Some(iterator_trait) =
-            db.lang_item(self.env.krate, LangItem::Iterator).and_then(|it| it.as_trait())
-        else {
+        let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else {
             return false;
         };
         let canonical_ty =
@@ -5042,12 +5020,13 @@ impl Type {
 
     /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
     pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option<Type> {
-        let trait_ = db.lang_item(self.env.krate, LangItem::IntoIterIntoIter).and_then(|it| {
-            let into_iter_fn = it.as_function()?;
-            let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
-            let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
-            Some(into_iter_trait.id)
-        })?;
+        let trait_ = LangItem::IntoIterIntoIter.resolve_function(db, self.env.krate).and_then(
+            |into_iter_fn| {
+                let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
+                let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
+                Some(into_iter_trait.id)
+            },
+        )?;
 
         let canonical_ty =
             Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
@@ -5133,10 +5112,8 @@ impl Type {
     }
 
     pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
-        let lang_item = db.lang_item(self.env.krate, LangItem::Copy);
-        let copy_trait = match lang_item {
-            Some(LangItemTarget::Trait(it)) => it,
-            _ => return false,
+        let Some(copy_trait) = LangItem::Copy.resolve_trait(db, self.env.krate) else {
+            return false;
         };
         self.impls_trait(db, copy_trait.into(), &[])
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index f708f2e1667..4d092c1f0bb 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -25,7 +25,6 @@ use hir_expand::{
     builtin::{BuiltinFnLikeExpander, EagerExpander},
     db::ExpandDatabase,
     files::{FileRangeWrapper, InRealFile},
-    hygiene::SyntaxContextExt as _,
     inert_attr_macro::find_builtin_attr_idx,
     mod_path::{ModPath, PathKind},
     name::AsName,
@@ -927,7 +926,7 @@ impl<'db> SemanticsImpl<'db> {
         token: InRealFile<SyntaxToken>,
         mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext) -> ControlFlow<T>,
     ) -> Option<T> {
-        self.descend_into_macros_impl(token.clone(), &mut cb)
+        self.descend_into_macros_impl(token, &mut cb)
     }
 
     /// Descends the token into expansions, returning the tokens that matches the input
@@ -959,17 +958,13 @@ impl<'db> SemanticsImpl<'db> {
         let text = token.text();
         let kind = token.kind();
         if let Ok(token) = self.wrap_token_infile(token.clone()).into_real_file() {
-            self.descend_into_macros_breakable(
-                token.clone(),
-                |InFile { value, file_id: _ }, _ctx| {
-                    let mapped_kind = value.kind();
-                    let any_ident_match =
-                        || kind.is_any_identifier() && value.kind().is_any_identifier();
-                    let matches =
-                        (kind == mapped_kind || any_ident_match()) && text == value.text();
-                    if matches { ControlFlow::Break(value) } else { ControlFlow::Continue(()) }
-                },
-            )
+            self.descend_into_macros_breakable(token, |InFile { value, file_id: _ }, _ctx| {
+                let mapped_kind = value.kind();
+                let any_ident_match =
+                    || kind.is_any_identifier() && value.kind().is_any_identifier();
+                let matches = (kind == mapped_kind || any_ident_match()) && text == value.text();
+                if matches { ControlFlow::Break(value) } else { ControlFlow::Continue(()) }
+            })
         } else {
             None
         }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index 466bf7f6c82..587c51d8cc9 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -559,7 +559,7 @@ impl SourceToDefCtx<'_, '_> {
             let item = match ast::Item::cast(value.clone()) {
                 Some(it) => it,
                 None => {
-                    let variant = ast::Variant::cast(value.clone())?;
+                    let variant = ast::Variant::cast(value)?;
                     return this
                         .enum_variant_to_def(InFile::new(file_id, &variant))
                         .map(Into::into);
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 666efe8ec64..c1a75ce7e57 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -556,8 +556,8 @@ impl SourceAnalyzer {
             }
         }
 
-        let future_trait = db.lang_item(self.resolver.krate(), LangItem::Future)?.as_trait()?;
-        let poll_fn = db.lang_item(self.resolver.krate(), LangItem::FuturePoll)?.as_function()?;
+        let future_trait = LangItem::Future.resolve_trait(db, self.resolver.krate())?;
+        let poll_fn = LangItem::FuturePoll.resolve_function(db, self.resolver.krate())?;
         // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself
         // doesn't have any generic parameters, so we skip building another subst for `poll()`.
         let substs = hir_ty::TyBuilder::subst_for_def(db, future_trait, None).push(ty).build();
@@ -666,7 +666,7 @@ impl SourceAnalyzer {
     ) -> Option<FunctionId> {
         let ty = self.ty_of_expr(try_expr.expr()?)?;
 
-        let op_fn = db.lang_item(self.resolver.krate(), LangItem::TryTraitBranch)?.as_function()?;
+        let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?;
         let op_trait = match op_fn.lookup(db).container {
             ItemContainerId::TraitId(id) => id,
             _ => return None,
@@ -1425,13 +1425,13 @@ impl SourceAnalyzer {
         lang_trait: LangItem,
         method_name: &Name,
     ) -> Option<(TraitId, FunctionId)> {
-        let trait_id = db.lang_item(self.resolver.krate(), lang_trait)?.as_trait()?;
+        let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?;
         let fn_id = db.trait_items(trait_id).method_by_name(method_name)?;
         Some((trait_id, fn_id))
     }
 
     fn ty_of_expr(&self, expr: ast::Expr) -> Option<&Ty> {
-        self.infer()?.type_of_expr_or_pat(self.expr_id(expr.clone())?)
+        self.infer()?.type_of_expr_or_pat(self.expr_id(expr)?)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
index 41064d047a5..e87ab87407f 100644
--- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
@@ -13,13 +13,13 @@ use hir_def::{
 use hir_expand::{HirFileId, name::Name};
 use hir_ty::{
     db::HirDatabase,
-    display::{DisplayTarget, HirDisplay, hir_display_with_store},
+    display::{HirDisplay, hir_display_with_store},
 };
 use intern::Symbol;
 use rustc_hash::FxHashMap;
 use syntax::{AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast::HasName};
 
-use crate::{Module, ModuleDef, Semantics};
+use crate::{HasCrate, Module, ModuleDef, Semantics};
 
 pub type FxIndexSet<T> = indexmap::IndexSet<T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
 
@@ -66,7 +66,6 @@ pub struct SymbolCollector<'a> {
     symbols: FxIndexSet<FileSymbol>,
     work: Vec<SymbolCollectorWork>,
     current_container_name: Option<SmolStr>,
-    display_target: DisplayTarget,
 }
 
 /// Given a [`ModuleId`] and a [`HirDatabase`], use the DefMap for the module's crate to collect
@@ -78,10 +77,6 @@ impl<'a> SymbolCollector<'a> {
             symbols: Default::default(),
             work: Default::default(),
             current_container_name: None,
-            display_target: DisplayTarget::from_crate(
-                db,
-                *db.all_crates().last().expect("no crate graph present"),
-            ),
         }
     }
 
@@ -93,8 +88,7 @@ impl<'a> SymbolCollector<'a> {
 
     pub fn collect(&mut self, module: Module) {
         let _p = tracing::info_span!("SymbolCollector::collect", ?module).entered();
-        tracing::info!(?module, "SymbolCollector::collect",);
-        self.display_target = module.krate().to_display_target(self.db);
+        tracing::info!(?module, "SymbolCollector::collect");
 
         // The initial work is the root module we're collecting, additional work will
         // be populated as we traverse the module's definitions.
@@ -263,8 +257,9 @@ impl<'a> SymbolCollector<'a> {
         for (name, Item { def, vis, import }) in scope.macros() {
             if let Some(i) = import {
                 match i {
-                    ImportOrGlob::Import(i) => push_import(self, i, name, def.into(), vis),
-                    ImportOrGlob::Glob(_) => (),
+                    ImportOrExternCrate::Import(i) => push_import(self, i, name, def.into(), vis),
+                    ImportOrExternCrate::Glob(_) => (),
+                    ImportOrExternCrate::ExternCrate(_) => (),
                 }
                 continue;
             }
@@ -320,7 +315,10 @@ impl<'a> SymbolCollector<'a> {
         let impl_data = self.db.impl_signature(impl_id);
         let impl_name = Some(
             hir_display_with_store(impl_data.self_ty, &impl_data.store)
-                .display(self.db, self.display_target)
+                .display(
+                    self.db,
+                    crate::Impl::from(impl_id).krate(self.db).to_display_target(self.db),
+                )
                 .to_smolstr(),
         );
         self.with_container_name(impl_name, |s| {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
index 2de0013bb12..fb569f8cdae 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
@@ -5,7 +5,7 @@
 //! assists if we are allowed to.
 
 use hir::ImportPathConfig;
-use ide_db::{SnippetCap, imports::insert_use::InsertUseConfig};
+use ide_db::{SnippetCap, assists::ExprFillDefaultMode, imports::insert_use::InsertUseConfig};
 
 use crate::AssistKind;
 
@@ -21,6 +21,7 @@ pub struct AssistConfig {
     pub term_search_fuel: u64,
     pub term_search_borrowck: bool,
     pub code_action_grouping: bool,
+    pub expr_fill_default: ExprFillDefaultMode,
 }
 
 impl AssistConfig {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 887ec5aeec9..6a55f39e693 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -150,6 +150,7 @@ fn add_missing_impl_members_inner(
         let new_impl_def = edit.make_mut(impl_def.clone());
         let first_new_item = add_trait_assoc_items_to_impl(
             &ctx.sema,
+            ctx.config,
             &missing_items,
             trait_,
             &new_impl_def,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 8c1c83e3f71..858d4369914 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -3,6 +3,7 @@ use std::iter::{self, Peekable};
 use either::Either;
 use hir::{Adt, Crate, HasAttrs, ImportPathConfig, ModuleDef, Semantics, sym};
 use ide_db::RootDatabase;
+use ide_db::assists::ExprFillDefaultMode;
 use ide_db::syntax_helpers::suggest_name;
 use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};
 use itertools::Itertools;
@@ -216,7 +217,17 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                     // filter out hidden patterns because they're handled by the catch-all arm
                     !hidden
                 })
-                .map(|(pat, _)| make.match_arm(pat, None, make::ext::expr_todo()));
+                .map(|(pat, _)| {
+                    make.match_arm(
+                        pat,
+                        None,
+                        match ctx.config.expr_fill_default {
+                            ExprFillDefaultMode::Todo => make::ext::expr_todo(),
+                            ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
+                            ExprFillDefaultMode::Default => make::ext::expr_todo(),
+                        },
+                    )
+                });
 
             let mut arms: Vec<_> = match_arm_list
                 .arms()
@@ -246,7 +257,15 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
 
             if needs_catch_all_arm && !has_catch_all_arm {
                 cov_mark::hit!(added_wildcard_pattern);
-                let arm = make.match_arm(make.wildcard_pat().into(), None, make::ext::expr_todo());
+                let arm = make.match_arm(
+                    make.wildcard_pat().into(),
+                    None,
+                    match ctx.config.expr_fill_default {
+                        ExprFillDefaultMode::Todo => make::ext::expr_todo(),
+                        ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
+                        ExprFillDefaultMode::Default => make::ext::expr_todo(),
+                    },
+                );
                 arms.push(arm);
             }
 
@@ -474,8 +493,8 @@ fn build_pat(
                 hir::StructKind::Record => {
                     let fields = fields
                         .into_iter()
-                        .map(|f| make.name_ref(f.name(db).as_str()))
-                        .map(|name_ref| make.record_pat_field_shorthand(name_ref));
+                        .map(|f| make.ident_pat(false, false, make.name(f.name(db).as_str())))
+                        .map(|ident| make.record_pat_field_shorthand(ident.into()));
                     let fields = make.record_pat_field_list(fields, None);
                     make.record_pat_with_fields(path, fields).into()
                 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
index cd23ad22372..bcd06c1ef72 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
@@ -196,7 +196,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
             // Wrap all tails in `Some(...)`
             let none_path = mapless_make.expr_path(mapless_make.ident_path("None"));
             let some_path = mapless_make.expr_path(mapless_make.ident_path("Some"));
-            for_each_tail_expr(&ast::Expr::BlockExpr(closure_body.clone()), &mut |e| {
+            for_each_tail_expr(&ast::Expr::BlockExpr(closure_body), &mut |e| {
                 let e = match e {
                     ast::Expr::BreakExpr(e) => e.expr(),
                     ast::Expr::ReturnExpr(e) => e.expr(),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
index 1d3a2db3352..43515de71e2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs
@@ -1066,7 +1066,7 @@ fn foo() {
             r#"
 fn foo() {
     let (mut a, b) = (0.1, "abc");
-    fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) {
+    fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) {
         *a = 1.2;
         let c = *b;
     }
@@ -1098,7 +1098,7 @@ fn foo() {
             r#"
 fn foo() {
     let (mut a, b) = (0.1, "abc");
-    fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) {
+    fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) {
         let _: &mut bool = p2;
         *a = 1.2;
         let c = *b;
@@ -1136,7 +1136,7 @@ fn foo() {
             r#"
 fn foo() {
     let (mut a, b) = (0.1, "abc");
-    fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) {
+    fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) {
         let _: &mut bool = p2;
         *a = 1.2;
         let c = *b;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs
index 24cc32d10d8..db41927f1df 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs
@@ -80,7 +80,7 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_>
             let from_fn_name = builder.make_mut(from_fn_name);
             let tail_expr = builder.make_mut(tail_expr);
             let return_exprs = return_exprs.map(|r| builder.make_mut(r)).collect_vec();
-            let associated_items = builder.make_mut(associated_items).clone();
+            let associated_items = builder.make_mut(associated_items);
 
             ted::replace(
                 trait_ty.syntax(),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs
index df92b07cba7..ebfed9f9ca9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_let_else_to_match.rs
@@ -1,8 +1,9 @@
-use hir::Semantics;
-use ide_db::RootDatabase;
 use syntax::T;
 use syntax::ast::RangeItem;
-use syntax::ast::{AstNode, HasName, LetStmt, Name, Pat, edit::AstNodeEdit};
+use syntax::ast::edit::IndentLevel;
+use syntax::ast::edit_in_place::Indent;
+use syntax::ast::syntax_factory::SyntaxFactory;
+use syntax::ast::{self, AstNode, HasName, LetStmt, Pat};
 
 use crate::{AssistContext, AssistId, Assists};
 
@@ -25,155 +26,205 @@ use crate::{AssistContext, AssistId, Assists};
 // }
 // ```
 pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    // should focus on else token to trigger
+    // Should focus on the `else` token to trigger
     let let_stmt = ctx
         .find_token_syntax_at_offset(T![else])
         .and_then(|it| it.parent()?.parent())
         .or_else(|| ctx.find_token_syntax_at_offset(T![let])?.parent())?;
     let let_stmt = LetStmt::cast(let_stmt)?;
-    let let_else_block = let_stmt.let_else()?.block_expr()?;
-    let let_init = let_stmt.initializer()?;
+    let else_block = let_stmt.let_else()?.block_expr()?;
+    let else_expr = if else_block.statements().next().is_none() {
+        else_block.tail_expr()?
+    } else {
+        else_block.into()
+    };
+    let init = let_stmt.initializer()?;
+    // Ignore let stmt with type annotation
     if let_stmt.ty().is_some() {
-        // don't support let with type annotation
         return None;
     }
     let pat = let_stmt.pat()?;
-    let mut binders = Vec::new();
-    binders_in_pat(&mut binders, &pat, &ctx.sema)?;
 
-    let target = let_stmt.syntax().text_range();
+    let make = SyntaxFactory::with_mappings();
+    let mut idents = Vec::default();
+    let pat_without_mut = remove_mut_and_collect_idents(&make, &pat, &mut idents)?;
+    let bindings = idents
+        .into_iter()
+        .filter_map(|ref pat| {
+            // Identifiers which resolve to constants are not bindings
+            if ctx.sema.resolve_bind_pat_to_const(pat).is_none() {
+                Some((pat.name()?, pat.ref_token().is_none() && pat.mut_token().is_some()))
+            } else {
+                None
+            }
+        })
+        .collect::<Vec<_>>();
+
     acc.add(
         AssistId::refactor_rewrite("convert_let_else_to_match"),
-        "Convert let-else to let and match",
-        target,
-        |edit| {
-            let indent_level = let_stmt.indent_level().0 as usize;
-            let indent = "    ".repeat(indent_level);
-            let indent1 = "    ".repeat(indent_level + 1);
+        if bindings.is_empty() {
+            "Convert let-else to match"
+        } else {
+            "Convert let-else to let and match"
+        },
+        let_stmt.syntax().text_range(),
+        |builder| {
+            let mut editor = builder.make_editor(let_stmt.syntax());
 
-            let binders_str = binders_to_str(&binders, false);
-            let binders_str_mut = binders_to_str(&binders, true);
+            let binding_paths = bindings
+                .iter()
+                .map(|(name, _)| make.expr_path(make.ident_path(&name.to_string())))
+                .collect::<Vec<_>>();
 
-            let init_expr = let_init.syntax().text();
-            let mut pat_no_mut = pat.syntax().text().to_string();
-            // remove the mut from the pattern
-            for (b, ismut) in binders.iter() {
-                if *ismut {
-                    pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), &b.to_string());
-                }
-            }
+            let binding_arm = make.match_arm(
+                pat_without_mut,
+                None,
+                // There are three possible cases:
+                //
+                // - No bindings: `None => {}`
+                // - Single binding: `Some(it) => it`
+                // - Multiple bindings: `Foo::Bar { a, b, .. } => (a, b)`
+                match binding_paths.len() {
+                    0 => make.expr_empty_block().into(),
 
-            let only_expr = let_else_block.statements().next().is_none();
-            let branch2 = match &let_else_block.tail_expr() {
-                Some(tail) if only_expr => format!("{tail},"),
-                _ => let_else_block.syntax().text().to_string(),
-            };
-            let replace = if binders.is_empty() {
-                format!(
-                    "match {init_expr} {{
-{indent1}{pat_no_mut} => {binders_str}
-{indent1}_ => {branch2}
-{indent}}}"
-                )
+                    1 => binding_paths[0].clone(),
+                    _ => make.expr_tuple(binding_paths).into(),
+                },
+            );
+            let else_arm = make.match_arm(make.wildcard_pat().into(), None, else_expr);
+            let match_ = make.expr_match(init, make.match_arm_list([binding_arm, else_arm]));
+            match_.reindent_to(IndentLevel::from_node(let_stmt.syntax()));
+
+            if bindings.is_empty() {
+                editor.replace(let_stmt.syntax(), match_.syntax());
             } else {
-                format!(
-                    "let {binders_str_mut} = match {init_expr} {{
-{indent1}{pat_no_mut} => {binders_str},
-{indent1}_ => {branch2}
-{indent}}};"
-                )
-            };
-            edit.replace(target, replace);
+                let ident_pats = bindings
+                    .into_iter()
+                    .map(|(name, is_mut)| make.ident_pat(false, is_mut, name).into())
+                    .collect::<Vec<Pat>>();
+                let new_let_stmt = make.let_stmt(
+                    if ident_pats.len() == 1 {
+                        ident_pats[0].clone()
+                    } else {
+                        make.tuple_pat(ident_pats).into()
+                    },
+                    None,
+                    Some(match_.into()),
+                );
+                editor.replace(let_stmt.syntax(), new_let_stmt.syntax());
+            }
+
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.vfs_file_id(), editor);
         },
     )
 }
 
-/// Gets a list of binders in a pattern, and whether they are mut.
-fn binders_in_pat(
-    acc: &mut Vec<(Name, bool)>,
-    pat: &Pat,
-    sem: &Semantics<'_, RootDatabase>,
-) -> Option<()> {
-    use Pat::*;
-    match pat {
-        IdentPat(p) => {
-            let ident = p.name()?;
-            let ismut = p.ref_token().is_none() && p.mut_token().is_some();
-            // check for const reference
-            if sem.resolve_bind_pat_to_const(p).is_none() {
-                acc.push((ident, ismut));
-            }
+fn remove_mut_and_collect_idents(
+    make: &SyntaxFactory,
+    pat: &ast::Pat,
+    acc: &mut Vec<ast::IdentPat>,
+) -> Option<ast::Pat> {
+    Some(match pat {
+        ast::Pat::IdentPat(p) => {
+            acc.push(p.clone());
+            let non_mut_pat = make.ident_pat(
+                p.ref_token().is_some(),
+                p.ref_token().is_some() && p.mut_token().is_some(),
+                p.name()?,
+            );
             if let Some(inner) = p.pat() {
-                binders_in_pat(acc, &inner, sem)?;
-            }
-            Some(())
-        }
-        BoxPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
-        RestPat(_) | LiteralPat(_) | PathPat(_) | WildcardPat(_) | ConstBlockPat(_) => Some(()),
-        OrPat(p) => {
-            for p in p.pats() {
-                binders_in_pat(acc, &p, sem)?;
+                non_mut_pat.set_pat(remove_mut_and_collect_idents(make, &inner, acc));
             }
-            Some(())
+            non_mut_pat.into()
         }
-        ParenPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
-        RangePat(p) => {
-            if let Some(st) = p.start() {
-                binders_in_pat(acc, &st, sem)?
-            }
-            if let Some(ed) = p.end() {
-                binders_in_pat(acc, &ed, sem)?
-            }
-            Some(())
-        }
-        RecordPat(p) => {
-            for f in p.record_pat_field_list()?.fields() {
-                let pat = f.pat()?;
-                binders_in_pat(acc, &pat, sem)?;
-            }
-            Some(())
+        ast::Pat::BoxPat(p) => {
+            make.box_pat(remove_mut_and_collect_idents(make, &p.pat()?, acc)?).into()
         }
-        RefPat(p) => p.pat().and_then(|p| binders_in_pat(acc, &p, sem)),
-        SlicePat(p) => {
-            for p in p.pats() {
-                binders_in_pat(acc, &p, sem)?;
-            }
-            Some(())
-        }
-        TuplePat(p) => {
-            for p in p.fields() {
-                binders_in_pat(acc, &p, sem)?;
-            }
-            Some(())
+        ast::Pat::OrPat(p) => make
+            .or_pat(
+                p.pats()
+                    .map(|pat| remove_mut_and_collect_idents(make, &pat, acc))
+                    .collect::<Option<Vec<_>>>()?,
+                p.leading_pipe().is_some(),
+            )
+            .into(),
+        ast::Pat::ParenPat(p) => {
+            make.paren_pat(remove_mut_and_collect_idents(make, &p.pat()?, acc)?).into()
         }
-        TupleStructPat(p) => {
-            for p in p.fields() {
-                binders_in_pat(acc, &p, sem)?;
+        ast::Pat::RangePat(p) => make
+            .range_pat(
+                if let Some(start) = p.start() {
+                    Some(remove_mut_and_collect_idents(make, &start, acc)?)
+                } else {
+                    None
+                },
+                if let Some(end) = p.end() {
+                    Some(remove_mut_and_collect_idents(make, &end, acc)?)
+                } else {
+                    None
+                },
+            )
+            .into(),
+        ast::Pat::RecordPat(p) => make
+            .record_pat_with_fields(
+                p.path()?,
+                make.record_pat_field_list(
+                    p.record_pat_field_list()?
+                        .fields()
+                        .map(|field| {
+                            remove_mut_and_collect_idents(make, &field.pat()?, acc).map(|pat| {
+                                if let Some(name_ref) = field.name_ref() {
+                                    make.record_pat_field(name_ref, pat)
+                                } else {
+                                    make.record_pat_field_shorthand(pat)
+                                }
+                            })
+                        })
+                        .collect::<Option<Vec<_>>>()?,
+                    p.record_pat_field_list()?.rest_pat(),
+                ),
+            )
+            .into(),
+        ast::Pat::RefPat(p) => {
+            let inner = p.pat()?;
+            if let ast::Pat::IdentPat(ident) = inner {
+                acc.push(ident);
+                p.clone_for_update().into()
+            } else {
+                make.ref_pat(remove_mut_and_collect_idents(make, &inner, acc)?).into()
             }
-            Some(())
         }
+        ast::Pat::SlicePat(p) => make
+            .slice_pat(
+                p.pats()
+                    .map(|pat| remove_mut_and_collect_idents(make, &pat, acc))
+                    .collect::<Option<Vec<_>>>()?,
+            )
+            .into(),
+        ast::Pat::TuplePat(p) => make
+            .tuple_pat(
+                p.fields()
+                    .map(|field| remove_mut_and_collect_idents(make, &field, acc))
+                    .collect::<Option<Vec<_>>>()?,
+            )
+            .into(),
+        ast::Pat::TupleStructPat(p) => make
+            .tuple_struct_pat(
+                p.path()?,
+                p.fields()
+                    .map(|field| remove_mut_and_collect_idents(make, &field, acc))
+                    .collect::<Option<Vec<_>>>()?,
+            )
+            .into(),
+        ast::Pat::RestPat(_)
+        | ast::Pat::LiteralPat(_)
+        | ast::Pat::PathPat(_)
+        | ast::Pat::WildcardPat(_)
+        | ast::Pat::ConstBlockPat(_) => pat.clone(),
         // don't support macro pat yet
-        MacroPat(_) => None,
-    }
-}
-
-fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String {
-    let vars = binders
-        .iter()
-        .map(
-            |(ident, ismut)| {
-                if *ismut && addmut { format!("mut {ident}") } else { ident.to_string() }
-            },
-        )
-        .collect::<Vec<_>>()
-        .join(", ");
-    if binders.is_empty() {
-        String::from("{}")
-    } else if binders.len() == 1 {
-        vars
-    } else {
-        format!("({vars})")
-    }
+        ast::Pat::MacroPat(_) => return None,
+    })
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index 800ef89ac6e..b8c647ac8b7 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -196,7 +196,9 @@ fn destructure_pat(
             let fields = field_names.iter().map(|(old_name, new_name)| {
                 // Use shorthand syntax if possible
                 if old_name == new_name && !is_mut {
-                    make.record_pat_field_shorthand(make.name_ref(old_name))
+                    make.record_pat_field_shorthand(
+                        make.ident_pat(false, false, make.name(old_name)).into(),
+                    )
                 } else {
                     make.record_pat_field(
                         make.name_ref(old_name),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
index adf0f0997b3..f09389f8302 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
@@ -142,7 +142,7 @@ fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option<TupleDat
         .map(|(id, ty)| {
             match name_generator.for_type(&ty, ctx.db(), ctx.edition()) {
                 Some(name) => name,
-                None => name_generator.suggest_name(&format!("_{}", id)),
+                None => name_generator.suggest_name(&format!("_{id}")),
             }
             .to_string()
         })
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs
index 4e487e21626..b71de5e00c6 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_rest_pattern.rs
@@ -56,7 +56,12 @@ fn expand_record_rest_pattern(
             let new_field_list = make.record_pat_field_list(old_field_list.fields(), None);
             for (f, _) in missing_fields.iter() {
                 let field = make.record_pat_field_shorthand(
-                    make.name_ref(&f.name(ctx.sema.db).display_no_db(edition).to_smolstr()),
+                    make.ident_pat(
+                        false,
+                        false,
+                        make.name(&f.name(ctx.sema.db).display_no_db(edition).to_smolstr()),
+                    )
+                    .into(),
                 );
                 new_field_list.add_field(field);
             }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index 046af71a9dc..e977798c4fd 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -5033,7 +5033,7 @@ fn main() {
     fun_name(bar);
 }
 
-fn $0fun_name(bar: &str) {
+fn $0fun_name(bar: &'static str) {
     m!(bar);
 }
 "#,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
index 3971b60f253..31e84e9adcf 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
@@ -631,7 +631,7 @@ fn main() {
 "#,
             r#"
 fn main() {
-    const $0HELLO: &str = "hello";
+    const $0HELLO: &'static str = "hello";
 }
 "#,
             "Extract into constant",
@@ -726,7 +726,7 @@ fn main() {
 "#,
             r#"
 fn main() {
-    static $0HELLO: &str = "hello";
+    static $0HELLO: &'static str = "hello";
 }
 "#,
             "Extract into static",
@@ -2528,13 +2528,13 @@ fn foo() {
         check_assist_by_label(
             extract_variable,
             r#"
-struct Entry(&str);
+struct Entry<'a>(&'a str);
 fn foo() {
     let entry = Entry($0"Hello"$0);
 }
 "#,
             r#"
-struct Entry(&str);
+struct Entry<'a>(&'a str);
 fn foo() {
     let $0hello = "Hello";
     let entry = Entry(hello);
@@ -2546,13 +2546,13 @@ fn foo() {
         check_assist_by_label(
             extract_variable,
             r#"
-struct Entry(&str);
+struct Entry<'a>(&'a str);
 fn foo() {
     let entry = Entry($0"Hello"$0);
 }
 "#,
             r#"
-struct Entry(&str);
+struct Entry<'a>(&'a str);
 fn foo() {
     const $0HELLO: &str = "Hello";
     let entry = Entry(HELLO);
@@ -2564,13 +2564,13 @@ fn foo() {
         check_assist_by_label(
             extract_variable,
             r#"
-struct Entry(&str);
+struct Entry<'a>(&'a str);
 fn foo() {
     let entry = Entry($0"Hello"$0);
 }
 "#,
             r#"
-struct Entry(&str);
+struct Entry<'a>(&'a str);
 fn foo() {
     static $0HELLO: &str = "Hello";
     let entry = Entry(HELLO);
@@ -2587,13 +2587,13 @@ fn foo() {
         check_assist_by_label(
             extract_variable,
             r#"
-struct Entry { message: &str }
+struct Entry<'a> { message: &'a str }
 fn foo() {
     let entry = Entry { message: $0"Hello"$0 };
 }
 "#,
             r#"
-struct Entry { message: &str }
+struct Entry<'a> { message: &'a str }
 fn foo() {
     let $0message = "Hello";
     let entry = Entry { message };
@@ -2605,13 +2605,13 @@ fn foo() {
         check_assist_by_label(
             extract_variable,
             r#"
-struct Entry { message: &str }
+struct Entry<'a> { message: &'a str }
 fn foo() {
     let entry = Entry { message: $0"Hello"$0 };
 }
 "#,
             r#"
-struct Entry { message: &str }
+struct Entry<'a> { message: &'a str }
 fn foo() {
     const $0HELLO: &str = "Hello";
     let entry = Entry { message: HELLO };
@@ -2623,13 +2623,13 @@ fn foo() {
         check_assist_by_label(
             extract_variable,
             r#"
-struct Entry { message: &str }
+struct Entry<'a> { message: &'a str }
 fn foo() {
     let entry = Entry { message: $0"Hello"$0 };
 }
 "#,
             r#"
-struct Entry { message: &str }
+struct Entry<'a> { message: &'a str }
 fn foo() {
     static $0HELLO: &str = "Hello";
     let entry = Entry { message: HELLO };
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
index 824380253ae..30084d23d1f 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
@@ -4,6 +4,7 @@ use hir::{
 };
 use ide_db::{
     FileId, FxHashMap, FxHashSet, RootDatabase, SnippetCap,
+    assists::ExprFillDefaultMode,
     defs::{Definition, NameRefClass},
     famous_defs::FamousDefs,
     helpers::is_editable_crate,
@@ -46,7 +47,7 @@ use crate::{
 //     bar("", baz());
 // }
 //
-// fn bar(arg: &str, baz: Baz) ${0:-> _} {
+// fn bar(arg: &'static str, baz: Baz) ${0:-> _} {
 //     todo!()
 // }
 //
@@ -276,7 +277,11 @@ impl FunctionBuilder {
                 target_module,
                 &mut necessary_generic_params,
             );
-            let placeholder_expr = make::ext::expr_todo();
+            let placeholder_expr = match ctx.config.expr_fill_default {
+                ExprFillDefaultMode::Todo => make::ext::expr_todo(),
+                ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
+                ExprFillDefaultMode::Default => make::ext::expr_todo(),
+            };
             fn_body = make::block_expr(vec![], Some(placeholder_expr));
         };
 
@@ -331,7 +336,11 @@ impl FunctionBuilder {
         let (generic_param_list, where_clause) =
             fn_generic_params(ctx, necessary_generic_params, &target)?;
 
-        let placeholder_expr = make::ext::expr_todo();
+        let placeholder_expr = match ctx.config.expr_fill_default {
+            ExprFillDefaultMode::Todo => make::ext::expr_todo(),
+            ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
+            ExprFillDefaultMode::Default => make::ext::expr_todo(),
+        };
         let fn_body = make::block_expr(vec![], Some(placeholder_expr));
 
         Some(Self {
@@ -383,14 +392,14 @@ impl FunctionBuilder {
                 // Focus the return type if there is one
                 match ret_type {
                     Some(ret_type) => {
-                        edit.add_placeholder_snippet(cap, ret_type.clone());
+                        edit.add_placeholder_snippet(cap, ret_type);
                     }
                     None => {
-                        edit.add_placeholder_snippet(cap, tail_expr.clone());
+                        edit.add_placeholder_snippet(cap, tail_expr);
                     }
                 }
             } else {
-                edit.add_placeholder_snippet(cap, tail_expr.clone());
+                edit.add_placeholder_snippet(cap, tail_expr);
             }
         }
 
@@ -444,7 +453,11 @@ fn make_fn_body_as_new_function(
     let adt_info = adt_info.as_ref()?;
 
     let path_self = make::ext::ident_path("Self");
-    let placeholder_expr = make::ext::expr_todo();
+    let placeholder_expr = match ctx.config.expr_fill_default {
+        ExprFillDefaultMode::Todo => make::ext::expr_todo(),
+        ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
+        ExprFillDefaultMode::Default => make::ext::expr_todo(),
+    };
     let tail_expr = if let Some(strukt) = adt_info.adt.as_struct() {
         match strukt.kind(ctx.db()) {
             StructKind::Record => {
@@ -1505,7 +1518,7 @@ fn foo() {
     bar("bar")
 }
 
-fn bar(arg: &str) {
+fn bar(arg: &'static str) {
     ${0:todo!()}
 }
 "#,
@@ -2122,7 +2135,7 @@ fn foo() {
     bar(baz(), baz(), "foo", "bar")
 }
 
-fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) {
+fn bar(baz_1: Baz, baz_2: Baz, arg_1: &'static str, arg_2: &'static str) {
     ${0:todo!()}
 }
 "#,
@@ -3090,7 +3103,7 @@ pub struct Foo {
     field_2: String,
 }
 impl Foo {
-    fn new(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) -> Self {
+    fn new(baz_1: Baz, baz_2: Baz, arg_1: &'static str, arg_2: &'static str) -> Self {
         ${0:Self { field_1: todo!(), field_2: todo!() }}
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
index b7f7cb9cb01..6bf7f584914 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs
@@ -1,14 +1,14 @@
 use either::Either;
 use ide_db::imports::{
     insert_use::{ImportGranularity, InsertUseConfig},
-    merge_imports::{MergeBehavior, try_merge_imports, try_merge_trees, try_normalize_use_tree},
+    merge_imports::{MergeBehavior, try_merge_imports, try_merge_trees},
 };
-use itertools::Itertools;
 use syntax::{
     AstNode, SyntaxElement, SyntaxNode,
     algo::neighbor,
-    ast::{self, edit_in_place::Removable},
-    match_ast, ted,
+    ast::{self, syntax_factory::SyntaxFactory},
+    match_ast,
+    syntax_editor::Removable,
 };
 
 use crate::{
@@ -69,49 +69,32 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
         (selection_range, edits?)
     };
 
+    let parent_node = match ctx.covering_element() {
+        SyntaxElement::Node(n) => n,
+        SyntaxElement::Token(t) => t.parent()?,
+    };
+
     acc.add(AssistId::refactor_rewrite("merge_imports"), "Merge imports", target, |builder| {
-        let edits_mut: Vec<Edit> = edits
-            .into_iter()
-            .map(|it| match it {
-                Remove(Either::Left(it)) => Remove(Either::Left(builder.make_mut(it))),
-                Remove(Either::Right(it)) => Remove(Either::Right(builder.make_mut(it))),
-                Replace(old, new) => Replace(builder.make_syntax_mut(old), new),
-            })
-            .collect();
-        for edit in edits_mut {
+        let make = SyntaxFactory::with_mappings();
+        let mut editor = builder.make_editor(&parent_node);
+
+        for edit in edits {
             match edit {
-                Remove(it) => it.as_ref().either(Removable::remove, Removable::remove),
-                Replace(old, new) => {
-                    ted::replace(old, &new);
-
-                    // If there's a selection and we're replacing a use tree in a tree list,
-                    // normalize the parent use tree if it only contains the merged subtree.
-                    if !ctx.has_empty_selection() {
-                        let normalized_use_tree = ast::UseTree::cast(new)
-                            .as_ref()
-                            .and_then(ast::UseTree::parent_use_tree_list)
-                            .and_then(|use_tree_list| {
-                                if use_tree_list.use_trees().collect_tuple::<(_,)>().is_some() {
-                                    Some(use_tree_list.parent_use_tree())
-                                } else {
-                                    None
-                                }
-                            })
-                            .and_then(|target_tree| {
-                                try_normalize_use_tree(
-                                    &target_tree,
-                                    ctx.config.insert_use.granularity.into(),
-                                )
-                                .map(|top_use_tree_flat| (target_tree, top_use_tree_flat))
-                            });
-                        if let Some((old_tree, new_tree)) = normalized_use_tree {
-                            cov_mark::hit!(replace_parent_with_normalized_use_tree);
-                            ted::replace(old_tree.syntax(), new_tree.syntax());
-                        }
+                Remove(it) => {
+                    let node = it.as_ref();
+                    if let Some(left) = node.left() {
+                        left.remove(&mut editor);
+                    } else if let Some(right) = node.right() {
+                        right.remove(&mut editor);
                     }
                 }
+                Replace(old, new) => {
+                    editor.replace(old, &new);
+                }
             }
         }
+        editor.add_mappings(make.finish_with_mappings());
+        builder.add_file_edits(ctx.vfs_file_id(), editor);
     })
 }
 
@@ -723,11 +706,10 @@ use std::{
         );
 
         cov_mark::check!(merge_with_selected_use_tree_neighbors);
-        cov_mark::check!(replace_parent_with_normalized_use_tree);
         check_assist(
             merge_imports,
             r"use std::$0{fmt::Display, fmt::Debug}$0;",
-            r"use std::fmt::{Debug, Display};",
+            r"use std::{fmt::{Debug, Display}};",
         );
     }
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
index 6dcdf5edbd6..806c8fba9ea 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -9,7 +9,7 @@ use syntax::{
 };
 
 use crate::{
-    AssistId,
+    AssistConfig, AssistId,
     assist_context::{AssistContext, Assists, SourceChangeBuilder},
     utils::{
         DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items,
@@ -128,8 +128,14 @@ fn add_assist(
     acc.add(AssistId::refactor("replace_derive_with_manual_impl"), label, target, |builder| {
         let insert_after = ted::Position::after(builder.make_mut(adt.clone()).syntax());
         let impl_is_unsafe = trait_.map(|s| s.is_unsafe(ctx.db())).unwrap_or(false);
-        let impl_def_with_items =
-            impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path);
+        let impl_def_with_items = impl_def_from_trait(
+            &ctx.sema,
+            ctx.config,
+            adt,
+            &annotated_name,
+            trait_,
+            replace_trait_path,
+        );
         update_attribute(builder, old_derives, old_tree, old_trait_path, attr);
 
         let trait_path = make::ty_path(replace_trait_path.clone());
@@ -217,6 +223,7 @@ fn add_assist(
 
 fn impl_def_from_trait(
     sema: &hir::Semantics<'_, ide_db::RootDatabase>,
+    config: &AssistConfig,
     adt: &ast::Adt,
     annotated_name: &ast::Name,
     trait_: Option<hir::Trait>,
@@ -241,7 +248,7 @@ fn impl_def_from_trait(
     let impl_def = generate_trait_impl(adt, make::ty_path(trait_path.clone()));
 
     let first_assoc_item =
-        add_trait_assoc_items_to_impl(sema, &trait_items, trait_, &impl_def, &target_scope);
+        add_trait_assoc_items_to_impl(sema, config, &trait_items, trait_, &impl_def, &target_scope);
 
     // Generate a default `impl` function body for the derived trait.
     if let ast::AssocItem::Fn(ref func) = first_assoc_item {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_imports.rs
index 805a7344494..c066f41ca47 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_imports.rs
@@ -1,7 +1,10 @@
 use syntax::{
     AstNode, SyntaxKind,
-    ast::{self, HasVisibility, edit_in_place::Removable, make},
-    ted::{self, Position},
+    ast::{
+        self, HasAttrs, HasVisibility, edit::IndentLevel, edit_in_place::AttrsOwnerEdit, make,
+        syntax_factory::SyntaxFactory,
+    },
+    syntax_editor::{Element, Position, Removable},
 };
 
 use crate::{
@@ -9,9 +12,9 @@ use crate::{
     assist_context::{AssistContext, Assists},
 };
 
-// Assist: unmerge_use
+// Assist: unmerge_imports
 //
-// Extracts single use item from use list.
+// Extracts a use item from a use list into a standalone use list.
 //
 // ```
 // use std::fmt::{Debug, Display$0};
@@ -21,21 +24,18 @@ use crate::{
 // use std::fmt::{Debug};
 // use std::fmt::Display;
 // ```
-pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update();
+pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    let tree = ctx.find_node_at_offset::<ast::UseTree>()?;
 
     let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
     if tree_list.use_trees().count() < 2 {
-        cov_mark::hit!(skip_single_use_item);
+        cov_mark::hit!(skip_single_import);
         return None;
     }
 
-    let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
+    let use_ = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
     let path = resolve_full_path(&tree)?;
 
-    let old_parent_range = use_.syntax().parent()?.text_range();
-    let new_parent = use_.syntax().parent()?;
-
     // If possible, explain what is going to be done.
     let label = match tree.path().and_then(|path| path.first_segment()) {
         Some(name) => format!("Unmerge use of `{name}`"),
@@ -43,17 +43,31 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<
     };
 
     let target = tree.syntax().text_range();
-    acc.add(AssistId::refactor_rewrite("unmerge_use"), label, target, |builder| {
-        let new_use = make::use_(
+    acc.add(AssistId::refactor_rewrite("unmerge_imports"), label, target, |builder| {
+        let make = SyntaxFactory::with_mappings();
+        let new_use = make.use_(
             use_.visibility(),
-            make::use_tree(path, tree.use_tree_list(), tree.rename(), tree.star_token().is_some()),
-        )
-        .clone_for_update();
-
-        tree.remove();
-        ted::insert(Position::after(use_.syntax()), new_use.syntax());
+            make.use_tree(path, tree.use_tree_list(), tree.rename(), tree.star_token().is_some()),
+        );
+        // Add any attributes that are present on the use tree
+        use_.attrs().for_each(|attr| {
+            new_use.add_attr(attr.clone_for_update());
+        });
 
-        builder.replace(old_parent_range, new_parent.to_string());
+        let mut editor = builder.make_editor(use_.syntax());
+        // Remove the use tree from the current use item
+        tree.remove(&mut editor);
+        // Insert a newline and indentation, followed by the new use item
+        editor.insert_all(
+            Position::after(use_.syntax()),
+            vec![
+                make.whitespace(&format!("\n{}", IndentLevel::from_node(use_.syntax())))
+                    .syntax_element(),
+                new_use.syntax().syntax_element(),
+            ],
+        );
+        editor.add_mappings(make.finish_with_mappings());
+        builder.add_file_edits(ctx.vfs_file_id(), editor);
     })
 }
 
@@ -80,22 +94,22 @@ mod tests {
     use super::*;
 
     #[test]
-    fn skip_single_use_item() {
-        cov_mark::check!(skip_single_use_item);
+    fn skip_single_import() {
+        cov_mark::check!(skip_single_import);
         check_assist_not_applicable(
-            unmerge_use,
+            unmerge_imports,
             r"
 use std::fmt::Debug$0;
 ",
         );
         check_assist_not_applicable(
-            unmerge_use,
+            unmerge_imports,
             r"
 use std::fmt::{Debug$0};
 ",
         );
         check_assist_not_applicable(
-            unmerge_use,
+            unmerge_imports,
             r"
 use std::fmt::Debug as Dbg$0;
 ",
@@ -105,7 +119,7 @@ use std::fmt::Debug as Dbg$0;
     #[test]
     fn skip_single_glob_import() {
         check_assist_not_applicable(
-            unmerge_use,
+            unmerge_imports,
             r"
 use std::fmt::*$0;
 ",
@@ -113,9 +127,9 @@ use std::fmt::*$0;
     }
 
     #[test]
-    fn unmerge_use_item() {
+    fn unmerge_import() {
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"
 use std::fmt::{Debug, Display$0};
 ",
@@ -126,7 +140,7 @@ use std::fmt::Display;
         );
 
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"
 use std::fmt::{Debug, format$0, Display};
 ",
@@ -140,7 +154,7 @@ use std::fmt::format;
     #[test]
     fn unmerge_glob_import() {
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"
 use std::fmt::{*$0, Display};
 ",
@@ -152,9 +166,9 @@ use std::fmt::*;
     }
 
     #[test]
-    fn unmerge_renamed_use_item() {
+    fn unmerge_renamed_import() {
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"
 use std::fmt::{Debug, Display as Disp$0};
 ",
@@ -166,9 +180,9 @@ use std::fmt::Display as Disp;
     }
 
     #[test]
-    fn unmerge_indented_use_item() {
+    fn unmerge_indented_import() {
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"
 mod format {
     use std::fmt::{Debug, Display$0 as Disp, format};
@@ -184,9 +198,9 @@ mod format {
     }
 
     #[test]
-    fn unmerge_nested_use_item() {
+    fn unmerge_nested_import() {
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"
 use foo::bar::{baz::{qux$0, foobar}, barbaz};
 ",
@@ -196,7 +210,7 @@ use foo::bar::baz::qux;
 ",
         );
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"
 use foo::bar::{baz$0::{qux, foobar}, barbaz};
 ",
@@ -208,9 +222,9 @@ use foo::bar::baz::{qux, foobar};
     }
 
     #[test]
-    fn unmerge_use_item_with_visibility() {
+    fn unmerge_import_with_visibility() {
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"
 pub use std::fmt::{Debug, Display$0};
 ",
@@ -222,12 +236,27 @@ pub use std::fmt::Display;
     }
 
     #[test]
-    fn unmerge_use_item_on_self() {
+    fn unmerge_import_on_self() {
         check_assist(
-            unmerge_use,
+            unmerge_imports,
             r"use std::process::{Command, self$0};",
             r"use std::process::{Command};
 use std::process;",
         );
     }
+
+    #[test]
+    fn unmerge_import_with_attributes() {
+        check_assist(
+            unmerge_imports,
+            r"
+#[allow(deprecated)]
+use foo::{bar, baz$0};",
+            r"
+#[allow(deprecated)]
+use foo::{bar};
+#[allow(deprecated)]
+use foo::baz;",
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
index 31ff47a0549..5aedff5cc77 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
@@ -53,8 +53,14 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
         |edit| {
             let pats_after = pipe_token
                 .siblings_with_tokens(Direction::Next)
-                .filter_map(|it| ast::Pat::cast(it.into_node()?));
-            let new_pat = make::or_pat(pats_after, or_pat.leading_pipe().is_some());
+                .filter_map(|it| ast::Pat::cast(it.into_node()?))
+                .collect::<Vec<_>>();
+            // It is guaranteed that `pats_after` has at least one element
+            let new_pat = if pats_after.len() == 1 {
+                pats_after[0].clone()
+            } else {
+                make::or_pat(pats_after, or_pat.leading_pipe().is_some()).into()
+            };
             let new_match_arm =
                 make::match_arm(new_pat, match_arm.guard(), match_arm_body).clone_for_update();
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
index 1068d5d4cd5..e1b94673e77 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs
@@ -116,7 +116,7 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) -
             (Some(attr), Some(ident))
                 if attr.simple_name().map(|v| v.eq("derive")).unwrap_or_default() =>
             {
-                Some(attempt_get_derive(attr.clone(), ident))
+                Some(attempt_get_derive(attr, ident))
             }
 
             (Some(attr), _) => Some(WrapUnwrapOption::WrapAttr(attr)),
@@ -128,7 +128,7 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) -
             NodeOrToken::Node(node) => ast::Attr::cast(node).map(WrapUnwrapOption::WrapAttr),
             NodeOrToken::Token(ident) if ident.kind() == syntax::T![ident] => {
                 let attr = ident.parent_ancestors().find_map(ast::Attr::cast)?;
-                Some(attempt_get_derive(attr.clone(), ident))
+                Some(attempt_get_derive(attr, ident))
             }
             _ => None,
         }
@@ -233,7 +233,7 @@ fn wrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>, attr: ast::Attr) ->
         if let Some(meta) = attr.meta() {
             if let (Some(eq), Some(expr)) = (meta.eq_token(), meta.expr()) {
                 raw_tokens.push(NodeOrToken::Token(make::tokens::whitespace(" ")));
-                raw_tokens.push(NodeOrToken::Token(eq.clone()));
+                raw_tokens.push(NodeOrToken::Token(eq));
                 raw_tokens.push(NodeOrToken::Token(make::tokens::whitespace(" ")));
 
                 expr.syntax().descendants_with_tokens().for_each(|it| {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index a157483a449..627ed37b04e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -222,8 +222,8 @@ mod handlers {
     mod toggle_async_sugar;
     mod toggle_ignore;
     mod toggle_macro_delimiter;
+    mod unmerge_imports;
     mod unmerge_match_arm;
-    mod unmerge_use;
     mod unnecessary_async;
     mod unqualify_method_call;
     mod unwrap_block;
@@ -363,7 +363,7 @@ mod handlers {
             toggle_ignore::toggle_ignore,
             toggle_macro_delimiter::toggle_macro_delimiter,
             unmerge_match_arm::unmerge_match_arm,
-            unmerge_use::unmerge_use,
+            unmerge_imports::unmerge_imports,
             unnecessary_async::unnecessary_async,
             unqualify_method_call::unqualify_method_call,
             unwrap_block::unwrap_block,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
index 0593e6930dc..5e6889792db 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
@@ -4,6 +4,7 @@ use expect_test::expect;
 use hir::Semantics;
 use ide_db::{
     EditionedFileId, FileRange, RootDatabase, SnippetCap,
+    assists::ExprFillDefaultMode,
     base_db::SourceDatabase,
     imports::insert_use::{ImportGranularity, InsertUseConfig},
     source_change::FileSystemEdit,
@@ -35,6 +36,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
     term_search_fuel: 400,
     term_search_borrowck: true,
     code_action_grouping: true,
+    expr_fill_default: ExprFillDefaultMode::Todo,
 };
 
 pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig {
@@ -54,6 +56,7 @@ pub(crate) const TEST_CONFIG_NO_GROUPING: AssistConfig = AssistConfig {
     term_search_fuel: 400,
     term_search_borrowck: true,
     code_action_grouping: false,
+    expr_fill_default: ExprFillDefaultMode::Todo,
 };
 
 pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig {
@@ -73,6 +76,7 @@ pub(crate) const TEST_CONFIG_NO_SNIPPET_CAP: AssistConfig = AssistConfig {
     term_search_fuel: 400,
     term_search_borrowck: true,
     code_action_grouping: true,
+    expr_fill_default: ExprFillDefaultMode::Todo,
 };
 
 pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig {
@@ -92,6 +96,7 @@ pub(crate) const TEST_CONFIG_IMPORT_ONE: AssistConfig = AssistConfig {
     term_search_fuel: 400,
     term_search_borrowck: true,
     code_action_grouping: true,
+    expr_fill_default: ExprFillDefaultMode::Todo,
 };
 
 pub(crate) fn with_single_file(text: &str) -> (RootDatabase, EditionedFileId) {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 00a9d35c310..01ab0be34b2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -1737,7 +1737,7 @@ fn foo() {
     bar("", baz());
 }
 
-fn bar(arg: &str, baz: Baz) ${0:-> _} {
+fn bar(arg: &'static str, baz: Baz) ${0:-> _} {
     todo!()
 }
 
@@ -3340,6 +3340,20 @@ sth!{ }
 }
 
 #[test]
+fn doctest_unmerge_imports() {
+    check_doc_test(
+        "unmerge_imports",
+        r#####"
+use std::fmt::{Debug, Display$0};
+"#####,
+        r#####"
+use std::fmt::{Debug};
+use std::fmt::Display;
+"#####,
+    )
+}
+
+#[test]
 fn doctest_unmerge_match_arm() {
     check_doc_test(
         "unmerge_match_arm",
@@ -3366,20 +3380,6 @@ fn handle(action: Action) {
 }
 
 #[test]
-fn doctest_unmerge_use() {
-    check_doc_test(
-        "unmerge_use",
-        r#####"
-use std::fmt::{Debug, Display$0};
-"#####,
-        r#####"
-use std::fmt::{Debug};
-use std::fmt::Display;
-"#####,
-    )
-}
-
-#[test]
 fn doctest_unnecessary_async() {
     check_doc_test(
         "unnecessary_async",
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
index 0471998f0b1..ef6914fda1d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
@@ -8,6 +8,7 @@ use hir::{
 };
 use ide_db::{
     RootDatabase,
+    assists::ExprFillDefaultMode,
     famous_defs::FamousDefs,
     path_transform::PathTransform,
     syntax_helpers::{node_ext::preorder_expr, prettify_macro_expansion},
@@ -27,7 +28,10 @@ use syntax::{
     ted,
 };
 
-use crate::assist_context::{AssistContext, SourceChangeBuilder};
+use crate::{
+    AssistConfig,
+    assist_context::{AssistContext, SourceChangeBuilder},
+};
 
 mod gen_trait_fn_body;
 pub(crate) mod ref_field_expr;
@@ -174,6 +178,7 @@ pub fn filter_assoc_items(
 /// inserted.
 pub fn add_trait_assoc_items_to_impl(
     sema: &Semantics<'_, RootDatabase>,
+    config: &AssistConfig,
     original_items: &[InFile<ast::AssocItem>],
     trait_: hir::Trait,
     impl_: &ast::Impl,
@@ -219,7 +224,14 @@ pub fn add_trait_assoc_items_to_impl(
         match &item {
             ast::AssocItem::Fn(fn_) if fn_.body().is_none() => {
                 let body = AstNodeEdit::indent(
-                    &make::block_expr(None, Some(make::ext::expr_todo())),
+                    &make::block_expr(
+                        None,
+                        Some(match config.expr_fill_default {
+                            ExprFillDefaultMode::Todo => make::ext::expr_todo(),
+                            ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
+                            ExprFillDefaultMode::Default => make::ext::expr_todo(),
+                        }),
+                    ),
                     new_indent_level,
                 );
                 ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax())
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
index ee1a21f9a1a..7fbd1fbc1af 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
@@ -363,9 +363,14 @@ pub(crate) fn complete_expr_path(
                     add_keyword("true", "true");
                     add_keyword("false", "false");
 
-                    if in_condition || in_block_expr {
-                        add_keyword("letm", "let mut $0");
-                        add_keyword("let", "let $0");
+                    if in_condition {
+                        add_keyword("letm", "let mut $1 = $0");
+                        add_keyword("let", "let $1 = $0");
+                    }
+
+                    if in_block_expr {
+                        add_keyword("letm", "let mut $1 = $0;");
+                        add_keyword("let", "let $1 = $0;");
                     }
 
                     if after_if_expr {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
index 039742463c8..64bb1fce6ba 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
@@ -336,7 +336,7 @@ fn main() {
     }
 
     #[test]
-    fn completes_let_with_space() {
+    fn completes_let_in_block() {
         check_edit(
             "let",
             r#"
@@ -346,7 +346,7 @@ fn main() {
 "#,
             r#"
 fn main() {
-    let $0
+    let $1 = $0;
 }
 "#,
         );
@@ -359,7 +359,97 @@ fn main() {
 "#,
             r#"
 fn main() {
-    let mut $0
+    let mut $1 = $0;
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn completes_let_in_condition() {
+        check_edit(
+            "let",
+            r#"
+fn main() {
+    if $0 {}
+}
+"#,
+            r#"
+fn main() {
+    if let $1 = $0 {}
+}
+"#,
+        );
+        check_edit(
+            "letm",
+            r#"
+fn main() {
+    if $0 {}
+}
+"#,
+            r#"
+fn main() {
+    if let mut $1 = $0 {}
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn completes_let_in_no_empty_condition() {
+        check_edit(
+            "let",
+            r#"
+fn main() {
+    if $0x {}
+}
+"#,
+            r#"
+fn main() {
+    if let $1 = $0x {}
+}
+"#,
+        );
+        check_edit(
+            "letm",
+            r#"
+fn main() {
+    if $0x {}
+}
+"#,
+            r#"
+fn main() {
+    if let mut $1 = $0x {}
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn completes_let_in_condition_block() {
+        check_edit(
+            "let",
+            r#"
+fn main() {
+    if { $0 } {}
+}
+"#,
+            r#"
+fn main() {
+    if { let $1 = $0; } {}
+}
+"#,
+        );
+        check_edit(
+            "letm",
+            r#"
+fn main() {
+    if { $0 } {}
+}
+"#,
+            r#"
+fn main() {
+    if { let mut $1 = $0; } {}
 }
 "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
index b02f079b721..8902cd09cec 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs
@@ -116,13 +116,13 @@ fn foo<'lifetime>(foo: &'a$0) {}
         check(
             r#"
 struct Foo;
-impl<'impl> Foo {
+impl<'r#impl> Foo {
     fn foo<'func>(&'a$0 self) {}
 }
 "#,
             expect![[r#"
                 lt 'func
-                lt 'impl
+                lt 'r#impl
                 lt 'static
             "#]],
         );
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 59599735896..391e2379dcd 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
@@ -387,11 +387,7 @@ fn expand(
 
     match (
         sema.expand_macro_call(&actual_macro_call),
-        sema.speculative_expand_macro_call(
-            &actual_macro_call,
-            &speculative_args,
-            fake_ident_token.clone(),
-        ),
+        sema.speculative_expand_macro_call(&actual_macro_call, &speculative_args, fake_ident_token),
     ) {
         // successful expansions
         (Some(actual_expansion), Some((fake_expansion, fake_mapped_tokens))) => {
@@ -661,9 +657,8 @@ fn expected_type_and_name(
                             ))
                         } else {
                             cov_mark::hit!(expected_type_struct_field_without_leading_char);
-                            let expr_field = token.prev_sibling_or_token()?
-                                .into_node()
-                                .and_then(ast::RecordExprField::cast)?;
+                            cov_mark::hit!(expected_type_struct_field_followed_by_comma);
+                            let expr_field = previous_non_trivia_token(token.clone())?.parent().and_then(ast::RecordExprField::cast)?;
                             let (_, _, ty) = sema.resolve_record_field(&expr_field)?;
                             Some((
                                 Some(ty),
@@ -681,7 +676,6 @@ fn expected_type_and_name(
                             .or_else(|| sema.type_of_expr(&expr).map(TypeInfo::original));
                         (ty, field_name)
                     } else {
-                        cov_mark::hit!(expected_type_struct_field_followed_by_comma);
                         (field_ty, field_name)
                     }
                 },
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
index e208b9fd41a..19cdef30bd9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -135,7 +135,7 @@ impl fmt::Debug for CompletionItem {
                 },
                 CompletionItemRefMode::Dereference => "*",
             };
-            s.field("ref_match", &format!("{}@{offset:?}", prefix));
+            s.field("ref_match", &format!("{prefix}@{offset:?}"));
         }
         if self.trigger_call_info {
             s.field("trigger_call_info", &true);
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 b30ac43bf8f..d5137949d42 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
@@ -1517,7 +1517,7 @@ fn main() {
             en Enum                      Enum
             fn function()                fn()
             fn main()                    fn()
-            lc variable                  &str
+            lc variable          &'static str
             ma helper!(…) macro_rules! helper
             ma m!(…)           macro_rules! m
             ma makro!(…)   macro_rules! makro
@@ -2110,3 +2110,19 @@ fn foo() {
         "#]],
     );
 }
+
+#[test]
+fn escaped_label() {
+    check(
+        r#"
+fn main() {
+    'r#break: {
+        break '$0;
+    }
+}
+    "#,
+        expect![[r#"
+            lb 'r#break
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
index 15518e98370..148203107c4 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
@@ -1358,7 +1358,7 @@ pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone, { 0u8 }
 fn main() { fo$0 }
 "#,
         CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function),
-        expect!("fn(&mut T) -> u8"),
+        expect!("fn(&'x mut T) -> u8"),
         expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"),
     );
 
@@ -1391,7 +1391,7 @@ fn main() {
 }
 "#,
         CompletionItemKind::SymbolKind(SymbolKind::Method),
-        expect!("const fn(&'foo mut self, &Foo) -> !"),
+        expect!("const fn(&'foo mut self, &'foo Foo) -> !"),
         expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"),
     );
 }
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 c7e2d058257..125e11e9e35 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}>
-            st Record                Record
-            st S                          S
-            st Tuple                  Tuple
-            st Unit                    Unit
+            sp Self dyn Tr<{unknown}> + 'static
+            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 f1d6b605b00..583318de26d 100644
--- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
@@ -24,6 +24,7 @@ arrayvec.workspace = true
 indexmap.workspace = true
 memchr = "2.7.4"
 salsa.workspace = true
+salsa-macros.workspace = true
 query-group.workspace = true
 triomphe.workspace = true
 nohash-hasher.workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs
index 90ae4a3b5b3..384eb57c0fd 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/assists.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/assists.rs
@@ -169,3 +169,15 @@ impl AssistResolveStrategy {
 
 #[derive(Clone, Debug)]
 pub struct GroupLabel(pub String);
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum ExprFillDefaultMode {
+    Todo,
+    Default,
+    Underscore,
+}
+impl Default for ExprFillDefaultMode {
+    fn default() -> Self {
+        Self::Todo
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs
index e9385253250..4b0a84a559e 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs
@@ -86,7 +86,7 @@ pub fn items_with_name_in_module<T>(
     let local_query = match name {
         NameToImport::Prefix(exact_name, case_sensitive)
         | NameToImport::Exact(exact_name, case_sensitive) => {
-            let mut local_query = symbol_index::Query::new(exact_name.clone());
+            let mut local_query = symbol_index::Query::new(exact_name);
             local_query.assoc_search_mode(assoc_item_search);
             if prefix {
                 local_query.prefix();
@@ -99,7 +99,7 @@ pub fn items_with_name_in_module<T>(
             local_query
         }
         NameToImport::Fuzzy(fuzzy_search_string, case_sensitive) => {
-            let mut local_query = symbol_index::Query::new(fuzzy_search_string.clone());
+            let mut local_query = symbol_index::Query::new(fuzzy_search_string);
             local_query.fuzzy();
             local_query.assoc_search_mode(assoc_item_search);
 
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
index d3934e14abf..63cc7cde280 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -76,8 +76,10 @@ pub type FxIndexMap<K, V> =
 pub type FilePosition = FilePositionWrapper<FileId>;
 pub type FileRange = FileRangeWrapper<FileId>;
 
-#[salsa::db]
+#[salsa_macros::db]
 pub struct RootDatabase {
+    // FIXME: Revisit this commit now that we migrated to the new salsa, given we store arcs in this
+    // db directly now
     // We use `ManuallyDrop` here because every codegen unit that contains a
     // `&RootDatabase -> &dyn OtherDatabase` cast will instantiate its drop glue in the vtable,
     // which duplicates `Weak::drop` and `Arc::drop` tens of thousands of times, which makes
@@ -89,7 +91,7 @@ pub struct RootDatabase {
 
 impl std::panic::RefUnwindSafe for RootDatabase {}
 
-#[salsa::db]
+#[salsa_macros::db]
 impl salsa::Database for RootDatabase {
     fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {}
 }
@@ -116,7 +118,7 @@ impl fmt::Debug for RootDatabase {
     }
 }
 
-#[salsa::db]
+#[salsa_macros::db]
 impl SourceDatabase for RootDatabase {
     fn file_text(&self, file_id: vfs::FileId) -> FileText {
         self.files.file_text(file_id)
@@ -234,14 +236,6 @@ impl RootDatabase {
         // );
         // hir::db::BodyWithSourceMapQuery.in_db_mut(self).set_lru_capacity(2048);
     }
-
-    pub fn snapshot(&self) -> Self {
-        Self {
-            storage: self.storage.clone(),
-            files: self.files.clone(),
-            crates_map: self.crates_map.clone(),
-        }
-    }
 }
 
 #[query_group::query_group]
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
index 17c3f75ce17..cbe31405ab7 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
@@ -51,6 +51,7 @@ pub fn parallel_prime_caches(
     enum ParallelPrimeCacheWorkerProgress {
         BeginCrate { crate_id: Crate, crate_name: Symbol },
         EndCrate { crate_id: Crate },
+        Cancelled(Cancelled),
     }
 
     // We split off def map computation from other work,
@@ -71,27 +72,35 @@ pub fn parallel_prime_caches(
                 progress_sender
                     .send(ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name })?;
 
-                match kind {
+                let cancelled = Cancelled::catch(|| match kind {
                     PrimingPhase::DefMap => _ = db.crate_def_map(crate_id),
                     PrimingPhase::ImportMap => _ = db.import_map(crate_id),
                     PrimingPhase::CrateSymbols => _ = db.crate_symbols(crate_id.into()),
-                }
+                });
 
-                progress_sender.send(ParallelPrimeCacheWorkerProgress::EndCrate { crate_id })?;
+                match cancelled {
+                    Ok(()) => progress_sender
+                        .send(ParallelPrimeCacheWorkerProgress::EndCrate { crate_id })?,
+                    Err(cancelled) => progress_sender
+                        .send(ParallelPrimeCacheWorkerProgress::Cancelled(cancelled))?,
+                }
             }
 
             Ok::<_, crossbeam_channel::SendError<_>>(())
         };
 
         for id in 0..num_worker_threads {
-            let worker = prime_caches_worker.clone();
-            let db = db.snapshot();
-
-            stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
-                .allow_leak(true)
-                .name(format!("PrimeCaches#{id}"))
-                .spawn(move || Cancelled::catch(|| worker(db.snapshot())))
-                .expect("failed to spawn thread");
+            stdx::thread::Builder::new(
+                stdx::thread::ThreadIntent::Worker,
+                format!("PrimeCaches#{id}"),
+            )
+            .allow_leak(true)
+            .spawn({
+                let worker = prime_caches_worker.clone();
+                let db = db.clone();
+                move || worker(db)
+            })
+            .expect("failed to spawn thread");
         }
 
         (work_sender, progress_receiver)
@@ -142,9 +151,14 @@ pub fn parallel_prime_caches(
                 continue;
             }
             Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
-                // our workers may have died from a cancelled task, so we'll check and re-raise here.
-                db.unwind_if_revision_cancelled();
-                break;
+                // all our workers have exited, mark us as finished and exit
+                cb(ParallelPrimeCachesProgress {
+                    crates_currently_indexing: vec![],
+                    crates_done,
+                    crates_total: crates_done,
+                    work_type: "Indexing",
+                });
+                return;
             }
         };
         match worker_progress {
@@ -156,6 +170,10 @@ pub fn parallel_prime_caches(
                 crates_to_prime.mark_done(crate_id);
                 crates_done += 1;
             }
+            ParallelPrimeCacheWorkerProgress::Cancelled(cancelled) => {
+                // Cancelled::throw should probably be public
+                std::panic::resume_unwind(Box::new(cancelled));
+            }
         };
 
         let progress = ParallelPrimeCachesProgress {
@@ -186,9 +204,14 @@ pub fn parallel_prime_caches(
                 continue;
             }
             Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
-                // our workers may have died from a cancelled task, so we'll check and re-raise here.
-                db.unwind_if_revision_cancelled();
-                break;
+                // all our workers have exited, mark us as finished and exit
+                cb(ParallelPrimeCachesProgress {
+                    crates_currently_indexing: vec![],
+                    crates_done,
+                    crates_total: crates_done,
+                    work_type: "Populating symbols",
+                });
+                return;
             }
         };
         match worker_progress {
@@ -199,6 +222,10 @@ pub fn parallel_prime_caches(
                 crates_currently_indexing.swap_remove(&crate_id);
                 crates_done += 1;
             }
+            ParallelPrimeCacheWorkerProgress::Cancelled(cancelled) => {
+                // Cancelled::throw should probably be public
+                std::panic::resume_unwind(Box::new(cancelled));
+            }
         };
 
         let progress = ParallelPrimeCachesProgress {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
index af25c2b2e33..a6da0fd9c5e 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs
@@ -31,7 +31,7 @@ fn foo() {
     x();
  // ^^^ error: expected function, found i32
     ""();
- // ^^^^ error: expected function, found &str
+ // ^^^^ error: expected function, found &'static str
     foo();
 }
 "#,
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
index b56255b1fde..d72b21099ce 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
@@ -166,7 +166,7 @@ fn main() {
     let _ = ptr as bool;
           //^^^^^^^^^^^ error: cannot cast `*const ()` as `bool`
     let v = "hello" as bool;
-          //^^^^^^^^^^^^^^^ error: casting `&str` as `bool` is invalid: needs casting through a raw pointer first
+          //^^^^^^^^^^^^^^^ error: casting `&'static str` as `bool` is invalid: needs casting through a raw pointer first
 }
 "#,
         );
@@ -956,7 +956,7 @@ fn main() {
 fn main() {
     let pointer: usize = &1_i32 as *const i32 as usize;
     let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
-                                          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `*const i32` as `&i32`
+                                          //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `*const i32` as `&'static i32`
 }
 "#,
         );
@@ -992,7 +992,7 @@ impl Deref for Foo {
 
 fn main() {
     let _ = "foo" as bool;
-          //^^^^^^^^^^^^^ error: casting `&str` as `bool` is invalid: needs casting through a raw pointer first
+          //^^^^^^^^^^^^^ error: casting `&'static str` as `bool` is invalid: needs casting through a raw pointer first
 
     let _ = Foo as bool;
           //^^^^^^^^^^^ error: non-primitive cast: `Foo` as `bool`
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
index 6b02111016c..a354d123f5a 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -5,9 +5,13 @@ use hir::{
     sym,
 };
 use ide_db::{
-    FxHashMap, assists::Assist, famous_defs::FamousDefs,
-    imports::import_assets::item_for_path_search, source_change::SourceChange,
-    syntax_helpers::tree_diff::diff, text_edit::TextEdit,
+    FxHashMap,
+    assists::{Assist, ExprFillDefaultMode},
+    famous_defs::FamousDefs,
+    imports::import_assets::item_for_path_search,
+    source_change::SourceChange,
+    syntax_helpers::tree_diff::diff,
+    text_edit::TextEdit,
     use_trivial_constructor::use_trivial_constructor,
 };
 use stdx::format_to;
@@ -102,8 +106,9 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
             });
 
             let generate_fill_expr = |ty: &Type| match ctx.config.expr_fill_default {
-                crate::ExprFillDefaultMode::Todo => make::ext::expr_todo(),
-                crate::ExprFillDefaultMode::Default => {
+                ExprFillDefaultMode::Todo => make::ext::expr_todo(),
+                ExprFillDefaultMode::Underscore => make::ext::expr_underscore(),
+                ExprFillDefaultMode::Default => {
                     get_default_constructor(ctx, d, ty).unwrap_or_else(make::ext::expr_todo)
                 }
             };
@@ -158,9 +163,14 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
             let old_field_list = field_list_parent.record_pat_field_list()?;
             let new_field_list = old_field_list.clone_for_update();
             for (f, _) in missing_fields.iter() {
-                let field = make::record_pat_field_shorthand(make::name_ref(
-                    &f.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr(),
-                ));
+                let field = make::record_pat_field_shorthand(
+                    make::ident_pat(
+                        false,
+                        false,
+                        make::name(&f.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()),
+                    )
+                    .into(),
+                );
                 new_field_list.add_field(field.clone_for_update());
             }
             build_text_edit(new_field_list.syntax(), old_field_list.syntax())
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
index 7d0f10983d7..780271361d7 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
@@ -18,7 +18,22 @@ pub(crate) fn moved_out_of_ref(ctx: &DiagnosticsContext<'_>, d: &hir::MovedOutOf
 mod tests {
     use crate::tests::check_diagnostics;
 
-    // FIXME: spans are broken
+    #[test]
+    fn operand_field_span_respected() {
+        check_diagnostics(
+            r#"
+struct NotCopy;
+struct S {
+    field: NotCopy,
+}
+
+fn f(s: &S) -> S {
+    S { field: s.field }
+             //^^^^^^^ error: cannot move `NotCopy` out of reference
+}
+            "#,
+        );
+    }
 
     #[test]
     fn move_by_explicit_deref() {
@@ -85,7 +100,7 @@ fn consume<T>(_: X<T>) {
 fn main() {
     let a = &X(Y);
     consume(*a);
-  //^^^^^^^^^^^ error: cannot move `X<Y>` out of reference
+          //^^ error: cannot move `X<Y>` out of reference
     let a = &X(5);
     consume(*a);
 }
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 8f6ed1a7bdb..500c5de791d 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
@@ -195,7 +195,7 @@ fn remove_unnecessary_wrapper(
     let db = ctx.sema.db;
     let root = db.parse_or_expand(expr_ptr.file_id);
     let expr = expr_ptr.value.to_node(&root);
-    let expr = ctx.sema.original_ast_node(expr.clone())?;
+    let expr = ctx.sema.original_ast_node(expr)?;
 
     let Expr::CallExpr(call_expr) = expr else {
         return None;
@@ -306,10 +306,9 @@ fn str_ref_to_owned(
     acc: &mut Vec<Assist>,
 ) -> Option<()> {
     let expected = d.expected.display(ctx.sema.db, ctx.display_target);
-    let actual = d.actual.display(ctx.sema.db, ctx.display_target);
-
     // FIXME do this properly
-    if expected.to_string() != "String" || actual.to_string() != "&str" {
+    let is_applicable = d.actual.strip_reference().is_str() && expected.to_string() == "String";
+    if !is_applicable {
         return None;
     }
 
@@ -1176,7 +1175,7 @@ trait B {}
 
 fn test(a: &dyn A) -> &dyn B {
     a
-  //^ error: expected &dyn B, found &dyn A
+  //^ error: expected &(dyn B + 'static), found &(dyn A + 'static)
 }
 "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
index 277aff2e08f..a933f1b4261 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -1,3 +1,5 @@
+use std::ops::Not;
+
 use hir::{
     ClosureStyle, HirDisplay, ImportPathConfig,
     db::ExpandDatabase,
@@ -60,9 +62,13 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
 
     let mut formatter = |_: &hir::Type| String::from("_");
 
-    let assists: Vec<Assist> = paths
+    let assists: Vec<Assist> = d
+        .expected
+        .is_unknown()
+        .not()
+        .then(|| "todo!()".to_owned())
         .into_iter()
-        .filter_map(|path| {
+        .chain(paths.into_iter().filter_map(|path| {
             path.gen_source_code(
                 &scope,
                 &mut formatter,
@@ -75,7 +81,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
                 ctx.display_target,
             )
             .ok()
-        })
+        }))
         .unique()
         .map(|code| Assist {
             id: AssistId::quick_fix("typed-hole"),
@@ -95,9 +101,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
 
 #[cfg(test)]
 mod tests {
-    use crate::tests::{
-        check_diagnostics, check_fixes_unordered, check_has_fix, check_has_single_fix,
-    };
+    use crate::tests::{check_diagnostics, check_fixes_unordered, check_has_fix};
 
     #[test]
     fn unknown() {
@@ -119,9 +123,9 @@ fn main() {
     if _ {}
      //^ 💡 error: invalid `_` expression, expected type `bool`
     let _: fn() -> i32 = _;
-                       //^ error: invalid `_` expression, expected type `fn() -> i32`
+                       //^ 💡 error: invalid `_` expression, expected type `fn() -> i32`
     let _: fn() -> () = _; // FIXME: This should trigger an assist because `main` matches via *coercion*
-                      //^ error: invalid `_` expression, expected type `fn()`
+                      //^ 💡 error: invalid `_` expression, expected type `fn()`
 }
 "#,
         );
@@ -147,7 +151,7 @@ fn main() {
 fn main() {
     let mut x = t();
     x = _;
-      //^ error: invalid `_` expression, expected type `&str`
+      //^ 💡 error: invalid `_` expression, expected type `&'static str`
     x = "";
 }
 fn t<T>() -> T { loop {} }
@@ -308,7 +312,7 @@ fn main() {
 
     #[test]
     fn ignore_impl_func_with_incorrect_return() {
-        check_has_single_fix(
+        check_fixes_unordered(
             r#"
 struct Bar {}
 trait Foo {
@@ -323,7 +327,8 @@ fn main() {
     let a: i32 = 1;
     let c: Bar = _$0;
 }"#,
-            r#"
+            vec![
+                r#"
 struct Bar {}
 trait Foo {
     type Res;
@@ -337,6 +342,21 @@ fn main() {
     let a: i32 = 1;
     let c: Bar = Bar {  };
 }"#,
+                r#"
+struct Bar {}
+trait Foo {
+    type Res;
+    fn foo(&self) -> Self::Res;
+}
+impl Foo for i32 {
+    type Res = Self;
+    fn foo(&self) -> Self::Res { 1 }
+}
+fn main() {
+    let a: i32 = 1;
+    let c: Bar = todo!();
+}"#,
+            ],
         );
     }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
index 4422d8f8262..7f07009dc56 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs
@@ -269,7 +269,7 @@ impl<T, U> A<T, U> {
 }
 fn main() {
     let a = A {a: 0, b: ""};
-    A::<i32, &str>::foo();
+    A::<i32, &'static str>::foo();
 }
 "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 11efedd8a59..607721d611d 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -92,7 +92,7 @@ use hir::{
 };
 use ide_db::{
     EditionedFileId, FileId, FileRange, FxHashMap, FxHashSet, RootDatabase, Severity, SnippetCap,
-    assists::{Assist, AssistId, AssistResolveStrategy},
+    assists::{Assist, AssistId, AssistResolveStrategy, ExprFillDefaultMode},
     base_db::{ReleaseChannel, RootQueryDb as _},
     generated::lints::{CLIPPY_LINT_GROUPS, DEFAULT_LINT_GROUPS, DEFAULT_LINTS, Lint, LintGroup},
     imports::insert_use::InsertUseConfig,
@@ -219,17 +219,6 @@ impl Diagnostic {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum ExprFillDefaultMode {
-    Todo,
-    Default,
-}
-impl Default for ExprFillDefaultMode {
-    fn default() -> Self {
-        Self::Todo
-    }
-}
-
 #[derive(Debug, Clone)]
 pub struct DiagnosticsConfig {
     /// Whether native diagnostics are enabled.
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
index 13d08d46ded..4e4bd47e1c2 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
@@ -3,14 +3,16 @@
 mod overly_long_real_world_cases;
 
 use ide_db::{
-    LineIndexDatabase, RootDatabase, assists::AssistResolveStrategy, base_db::SourceDatabase,
+    LineIndexDatabase, RootDatabase,
+    assists::{AssistResolveStrategy, ExprFillDefaultMode},
+    base_db::SourceDatabase,
 };
 use itertools::Itertools;
 use stdx::trim_indent;
 use test_fixture::WithFixture;
 use test_utils::{MiniCore, assert_eq_text, extract_annotations};
 
-use crate::{DiagnosticsConfig, ExprFillDefaultMode, Severity};
+use crate::{DiagnosticsConfig, Severity};
 
 /// Takes a multi-file input fixture with annotated cursor positions,
 /// and checks that:
@@ -160,55 +162,6 @@ pub(crate) fn check_has_fix(
     assert!(fix.is_some(), "no diagnostic with desired fix");
 }
 
-#[track_caller]
-pub(crate) fn check_has_single_fix(
-    #[rust_analyzer::rust_fixture] ra_fixture_before: &str,
-    #[rust_analyzer::rust_fixture] ra_fixture_after: &str,
-) {
-    let after = trim_indent(ra_fixture_after);
-
-    let (db, file_position) = RootDatabase::with_position(ra_fixture_before);
-    let mut conf = DiagnosticsConfig::test_sample();
-    conf.expr_fill_default = ExprFillDefaultMode::Default;
-    let mut n_fixes = 0;
-    let fix = super::full_diagnostics(
-        &db,
-        &conf,
-        &AssistResolveStrategy::All,
-        file_position.file_id.file_id(&db),
-    )
-    .into_iter()
-    .find(|d| {
-        d.fixes
-            .as_ref()
-            .and_then(|fixes| {
-                n_fixes += fixes.len();
-                fixes.iter().find(|fix| {
-                    if !fix.target.contains_inclusive(file_position.offset) {
-                        return false;
-                    }
-                    let actual = {
-                        let source_change = fix.source_change.as_ref().unwrap();
-                        let file_id = *source_change.source_file_edits.keys().next().unwrap();
-                        let mut actual = db.file_text(file_id).text(&db).to_string();
-
-                        for (edit, snippet_edit) in source_change.source_file_edits.values() {
-                            edit.apply(&mut actual);
-                            if let Some(snippet_edit) = snippet_edit {
-                                snippet_edit.apply(&mut actual);
-                            }
-                        }
-                        actual
-                    };
-                    after == actual
-                })
-            })
-            .is_some()
-    });
-    assert!(fix.is_some(), "no diagnostic with desired fix");
-    assert!(n_fixes == 1, "Too many fixes suggested");
-}
-
 /// Checks that there's a diagnostic *without* fix at `$0`.
 pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
     let (db, file_position) = RootDatabase::with_position(ra_fixture);
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index ebbd68bcdf7..f0247f32d7e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -599,7 +599,7 @@ fn filename_and_frag_for_def(
             Some(name) => {
                 match m.attrs(db).by_key(sym::doc).find_string_value_in_tt(sym::keyword) {
                     Some(kw) => {
-                        format!("keyword.{}.html", kw)
+                        format!("keyword.{kw}.html")
                     }
                     None => format!("{}/index.html", name.as_str()),
                 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 2f2d2252f84..075afcec019 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -634,9 +634,7 @@ fn walk_and_push_ty(
         } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
             push_new_def(trait_.into());
         } else if let Some(tp) = t.as_type_param(db) {
-            let sized_trait = db
-                .lang_item(t.krate(db).into(), LangItem::Sized)
-                .and_then(|lang_item| lang_item.as_trait());
+            let sized_trait = LangItem::Sized.resolve_trait(db, t.krate(db).into());
             tp.trait_bounds(db)
                 .into_iter()
                 .filter(|&it| Some(it.into()) != sized_trait)
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index d469cd7c0cd..7b7eef9d579 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -7085,9 +7085,9 @@ fn foo() {
 }
 "#,
         expect![[r#"
-                ```rust
-                &str
-                ```"#]],
+            ```rust
+            &'static str
+            ```"#]],
     );
 }
 
@@ -8228,7 +8228,7 @@ format_args!("{aaaaa$0}");
             *aaaaa*
 
             ```rust
-            let aaaaa: &str
+            let aaaaa: &'static str
             ```
         "#]],
     );
@@ -8248,7 +8248,7 @@ format_args!("{$0aaaaa}");
             *aaaaa*
 
             ```rust
-            let aaaaa: &str
+            let aaaaa: &'static str
             ```
         "#]],
     );
@@ -8268,7 +8268,7 @@ format_args!(r"{$0aaaaa}");
             *aaaaa*
 
             ```rust
-            let aaaaa: &str
+            let aaaaa: &'static str
             ```
         "#]],
     );
@@ -8293,7 +8293,7 @@ foo!(r"{$0aaaaa}");
             *aaaaa*
 
             ```rust
-            let aaaaa: &str
+            let aaaaa: &'static str
             ```
         "#]],
     );
@@ -8337,7 +8337,7 @@ fn main() {
         expect![[r#"
             *"🦀\u{1f980}\\\x41"*
             ```rust
-            &str
+            &'static str
             ```
             ___
 
@@ -8353,7 +8353,7 @@ fn main() {
         expect![[r#"
             *r"🦀\u{1f980}\\\x41"*
             ```rust
-            &str
+            &'static str
             ```
             ___
 
@@ -8375,7 +8375,7 @@ fsdghs";
 
             fsdghs"*
             ```rust
-            &str
+            &'static str
             ```
             ___
 
@@ -8395,7 +8395,7 @@ fn main() {
         expect![[r#"
             *c"🦀\u{1f980}\\\x41"*
             ```rust
-            &{unknown}
+            &'static {unknown}
             ```
             ___
 
@@ -8414,7 +8414,7 @@ fn main() {
         expect![[r#"
             *r"`[^`]*`"*
             ```rust
-            &str
+            &'static str
             ```
             ___
 
@@ -8429,7 +8429,7 @@ fn main() {
         expect![[r#"
             *r"`"*
             ```rust
-            &str
+            &'static str
             ```
             ___
 
@@ -8444,7 +8444,7 @@ fn main() {
         expect![[r#"
             *r"    "*
             ```rust
-            &str
+            &'static str
             ```
             ___
 
@@ -8460,12 +8460,12 @@ fn main() {
         expect![[r#"
             *r" Hello World "*
             ```rust
-            &str
+            &'static str
             ```
             ___
 
             value of literal: `  Hello World  `
-"#]],
+        "#]],
     )
 }
 
@@ -8480,7 +8480,7 @@ fn main() {
         expect![[r#"
             *b"\xF0\x9F\xA6\x80\\"*
             ```rust
-            &[u8; 5]
+            &'static [u8; 5]
             ```
             ___
 
@@ -8496,7 +8496,7 @@ fn main() {
         expect![[r#"
             *br"\xF0\x9F\xA6\x80\\"*
             ```rust
-            &[u8; 18]
+            &'static [u8; 18]
             ```
             ___
 
@@ -9070,7 +9070,7 @@ struct Pedro$0<'a> {
 
             ```rust
             struct Pedro<'a> {
-                hola: &str,
+                hola: &'a str,
             }
             ```
 
@@ -9937,7 +9937,7 @@ fn baz() {
 
             ---
 
-            `U` = `i32`, `T` = `&str`
+            `U` = `i32`, `T` = `&'static str`
         "#]],
     );
 }
@@ -10030,7 +10030,7 @@ fn bar() {
 
             ---
 
-            `T` = `i8`, `U` = `&str`
+            `T` = `i8`, `U` = `&'static str`
         "#]],
     );
 }
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 52ea2e5ec58..36fdd90e8ae 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();
-     // ^^^ &dyn Fn(f64, f64) -> u32
+     // ^^^ &'static (dyn Fn(f64, f64) -> u32 + 'static)
     let foo = foo5();
-     // ^^^ &dyn Fn(&dyn Fn(f64, f64) -> u32, f64) -> u32
+     // ^^^ &'static (dyn Fn(&(dyn Fn(f64, f64) -> u32 + 'static), f64) -> u32 + 'static)
     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();
-     // ^^^ &dyn Fn(f64, f64) -> u32
+     // ^^^ &'static (dyn Fn(f64, f64) -> u32 + 'static)
     let foo = foo5();
     let foo = foo6();
     let foo = foo7();
@@ -528,7 +528,7 @@ fn main() {
           //^^^^ i32
     let _ = 22;
     let test = "test";
-      //^^^^ &str
+      //^^^^ &'static str
     let test = InnerStruct {};
       //^^^^ InnerStruct
 
@@ -618,12 +618,12 @@ impl<T> Iterator for IntoIter<T> {
 
 fn main() {
     let mut data = Vec::new();
-          //^^^^ Vec<&str>
+          //^^^^ Vec<&'static str>
     data.push("foo");
     for i in data {
-      //^ &str
+      //^ &'static str
       let z = i;
-        //^ &str
+        //^ &'static str
     }
 }
 "#,
@@ -651,8 +651,8 @@ fn main() {
       //^^ Vec<Box<&(dyn Display + Sync)>>
     let _v = { Vec::<Box<*const (dyn Display + Sync)>>::new() };
       //^^ Vec<Box<*const (dyn Display + Sync)>>
-    let _v = { Vec::<Box<dyn Display + Sync>>::new() };
-      //^^ Vec<Box<dyn Display + Sync>>
+    let _v = { Vec::<Box<dyn Display + Sync + 'static>>::new() };
+      //^^ Vec<Box<dyn Display + Sync + 'static>>
 }
 "#,
         );
@@ -1017,7 +1017,7 @@ fn test<T>(t: T) {
 "#,
             expect![[r#"
                 fn test<T>(t: T) {
-                    let f = |a: i32, b: &str, c: T| {};
+                    let f = |a: i32, b: &'static str, c: T| {};
                     let result: () = f(42, "", t);
                 }
             "#]],
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 de9ca8c000f..2ec85da4a42 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
@@ -194,7 +194,7 @@ impl Tr for () {
 //^ impl Tr for ()
 impl dyn Tr {
   }
-//^ impl dyn Tr
+//^ impl dyn Tr + 'static
 
 static S0: () = 0;
 static S1: () = {};
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index a13be6c4927..aa525a86123 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -123,9 +123,9 @@ pub use ide_completion::{
     CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem,
     CompletionItemKind, CompletionItemRefMode, CompletionRelevance, Snippet, SnippetScope,
 };
-pub use ide_db::text_edit::{Indel, TextEdit};
 pub use ide_db::{
     FileId, FilePosition, FileRange, RootDatabase, Severity, SymbolKind,
+    assists::ExprFillDefaultMode,
     base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId},
     documentation::Documentation,
     label::Label,
@@ -134,8 +134,9 @@ pub use ide_db::{
     search::{ReferenceCategory, SearchScope},
     source_change::{FileSystemEdit, SnippetEdit, SourceChange},
     symbol_index::Query,
+    text_edit::{Indel, TextEdit},
 };
-pub use ide_diagnostics::{Diagnostic, DiagnosticCode, DiagnosticsConfig, ExprFillDefaultMode};
+pub use ide_diagnostics::{Diagnostic, DiagnosticCode, DiagnosticsConfig};
 pub use ide_ssr::SsrError;
 pub use span::Edition;
 pub use syntax::{TextRange, TextSize};
@@ -181,7 +182,7 @@ impl AnalysisHost {
     /// Returns a snapshot of the current state, which you can query for
     /// semantic information.
     pub fn analysis(&self) -> Analysis {
-        Analysis { db: self.db.snapshot() }
+        Analysis { db: self.db.clone() }
     }
 
     /// Applies changes to the current state of the world. If there are
@@ -863,7 +864,7 @@ impl Analysis {
     where
         F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe,
     {
-        let snap = self.db.snapshot();
+        let snap = self.db.clone();
         Cancelled::catch(|| f(&snap))
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 4a06cd919fc..795c1f2ca3c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -451,7 +451,7 @@ mod tests {
         assert_eq!(x.len(), 1);
         match x.into_iter().next().unwrap() {
             MonikerResult::Local { enclosing_moniker } => {
-                panic!("Unexpected local enclosed in {:?}", enclosing_moniker);
+                panic!("Unexpected local enclosed in {enclosing_moniker:?}");
             }
             MonikerResult::Moniker(x) => {
                 assert_eq!(identifier, x.identifier.to_string());
diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs
index 55a0db2d820..cfcd76d2aa3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/status.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/status.rs
@@ -51,8 +51,8 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
                 buf,
                 "Crate: {}\n",
                 match display_name {
-                    Some(it) => format!("{it}({:?})", crate_id),
-                    None => format!("{:?}", crate_id),
+                    Some(it) => format!("{it}({crate_id:?})"),
+                    None => format!("{crate_id:?}"),
                 }
             );
             format_to!(buf, "    Root module file id: {}\n", root_file_id.index());
diff --git a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs
index 4696fef3209..7985279679c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/view_crate_graph.rs
@@ -80,7 +80,7 @@ impl<'a> dot::Labeller<'a, Crate, Edge<'a>> for DotCrateGraph<'_> {
 
     fn node_id(&'a self, n: &Crate) -> Id<'a> {
         let id = n.as_id().as_u32();
-        Id::new(format!("_{:?}", id)).unwrap()
+        Id::new(format!("_{id:?}")).unwrap()
     }
 
     fn node_shape(&'a self, _node: &Crate) -> Option<LabelText<'a>> {
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol.rs b/src/tools/rust-analyzer/crates/intern/src/symbol.rs
index 89c3be96fcb..8b2d6e8717d 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol.rs
@@ -163,28 +163,28 @@ impl Symbol {
 
     pub fn integer(i: usize) -> Self {
         match i {
-            0 => symbols::INTEGER_0.clone(),
-            1 => symbols::INTEGER_1.clone(),
-            2 => symbols::INTEGER_2.clone(),
-            3 => symbols::INTEGER_3.clone(),
-            4 => symbols::INTEGER_4.clone(),
-            5 => symbols::INTEGER_5.clone(),
-            6 => symbols::INTEGER_6.clone(),
-            7 => symbols::INTEGER_7.clone(),
-            8 => symbols::INTEGER_8.clone(),
-            9 => symbols::INTEGER_9.clone(),
-            10 => symbols::INTEGER_10.clone(),
-            11 => symbols::INTEGER_11.clone(),
-            12 => symbols::INTEGER_12.clone(),
-            13 => symbols::INTEGER_13.clone(),
-            14 => symbols::INTEGER_14.clone(),
-            15 => symbols::INTEGER_15.clone(),
+            0 => symbols::INTEGER_0,
+            1 => symbols::INTEGER_1,
+            2 => symbols::INTEGER_2,
+            3 => symbols::INTEGER_3,
+            4 => symbols::INTEGER_4,
+            5 => symbols::INTEGER_5,
+            6 => symbols::INTEGER_6,
+            7 => symbols::INTEGER_7,
+            8 => symbols::INTEGER_8,
+            9 => symbols::INTEGER_9,
+            10 => symbols::INTEGER_10,
+            11 => symbols::INTEGER_11,
+            12 => symbols::INTEGER_12,
+            13 => symbols::INTEGER_13,
+            14 => symbols::INTEGER_14,
+            15 => symbols::INTEGER_15,
             i => Symbol::intern(&format!("{i}")),
         }
     }
 
     pub fn empty() -> Self {
-        symbols::__empty.clone()
+        symbols::__empty
     }
 
     #[inline]
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index 3e52dbaea65..2686a75c7c8 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -292,7 +292,7 @@ impl ProjectFolders {
             };
 
             let file_set_roots = vec![VfsPath::from(ratoml_path.to_owned())];
-            let entry = vfs::loader::Entry::Files(vec![ratoml_path.to_owned()]);
+            let entry = vfs::loader::Entry::Files(vec![ratoml_path]);
 
             res.watch.push(res.load.len());
             res.load.push(entry);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index 34dcf2a1822..0ac25da3294 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -4,7 +4,7 @@ use crate::grammar::attributes::ATTRIBUTE_FIRST;
 
 use super::*;
 
-pub(super) use atom::{LITERAL_FIRST, literal};
+pub(super) use atom::{EXPR_RECOVERY_SET, LITERAL_FIRST, literal};
 pub(crate) use atom::{block_expr, match_arm_list};
 
 #[derive(PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
index c66afed91c5..5faf6fc2759 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
@@ -46,7 +46,6 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
         T!['['],
         T![|],
         T![async],
-        T![box],
         T![break],
         T![const],
         T![continue],
@@ -68,7 +67,8 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet =
         LIFETIME_IDENT,
     ]));
 
-pub(super) const EXPR_RECOVERY_SET: TokenSet = TokenSet::new(&[T![')'], T![']']]);
+pub(in crate::grammar) const EXPR_RECOVERY_SET: TokenSet =
+    TokenSet::new(&[T!['}'], T![')'], T![']'], T![,]]);
 
 pub(super) fn atom_expr(
     p: &mut Parser<'_>,
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
index f5f003be489..b9f4866574a 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
@@ -32,6 +32,9 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
     T![impl],
     T![trait],
     T![const],
+    T![async],
+    T![unsafe],
+    T![extern],
     T![static],
     T![let],
     T![mod],
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
index 3410505cd46..770827c6b0d 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
@@ -81,7 +81,7 @@ fn path_for_qualifier(
 }
 
 const EXPR_PATH_SEGMENT_RECOVERY_SET: TokenSet =
-    items::ITEM_RECOVERY_SET.union(TokenSet::new(&[T![')'], T![,], T![let]]));
+    expressions::EXPR_RECOVERY_SET.union(items::ITEM_RECOVERY_SET);
 const TYPE_PATH_SEGMENT_RECOVERY_SET: TokenSet = types::TYPE_RECOVERY_SET;
 
 fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) -> Option<CompletedMarker> {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
index 460051a0f4a..4dd44c030f3 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
@@ -199,8 +199,19 @@ fn pattern_single_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
     }
 }
 
-const PAT_RECOVERY_SET: TokenSet =
-    TokenSet::new(&[T![let], T![if], T![while], T![loop], T![match], T![')'], T![,], T![=]]);
+const PAT_RECOVERY_SET: TokenSet = TokenSet::new(&[
+    T![let],
+    T![if],
+    T![while],
+    T![loop],
+    T![match],
+    T![')'],
+    T![']'],
+    T!['}'],
+    T![,],
+    T![=],
+    T![&],
+]);
 
 fn atom_pat(p: &mut Parser<'_>, recovery_set: TokenSet) -> Option<CompletedMarker> {
     let m = match p.current() {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
index 0133b7d5d82..9d31e435cf9 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
@@ -20,10 +20,15 @@ pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(TokenSet::new(&[
 
 pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
     T![')'],
+    // test_err type_in_array_recover
+    // const _: [&];
+    T![']'],
+    T!['}'],
     T![>],
     T![,],
     // test_err struct_field_recover
     // struct S { f pub g: () }
+    // struct S { f: pub g: () }
     T![pub],
 ]);
 
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
index 6c9d02aaa8f..24db9478ee5 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
@@ -870,6 +870,10 @@ mod err {
         run_and_expect_errors("test_data/parser/inline/err/tuple_pat_leading_comma.rs");
     }
     #[test]
+    fn type_in_array_recover() {
+        run_and_expect_errors("test_data/parser/inline/err/type_in_array_recover.rs");
+    }
+    #[test]
     fn unsafe_block_in_mod() {
         run_and_expect_errors("test_data/parser/inline/err/unsafe_block_in_mod.rs");
     }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast
index d97fc6c7209..1a8e881dd9e 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0022_bad_exprs.rast
@@ -35,8 +35,8 @@ SOURCE_FILE
         WHITESPACE " "
         LET_STMT
           LET_KW "let"
-          ERROR
-            R_BRACK "]"
+        ERROR
+          R_BRACK "]"
         WHITESPACE " "
         R_CURLY "}"
   WHITESPACE "\n"
@@ -149,7 +149,8 @@ error 17: expected expression, item or let statement
 error 25: expected a name
 error 26: expected `;`, `{`, or `(`
 error 30: expected pattern
-error 31: expected SEMICOLON
+error 30: expected SEMICOLON
+error 30: expected expression, item or let statement
 error 53: expected expression
 error 54: expected R_PAREN
 error 54: expected SEMICOLON
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast
index feb617e1aa2..b57066f2fb3 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/comma_after_default_values_syntax.rast
@@ -23,8 +23,7 @@ SOURCE_FILE
               L_CURLY "{"
               WHITESPACE " "
               DOT2 ".."
-              ERROR
-                COMMA ","
+              COMMA ","
               WHITESPACE " "
               R_CURLY "}"
           SEMICOLON ";"
@@ -39,8 +38,7 @@ SOURCE_FILE
             L_CURLY "{"
             WHITESPACE " "
             DOT2 ".."
-            ERROR
-              COMMA ","
+            COMMA ","
             WHITESPACE " "
             RECORD_EXPR_FIELD
               NAME_REF
@@ -55,5 +53,6 @@ SOURCE_FILE
         R_CURLY "}"
   WHITESPACE "\n"
 error 21: expected expression
+error 21: cannot use a comma after the base struct
 error 36: expected expression
-error 37: expected COMMA
+error 36: cannot use a comma after the base struct
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast
index 458d7f4e2fa..5a12c21b647 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rast
@@ -26,6 +26,36 @@ SOURCE_FILE
       WHITESPACE " "
       R_CURLY "}"
   WHITESPACE "\n"
+  STRUCT
+    STRUCT_KW "struct"
+    WHITESPACE " "
+    NAME
+      IDENT "S"
+    WHITESPACE " "
+    RECORD_FIELD_LIST
+      L_CURLY "{"
+      WHITESPACE " "
+      RECORD_FIELD
+        NAME
+          IDENT "f"
+        COLON ":"
+      WHITESPACE " "
+      RECORD_FIELD
+        VISIBILITY
+          PUB_KW "pub"
+        WHITESPACE " "
+        NAME
+          IDENT "g"
+        COLON ":"
+        WHITESPACE " "
+        TUPLE_TYPE
+          L_PAREN "("
+          R_PAREN ")"
+      WHITESPACE " "
+      R_CURLY "}"
+  WHITESPACE "\n"
 error 12: expected COLON
 error 12: expected type
 error 12: expected COMMA
+error 38: expected type
+error 38: expected COMMA
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs
index da32227adcd..5b1e5a5b8a2 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/struct_field_recover.rs
@@ -1 +1,2 @@
 struct S { f pub g: () }
+struct S { f: pub g: () }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast
new file mode 100644
index 00000000000..db76e8d7c88
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rast
@@ -0,0 +1,15 @@
+SOURCE_FILE
+  CONST
+    CONST_KW "const"
+    WHITESPACE " "
+    UNDERSCORE "_"
+    COLON ":"
+    WHITESPACE " "
+    SLICE_TYPE
+      L_BRACK "["
+      REF_TYPE
+        AMP "&"
+      R_BRACK "]"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+error 11: expected type
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs
new file mode 100644
index 00000000000..039bf829977
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/type_in_array_recover.rs
@@ -0,0 +1 @@
+const _: [&];
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs
index 07a10aaae57..97c0c4bda7d 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs
@@ -12,5 +12,5 @@ fn main() {
     let version_string = std::str::from_utf8(&output.stdout[..])
         .expect("rustc --version output must be UTF-8")
         .trim();
-    println!("cargo::rustc-env=RUSTC_VERSION={}", version_string);
+    println!("cargo::rustc-env=RUSTC_VERSION={version_string}");
 }
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 f2e5df171ae..e7293b0b2ef 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/env.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs
@@ -25,7 +25,7 @@ pub(crate) fn inject_cargo_package_env(env: &mut Env, package: &PackageData) {
     env.set("CARGO_PKG_VERSION_PATCH", package.version.patch.to_string());
     env.set("CARGO_PKG_VERSION_PRE", package.version.pre.to_string());
 
-    env.set("CARGO_PKG_AUTHORS", package.authors.join(":").clone());
+    env.set("CARGO_PKG_AUTHORS", package.authors.join(":"));
 
     env.set("CARGO_PKG_NAME", package.name.clone());
     env.set("CARGO_PKG_DESCRIPTION", package.description.as_deref().unwrap_or_default());
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 c6e0cf36aff..eec0077ea6e 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -1370,7 +1370,7 @@ fn detached_file_to_crate_graph(
         Edition::CURRENT,
         display_name.clone(),
         None,
-        cfg_options.clone(),
+        cfg_options,
         None,
         Env::default(),
         CrateOrigin::Local {
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 8aeb2629423..8b03d8f8cc7 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/query-group-macro/Cargo.toml
@@ -20,3 +20,4 @@ syn = { version = "2.0", features = ["full", "extra-traits", "visit-mut"] }
 [dev-dependencies]
 expect-test = "1.5.1"
 salsa.workspace = true
+salsa-macros.workspace = true
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs b/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs
index f4f316c1ac1..ec4b6b2a4ac 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/query-group-macro/src/lib.rs
@@ -178,7 +178,7 @@ pub(crate) fn query_group_impl(
     let supertraits = &item_trait.supertraits;
 
     let db_attr: Attribute = parse_quote! {
-        #[salsa::db]
+        #[salsa_macros::db]
     };
     item_trait.attrs.push(db_attr);
 
@@ -210,7 +210,7 @@ pub(crate) fn query_group_impl(
                 .into_iter()
                 .filter(|fn_arg| matches!(fn_arg, FnArg::Typed(_)))
                 .map(|fn_arg| match fn_arg {
-                    FnArg::Typed(pat_type) => pat_type.clone(),
+                    FnArg::Typed(pat_type) => pat_type,
                     FnArg::Receiver(_) => unreachable!("this should have been filtered out"),
                 })
                 .collect::<Vec<syn::PatType>>();
@@ -407,7 +407,7 @@ pub(crate) fn query_group_impl(
         .collect::<Vec<proc_macro2::TokenStream>>();
 
     let input_struct = quote! {
-        #[salsa::input]
+        #[salsa_macros::input]
         pub(crate) struct #input_struct_name {
             #(#fields),*
         }
@@ -418,7 +418,7 @@ pub(crate) fn query_group_impl(
 
     let create_data_method = quote! {
         #[allow(non_snake_case)]
-        #[salsa::tracked]
+        #[salsa_macros::tracked]
         fn #create_data_ident(db: &dyn #trait_name_ident) -> #input_struct_name {
             #input_struct_name::new(db, #(#field_params),*)
         }
@@ -443,7 +443,7 @@ pub(crate) fn query_group_impl(
     item_trait.items.append(&mut lookup_signatures);
 
     let trait_impl = quote! {
-        #[salsa::db]
+        #[salsa_macros::db]
         impl<DB> #trait_name_ident for DB
         where
             DB: #supertraits,
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs b/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs
index d4d40588bfc..baac3e8bbfe 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs
+++ b/src/tools/rust-analyzer/crates/query-group-macro/src/queries.rs
@@ -49,7 +49,7 @@ impl ToTokens for TrackedQuery {
             })
             .into_iter()
             .chain(self.lru.map(|lru| quote!(lru = #lru)));
-        let annotation = quote!(#[salsa::tracked( #(#options),* )]);
+        let annotation = quote!(#[salsa_macros::tracked( #(#options),* )]);
 
         let pat_and_tys = &self.pat_and_tys;
         let params = self
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs
index 26ed316122a..f738185b1fe 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs
+++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/interned.rs
@@ -6,7 +6,7 @@ use salsa::plumbing::AsId;
 mod logger_db;
 use logger_db::LoggerDb;
 
-#[salsa::interned(no_lifetime)]
+#[salsa_macros::interned(no_lifetime)]
 pub struct InternedString {
     data: String,
 }
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs
index 5cf9be36f70..bade0c2cd6f 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs
+++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/logger_db.rs
@@ -1,6 +1,6 @@
 use std::sync::{Arc, Mutex};
 
-#[salsa::db]
+#[salsa_macros::db]
 #[derive(Default, Clone)]
 pub(crate) struct LoggerDb {
     storage: salsa::Storage<Self>,
@@ -12,7 +12,7 @@ struct Logger {
     logs: Arc<Mutex<Vec<String>>>,
 }
 
-#[salsa::db]
+#[salsa_macros::db]
 impl salsa::Database for LoggerDb {
     fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) {
         let event = event();
@@ -40,7 +40,7 @@ impl LoggerDb {
     /// it is meant to be run from outside any tracked functions.
     pub(crate) fn assert_logs(&self, expected: expect_test::Expect) {
         let logs = std::mem::take(&mut *self.logger.logs.lock().unwrap());
-        expected.assert_eq(&format!("{:#?}", logs));
+        expected.assert_eq(&format!("{logs:#?}"));
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs
index a18b23a7d8a..cc57ba78455 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs
+++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/old_and_new.rs
@@ -4,7 +4,7 @@ mod logger_db;
 use logger_db::LoggerDb;
 use query_group_macro::query_group;
 
-#[salsa::input]
+#[salsa_macros::input]
 struct Input {
     str: String,
 }
@@ -30,7 +30,7 @@ fn invoke_length_query_actual(db: &dyn PartialMigrationDatabase, input: Input) -
     input.str(db).len()
 }
 
-#[salsa::tracked]
+#[salsa_macros::tracked]
 fn invoke_length_tracked_actual(db: &dyn PartialMigrationDatabase, input: Input) -> usize {
     input.str(db).len()
 }
@@ -87,12 +87,12 @@ fn invoke_tracked_query() {
 fn new_salsa_baseline() {
     let db = LoggerDb::default();
 
-    #[salsa::input]
+    #[salsa_macros::input]
     struct Input {
         str: String,
     }
 
-    #[salsa::tracked]
+    #[salsa_macros::tracked]
     fn new_salsa_length_query(db: &dyn PartialMigrationDatabase, input: Input) -> usize {
         input.str(db).len()
     }
diff --git a/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs b/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs
index 70073ac1de3..ad8ada3ef15 100644
--- a/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs
+++ b/src/tools/rust-analyzer/crates/query-group-macro/tests/supertrait.rs
@@ -1,6 +1,6 @@
 use query_group_macro::query_group;
 
-#[salsa::db]
+#[salsa_macros::db]
 pub trait SourceDb: salsa::Database {
     /// Text of the file.
     fn file_text(&self, id: usize) -> String;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
index ea5a5eaa6a4..4dba97c8ec4 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs
@@ -182,10 +182,8 @@ fn with_extra_thread(
     thread_intent: stdx::thread::ThreadIntent,
     f: impl FnOnce() -> anyhow::Result<()> + Send + 'static,
 ) -> anyhow::Result<()> {
-    let handle = stdx::thread::Builder::new(thread_intent)
-        .name(thread_name.into())
-        .stack_size(STACK_SIZE)
-        .spawn(f)?;
+    let handle =
+        stdx::thread::Builder::new(thread_intent, thread_name).stack_size(STACK_SIZE).spawn(f)?;
 
     handle.join()?;
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index a62005e3c08..a1e4adf0844 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -175,7 +175,7 @@ impl flags::AnalysisStats {
             UsizeWithUnderscore(dep_loc),
             UsizeWithUnderscore(dep_item_trees),
         );
-        eprintln!("  dependency item stats: {}", dep_item_stats);
+        eprintln!("  dependency item stats: {dep_item_stats}");
 
         // FIXME(salsa-transition): bring back stats for ParseQuery (file size)
         // and ParseMacroExpansionQuery (macro expansion "file") size whenever we implement
@@ -295,7 +295,7 @@ impl flags::AnalysisStats {
             UsizeWithUnderscore(workspace_loc),
             UsizeWithUnderscore(workspace_item_trees),
         );
-        eprintln!("    usages: {}", workspace_item_stats);
+        eprintln!("    usages: {workspace_item_stats}");
 
         eprintln!("  Dependencies:");
         eprintln!(
@@ -303,7 +303,7 @@ impl flags::AnalysisStats {
             UsizeWithUnderscore(dep_loc),
             UsizeWithUnderscore(dep_item_trees),
         );
-        eprintln!("    declarations: {}", dep_item_stats);
+        eprintln!("    declarations: {dep_item_stats}");
 
         let crate_def_map_time = crate_def_map_sw.elapsed();
         eprintln!("{:<20} {}", "Item Collection:", crate_def_map_time);
@@ -701,10 +701,9 @@ impl flags::AnalysisStats {
 
         if self.parallel {
             let mut inference_sw = self.stop_watch();
-            let snap = db.snapshot();
             bodies
                 .par_iter()
-                .map_with(snap, |snap, &body| {
+                .map_with(db.clone(), |snap, &body| {
                     snap.body(body.into());
                     snap.infer(body.into());
                 })
@@ -1294,7 +1293,7 @@ impl fmt::Display for UsizeWithUnderscore {
         let num_str = self.0.to_string();
 
         if num_str.len() <= 3 {
-            return write!(f, "{}", num_str);
+            return write!(f, "{num_str}");
         }
 
         let mut result = String::new();
@@ -1307,7 +1306,7 @@ impl fmt::Display for UsizeWithUnderscore {
         }
 
         let result = result.chars().rev().collect::<String>();
-        write!(f, "{}", result)
+        write!(f, "{result}")
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
index 7c4eeebdfa3..7b12cb14009 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -15,11 +15,13 @@ impl flags::Diagnostics {
     pub fn run(self) -> anyhow::Result<()> {
         const STACK_SIZE: usize = 1024 * 1024 * 8;
 
-        let handle = stdx::thread::Builder::new(stdx::thread::ThreadIntent::LatencySensitive)
-            .name("BIG_STACK_THREAD".into())
-            .stack_size(STACK_SIZE)
-            .spawn(|| self.run_())
-            .unwrap();
+        let handle = stdx::thread::Builder::new(
+            stdx::thread::ThreadIntent::LatencySensitive,
+            "BIG_STACK_THREAD",
+        )
+        .stack_size(STACK_SIZE)
+        .spawn(|| self.run_())
+        .unwrap();
 
         handle.join()
     }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
index c042c26bd18..e3b372c9149 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -7,6 +7,7 @@ use std::{cell::RefCell, fs::read_to_string, panic::AssertUnwindSafe, path::Path
 
 use hir::{ChangeWithProcMacros, Crate};
 use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig};
+use ide_db::base_db;
 use itertools::Either;
 use paths::Utf8PathBuf;
 use profile::StopWatch;
@@ -310,7 +311,7 @@ impl flags::RustcTests {
                 let tester = AssertUnwindSafe(&mut tester);
                 let p = p.clone();
                 move || {
-                    let _guard = stdx::panic_context::enter(p.display().to_string());
+                    let _guard = base_db::DbPanicContext::enter(p.display().to_string());
                     { tester }.0.test(p);
                 }
             }) {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
index 2062294f807..d258c5d8191 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
@@ -265,10 +265,10 @@ impl flags::Scip {
         };
 
         if !duplicate_symbol_errors.is_empty() {
-            eprintln!("{}", DUPLICATE_SYMBOLS_MESSAGE);
+            eprintln!("{DUPLICATE_SYMBOLS_MESSAGE}");
             for (source_location, symbol) in duplicate_symbol_errors {
-                eprintln!("{}", source_location);
-                eprintln!("  Duplicate symbol: {}", symbol);
+                eprintln!("{source_location}");
+                eprintln!("  Duplicate symbol: {symbol}");
                 eprintln!();
             }
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs
index bca7c8a098c..0362e13b88b 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/unresolved_references.rs
@@ -15,11 +15,13 @@ impl flags::UnresolvedReferences {
     pub fn run(self) -> anyhow::Result<()> {
         const STACK_SIZE: usize = 1024 * 1024 * 8;
 
-        let handle = stdx::thread::Builder::new(stdx::thread::ThreadIntent::LatencySensitive)
-            .name("BIG_STACK_THREAD".into())
-            .stack_size(STACK_SIZE)
-            .spawn(|| self.run_())
-            .unwrap();
+        let handle = stdx::thread::Builder::new(
+            stdx::thread::ThreadIntent::LatencySensitive,
+            "BIG_STACK_THREAD",
+        )
+        .stack_size(STACK_SIZE)
+        .spawn(|| self.run_())
+        .unwrap();
 
         handle.join()
     }
@@ -28,7 +30,7 @@ impl flags::UnresolvedReferences {
         let root =
             vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(&self.path)).normalize();
         let config = crate::config::Config::new(
-            root.clone(),
+            root,
             lsp_types::ClientCapabilities::default(),
             vec![],
             None,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs
index 0035d941e2c..d6c80c399ba 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/command.rs
@@ -148,10 +148,10 @@ impl<T: Sized + Send + 'static> CommandHandle<T> {
         let stderr = child.0.stderr().take().unwrap();
 
         let actor = CargoActor::<T>::new(parser, sender, stdout, stderr);
-        let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
-            .name("CommandHandle".to_owned())
-            .spawn(move || actor.run())
-            .expect("failed to spawn thread");
+        let thread =
+            stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "CommandHandle")
+                .spawn(move || actor.run())
+                .expect("failed to spawn thread");
         Ok(CommandHandle { program, arguments, current_dir, child, thread, _phantom: PhantomData })
     }
 
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 dd827949a9c..03e5b1f6f4b 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -9,13 +9,14 @@ use cfg::{CfgAtom, CfgDiff};
 use hir::Symbol;
 use ide::{
     AssistConfig, CallHierarchyConfig, CallableSnippets, CompletionConfig,
-    CompletionFieldsToResolve, DiagnosticsConfig, ExprFillDefaultMode, GenericParameterHints,
-    HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve,
-    InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
-    Snippet, SnippetScope, SourceRootId,
+    CompletionFieldsToResolve, DiagnosticsConfig, GenericParameterHints, HighlightConfig,
+    HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve, InlayHintsConfig,
+    JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, Snippet, SnippetScope,
+    SourceRootId,
 };
 use ide_db::{
     SnippetCap,
+    assists::ExprFillDefaultMode,
     imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
 };
 use itertools::{Either, Itertools};
@@ -1182,7 +1183,7 @@ impl ConfigChange {
         source_root_map: Arc<FxHashMap<SourceRootId, SourceRootId>>,
     ) {
         assert!(self.source_map_change.is_none());
-        self.source_map_change = Some(source_root_map.clone());
+        self.source_map_change = Some(source_root_map);
     }
 }
 
@@ -1493,6 +1494,11 @@ impl Config {
             term_search_fuel: self.assist_termSearch_fuel(source_root).to_owned() as u64,
             term_search_borrowck: self.assist_termSearch_borrowcheck(source_root).to_owned(),
             code_action_grouping: self.code_action_group(),
+            expr_fill_default: match self.assist_expressionFillDefault(source_root) {
+                ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo,
+                ExprFillDefaultDef::Default => ExprFillDefaultMode::Default,
+                ExprFillDefaultDef::Underscore => ExprFillDefaultMode::Underscore,
+            },
         }
     }
 
@@ -1577,6 +1583,7 @@ impl Config {
             expr_fill_default: match self.assist_expressionFillDefault(source_root) {
                 ExprFillDefaultDef::Todo => ExprFillDefaultMode::Todo,
                 ExprFillDefaultDef::Default => ExprFillDefaultMode::Default,
+                ExprFillDefaultDef::Underscore => ExprFillDefaultMode::Underscore,
             },
             snippet_cap: self.snippet_cap(),
             insert_use: self.insert_use_config(source_root),
@@ -2527,6 +2534,7 @@ where
 enum ExprFillDefaultDef {
     Todo,
     Default,
+    Underscore,
 }
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
index 9b1463b1126..438a2a0ba1e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
@@ -5,7 +5,7 @@ use std::mem;
 
 use cargo_metadata::PackageId;
 use ide::FileId;
-use ide_db::FxHashMap;
+use ide_db::{FxHashMap, base_db::DbPanicContext};
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
 use stdx::iter_eq_by;
@@ -215,7 +215,7 @@ pub(crate) fn fetch_native_diagnostics(
     kind: NativeDiagnosticsFetchKind,
 ) -> Vec<(FileId, Vec<lsp_types::Diagnostic>)> {
     let _p = tracing::info_span!("fetch_native_diagnostics").entered();
-    let _ctx = stdx::panic_context::enter("fetch_native_diagnostics".to_owned());
+    let _ctx = DbPanicContext::enter("fetch_native_diagnostics".to_owned());
 
     // the diagnostics produced may point to different files not requested by the concrete request,
     // put those into here and filter later
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs
index 67ddc41f3b2..24c433610f1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs
@@ -126,10 +126,8 @@ impl CargoParser<DiscoverProjectMessage> for DiscoverProjectParser {
                 Some(msg)
             }
             Err(err) => {
-                let err = DiscoverProjectData::Error {
-                    error: format!("{:#?}\n{}", err, line),
-                    source: None,
-                };
+                let err =
+                    DiscoverProjectData::Error { error: format!("{err:#?}\n{line}"), source: None };
                 Some(DiscoverProjectMessage::new(err))
             }
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
index 2778b311e1e..fc312439d58 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
@@ -133,10 +133,10 @@ impl FlycheckHandle {
         let actor =
             FlycheckActor::new(id, sender, config, sysroot_root, workspace_root, manifest_path);
         let (sender, receiver) = unbounded::<StateChange>();
-        let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
-            .name("Flycheck".to_owned())
-            .spawn(move || actor.run(receiver))
-            .expect("failed to spawn thread");
+        let thread =
+            stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, format!("Flycheck{id}"))
+                .spawn(move || actor.run(receiver))
+                .expect("failed to spawn thread");
         FlycheckHandle { id, sender, _thread: thread }
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index 820276e8aea..3b3b9c87975 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -511,7 +511,7 @@ impl GlobalState {
 
                 self.fetch_workspaces_queue.request_op(
                     format!("workspace vfs file change: {path}"),
-                    FetchWorkspaceRequest { path: Some(path.to_owned()), force_crate_graph_reload },
+                    FetchWorkspaceRequest { path: Some(path), force_crate_graph_reload },
                 );
             }
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
index 3b76edf528b..f04ada38893 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
@@ -4,7 +4,10 @@ use std::{
     panic, thread,
 };
 
-use ide_db::base_db::salsa::{self, Cancelled};
+use ide_db::base_db::{
+    DbPanicContext,
+    salsa::{self, Cancelled},
+};
 use lsp_server::{ExtractError, Response, ResponseError};
 use serde::{Serialize, de::DeserializeOwned};
 use stdx::thread::ThreadIntent;
@@ -56,7 +59,7 @@ impl RequestDispatcher<'_> {
             tracing::info_span!("request", method = ?req.method, "request_id" = ?req.id).entered();
         tracing::debug!(?params);
         let result = {
-            let _pctx = stdx::panic_context::enter(panic_context);
+            let _pctx = DbPanicContext::enter(panic_context);
             f(self.global_state, params)
         };
         if let Ok(response) = result_to_response::<R>(req.id, result) {
@@ -86,7 +89,7 @@ impl RequestDispatcher<'_> {
         let global_state_snapshot = self.global_state.snapshot();
 
         let result = panic::catch_unwind(move || {
-            let _pctx = stdx::panic_context::enter(panic_context);
+            let _pctx = DbPanicContext::enter(panic_context);
             f(global_state_snapshot, params)
         });
 
@@ -257,7 +260,7 @@ impl RequestDispatcher<'_> {
         }
         .spawn(intent, move || {
             let result = panic::catch_unwind(move || {
-                let _pctx = stdx::panic_context::enter(panic_context);
+                let _pctx = DbPanicContext::enter(panic_context);
                 f(world, params)
             });
             match thread_result_to_response::<R>(req.id.clone(), result) {
@@ -421,11 +424,8 @@ impl NotificationDispatcher<'_> {
 
         tracing::debug!(?params);
 
-        let _pctx = stdx::panic_context::enter(format!(
-            "\nversion: {}\nnotification: {}",
-            version(),
-            N::METHOD
-        ));
+        let _pctx =
+            DbPanicContext::enter(format!("\nversion: {}\nnotification: {}", version(), N::METHOD));
         if let Err(e) = f(self.global_state, params) {
             tracing::error!(handler = %N::METHOD, error = %e, "notification handler failed");
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
index a30e5d8ce26..b7373f274f0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
@@ -309,7 +309,7 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
         let task = move || -> std::result::Result<(), Cancelled> {
             if invocation_strategy_once {
                 let saved_file = vfs_path.as_path().map(|p| p.to_owned());
-                world.flycheck[0].restart_workspace(saved_file.clone());
+                world.flycheck[0].restart_workspace(saved_file);
             }
 
             let target = TargetSpec::for_file(&world, file_id)?.and_then(|it| {
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 e08dd80973a..69983a67626 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
@@ -2210,7 +2210,7 @@ fn runnable_action_links(
         let label = update_test.label();
         if let Some(r) = to_proto::make_update_runnable(&r, update_test) {
             let update_command = to_proto::command::run_single(&r, label.unwrap().as_str());
-            group.commands.push(to_command_link(update_command, r.label.clone()));
+            group.commands.push(to_command_link(update_command, r.label));
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
index 96c2ceef6ba..f6bcb5642c3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -1064,7 +1064,7 @@ fn main() {
         ),
         work_done_progress_params: Default::default(),
     });
-    assert!(res.to_string().contains("&str"));
+    assert!(res.to_string().contains("&'static str"));
 
     let res = server.send_request::<HoverRequest>(HoverParams {
         text_document_position_params: TextDocumentPositionParams::new(
@@ -1073,7 +1073,7 @@ fn main() {
         ),
         work_done_progress_params: Default::default(),
     });
-    assert!(res.to_string().contains("&str"));
+    assert!(res.to_string().contains("&'static str"));
 
     server.request::<GotoTypeDefinition>(
         GotoDefinitionParams {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
index 3f313b7e57f..485f32281dd 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs
@@ -82,11 +82,8 @@ impl RatomlTest {
         }
 
         Url::parse(
-            format!(
-                "file://{}",
-                path.into_string().to_owned().replace("C:\\", "/c:/").replace('\\', "/")
-            )
-            .as_str(),
+            format!("file://{}", path.into_string().replace("C:\\", "/c:/").replace('\\', "/"))
+                .as_str(),
         )
         .unwrap()
     }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
index 3f97952365f..2bebb0c1b97 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -202,7 +202,7 @@ impl Project<'_> {
         }
 
         let mut config = Config::new(
-            tmp_dir_path.clone(),
+            tmp_dir_path,
             lsp_types::ClientCapabilities {
                 workspace: Some(lsp_types::WorkspaceClientCapabilities {
                     did_change_watched_files: Some(
@@ -298,8 +298,7 @@ impl Server {
     ) -> Server {
         let (connection, client) = Connection::memory();
 
-        let _thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
-            .name("test server".to_owned())
+        let _thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "test server")
             .spawn(move || main_loop(config, connection).unwrap())
             .expect("failed to spawn a thread");
 
diff --git a/src/tools/rust-analyzer/crates/span/src/hygiene.rs b/src/tools/rust-analyzer/crates/span/src/hygiene.rs
index b21102f2db7..7bb88ac3658 100644
--- a/src/tools/rust-analyzer/crates/span/src/hygiene.rs
+++ b/src/tools/rust-analyzer/crates/span/src/hygiene.rs
@@ -94,16 +94,11 @@ const _: () = {
         }
     }
     impl zalsa_struct_::Configuration for SyntaxContext {
+        const LOCATION: salsa::plumbing::Location =
+            salsa::plumbing::Location { file: file!(), line: line!() };
         const DEBUG_NAME: &'static str = "SyntaxContextData";
         type Fields<'a> = SyntaxContextData;
         type Struct<'a> = SyntaxContext;
-        fn struct_from_id<'db>(id: salsa::Id) -> Self::Struct<'db> {
-            SyntaxContext::from_salsa_id(id)
-        }
-        fn deref_struct(s: Self::Struct<'_>) -> salsa::Id {
-            s.as_salsa_id()
-                .expect("`SyntaxContext::deref_structs()` called on a root `SyntaxContext`")
-        }
     }
     impl SyntaxContext {
         pub fn ingredient<Db>(db: &Db) -> &zalsa_struct_::IngredientImpl<Self>
@@ -308,7 +303,7 @@ impl SyntaxContext {
 }
 
 #[cfg(feature = "salsa")]
-impl SyntaxContext {
+impl<'db> SyntaxContext {
     const MAX_ID: u32 = salsa::Id::MAX_U32 - 1;
 
     #[inline]
@@ -340,6 +335,60 @@ impl SyntaxContext {
         // SAFETY: This comes from a Salsa ID.
         unsafe { Self::from_u32(id.as_u32()) }
     }
+
+    #[inline]
+    pub fn outer_mark(
+        self,
+        db: &'db dyn salsa::Database,
+    ) -> (Option<crate::MacroCallId>, Transparency) {
+        (self.outer_expn(db), self.outer_transparency(db))
+    }
+
+    #[inline]
+    pub fn normalize_to_macros_2_0(self, db: &'db dyn salsa::Database) -> SyntaxContext {
+        self.opaque(db)
+    }
+
+    #[inline]
+    pub fn normalize_to_macro_rules(self, db: &'db dyn salsa::Database) -> SyntaxContext {
+        self.opaque_and_semitransparent(db)
+    }
+
+    pub fn is_opaque(self, db: &'db dyn salsa::Database) -> bool {
+        !self.is_root() && self.outer_transparency(db).is_opaque()
+    }
+
+    pub fn remove_mark(
+        &mut self,
+        db: &'db dyn salsa::Database,
+    ) -> (Option<crate::MacroCallId>, Transparency) {
+        let data = *self;
+        *self = data.parent(db);
+        (data.outer_expn(db), data.outer_transparency(db))
+    }
+
+    pub fn marks(
+        self,
+        db: &'db dyn salsa::Database,
+    ) -> impl Iterator<Item = (crate::MacroCallId, Transparency)> {
+        let mut marks = self.marks_rev(db).collect::<Vec<_>>();
+        marks.reverse();
+        marks.into_iter()
+    }
+
+    pub fn marks_rev(
+        self,
+        db: &'db dyn salsa::Database,
+    ) -> impl Iterator<Item = (crate::MacroCallId, Transparency)> {
+        std::iter::successors(Some(self), move |&mark| Some(mark.parent(db)))
+            .take_while(|&it| !it.is_root())
+            .map(|ctx| {
+                let mark = ctx.outer_mark(db);
+                // We stop before taking the root expansion, as such we cannot encounter a `None` outer
+                // expansion, as only the ROOT has it.
+                (mark.0.unwrap(), mark.1)
+            })
+    }
 }
 #[cfg(not(feature = "salsa"))]
 #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
diff --git a/src/tools/rust-analyzer/crates/stdx/src/thread.rs b/src/tools/rust-analyzer/crates/stdx/src/thread.rs
index 6c742fecf1b..a34e9e4a655 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/thread.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/thread.rs
@@ -26,12 +26,12 @@ pub use pool::Pool;
 /// # Panics
 ///
 /// Panics if failed to spawn the thread.
-pub fn spawn<F, T>(intent: ThreadIntent, f: F) -> JoinHandle<T>
+pub fn spawn<F, T>(intent: ThreadIntent, name: String, f: F) -> JoinHandle<T>
 where
     F: (FnOnce() -> T) + Send + 'static,
     T: Send + 'static,
 {
-    Builder::new(intent).spawn(f).expect("failed to spawn thread")
+    Builder::new(intent, name).spawn(f).expect("failed to spawn thread")
 }
 
 pub struct Builder {
@@ -42,13 +42,8 @@ pub struct Builder {
 
 impl Builder {
     #[must_use]
-    pub fn new(intent: ThreadIntent) -> Self {
-        Self { intent, inner: jod_thread::Builder::new(), allow_leak: false }
-    }
-
-    #[must_use]
-    pub fn name(self, name: String) -> Self {
-        Self { inner: self.inner.name(name), ..self }
+    pub fn new(intent: ThreadIntent, name: impl Into<String>) -> Self {
+        Self { intent, inner: jod_thread::Builder::new().name(name.into()), allow_leak: false }
     }
 
     #[must_use]
@@ -56,6 +51,8 @@ impl Builder {
         Self { inner: self.inner.stack_size(size), ..self }
     }
 
+    /// Whether dropping should detach the thread
+    /// instead of joining it.
     #[must_use]
     pub fn allow_leak(self, allow_leak: bool) -> Self {
         Self { allow_leak, ..self }
diff --git a/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs b/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs
index 074cd747dac..a8de4db624f 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs
@@ -50,10 +50,9 @@ impl Pool {
         let extant_tasks = Arc::new(AtomicUsize::new(0));
 
         let mut handles = Vec::with_capacity(threads);
-        for _ in 0..threads {
-            let handle = Builder::new(INITIAL_INTENT)
+        for idx in 0..threads {
+            let handle = Builder::new(INITIAL_INTENT, format!("Worker{idx}",))
                 .stack_size(STACK_SIZE)
-                .name("Worker".into())
                 .allow_leak(true)
                 .spawn({
                     let extant_tasks = Arc::clone(&extant_tasks);
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
index 510d44d0091..4c7704803ef 100644
--- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
@@ -14,7 +14,7 @@ rust-version.workspace = true
 [dependencies]
 either.workspace = true
 itertools.workspace = true
-rowan = "=0.15.15"
+rowan.workspace = true
 rustc-hash.workspace = true
 rustc-literal-escaper.workspace = true
 smol_str.workspace = true
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
index d608a35effa..596f73e0b10 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -69,6 +69,9 @@ pub mod ext {
     pub fn expr_todo() -> ast::Expr {
         expr_from_text("todo!()")
     }
+    pub fn expr_underscore() -> ast::Expr {
+        expr_from_text("_")
+    }
     pub fn expr_ty_default(ty: &ast::Type) -> ast::Expr {
         expr_from_text(&format!("{ty}::default()"))
     }
@@ -706,7 +709,7 @@ pub fn wildcard_pat() -> ast::WildcardPat {
 }
 
 pub fn rest_pat() -> ast::RestPat {
-    ast_from_text("fn f(..)")
+    ast_from_text("fn f() { let ..; }")
 }
 
 pub fn literal_pat(lit: &str) -> ast::LiteralPat {
@@ -785,8 +788,8 @@ pub fn record_pat_field(name_ref: ast::NameRef, pat: ast::Pat) -> ast::RecordPat
     ast_from_text(&format!("fn f(S {{ {name_ref}: {pat} }}: ()))"))
 }
 
-pub fn record_pat_field_shorthand(name_ref: ast::NameRef) -> ast::RecordPatField {
-    ast_from_text(&format!("fn f(S {{ {name_ref} }}: ()))"))
+pub fn record_pat_field_shorthand(pat: ast::Pat) -> ast::RecordPatField {
+    ast_from_text(&format!("fn f(S {{ {pat} }}: ()))"))
 }
 
 /// Returns a `IdentPat` if the path has just one segment, a `PathPat` otherwise.
@@ -798,16 +801,38 @@ pub fn path_pat(path: ast::Path) -> ast::Pat {
 }
 
 /// Returns a `Pat` if the path has just one segment, an `OrPat` otherwise.
-pub fn or_pat(pats: impl IntoIterator<Item = ast::Pat>, leading_pipe: bool) -> ast::Pat {
+///
+/// Invariant: `pats` must be length > 1.
+pub fn or_pat(pats: impl IntoIterator<Item = ast::Pat>, leading_pipe: bool) -> ast::OrPat {
     let leading_pipe = if leading_pipe { "| " } else { "" };
     let pats = pats.into_iter().join(" | ");
 
     return from_text(&format!("{leading_pipe}{pats}"));
-    fn from_text(text: &str) -> ast::Pat {
+    fn from_text(text: &str) -> ast::OrPat {
         ast_from_text(&format!("fn f({text}: ())"))
     }
 }
 
+pub fn box_pat(pat: ast::Pat) -> ast::BoxPat {
+    ast_from_text(&format!("fn f(box {pat}: ())"))
+}
+
+pub fn paren_pat(pat: ast::Pat) -> ast::ParenPat {
+    ast_from_text(&format!("fn f(({pat}): ())"))
+}
+
+pub fn range_pat(start: Option<ast::Pat>, end: Option<ast::Pat>) -> ast::RangePat {
+    ast_from_text(&format!(
+        "fn f({}..{}: ())",
+        start.map(|e| e.to_string()).unwrap_or_default(),
+        end.map(|e| e.to_string()).unwrap_or_default()
+    ))
+}
+
+pub fn ref_pat(pat: ast::Pat) -> ast::RefPat {
+    ast_from_text(&format!("fn f(&{pat}: ())"))
+}
+
 pub fn match_arm(pat: ast::Pat, guard: Option<ast::MatchGuard>, expr: ast::Expr) -> ast::MatchArm {
     return match guard {
         Some(guard) => from_text(&format!("{pat} {guard} => {expr}")),
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
index 1854000d3db..8dee3964d44 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -3,7 +3,7 @@ use crate::{
     AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken,
     ast::{
         self, HasArgList, HasGenericArgs, HasGenericParams, HasLoopBody, HasName, HasTypeBounds,
-        HasVisibility, make,
+        HasVisibility, RangeItem, make,
     },
     syntax_editor::SyntaxMappingBuilder,
 };
@@ -107,6 +107,20 @@ impl SyntaxFactory {
         ast
     }
 
+    pub fn use_(&self, visibility: Option<ast::Visibility>, use_tree: ast::UseTree) -> ast::Use {
+        make::use_(visibility, use_tree).clone_for_update()
+    }
+
+    pub fn use_tree(
+        &self,
+        path: ast::Path,
+        use_tree_list: Option<ast::UseTreeList>,
+        alias: Option<ast::Rename>,
+        add_star: bool,
+    ) -> ast::UseTree {
+        make::use_tree(path, use_tree_list, alias, add_star).clone_for_update()
+    }
+
     pub fn path_unqualified(&self, segment: ast::PathSegment) -> ast::Path {
         let ast = make::path_unqualified(segment.clone()).clone_for_update();
 
@@ -254,12 +268,12 @@ impl SyntaxFactory {
         ast
     }
 
-    pub fn record_pat_field_shorthand(&self, name_ref: ast::NameRef) -> ast::RecordPatField {
-        let ast = make::record_pat_field_shorthand(name_ref.clone()).clone_for_update();
+    pub fn record_pat_field_shorthand(&self, pat: ast::Pat) -> ast::RecordPatField {
+        let ast = make::record_pat_field_shorthand(pat.clone()).clone_for_update();
 
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_node(name_ref.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
             builder.finish(&mut mapping);
         }
 
@@ -294,6 +308,76 @@ impl SyntaxFactory {
         make::rest_pat().clone_for_update()
     }
 
+    pub fn or_pat(
+        &self,
+        pats: impl IntoIterator<Item = ast::Pat>,
+        leading_pipe: bool,
+    ) -> ast::OrPat {
+        let (pats, input) = iterator_input(pats);
+        let ast = make::or_pat(pats, leading_pipe).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_children(input, ast.pats().map(|it| it.syntax().clone()));
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn box_pat(&self, pat: ast::Pat) -> ast::BoxPat {
+        let ast = make::box_pat(pat.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn paren_pat(&self, pat: ast::Pat) -> ast::ParenPat {
+        let ast = make::paren_pat(pat.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn range_pat(&self, start: Option<ast::Pat>, end: Option<ast::Pat>) -> ast::RangePat {
+        let ast = make::range_pat(start.clone(), end.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            if let Some(start) = start {
+                builder.map_node(start.syntax().clone(), ast.start().unwrap().syntax().clone());
+            }
+            if let Some(end) = end {
+                builder.map_node(end.syntax().clone(), ast.end().unwrap().syntax().clone());
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn ref_pat(&self, pat: ast::Pat) -> ast::RefPat {
+        let ast = make::ref_pat(pat.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn block_expr(
         &self,
         statements: impl IntoIterator<Item = ast::Stmt>,
@@ -673,6 +757,38 @@ impl SyntaxFactory {
         ast
     }
 
+    pub fn let_else_stmt(
+        &self,
+        pattern: ast::Pat,
+        ty: Option<ast::Type>,
+        initializer: ast::Expr,
+        diverging: ast::BlockExpr,
+    ) -> ast::LetStmt {
+        let ast = make::let_else_stmt(
+            pattern.clone(),
+            ty.clone(),
+            initializer.clone(),
+            diverging.clone(),
+        )
+        .clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(pattern.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            if let Some(input) = ty {
+                builder.map_node(input.syntax().clone(), ast.ty().unwrap().syntax().clone());
+            }
+            builder.map_node(
+                initializer.syntax().clone(),
+                ast.initializer().unwrap().syntax().clone(),
+            );
+            builder.map_node(diverging.syntax().clone(), ast.let_else().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn type_arg(&self, ty: ast::Type) -> ast::TypeArg {
         let ast = make::type_arg(ty.clone()).clone_for_update();
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
index 58200189c46..31caf618be9 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
@@ -20,6 +20,7 @@ mod edit_algo;
 mod edits;
 mod mapping;
 
+pub use edits::Removable;
 pub use mapping::{SyntaxMapping, SyntaxMappingBuilder};
 
 #[derive(Debug)]
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
index 6a9c88b55d7..01c1f0d49bf 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
@@ -391,7 +391,7 @@ fn report_intersecting_changes(
 fn to_owning_node(element: &SyntaxElement) -> SyntaxNode {
     match element {
         SyntaxElement::Node(node) => node.clone(),
-        SyntaxElement::Token(token) => token.parent().unwrap().clone(),
+        SyntaxElement::Token(token) => token.parent().unwrap(),
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs
index 350cb3e2544..d66ea8aa28c 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs
@@ -1,7 +1,8 @@
 //! Structural editing for ast using `SyntaxEditor`
 
 use crate::{
-    Direction, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T,
+    AstToken, Direction, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T,
+    algo::neighbor,
     ast::{
         self, AstNode, Fn, GenericParam, HasGenericParams, HasName, edit::IndentLevel, make,
         syntax_factory::SyntaxFactory,
@@ -143,6 +144,53 @@ fn normalize_ws_between_braces(editor: &mut SyntaxEditor, node: &SyntaxNode) ->
     Some(())
 }
 
+pub trait Removable: AstNode {
+    fn remove(&self, editor: &mut SyntaxEditor);
+}
+
+impl Removable for ast::Use {
+    fn remove(&self, editor: &mut SyntaxEditor) {
+        let make = SyntaxFactory::without_mappings();
+
+        let next_ws = self
+            .syntax()
+            .next_sibling_or_token()
+            .and_then(|it| it.into_token())
+            .and_then(ast::Whitespace::cast);
+        if let Some(next_ws) = next_ws {
+            let ws_text = next_ws.syntax().text();
+            if let Some(rest) = ws_text.strip_prefix('\n') {
+                if rest.is_empty() {
+                    editor.delete(next_ws.syntax());
+                } else {
+                    editor.replace(next_ws.syntax(), make.whitespace(rest));
+                }
+            }
+        }
+
+        editor.delete(self.syntax());
+    }
+}
+
+impl Removable for ast::UseTree {
+    fn remove(&self, editor: &mut SyntaxEditor) {
+        for dir in [Direction::Next, Direction::Prev] {
+            if let Some(next_use_tree) = neighbor(self, dir) {
+                let separators = self
+                    .syntax()
+                    .siblings_with_tokens(dir)
+                    .skip(1)
+                    .take_while(|it| it.as_node() != Some(next_use_tree.syntax()));
+                for sep in separators {
+                    editor.delete(sep);
+                }
+                break;
+            }
+        }
+        editor.delete(self.syntax());
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use parser::Edition;
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index 2f379d419e8..f6ca5ab6c8c 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -353,7 +353,7 @@ impl ChangeFixture {
                 )]),
                 CrateOrigin::Local { repo: None, name: None },
                 true,
-                proc_macro_cwd.clone(),
+                proc_macro_cwd,
                 crate_ws_data,
             );
             proc_macros.insert(proc_macros_crate, Ok(proc_macro));
diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs
index 36ccb67f3b8..1dbc07c0929 100644
--- a/src/tools/rust-analyzer/crates/tt/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs
@@ -728,9 +728,9 @@ fn print_debug_subtree<S: fmt::Debug>(
     };
 
     write!(f, "{align}SUBTREE {delim} ",)?;
-    write!(f, "{:#?}", open)?;
+    write!(f, "{open:#?}")?;
     write!(f, " ")?;
-    write!(f, "{:#?}", close)?;
+    write!(f, "{close:#?}")?;
     for child in iter {
         writeln!(f)?;
         print_debug_token(f, level + 1, child)?;
@@ -855,7 +855,7 @@ impl<S> fmt::Display for Literal<S> {
             }
         }?;
         if let Some(suffix) = &self.suffix {
-            write!(f, "{}", suffix)?;
+            write!(f, "{suffix}")?;
         }
         Ok(())
     }
diff --git a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs
index e918fd0887d..a03337dbc51 100644
--- a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs
@@ -38,8 +38,7 @@ impl loader::Handle for NotifyHandle {
     fn spawn(sender: loader::Sender) -> NotifyHandle {
         let actor = NotifyActor::new(sender);
         let (sender, receiver) = unbounded::<Message>();
-        let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
-            .name("VfsLoader".to_owned())
+        let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker, "VfsLoader")
             .spawn(move || actor.run(receiver))
             .expect("failed to spawn thread");
         NotifyHandle { sender, _thread: thread }
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index 09c127f6bcd..90e4d65bf96 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-21079f53a359d9fc82668d4175d49dafdb600563
+6e23095adf9209614a45f7f75fea36dad7b92afb
diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
index 82df78c1a89..4b9c6edbe30 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
@@ -414,7 +414,7 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
         .map(|kind| to_pascal_case(kind))
         .filter(|name| !defined_nodes.iter().any(|&it| it == name))
     {
-        eprintln!("Warning: node {} not defined in AST source", node);
+        eprintln!("Warning: node {node} not defined in AST source");
         drop(node);
     }
 
diff --git a/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs b/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs
index f3b786b9d86..ae53771fe8e 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/parser_inline_tests.rs
@@ -159,7 +159,7 @@ fn collect_tests(s: &str) -> Vec<Test> {
                 (name.to_owned(), Some(edition.to_owned()))
             }
             [name] => (name.to_owned(), None),
-            _ => panic!("invalid test name: {:?}", name),
+            _ => panic!("invalid test name: {name:?}"),
         };
         let text: String = edition
             .as_ref()
@@ -212,7 +212,7 @@ fn existing_tests(dir: &Path, ok: TestKind) -> Result<HashMap<String, (PathBuf,
                 text.lines().next().and_then(|it| it.strip_prefix("// ")).map(ToOwned::to_owned);
             let test = Test { name: name.clone(), text, kind: ok, edition };
             if let Some(old) = res.insert(name, (path, test)) {
-                println!("Duplicate test: {:?}", old);
+                println!("Duplicate test: {old:?}");
             }
         }
     }
diff --git a/src/tools/rust-analyzer/xtask/src/dist.rs b/src/tools/rust-analyzer/xtask/src/dist.rs
index b3d6f06b073..dbfecdbe112 100644
--- a/src/tools/rust-analyzer/xtask/src/dist.rs
+++ b/src/tools/rust-analyzer/xtask/src/dist.rs
@@ -1,9 +1,6 @@
 use anyhow::Context;
 use flate2::{Compression, write::GzEncoder};
-use std::env::consts::EXE_EXTENSION;
-use std::ffi::OsStr;
 use std::{
-    env,
     fs::File,
     io::{self, BufWriter},
     path::{Path, PathBuf},
@@ -12,11 +9,11 @@ use time::OffsetDateTime;
 use xshell::{Cmd, Shell, cmd};
 use zip::{DateTime, ZipWriter, write::SimpleFileOptions};
 
-use crate::flags::PgoTrainingCrate;
 use crate::{
     date_iso,
-    flags::{self, Malloc},
+    flags::{self, Malloc, PgoTrainingCrate},
     project_root,
+    util::detect_target,
 };
 
 const VERSION_STABLE: &str = "0.3";
@@ -28,7 +25,7 @@ impl flags::Dist {
         let stable = sh.var("GITHUB_REF").unwrap_or_default().as_str() == "refs/heads/release";
 
         let project_root = project_root();
-        let target = Target::get(&project_root);
+        let target = Target::get(&project_root, sh);
         let allocator = self.allocator();
         let dist = project_root.join("dist");
         sh.remove_path(&dist)?;
@@ -113,9 +110,9 @@ fn dist_server(
     let command = if linux_target && zig { "zigbuild" } else { "build" };
 
     let pgo_profile = if let Some(train_crate) = pgo {
-        Some(gather_pgo_profile(
+        Some(crate::pgo::gather_pgo_profile(
             sh,
-            build_command(sh, command, &target_name, features),
+            crate::pgo::build_command(sh, command, &target_name, features),
             &target_name,
             train_crate,
         )?)
@@ -151,85 +148,6 @@ fn build_command<'a>(
     )
 }
 
-/// Decorates `ra_build_cmd` to add PGO instrumentation, and then runs the PGO instrumented
-/// Rust Analyzer on itself to gather a PGO profile.
-fn gather_pgo_profile<'a>(
-    sh: &'a Shell,
-    ra_build_cmd: Cmd<'a>,
-    target: &str,
-    train_crate: PgoTrainingCrate,
-) -> anyhow::Result<PathBuf> {
-    let pgo_dir = std::path::absolute("rust-analyzer-pgo")?;
-    // Clear out any stale profiles
-    if pgo_dir.is_dir() {
-        std::fs::remove_dir_all(&pgo_dir)?;
-    }
-    std::fs::create_dir_all(&pgo_dir)?;
-
-    // Figure out a path to `llvm-profdata`
-    let target_libdir = cmd!(sh, "rustc --print=target-libdir")
-        .read()
-        .context("cannot resolve target-libdir from rustc")?;
-    let target_bindir = PathBuf::from(target_libdir).parent().unwrap().join("bin");
-    let llvm_profdata = target_bindir.join("llvm-profdata").with_extension(EXE_EXTENSION);
-
-    // Build RA with PGO instrumentation
-    let cmd_gather =
-        ra_build_cmd.env("RUSTFLAGS", format!("-Cprofile-generate={}", pgo_dir.to_str().unwrap()));
-    cmd_gather.run().context("cannot build rust-analyzer with PGO instrumentation")?;
-
-    let (train_path, label) = match &train_crate {
-        PgoTrainingCrate::RustAnalyzer => (PathBuf::from("."), "itself"),
-        PgoTrainingCrate::GitHub(repo) => {
-            (download_crate_for_training(sh, &pgo_dir, repo)?, repo.as_str())
-        }
-    };
-
-    // Run RA either on itself or on a downloaded crate
-    eprintln!("Training RA on {label}...");
-    cmd!(
-        sh,
-        "target/{target}/release/rust-analyzer analysis-stats -q --run-all-ide-things {train_path}"
-    )
-    .run()
-    .context("cannot generate PGO profiles")?;
-
-    // Merge profiles into a single file
-    let merged_profile = pgo_dir.join("merged.profdata");
-    let profile_files = std::fs::read_dir(pgo_dir)?.filter_map(|entry| {
-        let entry = entry.ok()?;
-        if entry.path().extension() == Some(OsStr::new("profraw")) {
-            Some(entry.path().to_str().unwrap().to_owned())
-        } else {
-            None
-        }
-    });
-    cmd!(sh, "{llvm_profdata} merge {profile_files...} -o {merged_profile}").run().context(
-        "cannot merge PGO profiles. Do you have the rustup `llvm-tools` component installed?",
-    )?;
-
-    Ok(merged_profile)
-}
-
-/// Downloads a crate from GitHub, stores it into `pgo_dir` and returns a path to it.
-fn download_crate_for_training(sh: &Shell, pgo_dir: &Path, repo: &str) -> anyhow::Result<PathBuf> {
-    let mut it = repo.splitn(2, '@');
-    let repo = it.next().unwrap();
-    let revision = it.next();
-
-    // FIXME: switch to `--revision` here around 2035 or so
-    let revision =
-        if let Some(revision) = revision { &["--branch", revision] as &[&str] } else { &[] };
-
-    let normalized_path = repo.replace("/", "-");
-    let target_path = pgo_dir.join(normalized_path);
-    cmd!(sh, "git clone --depth 1 https://github.com/{repo} {revision...} {target_path}")
-        .run()
-        .with_context(|| "cannot download PGO training crate from {repo}")?;
-
-    Ok(target_path)
-}
-
 fn gzip(src_path: &Path, dest_path: &Path) -> anyhow::Result<()> {
     let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best());
     let mut input = io::BufReader::new(File::open(src_path)?);
@@ -283,21 +201,8 @@ struct Target {
 }
 
 impl Target {
-    fn get(project_root: &Path) -> Self {
-        let name = match env::var("RA_TARGET") {
-            Ok(target) => target,
-            _ => {
-                if cfg!(target_os = "linux") {
-                    "x86_64-unknown-linux-gnu".to_owned()
-                } else if cfg!(target_os = "windows") {
-                    "x86_64-pc-windows-msvc".to_owned()
-                } else if cfg!(target_os = "macos") {
-                    "x86_64-apple-darwin".to_owned()
-                } else {
-                    panic!("Unsupported OS, maybe try setting RA_TARGET")
-                }
-            }
-        };
+    fn get(project_root: &Path, sh: &Shell) -> Self {
+        let name = detect_target(sh);
         let (name, libc_suffix) = match name.split_once('.') {
             Some((l, r)) => (l.to_owned(), Some(r.to_owned())),
             None => (name, None),
diff --git a/src/tools/rust-analyzer/xtask/src/flags.rs b/src/tools/rust-analyzer/xtask/src/flags.rs
index 700806d178c..2fd471b35c7 100644
--- a/src/tools/rust-analyzer/xtask/src/flags.rs
+++ b/src/tools/rust-analyzer/xtask/src/flags.rs
@@ -4,6 +4,25 @@ use std::{fmt, str::FromStr};
 
 use crate::install::{ClientOpt, ProcMacroServerOpt, ServerOpt};
 
+#[derive(Debug, Clone)]
+pub enum PgoTrainingCrate {
+    // Use RA's own sources for PGO training
+    RustAnalyzer,
+    // Download a Rust crate from `https://github.com/{0}` and use it for PGO training.
+    GitHub(String),
+}
+
+impl FromStr for PgoTrainingCrate {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "rust-analyzer" => Ok(Self::RustAnalyzer),
+            url => Ok(Self::GitHub(url.to_owned())),
+        }
+    }
+}
+
 xflags::xflags! {
     src "./src/flags.rs"
 
@@ -29,6 +48,9 @@ xflags::xflags! {
 
             /// build in release with debug info set to 2.
             optional --dev-rel
+
+            /// Apply PGO optimizations
+            optional --pgo pgo: PgoTrainingCrate
         }
 
         cmd fuzz-tests {}
@@ -110,17 +132,15 @@ pub enum XtaskCmd {
 }
 
 #[derive(Debug)]
-pub struct Tidy {}
-
-#[derive(Debug)]
 pub struct Install {
     pub client: bool,
     pub code_bin: Option<String>,
     pub server: bool,
-    pub proc_macro_server: bool,
     pub mimalloc: bool,
     pub jemalloc: bool,
+    pub proc_macro_server: bool,
     pub dev_rel: bool,
+    pub pgo: Option<PgoTrainingCrate>,
 }
 
 #[derive(Debug)]
@@ -144,25 +164,6 @@ pub struct RustcPush {
 }
 
 #[derive(Debug)]
-pub enum PgoTrainingCrate {
-    // Use RA's own sources for PGO training
-    RustAnalyzer,
-    // Download a Rust crate from `https://github.com/{0}` and use it for PGO training.
-    GitHub(String),
-}
-
-impl FromStr for PgoTrainingCrate {
-    type Err = String;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "rust-analyzer" => Ok(Self::RustAnalyzer),
-            url => Ok(Self::GitHub(url.to_owned())),
-        }
-    }
-}
-
-#[derive(Debug)]
 pub struct Dist {
     pub mimalloc: bool,
     pub jemalloc: bool,
@@ -195,6 +196,9 @@ pub struct Codegen {
     pub check: bool,
 }
 
+#[derive(Debug)]
+pub struct Tidy;
+
 impl Xtask {
     #[allow(dead_code)]
     pub fn from_env_or_exit() -> Self {
@@ -324,7 +328,7 @@ impl Install {
         } else {
             Malloc::System
         };
-        Some(ServerOpt { malloc, dev_rel: self.dev_rel })
+        Some(ServerOpt { malloc, dev_rel: self.dev_rel, pgo: self.pgo.clone() })
     }
     pub(crate) fn proc_macro_server(&self) -> Option<ProcMacroServerOpt> {
         if !self.proc_macro_server {
diff --git a/src/tools/rust-analyzer/xtask/src/install.rs b/src/tools/rust-analyzer/xtask/src/install.rs
index 4e2093f0691..f0cc445dfa2 100644
--- a/src/tools/rust-analyzer/xtask/src/install.rs
+++ b/src/tools/rust-analyzer/xtask/src/install.rs
@@ -5,7 +5,10 @@ use std::{env, path::PathBuf, str};
 use anyhow::{Context, bail, format_err};
 use xshell::{Shell, cmd};
 
-use crate::flags::{self, Malloc};
+use crate::{
+    flags::{self, Malloc, PgoTrainingCrate},
+    util::detect_target,
+};
 
 impl flags::Install {
     pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
@@ -35,6 +38,7 @@ const VS_CODES: &[&str] = &["code", "code-exploration", "code-insiders", "codium
 pub(crate) struct ServerOpt {
     pub(crate) malloc: Malloc,
     pub(crate) dev_rel: bool,
+    pub(crate) pgo: Option<PgoTrainingCrate>,
 }
 
 pub(crate) struct ProcMacroServerOpt {
@@ -135,21 +139,33 @@ fn install_server(sh: &Shell, opts: ServerOpt) -> anyhow::Result<()> {
     let features = opts.malloc.to_features();
     let profile = if opts.dev_rel { "dev-rel" } else { "release" };
 
-    let cmd = cmd!(
+    let mut install_cmd = cmd!(
         sh,
         "cargo install --path crates/rust-analyzer --profile={profile} --locked --force --features force-always-assert {features...}"
     );
-    cmd.run()?;
+
+    if let Some(train_crate) = opts.pgo {
+        let build_cmd = cmd!(
+            sh,
+            "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --profile={profile} --locked --features force-always-assert {features...}"
+        );
+
+        let target = detect_target(sh);
+        let profile = crate::pgo::gather_pgo_profile(sh, build_cmd, &target, train_crate)?;
+        install_cmd = crate::pgo::apply_pgo_to_cmd(install_cmd, &profile);
+    }
+
+    install_cmd.run()?;
     Ok(())
 }
 
 fn install_proc_macro_server(sh: &Shell, opts: ProcMacroServerOpt) -> anyhow::Result<()> {
     let profile = if opts.dev_rel { "dev-rel" } else { "release" };
 
-    let cmd = cmd!(
+    cmd!(
         sh,
         "cargo +nightly install --path crates/proc-macro-srv-cli --profile={profile} --locked --force --features sysroot-abi"
-    );
-    cmd.run()?;
+    ).run()?;
+
     Ok(())
 }
diff --git a/src/tools/rust-analyzer/xtask/src/main.rs b/src/tools/rust-analyzer/xtask/src/main.rs
index 52ea896c734..aaa8d0e1d4d 100644
--- a/src/tools/rust-analyzer/xtask/src/main.rs
+++ b/src/tools/rust-analyzer/xtask/src/main.rs
@@ -22,6 +22,7 @@ mod codegen;
 mod dist;
 mod install;
 mod metrics;
+mod pgo;
 mod publish;
 mod release;
 mod tidy;
diff --git a/src/tools/rust-analyzer/xtask/src/pgo.rs b/src/tools/rust-analyzer/xtask/src/pgo.rs
new file mode 100644
index 00000000000..7f7b3311d96
--- /dev/null
+++ b/src/tools/rust-analyzer/xtask/src/pgo.rs
@@ -0,0 +1,105 @@
+//! PGO (Profile-Guided Optimization) utilities.
+
+use anyhow::Context;
+use std::env::consts::EXE_EXTENSION;
+use std::ffi::OsStr;
+use std::path::{Path, PathBuf};
+use xshell::{Cmd, Shell, cmd};
+
+use crate::flags::PgoTrainingCrate;
+
+/// Decorates `ra_build_cmd` to add PGO instrumentation, and then runs the PGO instrumented
+/// Rust Analyzer on itself to gather a PGO profile.
+pub(crate) fn gather_pgo_profile<'a>(
+    sh: &'a Shell,
+    ra_build_cmd: Cmd<'a>,
+    target: &str,
+    train_crate: PgoTrainingCrate,
+) -> anyhow::Result<PathBuf> {
+    let pgo_dir = std::path::absolute("rust-analyzer-pgo")?;
+    // Clear out any stale profiles
+    if pgo_dir.is_dir() {
+        std::fs::remove_dir_all(&pgo_dir)?;
+    }
+    std::fs::create_dir_all(&pgo_dir)?;
+
+    // Figure out a path to `llvm-profdata`
+    let target_libdir = cmd!(sh, "rustc --print=target-libdir")
+        .read()
+        .context("cannot resolve target-libdir from rustc")?;
+    let target_bindir = PathBuf::from(target_libdir).parent().unwrap().join("bin");
+    let llvm_profdata = target_bindir.join("llvm-profdata").with_extension(EXE_EXTENSION);
+
+    // Build RA with PGO instrumentation
+    let cmd_gather =
+        ra_build_cmd.env("RUSTFLAGS", format!("-Cprofile-generate={}", pgo_dir.to_str().unwrap()));
+    cmd_gather.run().context("cannot build rust-analyzer with PGO instrumentation")?;
+
+    let (train_path, label) = match &train_crate {
+        PgoTrainingCrate::RustAnalyzer => (PathBuf::from("."), "itself"),
+        PgoTrainingCrate::GitHub(repo) => {
+            (download_crate_for_training(sh, &pgo_dir, repo)?, repo.as_str())
+        }
+    };
+
+    // Run RA either on itself or on a downloaded crate
+    eprintln!("Training RA on {label}...");
+    cmd!(
+        sh,
+        "target/{target}/release/rust-analyzer analysis-stats -q --run-all-ide-things {train_path}"
+    )
+    .run()
+    .context("cannot generate PGO profiles")?;
+
+    // Merge profiles into a single file
+    let merged_profile = pgo_dir.join("merged.profdata");
+    let profile_files = std::fs::read_dir(pgo_dir)?.filter_map(|entry| {
+        let entry = entry.ok()?;
+        if entry.path().extension() == Some(OsStr::new("profraw")) {
+            Some(entry.path().to_str().unwrap().to_owned())
+        } else {
+            None
+        }
+    });
+    cmd!(sh, "{llvm_profdata} merge {profile_files...} -o {merged_profile}").run().context(
+        "cannot merge PGO profiles. Do you have the rustup `llvm-tools` component installed?",
+    )?;
+
+    Ok(merged_profile)
+}
+
+/// Downloads a crate from GitHub, stores it into `pgo_dir` and returns a path to it.
+fn download_crate_for_training(sh: &Shell, pgo_dir: &Path, repo: &str) -> anyhow::Result<PathBuf> {
+    let mut it = repo.splitn(2, '@');
+    let repo = it.next().unwrap();
+    let revision = it.next();
+
+    // FIXME: switch to `--revision` here around 2035 or so
+    let revision =
+        if let Some(revision) = revision { &["--branch", revision] as &[&str] } else { &[] };
+
+    let normalized_path = repo.replace("/", "-");
+    let target_path = pgo_dir.join(normalized_path);
+    cmd!(sh, "git clone --depth 1 https://github.com/{repo} {revision...} {target_path}")
+        .run()
+        .with_context(|| "cannot download PGO training crate from {repo}")?;
+
+    Ok(target_path)
+}
+
+/// Helper function to create a build command for rust-analyzer
+pub(crate) fn build_command<'a>(
+    sh: &'a Shell,
+    command: &str,
+    target_name: &str,
+    features: &[&str],
+) -> Cmd<'a> {
+    cmd!(
+        sh,
+        "cargo {command} --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} {features...} --release"
+    )
+}
+
+pub(crate) fn apply_pgo_to_cmd<'a>(cmd: Cmd<'a>, profile_path: &Path) -> Cmd<'a> {
+    cmd.env("RUSTFLAGS", format!("-Cprofile-use={}", profile_path.to_str().unwrap()))
+}
diff --git a/src/tools/rust-analyzer/xtask/src/util.rs b/src/tools/rust-analyzer/xtask/src/util.rs
index 39f52938c8c..e5404d57171 100644
--- a/src/tools/rust-analyzer/xtask/src/util.rs
+++ b/src/tools/rust-analyzer/xtask/src/util.rs
@@ -1,5 +1,7 @@
 use std::path::{Path, PathBuf};
 
+use xshell::{Shell, cmd};
+
 pub(crate) fn list_rust_files(dir: &Path) -> Vec<PathBuf> {
     let mut res = list_files(dir);
     res.retain(|it| {
@@ -29,3 +31,13 @@ pub(crate) fn list_files(dir: &Path) -> Vec<PathBuf> {
     }
     res
 }
+
+pub(crate) fn detect_target(sh: &Shell) -> String {
+    match std::env::var("RA_TARGET") {
+        Ok(target) => target,
+        _ => match cmd!(sh, "rustc --print=host-tuple").read() {
+            Ok(target) => target,
+            Err(e) => panic!("Failed to detect target: {e}\nPlease set RA_TARGET explicitly"),
+        },
+    }
+}
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff
index f36157a762c..39ba480d203 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff
@@ -8,9 +8,9 @@
       let mut _3: u16;
       let mut _4: u32;
 +     scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
-+         let mut _5: bool;
-+         let _6: ();
++         let _5: ();
 +         scope 2 (inlined core::ub_checks::check_language_ub) {
++             let mut _6: bool;
 +             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
 +             }
 +         }
@@ -22,20 +22,20 @@
           StorageLive(_4);
           _4 = copy _2;
 -         _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable];
-+         StorageLive(_6);
 +         StorageLive(_5);
-+         _5 = UbChecks();
-+         switchInt(move _5) -> [0: bb2, otherwise: bb1];
++         StorageLive(_6);
++         _6 = UbChecks();
++         switchInt(copy _6) -> [0: bb2, otherwise: bb1];
       }
   
       bb1: {
-+         _6 = core::num::<impl u16>::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable];
++         _5 = core::num::<impl u16>::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable];
 +     }
 + 
 +     bb2: {
-+         StorageDead(_5);
 +         _0 = ShlUnchecked(copy _3, copy _4);
 +         StorageDead(_6);
++         StorageDead(_5);
           StorageDead(_4);
           StorageDead(_3);
           return;
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff
index be1b066c6c1..5a758d35740 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff
@@ -8,9 +8,9 @@
       let mut _3: u16;
       let mut _4: u32;
 +     scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
-+         let mut _5: bool;
-+         let _6: ();
++         let _5: ();
 +         scope 2 (inlined core::ub_checks::check_language_ub) {
++             let mut _6: bool;
 +             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
 +             }
 +         }
@@ -22,20 +22,20 @@
           StorageLive(_4);
           _4 = copy _2;
 -         _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> [return: bb1, unwind continue];
-+         StorageLive(_6);
 +         StorageLive(_5);
-+         _5 = UbChecks();
-+         switchInt(move _5) -> [0: bb2, otherwise: bb1];
++         StorageLive(_6);
++         _6 = UbChecks();
++         switchInt(copy _6) -> [0: bb2, otherwise: bb1];
       }
   
       bb1: {
-+         _6 = core::num::<impl u16>::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable];
++         _5 = core::num::<impl u16>::unchecked_shl::precondition_check(copy _4) -> [return: bb2, unwind unreachable];
 +     }
 + 
 +     bb2: {
-+         StorageDead(_5);
 +         _0 = ShlUnchecked(copy _3, copy _4);
 +         StorageDead(_6);
++         StorageDead(_5);
           StorageDead(_4);
           StorageDead(_3);
           return;
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff
index 360687f3c4e..a0caf141f2d 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff
@@ -8,9 +8,9 @@
       let mut _3: i64;
       let mut _4: u32;
 +     scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
-+         let mut _5: bool;
-+         let _6: ();
++         let _5: ();
 +         scope 2 (inlined core::ub_checks::check_language_ub) {
++             let mut _6: bool;
 +             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
 +             }
 +         }
@@ -22,20 +22,20 @@
           StorageLive(_4);
           _4 = copy _2;
 -         _0 = core::num::<impl i64>::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable];
-+         StorageLive(_6);
 +         StorageLive(_5);
-+         _5 = UbChecks();
-+         switchInt(move _5) -> [0: bb2, otherwise: bb1];
++         StorageLive(_6);
++         _6 = UbChecks();
++         switchInt(copy _6) -> [0: bb2, otherwise: bb1];
       }
   
       bb1: {
-+         _6 = core::num::<impl i64>::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable];
++         _5 = core::num::<impl i64>::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable];
 +     }
 + 
 +     bb2: {
-+         StorageDead(_5);
 +         _0 = ShrUnchecked(copy _3, copy _4);
 +         StorageDead(_6);
++         StorageDead(_5);
           StorageDead(_4);
           StorageDead(_3);
           return;
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff
index 986df55df03..633089e7b2a 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff
@@ -8,9 +8,9 @@
       let mut _3: i64;
       let mut _4: u32;
 +     scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
-+         let mut _5: bool;
-+         let _6: ();
++         let _5: ();
 +         scope 2 (inlined core::ub_checks::check_language_ub) {
++             let mut _6: bool;
 +             scope 3 (inlined core::ub_checks::check_language_ub::runtime) {
 +             }
 +         }
@@ -22,20 +22,20 @@
           StorageLive(_4);
           _4 = copy _2;
 -         _0 = core::num::<impl i64>::unchecked_shr(move _3, move _4) -> [return: bb1, unwind continue];
-+         StorageLive(_6);
 +         StorageLive(_5);
-+         _5 = UbChecks();
-+         switchInt(move _5) -> [0: bb2, otherwise: bb1];
++         StorageLive(_6);
++         _6 = UbChecks();
++         switchInt(copy _6) -> [0: bb2, otherwise: bb1];
       }
   
       bb1: {
-+         _6 = core::num::<impl i64>::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable];
++         _5 = core::num::<impl i64>::unchecked_shr::precondition_check(copy _4) -> [return: bb2, unwind unreachable];
 +     }
 + 
 +     bb2: {
-+         StorageDead(_5);
 +         _0 = ShrUnchecked(copy _3, copy _4);
 +         StorageDead(_6);
++         StorageDead(_5);
           StorageDead(_4);
           StorageDead(_3);
           return;
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
index 28878736ed7..a5986a4315a 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
@@ -10,9 +10,9 @@
 +         scope 2 {
 +         }
 +         scope 3 (inlined unreachable_unchecked) {
-+             let mut _4: bool;
-+             let _5: ();
++             let _4: ();
 +             scope 4 (inlined core::ub_checks::check_language_ub) {
++                 let mut _5: bool;
 +                 scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
 +                 }
 +             }
@@ -24,7 +24,7 @@
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
 +         StorageLive(_3);
-+         StorageLive(_5);
++         StorageLive(_4);
 +         _3 = discriminant(_2);
 +         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
       }
@@ -34,15 +34,15 @@
 +     }
 + 
 +     bb2: {
-+         StorageLive(_4);
-+         _4 = UbChecks();
-+         assume(copy _4);
-+         _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable];
++         StorageLive(_5);
++         _5 = UbChecks();
++         assume(copy _5);
++         _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable];
 +     }
 + 
 +     bb3: {
 +         _0 = move ((_2 as Some).0: T);
-+         StorageDead(_5);
++         StorageDead(_4);
 +         StorageDead(_3);
           StorageDead(_2);
           return;
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
index 27b6bb6a5bb..12b03a6b6d9 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
@@ -10,9 +10,9 @@
 +         scope 2 {
 +         }
 +         scope 3 (inlined unreachable_unchecked) {
-+             let mut _4: bool;
-+             let _5: ();
++             let _4: ();
 +             scope 4 (inlined core::ub_checks::check_language_ub) {
++                 let mut _5: bool;
 +                 scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
 +                 }
 +             }
@@ -24,7 +24,7 @@
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
 +         StorageLive(_3);
-+         StorageLive(_5);
++         StorageLive(_4);
 +         _3 = discriminant(_2);
 +         switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
       }
@@ -38,15 +38,15 @@
 -     bb2 (cleanup): {
 -         resume;
 +     bb2: {
-+         StorageLive(_4);
-+         _4 = UbChecks();
-+         assume(copy _4);
-+         _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable];
++         StorageLive(_5);
++         _5 = UbChecks();
++         assume(copy _5);
++         _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable];
 +     }
 + 
 +     bb3: {
 +         _0 = move ((_2 as Some).0: T);
-+         StorageDead(_5);
++         StorageDead(_4);
 +         StorageDead(_3);
 +         StorageDead(_2);
 +         return;
diff --git a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
index 5fee9a6733d..82353a2d540 100644
--- a/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
+++ b/tests/mir-opt/instsimplify/ub_check.unwrap_unchecked.InstSimplify-after-simplifycfg.diff
@@ -10,9 +10,9 @@
           scope 2 {
           }
           scope 3 (inlined unreachable_unchecked) {
-              let mut _4: bool;
-              let _5: ();
+              let _4: ();
               scope 4 (inlined core::ub_checks::check_language_ub) {
+                  let mut _5: bool;
                   scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
                   }
               }
@@ -23,7 +23,7 @@
           StorageLive(_2);
           _2 = copy _1;
           StorageLive(_3);
-          StorageLive(_5);
+          StorageLive(_4);
           _3 = discriminant(_2);
           switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
       }
@@ -33,16 +33,16 @@
       }
   
       bb2: {
-          StorageLive(_4);
--         _4 = UbChecks();
-+         _4 = const false;
-          assume(copy _4);
-          _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable];
+          StorageLive(_5);
+-         _5 = UbChecks();
++         _5 = const false;
+          assume(copy _5);
+          _4 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable];
       }
   
       bb3: {
           _0 = move ((_2 as Some).0: i32);
-          StorageDead(_5);
+          StorageDead(_4);
           StorageDead(_3);
           StorageDead(_2);
           return;
diff --git a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
index 1ab9be96652..d8eace98d55 100644
--- a/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
+++ b/tests/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
@@ -5,23 +5,18 @@
       debug bytes => _1;
       let mut _0: std::option::Option<[u8; 4]>;
       let _2: [u32; 4];
-      let mut _3: [u8; 16];
-      let mut _5: [u8; 4];
-      let mut _6: u32;
+      let mut _4: [u8; 4];
       scope 1 {
           debug dwords => _2;
           scope 2 {
-              debug ip => _4;
-              let _4: u32;
+              debug ip => _3;
+              let _3: u32;
           }
       }
   
       bb0: {
           StorageLive(_2);
-          StorageLive(_3);
-          _3 = copy _1;
-          _2 = move _3 as [u32; 4] (Transmute);
-          StorageDead(_3);
+          _2 = copy _1 as [u32; 4] (Transmute);
           switchInt(copy _2[0 of 4]) -> [0: bb1, otherwise: bb4];
       }
   
@@ -34,15 +29,10 @@
       }
   
       bb3: {
+          _3 = copy _2[3 of 4];
           StorageLive(_4);
-          _4 = copy _2[3 of 4];
-          StorageLive(_5);
-          StorageLive(_6);
-          _6 = copy _4;
-          _5 = move _6 as [u8; 4] (Transmute);
-          StorageDead(_6);
-          _0 = Option::<[u8; 4]>::Some(move _5);
-          StorageDead(_5);
+          _4 = copy _3 as [u8; 4] (Transmute);
+          _0 = Option::<[u8; 4]>::Some(move _4);
           StorageDead(_4);
           goto -> bb5;
       }
diff --git a/tests/mir-opt/pre-codegen/matchbr.match1.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/matchbr.match1.PreCodegen.after.mir
new file mode 100644
index 00000000000..3a202728ea9
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/matchbr.match1.PreCodegen.after.mir
@@ -0,0 +1,13 @@
+// MIR for `match1` after PreCodegen
+
+fn match1(_1: bool, _2: i32, _3: i32) -> i32 {
+    debug c => _1;
+    debug v1 => _2;
+    debug v2 => _3;
+    let mut _0: i32;
+
+    bb0: {
+        _0 = Sub(copy _2, copy _3);
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/matchbr.rs b/tests/mir-opt/pre-codegen/matchbr.rs
new file mode 100644
index 00000000000..1822739da2c
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/matchbr.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+
+// EMIT_MIR matchbr.match1.PreCodegen.after.mir
+pub fn match1(c: bool, v1: i32, v2: i32) -> i32 {
+    // CHECK-LABEL: fn match1(
+    // CHECK: bb0:
+    // CHECK-NEXT: _0 = Sub
+    // CHECK-NEXT: return;
+    if c { v1 - v2 } else { v1 - v2 }
+}
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
index c363dfcbf70..ff1bc58524b 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
+++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff
@@ -8,6 +8,9 @@
       let mut _3: std::option::Option<T>;
       let mut _4: isize;
       let mut _5: isize;
+-     let mut _7: bool;
+-     let mut _8: u8;
+-     let mut _9: bool;
       scope 1 {
           debug a => _6;
           let _6: u8;
@@ -32,9 +35,7 @@
       }
   
       bb2: {
-          StorageLive(_6);
           _6 = copy (((_1.0: std::option::Option<u8>) as Some).0: u8);
-          StorageDead(_6);
           goto -> bb3;
       }
   
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
index 895b0067d2e..2c289c66475 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
+++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff
@@ -8,6 +8,9 @@
       let mut _3: std::option::Option<T>;
       let mut _4: isize;
       let mut _5: isize;
+-     let mut _7: bool;
+-     let mut _8: u8;
+-     let mut _9: bool;
       scope 1 {
           debug a => _6;
           let _6: u8;
@@ -32,9 +35,7 @@
       }
   
       bb2: {
-          StorageLive(_6);
           _6 = copy (((_1.0: std::option::Option<u8>) as Some).0: u8);
-          StorageDead(_6);
           goto -> bb3;
       }
   
diff --git a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
index 755bec8747b..bb95bedf973 100644
--- a/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
+++ b/tests/ui-fulldeps/stable-mir/check_assoc_items.rs
@@ -17,13 +17,13 @@ extern crate rustc_driver;
 extern crate rustc_interface;
 extern crate stable_mir;
 
-use std::io::Write;
 use std::collections::HashSet;
-use stable_mir::CrateDef;
-use stable_mir::*;
-use stable_mir::ty::*;
+use std::io::Write;
 use std::ops::ControlFlow;
 
+use stable_mir::ty::*;
+use stable_mir::{CrateDef, *};
+
 const CRATE_NAME: &str = "crate_assoc_items";
 
 /// This function uses the Stable MIR APIs to get information about the test crate.
@@ -45,30 +45,30 @@ fn test_assoc_items() -> ControlFlow<()> {
     let local_impls = local_crate.trait_impls();
     let local_traits = local_crate.trait_decls();
 
-    let trait_assoc_item_defs: Vec<AssocDef> = local_traits[0].associated_items()
-        .iter().map(|assoc_item| assoc_item.def_id).collect();
+    let trait_assoc_item_defs: Vec<AssocDef> =
+        local_traits[0].associated_items().iter().map(|assoc_item| assoc_item.def_id).collect();
     check_items(
         &trait_assoc_item_defs,
         &[
-            "ATrait::{anon_assoc#0}",
+            "ATrait::rpitit::{anon_assoc#0}",
             "ATrait::rpitit",
             "ATrait::Assoc",
             "ATrait::assoc_fn_no_self",
             "ATrait::assoc_fn_has_self",
-        ]
+        ],
     );
 
-    let impl_assoc_item_defs: Vec<AssocDef> = local_impls[0].associated_items()
-        .iter().map(|assoc_item| assoc_item.def_id).collect();
+    let impl_assoc_item_defs: Vec<AssocDef> =
+        local_impls[0].associated_items().iter().map(|assoc_item| assoc_item.def_id).collect();
     check_items(
         &impl_assoc_item_defs,
         &[
-            "<AStruct as ATrait>::{anon_assoc#0}",
+            "<AStruct as ATrait>::rpitit::{anon_assoc#0}",
             "<AStruct as ATrait>::rpitit",
             "<AStruct as ATrait>::Assoc",
             "<AStruct as ATrait>::assoc_fn_no_self",
             "<AStruct as ATrait>::assoc_fn_has_self",
-        ]
+        ],
     );
 
     ControlFlow::Continue(())
diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr
index cb14d9f459a..53d05c3db8c 100644
--- a/tests/ui/delegation/unsupported.stderr
+++ b/tests/ui/delegation/unsupported.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::opaque_ret::{anon_assoc#0}`
   --> $DIR/unsupported.rs:22:25
    |
 LL |         reuse to_reuse::opaque_ret;
@@ -9,7 +9,7 @@ note: ...which requires comparing an impl and trait method signature, inferring
    |
 LL |         reuse to_reuse::opaque_ret;
    |                         ^^^^^^^^^^
-   = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::{anon_assoc#0}`, completing the cycle
+   = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::opaque_ret::{anon_assoc#0}`, completing the cycle
 note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>` is well-formed
   --> $DIR/unsupported.rs:21:5
    |
@@ -17,7 +17,7 @@ LL |     impl ToReuse for u8 {
    |     ^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`
+error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::opaque_ret::{anon_assoc#0}`
   --> $DIR/unsupported.rs:25:24
    |
 LL |         reuse ToReuse::opaque_ret;
@@ -28,7 +28,7 @@ note: ...which requires comparing an impl and trait method signature, inferring
    |
 LL |         reuse ToReuse::opaque_ret;
    |                        ^^^^^^^^^^
-   = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::{anon_assoc#0}`, completing the cycle
+   = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::opaque_ret::{anon_assoc#0}`, completing the cycle
 note: cycle used when checking that `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>` is well-formed
   --> $DIR/unsupported.rs:24:5
    |
diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
index a9dfac274d5..119195f17ff 100644
--- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
+++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
@@ -6,11 +6,11 @@ LL |     fn bar() -> () {}
    |
    = help: the trait `std::fmt::Display` is not implemented for `()`
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
-note: required by a bound in `Foo::{anon_assoc#0}`
+note: required by a bound in `Foo::bar::{anon_assoc#0}`
   --> $DIR/doesnt-satisfy.rs:2:22
    |
 LL |     fn bar() -> impl std::fmt::Display;
-   |                      ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{anon_assoc#0}`
+   |                      ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{anon_assoc#0}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/in-trait/dump.rs b/tests/ui/impl-trait/in-trait/dump.rs
index da3cfd099b5..0a951b4fd99 100644
--- a/tests/ui/impl-trait/in-trait/dump.rs
+++ b/tests/ui/impl-trait/in-trait/dump.rs
@@ -8,7 +8,7 @@ trait Foo {
 }
 
 fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> {
-//~^ ERROR <T as Foo>::{anon_assoc#0}<'s/#1>
+    //~^ ERROR <T as Foo>::hello::{anon_assoc#0}<'s/#1>
     x.hello()
 }
 
diff --git a/tests/ui/impl-trait/in-trait/dump.stderr b/tests/ui/impl-trait/in-trait/dump.stderr
index 15b6f186ced..35ed21bde11 100644
--- a/tests/ui/impl-trait/in-trait/dump.stderr
+++ b/tests/ui/impl-trait/in-trait/dump.stderr
@@ -1,4 +1,4 @@
-error: <T as Foo>::{anon_assoc#0}<'s/#1>
+error: <T as Foo>::hello::{anon_assoc#0}<'s/#1>
   --> $DIR/dump.rs:10:35
    |
 LL | fn hello<'s, T: Foo>(x: &'s T) -> impl Sized + use<'s, T> {
diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr
index bf598d62709..5d651245746 100644
--- a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr
+++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.current.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
+error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`
   --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
    |
 LL |     fn foo(b: bool) -> impl Sized {
@@ -45,7 +45,7 @@ note: ...which requires type-checking `<impl at $DIR/method-compatability-via-le
    |
 LL |     fn foo(b: bool) -> impl Sized {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
+   = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`, completing the cycle
 note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
   --> $DIR/method-compatability-via-leakage-cycle.rs:17:1
    |
diff --git a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr
index 6bec5bbc063..4bbba62bd71 100644
--- a/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr
+++ b/tests/ui/impl-trait/in-trait/method-compatability-via-leakage-cycle.next.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
+error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`
   --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
    |
 LL |     fn foo(b: bool) -> impl Sized {
@@ -49,7 +49,7 @@ note: ...which requires type-checking `<impl at $DIR/method-compatability-via-le
    |
 LL |     fn foo(b: bool) -> impl Sized {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
+   = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`, completing the cycle
 note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
   --> $DIR/method-compatability-via-leakage-cycle.rs:17:1
    |
@@ -57,7 +57,7 @@ LL | impl Trait for u32 {
    | ^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`
+error[E0391]: cycle detected when computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`
   --> $DIR/method-compatability-via-leakage-cycle.rs:21:24
    |
 LL |     fn foo(b: bool) -> impl Sized {
@@ -108,7 +108,7 @@ note: ...which requires type-checking `<impl at $DIR/method-compatability-via-le
    |
 LL |     fn foo(b: bool) -> impl Sized {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::{anon_assoc#0}`, completing the cycle
+   = note: ...which again requires computing type of `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>::foo::{anon_assoc#0}`, completing the cycle
 note: cycle used when checking that `<impl at $DIR/method-compatability-via-leakage-cycle.rs:17:1: 17:19>` is well-formed
   --> $DIR/method-compatability-via-leakage-cycle.rs:17:1
    |
diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
index 6571ce2d5f0..a16e0160223 100644
--- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
+++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
@@ -14,11 +14,11 @@ LL |     fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
    |                                  ^^^^^^^^^^^^ the trait `Foo<char>` is not implemented for `impl Foo<u8>`
    |
    = help: the trait `Foo<char>` is implemented for `Bar`
-note: required by a bound in `Foo::{anon_assoc#0}`
+note: required by a bound in `Foo::foo::{anon_assoc#0}`
   --> $DIR/return-dont-satisfy-bounds.rs:2:30
    |
 LL |     fn foo<F2>(self) -> impl Foo<T>;
-   |                              ^^^^^^ required by this bound in `Foo::{anon_assoc#0}`
+   |                              ^^^^^^ required by this bound in `Foo::foo::{anon_assoc#0}`
 
 error[E0277]: the trait bound `Bar: Foo<u8>` is not satisfied
   --> $DIR/return-dont-satisfy-bounds.rs:8:34
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
index 400969c279e..99fd83e7b6f 100644
--- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
@@ -4,11 +4,11 @@ error[E0277]: the trait bound `Something: Termination` is not satisfied
 LL |         fn main() -> Something {
    |                      ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
    |
-note: required by a bound in `Main::{anon_assoc#0}`
+note: required by a bound in `Main::main::{anon_assoc#0}`
   --> $DIR/issue-103052-2.rs:3:27
    |
 LL |         fn main() -> impl std::process::Termination;
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{anon_assoc#0}`
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{anon_assoc#0}`
 
 error: aborting due to 1 previous error