Repository: rust-lang/rust-analyzer
Pull request #16747 (2024-03-04 10:11:48)

internal: Clean some stuff up
Just a bunch of small refactorings, mainly from browsing through `hir-def`


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 982468765b..f074bb4e30 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -71,7 +71,6 @@ version = "0.0.0"
 dependencies = [
  "cfg",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "profile",
  "rustc-hash",
  "salsa",
  "semver",
@@ -501,7 +500,6 @@ dependencies = [
  "hir-ty",
  "itertools",
  "once_cell",
- "profile",
  "rustc-hash",
  "smallvec",
  "span",
@@ -565,7 +563,6 @@ dependencies = [
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "limit",
  "mbe",
- "profile",
  "rustc-hash",
  "smallvec",
  "span",
@@ -601,7 +598,6 @@ dependencies = [
  "nohash-hasher",
  "once_cell",
  "oorandom",
- "profile",
  "project-model",
  "ra-ap-rustc_abi",
  "ra-ap-rustc_index 0.35.0",
@@ -673,7 +669,6 @@ dependencies = [
  "hir",
  "ide-db",
  "itertools",
- "profile",
  "smallvec",
  "sourcegen",
  "stdx",
@@ -695,7 +690,6 @@ dependencies = [
  "ide-db",
  "itertools",
  "once_cell",
- "profile",
  "smallvec",
  "stdx",
  "syntax",
@@ -753,7 +747,6 @@ dependencies = [
  "ide-db",
  "itertools",
  "once_cell",
- "profile",
  "serde_json",
  "sourcegen",
  "stdx",
@@ -1233,6 +1226,7 @@ dependencies = [
  "ra-ap-rustc_lexer",
  "sourcegen",
  "stdx",
+ "tracing",
 ]
 
 [[package]]
@@ -1302,7 +1296,6 @@ dependencies = [
  "memmap2",
  "object 0.32.0",
  "paths",
- "profile",
  "rustc-hash",
  "serde",
  "serde_json",
@@ -1386,7 +1379,6 @@ dependencies = [
  "itertools",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "paths",
- "profile",
  "rustc-hash",
  "semver",
  "serde",
@@ -1470,12 +1462,12 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.40.0"
+version = "0.37.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "371db64f1be25aae96650b5528c76066ac325f0fe23efec0aab1179d75eea5c3"
+checksum = "df5a0ba0d08af366cf235dbe8eb7226cced7a4fe502c98aa434ccf416defd746"
 dependencies = [
  "arrayvec",
- "ra-ap-rustc_index_macros 0.40.0",
+ "ra-ap-rustc_index_macros 0.37.0",
  "smallvec",
 ]
 
@@ -1493,9 +1485,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.40.0"
+version = "0.37.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4a454193807f557a991f52157250fd2db95abfb96da65e85355e6949802a98"
+checksum = "1971ebf9a701e0e68387c264a32517dcb4861ad3a4862f2e2803c1121ade20d5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1525,11 +1517,11 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.40.0"
+version = "0.37.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9cb49490fadb58e6b8cc825f73157a33730495bfd5c6e9eef067a4b50ad1836"
+checksum = "2c3c0e7ca9c5bdc66e3b590688e237a22ac47a48e4eac7f46b05b2abbfaf0abd"
 dependencies = [
- "ra-ap-rustc_index 0.40.0",
+ "ra-ap-rustc_index 0.37.0",
  "rustc-hash",
  "rustc_apfloat",
  "smallvec",
@@ -1925,7 +1917,6 @@ dependencies = [
  "once_cell",
  "parser",
  "proc-macro2",
- "profile",
  "quote",
  "ra-ap-rustc_lexer",
  "rayon",
diff --git a/Cargo.toml b/Cargo.toml
index e68613c6d3..16dd510389 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -88,7 +88,7 @@ ra-ap-rustc_lexer = { version = "0.35.0", default-features = false }
 ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false }
 ra-ap-rustc_index = { version = "0.35.0", default-features = false }
 ra-ap-rustc_abi = { version = "0.35.0", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.40.0", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.37.0", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 sourcegen = { path = "./crates/sourcegen" }
diff --git a/crates/base-db/Cargo.toml b/crates/base-db/Cargo.toml
index 801ba2d1f6..118abf5d6e 100644
--- a/crates/base-db/Cargo.toml
+++ b/crates/base-db/Cargo.toml
@@ -21,7 +21,6 @@ tracing.workspace = true
 
 # local deps
 cfg.workspace = true
-profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 vfs.workspace = true
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs
index ce8a9eab14..37d37fd331 100644
--- a/crates/hir-def/src/body.rs
+++ b/crates/hir-def/src/body.rs
@@ -13,7 +13,6 @@ use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 use hir_expand::{name::Name, HirFileId, InFile};
 use la_arena::{Arena, ArenaMap};
-use profile::Count;
 use rustc_hash::FxHashMap;
 use syntax::{ast, AstPtr, SyntaxNodePtr};
 use triomphe::Arc;
@@ -51,7 +50,6 @@ pub struct Body {
     pub body_expr: ExprId,
     /// Block expressions in this body that may contain inner items.
     block_scopes: Vec<BlockId>,
-    _c: Count<Self>,
 }
 
 pub type ExprPtr = AstPtr<ast::Expr>;
@@ -216,7 +214,6 @@ impl Body {
 
     fn shrink_to_fit(&mut self) {
         let Self {
-            _c: _,
             body_expr: _,
             block_scopes,
             exprs,
@@ -300,7 +297,6 @@ impl Default for Body {
             params: Default::default(),
             block_scopes: Default::default(),
             binding_owners: Default::default(),
-            _c: Default::default(),
         }
     }
 }
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index ad8782d3d1..c9300898b3 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -10,7 +10,6 @@ use hir_expand::{
     ExpandError, InFile,
 };
 use intern::Interned;
-use profile::Count;
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::AstIdMap;
@@ -76,7 +75,6 @@ pub(super) fn lower(
             params: Vec::new(),
             body_expr: dummy_expr_id(),
             block_scopes: Vec::new(),
-            _c: Count::new(),
         },
         expander,
         current_try_block_label: None,
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index c7cf611589..008fa7ef13 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -50,7 +50,6 @@ use either::Either;
 use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
 use intern::Interned;
 use la_arena::{Arena, Idx, IdxRange, RawIdx};
-use profile::Count;
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::{AstIdNode, FileAstId, Span};
@@ -94,8 +93,6 @@ impl fmt::Debug for RawVisibilityId {
 /// The item tree of a source file.
 #[derive(Debug, Default, Eq, PartialEq)]
 pub struct ItemTree {
-    _c: Count<Self>,
-
     top_level: SmallVec<[ModItem; 1]>,
     attrs: FxHashMap<AttrOwner, RawAttrs>,
 
@@ -263,14 +260,6 @@ impl ItemVisibilities {
     }
 }
 
-static VIS_PUB: RawVisibility = RawVisibility::Public;
-static VIS_PRIV_IMPLICIT: RawVisibility =
-    RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Implicit);
-static VIS_PRIV_EXPLICIT: RawVisibility =
-    RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Explicit);
-static VIS_PUB_CRATE: RawVisibility =
-    RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicitness::Explicit);
-
 #[derive(Default, Debug, Eq, PartialEq)]
 struct ItemTreeData {
     uses: Arena<Use>,
@@ -562,6 +551,20 @@ impl_index!(fields: Field, variants: Variant, params: Param);
 impl Index<RawVisibilityId> for ItemTree {
     type Output = RawVisibility;
     fn index(&self, index: RawVisibilityId) -> &Self::Output {
+        static VIS_PUB: RawVisibility = RawVisibility::Public;
+        static VIS_PRIV_IMPLICIT: RawVisibility = RawVisibility::Module(
+            ModPath::from_kind(PathKind::Super(0)),
+            VisibilityExplicitness::Implicit,
+        );
+        static VIS_PRIV_EXPLICIT: RawVisibility = RawVisibility::Module(
+            ModPath::from_kind(PathKind::Super(0)),
+            VisibilityExplicitness::Explicit,
+        );
+        static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(
+            ModPath::from_kind(PathKind::Crate),
+            VisibilityExplicitness::Explicit,
+        );
+
         match index {
             RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT,
             RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT,
@@ -871,25 +874,19 @@ impl UseTree {
             prefix: Option<ModPath>,
             path: &ModPath,
         ) -> Option<(ModPath, ImportKind)> {
-            match (prefix, &path.kind) {
+            match (prefix, path.kind) {
                 (None, _) => Some((path.clone(), ImportKind::Plain)),
                 (Some(mut prefix), PathKind::Plain) => {
-                    for segment in path.segments() {
-                        prefix.push_segment(segment.clone());
-                    }
+                    prefix.extend(path.segments().iter().cloned());
                     Some((prefix, ImportKind::Plain))
                 }
-                (Some(mut prefix), PathKind::Super(n))
-                    if *n > 0 && prefix.segments().is_empty() =>
-                {
+                (Some(mut prefix), PathKind::Super(n)) if n > 0 && prefix.segments().is_empty() => {
                     // `super::super` + `super::rest`
                     match &mut prefix.kind {
                         PathKind::Super(m) => {
                             cov_mark::hit!(concat_super_mod_paths);
-                            *m += *n;
-                            for segment in path.segments() {
-                                prefix.push_segment(segment.clone());
-                            }
+                            *m += n;
+                            prefix.extend(path.segments().iter().cloned());
                             Some((prefix, ImportKind::Plain))
                         }
                         _ => None,
@@ -963,10 +960,10 @@ impl ModItem {
             | ModItem::Mod(_)
             | ModItem::MacroRules(_)
             | ModItem::Macro2(_) => None,
-            ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
-            ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
-            ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
-            ModItem::Function(func) => Some(AssocItem::Function(*func)),
+            &ModItem::MacroCall(call) => Some(AssocItem::MacroCall(call)),
+            &ModItem::Const(konst) => Some(AssocItem::Const(konst)),
+            &ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(alias)),
+            &ModItem::Function(func) => Some(AssocItem::Function(func)),
         }
     }
 
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 270468ad0a..764617eafb 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -65,7 +65,6 @@ use hir_expand::{
 };
 use itertools::Itertools;
 use la_arena::Arena;
-use profile::Count;
 use rustc_hash::{FxHashMap, FxHashSet};
 use span::FileAstId;
 use stdx::format_to;
@@ -95,7 +94,6 @@ use crate::{
 /// is computed by the `block_def_map` query.
 #[derive(Debug, PartialEq, Eq)]
 pub struct DefMap {
-    _c: Count<Self>,
     /// When this is a block def map, this will hold the block id of the block and module that
     /// contains this block.
     block: Option<BlockInfo>,
@@ -154,6 +152,23 @@ struct DefMapCrateData {
 }
 
 impl DefMapCrateData {
+    fn new(edition: Edition) -> Self {
+        Self {
+            extern_prelude: FxHashMap::default(),
+            exported_derives: FxHashMap::default(),
+            fn_proc_macro_mapping: FxHashMap::default(),
+            proc_macro_loading_error: None,
+            registered_attrs: Vec::new(),
+            registered_tools: Vec::new(),
+            unstable_features: FxHashSet::default(),
+            rustc_coherence_is_core: false,
+            no_core: false,
+            no_std: false,
+            edition,
+            recursion_limit: None,
+        }
+    }
+
     fn shrink_to_fit(&mut self) {
         let Self {
             extern_prelude,
@@ -305,67 +320,67 @@ impl DefMap {
     /// The module id of a crate or block root.
     pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0));
 
-    pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
+    pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc<DefMap> {
         let crate_graph = db.crate_graph();
-        let krate_name = crate_graph[krate].display_name.as_deref().unwrap_or_default();
-
-        let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?krate_name).entered();
+        let krate = &crate_graph[crate_id];
+        let name = krate.display_name.as_deref().unwrap_or_default();
+        let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?name).entered();
 
-        let crate_graph = db.crate_graph();
+        let module_data = ModuleData::new(
+            ModuleOrigin::CrateRoot { definition: krate.root_file_id },
+            Visibility::Public,
+        );
 
-        let edition = crate_graph[krate].edition;
-        let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id };
-        let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public));
-        let def_map = collector::collect_defs(
-            db,
-            def_map,
-            TreeId::new(crate_graph[krate].root_file_id.into(), None),
+        let def_map = DefMap::empty(
+            crate_id,
+            Arc::new(DefMapCrateData::new(krate.edition)),
+            module_data,
+            None,
         );
+        let def_map =
+            collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id.into(), None));
 
         Arc::new(def_map)
     }
 
     pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
-        let block: BlockLoc = block_id.lookup(db);
-
-        let parent_map = block.module.def_map(db);
-        let krate = block.module.krate;
-        let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
-        // NB: we use `None` as block here, which would be wrong for implicit
-        // modules declared by blocks with items. At the moment, we don't use
-        // this visibility for anything outside IDE, so that's probably OK.
+        let BlockLoc { ast_id, module } = block_id.lookup(db);
+
         let visibility = Visibility::Module(
-            ModuleId { krate, local_id, block: None },
+            ModuleId { krate: module.krate, local_id: Self::ROOT, block: module.block },
             VisibilityExplicitness::Implicit,
         );
-        let module_data = ModuleData::new(
-            ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id },
-            visibility,
+        let module_data =
+            ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
+
+        let parent_map = module.def_map(db);
+        let def_map = DefMap::empty(
+            module.krate,
+            parent_map.data.clone(),
+            module_data,
+            Some(BlockInfo {
+                block: block_id,
+                parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id },
+            }),
         );
 
-        let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data);
-        def_map.data = parent_map.data.clone();
-        def_map.block = Some(BlockInfo {
-            block: block_id,
-            parent: BlockRelativeModuleId {
-                block: block.module.block,
-                local_id: block.module.local_id,
-            },
-        });
-
         let def_map =
-            collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id)));
+            collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id)));
         Arc::new(def_map)
     }
 
-    fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap {
+    fn empty(
+        krate: CrateId,
+        crate_data: Arc<DefMapCrateData>,
+        module_data: ModuleData,
+        block: Option<BlockInfo>,
+    ) -> DefMap {
         let mut modules: Arena<ModuleData> = Arena::default();
         let root = modules.alloc(module_data);
         assert_eq!(root, Self::ROOT);
 
         DefMap {
-            _c: Count::new(),
-            block: None,
+            block,
             modules,
             krate,
             prelude: None,
@@ -373,23 +388,36 @@ impl DefMap {
             derive_helpers_in_scope: FxHashMap::default(),
             diagnostics: Vec::new(),
             enum_definitions: FxHashMap::default(),
-            data: Arc::new(DefMapCrateData {
-                extern_prelude: FxHashMap::default(),
-                exported_derives: FxHashMap::default(),
-                fn_proc_macro_mapping: FxHashMap::default(),
-                proc_macro_loading_error: None,
-                registered_attrs: Vec::new(),
-                registered_tools: Vec::new(),
-                unstable_features: FxHashSet::default(),
-                rustc_coherence_is_core: false,
-                no_core: false,
-                no_std: false,
-                edition,
-                recursion_limit: None,
-            }),
+            data: crate_data,
+        }
+    }
+    fn shrink_to_fit(&mut self) {
+        // Exhaustive match to require handling new fields.
+        let Self {
+            macro_use_prelude,
+            diagnostics,
+            modules,
+            derive_helpers_in_scope,
+            block: _,
+            krate: _,
+            prelude: _,
+            data: _,
+            enum_definitions,
+        } = self;
+
+        macro_use_prelude.shrink_to_fit();
+        diagnostics.shrink_to_fit();
+        modules.shrink_to_fit();
+        derive_helpers_in_scope.shrink_to_fit();
+        enum_definitions.shrink_to_fit();
+        for (_, module) in modules.iter_mut() {
+            module.children.shrink_to_fit();
+            module.scope.shrink_to_fit();
         }
     }
+}
 
+impl DefMap {
     pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
         self.modules
             .iter()
@@ -440,26 +468,6 @@ impl DefMap {
         self.krate
     }
 
-    pub(crate) fn block_id(&self) -> Option<BlockId> {
-        self.block.map(|block| block.block)
-    }
-
-    pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
-        self.prelude
-    }
-
-    pub(crate) fn extern_prelude(
-        &self,
-    ) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
-        self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
-    }
-
-    pub(crate) fn macro_use_prelude(
-        &self,
-    ) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
-        self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
-    }
-
     pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
         let block = self.block.map(|b| b.block);
         ModuleId { krate: self.krate, local_id, block }
@@ -475,68 +483,6 @@ impl DefMap {
         self.module_id(Self::ROOT)
     }
 
-    pub(crate) fn resolve_path(
-        &self,
-        db: &dyn DefDatabase,
-        original_module: LocalModuleId,
-        path: &ModPath,
-        shadow: BuiltinShadowMode,
-        expected_macro_subns: Option<MacroSubNs>,
-    ) -> (PerNs, Option<usize>) {
-        let res = self.resolve_path_fp_with_macro(
-            db,
-            ResolveMode::Other,
-            original_module,
-            path,
-            shadow,
-            expected_macro_subns,
-        );
-        (res.resolved_def, res.segment_index)
-    }
-
-    pub(crate) fn resolve_path_locally(
-        &self,
-        db: &dyn DefDatabase,
-        original_module: LocalModuleId,
-        path: &ModPath,
-        shadow: BuiltinShadowMode,
-    ) -> (PerNs, Option<usize>) {
-        let res = self.resolve_path_fp_with_macro_single(
-            db,
-            ResolveMode::Other,
-            original_module,
-            path,
-            shadow,
-            None, // Currently this function isn't used for macro resolution.
-        );
-        (res.resolved_def, res.segment_index)
-    }
-
-    /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
-    ///
-    /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
-    /// `None`, iteration continues.
-    pub(crate) fn with_ancestor_maps<T>(
-        &self,
-        db: &dyn DefDatabase,
-        local_mod: LocalModuleId,
-        f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
-    ) -> Option<T> {
-        if let Some(it) = f(self, local_mod) {
-            return Some(it);
-        }
-        let mut block = self.block;
-        while let Some(block_info) = block {
-            let parent = block_info.parent.def_map(db, self.krate);
-            if let Some(it) = f(&parent, block_info.parent.local_id) {
-                return Some(it);
-            }
-            block = parent.block;
-        }
-
-        None
-    }
-
     /// If this `DefMap` is for a block expression, returns the module containing the block (which
     /// might again be a block, or a module inside a block).
     pub fn parent(&self) -> Option<ModuleId> {
@@ -559,6 +505,16 @@ impl DefMap {
         }
     }
 
+    /// Get a reference to the def map's diagnostics.
+    pub fn diagnostics(&self) -> &[DefDiagnostic] {
+        self.diagnostics.as_slice()
+    }
+
+    pub fn recursion_limit(&self) -> u32 {
+        // 128 is the default in rustc
+        self.data.recursion_limit.unwrap_or(128)
+    }
+
     // FIXME: this can use some more human-readable format (ideally, an IR
     // even), as this should be a great debugging aid.
     pub fn dump(&self, db: &dyn DefDatabase) -> String {
@@ -608,41 +564,89 @@ impl DefMap {
         format_to!(buf, "crate scope\n");
         buf
     }
+}
 
-    fn shrink_to_fit(&mut self) {
-        // Exhaustive match to require handling new fields.
-        let Self {
-            _c: _,
-            macro_use_prelude,
-            diagnostics,
-            modules,
-            derive_helpers_in_scope,
-            block: _,
-            krate: _,
-            prelude: _,
-            data: _,
-            enum_definitions,
-        } = self;
+impl DefMap {
+    pub(crate) fn block_id(&self) -> Option<BlockId> {
+        self.block.map(|block| block.block)
+    }
 
-        macro_use_prelude.shrink_to_fit();
-        diagnostics.shrink_to_fit();
-        modules.shrink_to_fit();
-        derive_helpers_in_scope.shrink_to_fit();
-        enum_definitions.shrink_to_fit();
-        for (_, module) in modules.iter_mut() {
-            module.children.shrink_to_fit();
-            module.scope.shrink_to_fit();
-        }
+    pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
+        self.prelude
     }
 
-    /// Get a reference to the def map's diagnostics.
-    pub fn diagnostics(&self) -> &[DefDiagnostic] {
-        self.diagnostics.as_slice()
+    pub(crate) fn extern_prelude(
+        &self,
+    ) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
+        self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
     }
 
-    pub fn recursion_limit(&self) -> u32 {
-        // 128 is the default in rustc
-        self.data.recursion_limit.unwrap_or(128)
+    pub(crate) fn macro_use_prelude(
+        &self,
+    ) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
+        self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
+    }
+
+    pub(crate) fn resolve_path(
+        &self,
+        db: &dyn DefDatabase,
+        original_module: LocalModuleId,
+        path: &ModPath,
+        shadow: BuiltinShadowMode,
+        expected_macro_subns: Option<MacroSubNs>,
+    ) -> (PerNs, Option<usize>) {
+        let res = self.resolve_path_fp_with_macro(
+            db,
+            ResolveMode::Other,
+            original_module,
+            path,
+            shadow,
+            expected_macro_subns,
+        );
+        (res.resolved_def, res.segment_index)
+    }
+
+    pub(crate) fn resolve_path_locally(
+        &self,
+        db: &dyn DefDatabase,
+        original_module: LocalModuleId,
+        path: &ModPath,
+        shadow: BuiltinShadowMode,
+    ) -> (PerNs, Option<usize>) {
+        let res = self.resolve_path_fp_with_macro_single(
+            db,
+            ResolveMode::Other,
+            original_module,
+            path,
+            shadow,
+            None, // Currently this function isn't used for macro resolution.
+        );
+        (res.resolved_def, res.segment_index)
+    }
+
+    /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
+    ///
+    /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
+    /// `None`, iteration continues.
+    pub(crate) fn with_ancestor_maps<T>(
+        &self,
+        db: &dyn DefDatabase,
+        local_mod: LocalModuleId,
+        f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
+    ) -> Option<T> {
+        if let Some(it) = f(self, local_mod) {
+            return Some(it);
+        }
+        let mut block = self.block;
+        while let Some(block_info) = block {
+            let parent = block_info.parent.def_map(db, self.krate);
+            if let Some(it) = f(&parent, block_info.parent.local_id) {
+                return Some(it);
+            }
+            block = parent.block;
+        }
+
+        None
     }
 }
 
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 538e735688..18aefbf332 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -64,19 +64,18 @@ static FIXED_POINT_LIMIT: Limit = Limit::new(8192);
 pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap {
     let crate_graph = db.crate_graph();
 
-    let mut deps = FxHashMap::default();
-    // populate external prelude and dependency list
     let krate = &crate_graph[def_map.krate];
+
+    // populate external prelude and dependency list
+    let mut deps =
+        FxHashMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
     for dep in &krate.dependencies {
         tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
 
         deps.insert(dep.as_name(), dep.clone());
     }
 
-    let cfg_options = &krate.cfg_options;
-
-    let is_proc_macro = krate.is_proc_macro;
-    let proc_macros = if is_proc_macro {
+    let proc_macros = if krate.is_proc_macro {
         match db.proc_macros().get(&def_map.krate) {
             Some(Ok(proc_macros)) => {
                 Ok(proc_macros
@@ -124,11 +123,11 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
         indeterminate_imports: Vec::new(),
         unresolved_macros: Vec::new(),
         mod_dirs: FxHashMap::default(),
-        cfg_options,
+        cfg_options: &krate.cfg_options,
         proc_macros,
         from_glob_import: Default::default(),
         skip_attrs: Default::default(),
-        is_proc_macro,
+        is_proc_macro: krate.is_proc_macro,
     };
     if tree_id.is_block() {
         collector.seed_with_inner(tree_id);
@@ -302,71 +301,50 @@ impl DefCollector<'_> {
                     return;
                 }
             }
-            let attr_name = match attr.path.as_ident() {
-                Some(name) => name,
-                None => continue,
-            };
+            let Some(attr_name) = attr.path.as_ident() else { continue };
 
-            if *attr_name == hir_expand::name![recursion_limit] {
-                if let Some(limit) = attr.string_value() {
-                    if let Ok(limit) = limit.parse() {
-                        crate_data.recursion_limit = Some(limit);
+            match () {
+                () if *attr_name == hir_expand::name![recursion_limit] => {
+                    if let Some(limit) = attr.string_value() {
+                        if let Ok(limit) = limit.parse() {
+                            crate_data.recursion_limit = Some(limit);
+                        }
                     }
                 }
-                continue;
-            }
-
-            if *attr_name == hir_expand::name![crate_type] {
-                if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
-                    self.is_proc_macro = true;
+                () if *attr_name == hir_expand::name![crate_type] => {
+                    if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
+                        self.is_proc_macro = true;
+                    }
                 }
-                continue;
-            }
-
-            if *attr_name == hir_expand::name![no_core] {
-                crate_data.no_core = true;
-                continue;
-            }
-
-            if *attr_name == hir_expand::name![no_std] {
-                crate_data.no_std = true;
-                continue;
-            }
-
-            if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") {
-                crate_data.rustc_coherence_is_core = true;
-                continue;
-            }
-
-            if *attr_name == hir_expand::name![feature] {
-                let features = attr
-                    .parse_path_comma_token_tree(self.db.upcast())
-                    .into_iter()
-                    .flatten()
-                    .filter_map(|(feat, _)| match feat.segments() {
-                        [name] => Some(name.to_smol_str()),
-                        _ => None,
-                    });
-                crate_data.unstable_features.extend(features);
-            }
-
-            let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
-                || *attr_name == hir_expand::name![register_tool];
-            if !attr_is_register_like {
-                continue;
-            }
-
-            let registered_name = match attr.single_ident_value() {
-                Some(ident) => ident.as_name(),
-                _ => continue,
-            };
-
-            if *attr_name == hir_expand::name![register_attr] {
-                crate_data.registered_attrs.push(registered_name.to_smol_str());
-                cov_mark::hit!(register_attr);
-            } else {
-                crate_data.registered_tools.push(registered_name.to_smol_str());
-                cov_mark::hit!(register_tool);
+                () if *attr_name == hir_expand::name![no_core] => crate_data.no_core = true,
+                () if *attr_name == hir_expand::name![no_std] => crate_data.no_std = true,
+                () if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") => {
+                    crate_data.rustc_coherence_is_core = true;
+                }
+                () if *attr_name == hir_expand::name![feature] => {
+                    let features = attr
+                        .parse_path_comma_token_tree(self.db.upcast())
+                        .into_iter()
+                        .flatten()
+                        .filter_map(|(feat, _)| match feat.segments() {
+                            [name] => Some(name.to_smol_str()),
+                            _ => None,
+                        });
+                    crate_data.unstable_features.extend(features);
+                }
+                () if *attr_name == hir_expand::name![register_attr] => {
+                    if let Some(ident) = attr.single_ident_value() {
+                        crate_data.registered_attrs.push(ident.text.clone());
+                        cov_mark::hit!(register_attr);
+                    }
+                }
+                () if *attr_name == hir_expand::name![register_tool] => {
+                    if let Some(ident) = attr.single_ident_value() {
+                        crate_data.registered_tools.push(ident.text.clone());
+                        cov_mark::hit!(register_tool);
+                    }
+                }
+                () => (),
             }
         }
 
@@ -409,6 +387,7 @@ impl DefCollector<'_> {
         // main name resolution fixed-point loop.
         let mut i = 0;
         'resolve_attr: loop {
+            let _p = tracing::span!(tracing::Level::INFO, "resolve_macros loop").entered();
             'resolve_macros: loop {
                 self.db.unwind_if_cancelled();
 
@@ -466,9 +445,8 @@ impl DefCollector<'_> {
             // Additionally, while the proc macro entry points must be `pub`, they are not publicly
             // exported in type/value namespace. This function reduces the visibility of all items
             // in the crate root that aren't proc macros.
-            let root = DefMap::ROOT;
-            let module_id = self.def_map.module_id(root);
-            let root = &mut self.def_map.modules[root];
+            let module_id = self.def_map.module_id(DefMap::ROOT);
+            let root = &mut self.def_map.modules[DefMap::ROOT];
             root.scope.censor_non_proc_macros(module_id);
         }
     }
@@ -828,12 +806,10 @@ impl DefCollector<'_> {
                     return PartialResolvedImport::Unresolved;
                 }
 
-                if let Some(krate) = res.krate {
-                    if krate != self.def_map.krate {
-                        return PartialResolvedImport::Resolved(
-                            def.filter_visibility(|v| matches!(v, Visibility::Public)),
-                        );
-                    }
+                if res.from_differing_crate {
+                    return PartialResolvedImport::Resolved(
+                        def.filter_visibility(|v| matches!(v, Visibility::Public)),
+                    );
                 }
 
                 // Check whether all namespaces are resolved.
@@ -1920,7 +1896,7 @@ impl ModCollector<'_, '_> {
     }
 
     fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
-        let path_attr = attrs.by_key("path").string_value();
+        let path_attr = attrs.by_key("path").string_value().map(SmolStr::as_str);
         let is_macro_use = attrs.by_key("macro_use").exists();
         let module = &self.item_tree[module_id];
         match &module.kind {
@@ -1934,25 +1910,26 @@ impl ModCollector<'_, '_> {
                     module_id,
                 );
 
-                if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
-                {
-                    ModCollector {
-                        def_collector: &mut *self.def_collector,
-                        macro_depth: self.macro_depth,
-                        module_id,
-                        tree_id: self.tree_id,
-                        item_tree: self.item_tree,
-                        mod_dir,
-                    }
-                    .collect_in_top_module(items);
-                    if is_macro_use {
-                        self.import_all_legacy_macros(module_id);
-                    }
+                let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
+                else {
+                    return;
+                };
+                ModCollector {
+                    def_collector: &mut *self.def_collector,
+                    macro_depth: self.macro_depth,
+                    module_id,
+                    tree_id: self.tree_id,
+                    item_tree: self.item_tree,
+                    mod_dir,
+                }
+                .collect_in_top_module(items);
+                if is_macro_use {
+                    self.import_all_legacy_macros(module_id);
                 }
             }
             // out of line module, resolve, parse and recurse
             ModKind::Outline => {
-                let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id);
+                let ast_id = AstId::new(self.file_id(), module.ast_id);
                 let db = self.def_collector.db;
                 match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr)
                 {
@@ -2445,7 +2422,7 @@ mod tests {
     use base_db::SourceDatabase;
     use test_fixture::WithFixture;
 
-    use crate::test_db::TestDB;
+    use crate::{nameres::DefMapCrateData, test_db::TestDB};
 
     use super::*;
 
@@ -2476,8 +2453,12 @@ mod tests {
 
         let edition = db.crate_graph()[krate].edition;
         let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
-        let def_map =
-            DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public));
+        let def_map = DefMap::empty(
+            krate,
+            Arc::new(DefMapCrateData::new(edition)),
+            ModuleData::new(module_origin, Visibility::Public),
+            None,
+        );
         do_collect_defs(&db, def_map)
     }
 
diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs
index 161b2c0599..b5a302dbca 100644
--- a/crates/hir-def/src/nameres/diagnostics.rs
+++ b/crates/hir-def/src/nameres/diagnostics.rs
@@ -1,5 +1,7 @@
 //! Diagnostics emitted during DefMap construction.
 
+use std::ops::Not;
+
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
 use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
@@ -16,27 +18,16 @@ use crate::{
 #[derive(Debug, PartialEq, Eq)]
 pub enum DefDiagnosticKind {
     UnresolvedModule { ast: AstId<ast::Module>, candidates: Box<[String]> },
-
     UnresolvedExternCrate { ast: AstId<ast::ExternCrate> },
-
     UnresolvedImport { id: ItemTreeId<item_tree::Use>, index: Idx<ast::UseTree> },
-
     UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
-
     UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
-
     UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
-
     MacroError { ast: MacroCallKind, message: String },
-
     MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> },
-
     UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
-
     InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
-
     MalformedDerive { ast: AstId<ast::Adt>, id: usize },
-
     MacroDefError { ast: AstId<ast::Macro>, message: String },
 }
 
@@ -45,11 +36,12 @@ pub struct DefDiagnostics(Option<triomphe::Arc<Box<[DefDiagnostic]>>>);
 
 impl DefDiagnostics {
     pub fn new(diagnostics: Vec<DefDiagnostic>) -> Self {
-        Self(if diagnostics.is_empty() {
-            None
-        } else {
-            Some(triomphe::Arc::new(diagnostics.into_boxed_slice()))
-        })
+        Self(
+            diagnostics
+                .is_empty()
+                .not()
+                .then(|| triomphe::Arc::new(diagnostics.into_boxed_slice())),
+        )
     }
 
     pub fn iter(&self) -> impl Iterator<Item = &DefDiagnostic> {
diff --git a/crates/hir-def/src/nameres/mod_resolution.rs b/crates/hir-def/src/nameres/mod_resolution.rs
index c45200e2de..696fb6a961 100644
--- a/crates/hir-def/src/nameres/mod_resolution.rs
+++ b/crates/hir-def/src/nameres/mod_resolution.rs
@@ -3,7 +3,6 @@ use arrayvec::ArrayVec;
 use base_db::{AnchoredPath, FileId};
 use hir_expand::{name::Name, HirFileIdExt, MacroFileIdExt};
 use limit::Limit;
-use syntax::SmolStr;
 
 use crate::{db::DefDatabase, HirFileId};
 
@@ -29,9 +28,9 @@ impl ModDir {
     pub(super) fn descend_into_definition(
         &self,
         name: &Name,
-        attr_path: Option<&SmolStr>,
+        attr_path: Option<&str>,
     ) -> Option<ModDir> {
-        let path = match attr_path.map(SmolStr::as_str) {
+        let path = match attr_path {
             None => {
                 let mut path = self.dir_path.clone();
                 path.push(&name.unescaped().to_smol_str());
@@ -63,10 +62,9 @@ impl ModDir {
         db: &dyn DefDatabase,
         file_id: HirFileId,
         name: &Name,
-        attr_path: Option<&SmolStr>,
+        attr_path: Option<&str>,
     ) -> Result<(FileId, bool, ModDir), Box<[String]>> {
         let name = name.unescaped();
-        let orig_file_id = file_id.original_file_respecting_includes(db.upcast());
 
         let mut candidate_files = ArrayVec::<_, 2>::new();
         match attr_path {
@@ -91,17 +89,19 @@ impl ModDir {
             }
         };
 
+        let orig_file_id = file_id.original_file_respecting_includes(db.upcast());
         for candidate in candidate_files.iter() {
             let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() };
             if let Some(file_id) = db.resolve_path(path) {
                 let is_mod_rs = candidate.ends_with("/mod.rs");
 
-                let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() {
-                    (DirPath::empty(), false)
+                let root_dir_owner = is_mod_rs || attr_path.is_some();
+                let dir_path = if root_dir_owner {
+                    DirPath::empty()
                 } else {
-                    (DirPath::new(format!("{}/", name.display(db.upcast()))), true)
+                    DirPath::new(format!("{}/", name.display(db.upcast())))
                 };
-                if let Some(mod_dir) = self.child(dir_path, root_non_dir_owner) {
+                if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
                     return Ok((file_id, is_mod_rs, mod_dir));
                 }
             }
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index 1e13f7f8fd..9e53b03728 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -22,7 +22,7 @@ use crate::{
     path::{ModPath, PathKind},
     per_ns::PerNs,
     visibility::{RawVisibility, Visibility},
-    AdtId, CrateId, LocalModuleId, ModuleDefId,
+    AdtId, LocalModuleId, ModuleDefId,
 };
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -42,21 +42,21 @@ pub(super) struct ResolvePathResult {
     pub(super) resolved_def: PerNs,
     pub(super) segment_index: Option<usize>,
     pub(super) reached_fixedpoint: ReachedFixedPoint,
-    pub(super) krate: Option<CrateId>,
+    pub(super) from_differing_crate: bool,
 }
 
 impl ResolvePathResult {
     fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
-        ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None)
+        ResolvePathResult::new(PerNs::none(), reached_fixedpoint, None, false)
     }
 
-    fn with(
+    fn new(
         resolved_def: PerNs,
         reached_fixedpoint: ReachedFixedPoint,
         segment_index: Option<usize>,
-        krate: Option<CrateId>,
+        from_differing_crate: bool,
     ) -> ResolvePathResult {
-        ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, krate }
+        ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, from_differing_crate }
     }
 }
 
@@ -134,7 +134,19 @@ impl DefMap {
         // resolving them to. Pass `None` otherwise, e.g. when we're resolving import paths.
         expected_macro_subns: Option<MacroSubNs>,
     ) -> ResolvePathResult {
-        let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
+        let mut result = self.resolve_path_fp_with_macro_single(
+            db,
+            mode,
+            original_module,
+            path,
+            shadow,
+            expected_macro_subns,
+        );
+
+        if self.block.is_none() {
+            // If we're in the root `DefMap`, we can resolve the path directly.
+            return result;
+        }
 
         let mut arc;
         let mut current_map = self;
@@ -153,8 +165,7 @@ impl DefMap {
             if result.reached_fixedpoint == ReachedFixedPoint::No {
                 result.reached_fixedpoint = new.reached_fixedpoint;
             }
-            // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates?
-            result.krate = result.krate.or(new.krate);
+            result.from_differing_crate |= new.from_differing_crate;
             result.segment_index = match (result.segment_index, new.segment_index) {
                 (Some(idx), None) => Some(idx),
                 (Some(old), Some(new)) => Some(old.max(new)),
@@ -333,11 +344,11 @@ impl DefMap {
                         // expectation is discarded.
                         let (def, s) =
                             defp_map.resolve_path(db, module.local_id, &path, shadow, None);
-                        return ResolvePathResult::with(
+                        return ResolvePathResult::new(
                             def,
                             ReachedFixedPoint::Yes,
                             s.map(|s| s + i),
-                            Some(module.krate),
+                            true,
                         );
                     }
 
@@ -385,11 +396,11 @@ impl DefMap {
                     match res {
                         Some(res) => res,
                         None => {
-                            return ResolvePathResult::with(
+                            return ResolvePathResult::new(
                                 PerNs::types(e.into(), vis, imp),
                                 ReachedFixedPoint::Yes,
                                 Some(i),
-                                Some(self.krate),
+                                false,
                             )
                         }
                     }
@@ -403,11 +414,11 @@ impl DefMap {
                         curr,
                     );
 
-                    return ResolvePathResult::with(
+                    return ResolvePathResult::new(
                         PerNs::types(s, vis, imp),
                         ReachedFixedPoint::Yes,
                         Some(i),
-                        Some(self.krate),
+                        false,
                     );
                 }
             };
@@ -416,7 +427,7 @@ impl DefMap {
                 .filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module));
         }
 
-        ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))
+        ResolvePathResult::new(curr_per_ns, ReachedFixedPoint::Yes, None, false)
     }
 
     fn resolve_name_in_module(
diff --git a/crates/hir-expand/Cargo.toml b/crates/hir-expand/Cargo.toml
index 506a188a21..4f30808015 100644
--- a/crates/hir-expand/Cargo.toml
+++ b/crates/hir-expand/Cargo.toml
@@ -28,7 +28,6 @@ intern.workspace = true
 base-db.workspace = true
 cfg.workspace = true
 syntax.workspace = true
-profile.workspace = true
 tt.workspace = true
 mbe.workspace = true
 limit.workspace = true
@@ -38,4 +37,4 @@ span.workspace = true
 expect-test = "1.4.0"
 
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/crates/hir-expand/src/builtin_attr_macro.rs b/crates/hir-expand/src/builtin_attr_macro.rs
index 903b0d4807..a0102f36af 100644
--- a/crates/hir-expand/src/builtin_attr_macro.rs
+++ b/crates/hir-expand/src/builtin_attr_macro.rs
@@ -4,23 +4,17 @@ use span::{MacroCallId, Span};
 use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind};
 
 macro_rules! register_builtin {
-    ($expand_fn:ident: $(($name:ident, $variant:ident) => $expand:ident),* ) => {
+    ($(($name:ident, $variant:ident) => $expand:ident),* ) => {
         #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
         pub enum BuiltinAttrExpander {
             $($variant),*
         }
 
         impl BuiltinAttrExpander {
-            pub fn $expand_fn(
-                &self,
-                db: &dyn ExpandDatabase,
-                id: MacroCallId,
-                tt: &tt::Subtree,
-            ) -> ExpandResult<tt::Subtree> {
-                let expander = match *self {
+            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree) -> ExpandResult<tt::Subtree>  {
+                match *self {
                     $( BuiltinAttrExpander::$variant => $expand, )*
-                };
-                expander(db, id, tt)
+                }
             }
 
             fn find_by_name(name: &name::Name) -> Option<Self> {
@@ -35,6 +29,15 @@ macro_rules! register_builtin {
 }
 
 impl BuiltinAttrExpander {
+    pub fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &tt::Subtree,
+    ) -> ExpandResult<tt::Subtree> {
+        self.expander()(db, id, tt)
+    }
+
     pub fn is_derive(self) -> bool {
         matches!(self, BuiltinAttrExpander::Derive | BuiltinAttrExpander::DeriveConst)
     }
@@ -46,7 +49,7 @@ impl BuiltinAttrExpander {
     }
 }
 
-register_builtin! { expand:
+register_builtin! {
     (bench, Bench) => dummy_attr_expand,
     (cfg, Cfg) => dummy_attr_expand,
     (cfg_attr, CfgAttr) => dummy_attr_expand,
diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs
index 2795487514..f36f48baae 100644
--- a/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/crates/hir-expand/src/builtin_derive_macro.rs
@@ -25,20 +25,10 @@ macro_rules! register_builtin {
         }
 
         impl BuiltinDeriveExpander {
-            pub fn expand(
-                &self,
-                db: &dyn ExpandDatabase,
-                id: MacroCallId,
-                tt: &ast::Adt,
-                token_map: SpanMapRef<'_>,
-            ) -> ExpandResult<tt::Subtree> {
-                let expander = match *self {
+            pub fn expander(&self) -> fn(Span, &ast::Adt, SpanMapRef<'_>) -> ExpandResult<tt::Subtree>  {
+                match *self {
                     $( BuiltinDeriveExpander::$trait => $expand, )*
-                };
-
-                let span = db.lookup_intern_macro_call(id).call_site;
-                let span = span_with_def_site_ctxt(db, span, id);
-                expander(span, tt, token_map)
+                }
             }
 
             fn find_by_name(name: &name::Name) -> Option<Self> {
@@ -52,6 +42,20 @@ macro_rules! register_builtin {
     };
 }
 
+impl BuiltinDeriveExpander {
+    pub fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &ast::Adt,
+        token_map: SpanMapRef<'_>,
+    ) -> ExpandResult<tt::Subtree> {
+        let span = db.lookup_intern_macro_call(id).call_site;
+        let span = span_with_def_site_ctxt(db, span, id);
+        self.expander()(span, tt, token_map)
+    }
+}
+
 register_builtin! {
     Copy => copy_expand,
     Clone => clone_expand,
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 90cd3af757..0fd0c25dcc 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -31,36 +31,18 @@ macro_rules! register_builtin {
         }
 
         impl BuiltinFnLikeExpander {
-            pub fn expand(
-                &self,
-                db: &dyn ExpandDatabase,
-                id: MacroCallId,
-                tt: &tt::Subtree,
-            ) -> ExpandResult<tt::Subtree> {
-                let expander = match *self {
+            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree>  {
+                match *self {
                     $( BuiltinFnLikeExpander::$kind => $expand, )*
-                };
-
-                let span = db.lookup_intern_macro_call(id).call_site;
-                let span = span_with_def_site_ctxt(db, span, id);
-                expander(db, id, tt, span)
+                }
             }
         }
 
         impl EagerExpander {
-            pub fn expand(
-                &self,
-                db: &dyn ExpandDatabase,
-                id: MacroCallId,
-                tt: &tt::Subtree,
-            ) -> ExpandResult<tt::Subtree> {
-                let expander = match *self {
+            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree>  {
+                match *self {
                     $( EagerExpander::$e_kind => $e_expand, )*
-                };
-
-                let span = db.lookup_intern_macro_call(id).call_site;
-                let span = span_with_def_site_ctxt(db, span, id);
-                expander(db, id, tt, span)
+                }
             }
         }
 
@@ -74,7 +56,31 @@ macro_rules! register_builtin {
     };
 }
 
+impl BuiltinFnLikeExpander {
+    pub fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &tt::Subtree,
+    ) -> ExpandResult<tt::Subtree> {
+        let span = db.lookup_intern_macro_call(id).call_site;
+        let span = span_with_def_site_ctxt(db, span, id);
+        self.expander()(db, id, tt, span)
+    }
+}
+
 impl EagerExpander {
+    pub fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &tt::Subtree,
+    ) -> ExpandResult<tt::Subtree> {
+        let span = db.lookup_intern_macro_call(id).call_site;
+        let span = span_with_def_site_ctxt(db, span, id);
+        self.expander()(db, id, tt, span)
+    }
+
     pub fn is_include(&self) -> bool {
         matches!(self, EagerExpander::Include)
     }
diff --git a/crates/hir-expand/src/change.rs b/crates/hir-expand/src/change.rs
index c6611438e6..8b9e5a59df 100644
--- a/crates/hir-expand/src/change.rs
+++ b/crates/hir-expand/src/change.rs
@@ -11,14 +11,14 @@ use triomphe::Arc;
 use crate::{db::ExpandDatabase, proc_macro::ProcMacros};
 
 #[derive(Debug, Default)]
-pub struct Change {
+pub struct ChangeWithProcMacros {
     pub source_change: FileChange,
     pub proc_macros: Option<ProcMacros>,
     pub toolchains: Option<Vec<Option<Version>>>,
     pub target_data_layouts: Option<Vec<TargetLayoutLoadResult>>,
 }
 
-impl Change {
+impl ChangeWithProcMacros {
     pub fn new() -> Self {
         Self::default()
     }
diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs
index 0cf1fadec9..ae10ad2f80 100644
--- a/crates/hir-expand/src/mod_path.rs
+++ b/crates/hir-expand/src/mod_path.rs
@@ -144,6 +144,12 @@ impl ModPath {
     }
 }
 
+impl Extend<Name> for ModPath {
+    fn extend<T: IntoIterator<Item = Name>>(&mut self, iter: T) {
+        self.segments.extend(iter);
+    }
+}
+
 struct Display<'a> {
     db: &'a dyn ExpandDatabase,
     path: &'a ModPath,
diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml
index 1f8f8744f9..41e2f7ad73 100644
--- a/crates/hir-ty/Cargo.toml
+++ b/crates/hir-ty/Cargo.toml
@@ -45,7 +45,6 @@ intern.workspace = true
 hir-def.workspace = true
 hir-expand.workspace = true
 base-db.workspace = true
-profile.workspace = true
 syntax.workspace = true
 limit.workspace = true
 
diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml
index 7fea837287..190722075a 100644
--- a/crates/hir/Cargo.toml
+++ b/crates/hir/Cargo.toml
@@ -27,7 +27,6 @@ cfg.workspace = true
 hir-def.workspace = true
 hir-expand.workspace = true
 hir-ty.workspace = true
-profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 tt.workspace = true
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 5c60703016..1e16f78ca2 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -126,7 +126,7 @@ pub use {
     },
     hir_expand::{
         attrs::{Attr, AttrId},
-        change::Change,
+        change::ChangeWithProcMacros,
         hygiene::{marks_rev, SyntaxContextExt},
         name::{known, Name},
         proc_macro::ProcMacros,
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index ca8bd65510..cfda8d4f93 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -38,11 +38,10 @@ use crate::{
     db::HirDatabase,
     semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
     source_analyzer::{resolve_hir_path, SourceAnalyzer},
-    Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const,
-    ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile,
-    Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef,
-    Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union,
-    Variant, VariantDef,
+    Access, Adjust, Adjustment, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate,
+    DeriveHelper, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local,
+    Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Struct, ToolModule, Trait,
+    TupleField, Type, TypeAlias, TypeParam, VariantDef,
 };
 
 pub enum DescendPreference {
@@ -224,68 +223,20 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.resolve_variant(record_lit).map(VariantDef::from)
     }
 
-    pub fn file_to_module_def(&self, file: FileId) -> Option<Module> {
-        self.imp.file_to_module_defs(file).next()
+    pub fn to_module_def(&self, file: FileId) -> Option<Module> {
+        self.imp.to_module_def(file).next()
     }
 
-    pub fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
-        self.imp.file_to_module_defs(file)
-    }
-
-    pub fn to_adt_def(&self, a: &ast::Adt) -> Option<Adt> {
-        self.imp.to_def(a).map(Adt::from)
-    }
-
-    pub fn to_const_def(&self, c: &ast::Const) -> Option<Const> {
-        self.imp.to_def(c).map(Const::from)
-    }
-
-    pub fn to_enum_def(&self, e: &ast::Enum) -> Option<Enum> {
-        self.imp.to_def(e).map(Enum::from)
-    }
-
-    pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option<Variant> {
-        self.imp.to_def(v).map(Variant::from)
-    }
-
-    pub fn to_fn_def(&self, f: &ast::Fn) -> Option<Function> {
-        self.imp.to_def(f).map(Function::from)
-    }
-
-    pub fn to_impl_def(&self, i: &ast::Impl) -> Option<Impl> {
-        self.imp.to_def(i).map(Impl::from)
-    }
-
-    pub fn to_macro_def(&self, m: &ast::Macro) -> Option<Macro> {
-        self.imp.to_def(m).map(Macro::from)
-    }
-
-    pub fn to_module_def(&self, m: &ast::Module) -> Option<Module> {
-        self.imp.to_def(m).map(Module::from)
-    }
-
-    pub fn to_static_def(&self, s: &ast::Static) -> Option<Static> {
-        self.imp.to_def(s).map(Static::from)
+    pub fn to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
+        self.imp.to_module_def(file)
     }
 
     pub fn to_struct_def(&self, s: &ast::Struct) -> Option<Struct> {
         self.imp.to_def(s).map(Struct::from)
     }
 
-    pub fn to_trait_alias_def(&self, t: &ast::TraitAlias) -> Option<TraitAlias> {
-        self.imp.to_def(t).map(TraitAlias::from)
-    }
-
-    pub fn to_trait_def(&self, t: &ast::Trait) -> Option<Trait> {
-        self.imp.to_def(t).map(Trait::from)
-    }
-
-    pub fn to_type_alias_def(&self, t: &ast::TypeAlias) -> Option<TypeAlias> {
-        self.imp.to_def(t).map(TypeAlias::from)
-    }
-
-    pub fn to_union_def(&self, u: &ast::Union) -> Option<Union> {
-        self.imp.to_def(u).map(Union::from)
+    pub fn to_impl_def(&self, i: &ast::Impl) -> Option<Impl> {
+        self.imp.to_def(i).map(Impl::from)
     }
 }
 
@@ -1290,7 +1241,7 @@ impl<'db> SemanticsImpl<'db> {
         T::to_def(self, src)
     }
 
-    fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
+    fn to_module_def(&self, file: FileId) -> impl Iterator<Item = Module> {
         self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from)
     }
 
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 4733ea5a35..ef4ed90ce3 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -118,7 +118,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> {
 
 impl SourceToDefCtx<'_, '_> {
     pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> {
-        let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::file_to_module_def");
+        let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::to_module_def");
         let mut mods = SmallVec::new();
         for &crate_id in self.db.relevant_crates(file).iter() {
             // FIXME: inner items
diff --git a/crates/ide-assists/Cargo.toml b/crates/ide-assists/Cargo.toml
index 98961a18de..e1375f9c3e 100644
--- a/crates/ide-assists/Cargo.toml
+++ b/crates/ide-assists/Cargo.toml
@@ -23,7 +23,6 @@ tracing.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 text-edit.workspace = true
-profile.workspace = true
 ide-db.workspace = true
 hir.workspace = true
 
diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs
index e0bcd78c99..7a60287f92 100644
--- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs
+++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs
@@ -116,7 +116,7 @@ impl Field {
     ) -> Option<Field> {
         let db = ctx.sema.db;
 
-        let module = ctx.sema.file_to_module_def(ctx.file_id())?;
+        let module = ctx.sema.to_module_def(ctx.file_id())?;
 
         let (name, range, ty) = match f {
             Either::Left(f) => {
diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs
index 50ec4347dc..2b9ed86e41 100644
--- a/crates/ide-assists/src/handlers/inline_call.rs
+++ b/crates/ide-assists/src/handlers/inline_call.rs
@@ -418,15 +418,24 @@ fn inline(
         let expr: &ast::Expr = expr;
 
         let mut insert_let_stmt = || {
-            let param_ty = param_ty.clone().map(|param_ty| {
-                if sema.hir_file_for(param_ty.syntax()).is_macro() {
-                    ast::Type::cast(insert_ws_into(param_ty.syntax().clone())).unwrap_or(param_ty)
-                } else {
-                    param_ty
+            let param_ty = match param_ty {
+                None => None,
+                Some(param_ty) => {
+                    if sema.hir_file_for(param_ty.syntax()).is_macro() {
+                        if let Some(param_ty) =
+                            ast::Type::cast(insert_ws_into(param_ty.syntax().clone()))
+                        {
+                            Some(param_ty)
+                        } else {
+                            Some(param_ty.clone_for_update())
+                        }
+                    } else {
+                        Some(param_ty.clone_for_update())
+                    }
                 }
-            });
-
-            let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty);
+            };
+            let ty: Option<syntax::ast::Type> =
+                sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty);
 
             let is_self = param
                 .name(sema.db)
@@ -1350,8 +1359,8 @@ macro_rules! define_foo {
 define_foo!();
 fn bar() -> u32 {
     {
-        let x = 0;
-        x
+      let x = 0;
+      x
     }
 }
 "#,
@@ -1664,7 +1673,7 @@ fn main() {
     let a: A = A{};
     let b = {
         let a = a;
-        a as A
+      a as A
     };
 }
 "#,
@@ -1783,7 +1792,7 @@ fn _hash2(self_: &u64, state: &mut u64) {
     {
         let inner_self_: &u64 = &self_;
         let state: &mut u64 = state;
-        _write_u64(state, *inner_self_)
+      _write_u64(state, *inner_self_)
     };
 }
 "#,
diff --git a/crates/ide-assists/src/handlers/inline_macro.rs b/crates/ide-assists/src/handlers/inline_macro.rs
index 4708be6169..0c9e971dd2 100644
--- a/crates/ide-assists/src/handlers/inline_macro.rs
+++ b/crates/ide-assists/src/handlers/inline_macro.rs
@@ -288,11 +288,11 @@ macro_rules! foo {
 }
 fn main() {
     cfg_if!{
-    if #[cfg(test)]{
-        1;
-    }else {
-        1;
-    }
+  if #[cfg(test)]{
+    1;
+  }else {
+    1;
+  }
 };
 }
 "#,
diff --git a/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/crates/ide-assists/src/handlers/move_from_mod_rs.rs
index a256f60c42..917d0b3671 100644
--- a/crates/ide-assists/src/handlers/move_from_mod_rs.rs
+++ b/crates/ide-assists/src/handlers/move_from_mod_rs.rs
@@ -25,7 +25,7 @@ use crate::{
 // ```
 pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?;
-    let module = ctx.sema.file_to_module_def(ctx.file_id())?;
+    let module = ctx.sema.to_module_def(ctx.file_id())?;
     // Enable this assist if the user select all "meaningful" content in the source file
     let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed());
     let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range());
diff --git a/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/crates/ide-assists/src/handlers/move_to_mod_rs.rs
index a8a124eebb..b73270cd05 100644
--- a/crates/ide-assists/src/handlers/move_to_mod_rs.rs
+++ b/crates/ide-assists/src/handlers/move_to_mod_rs.rs
@@ -25,7 +25,7 @@ use crate::{
 // ```
 pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?;
-    let module = ctx.sema.file_to_module_def(ctx.file_id())?;
+    let module = ctx.sema.to_module_def(ctx.file_id())?;
     // Enable this assist if the user select all "meaningful" content in the source file
     let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed());
     let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range());
diff --git a/crates/ide-completion/Cargo.toml b/crates/ide-completion/Cargo.toml
index f2a11276ba..6a4c70d460 100644
--- a/crates/ide-completion/Cargo.toml
+++ b/crates/ide-completion/Cargo.toml
@@ -23,7 +23,6 @@ smallvec.workspace = true
 # local deps
 base-db.workspace = true
 ide-db.workspace = true
-profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 text-edit.workspace = true
diff --git a/crates/ide-completion/src/completions/format_string.rs b/crates/ide-completion/src/completions/format_string.rs
index 5512ac2153..cecbe75391 100644
--- a/crates/ide-completion/src/completions/format_string.rs
+++ b/crates/ide-completion/src/completions/format_string.rs
@@ -1,7 +1,6 @@
 //! Completes identifiers in format string literals.
 
-use hir::{ModuleDef, ScopeDef};
-use ide_db::{syntax_helpers::format_string::is_format_string, SymbolKind};
+use ide_db::syntax_helpers::format_string::is_format_string;
 use itertools::Itertools;
 use syntax::{ast, AstToken, TextRange, TextSize};
 
@@ -34,23 +33,7 @@ pub(crate) fn format_string(
     ctx.locals.iter().for_each(|(name, _)| {
         CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str())
             .add_to(acc, ctx.db);
-    });
-    ctx.scope.process_all_names(&mut |name, scope| {
-        if let ScopeDef::ModuleDef(module_def) = scope {
-            let symbol_kind = match module_def {
-                ModuleDef::Const(..) => SymbolKind::Const,
-                ModuleDef::Static(..) => SymbolKind::Static,
-                _ => return,
-            };
-
-            CompletionItem::new(
-                CompletionItemKind::SymbolKind(symbol_kind),
-                source_range,
-                name.to_smol_str(),
-            )
-            .add_to(acc, ctx.db);
-        }
-    });
+    })
 }
 
 #[cfg(test)]
@@ -127,80 +110,6 @@ fn main() {
     let foobar = 1;
     format_args!("{foobar");
 }
-"#,
-        );
-    }
-
-    #[test]
-    fn completes_constants() {
-        check_edit(
-            "FOOBAR",
-            r#"
-//- minicore: fmt
-fn main() {
-    const FOOBAR: usize = 42;
-    format_args!("{f$0");
-}
-"#,
-            r#"
-fn main() {
-    const FOOBAR: usize = 42;
-    format_args!("{FOOBAR");
-}
-"#,
-        );
-
-        check_edit(
-            "FOOBAR",
-            r#"
-//- minicore: fmt
-fn main() {
-    const FOOBAR: usize = 42;
-    format_args!("{$0");
-}
-"#,
-            r#"
-fn main() {
-    const FOOBAR: usize = 42;
-    format_args!("{FOOBAR");
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn completes_static_constants() {
-        check_edit(
-            "FOOBAR",
-            r#"
-//- minicore: fmt
-fn main() {
-    static FOOBAR: usize = 42;
-    format_args!("{f$0");
-}
-"#,
-            r#"
-fn main() {
-    static FOOBAR: usize = 42;
-    format_args!("{FOOBAR");
-}
-"#,
-        );
-
-        check_edit(
-            "FOOBAR",
-            r#"
-//- minicore: fmt
-fn main() {
-    static FOOBAR: usize = 42;
-    format_args!("{$0");
-}
-"#,
-            r#"
-fn main() {
-    static FOOBAR: usize = 42;
-    format_args!("{FOOBAR");
-}
 "#,
         );
     }
diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs
index 2b2df144d6..f769f72d46 100644
--- a/crates/ide-db/src/apply_change.rs
+++ b/crates/ide-db/src/apply_change.rs
@@ -11,7 +11,7 @@ use profile::{memory_usage, Bytes};
 use rustc_hash::FxHashSet;
 use triomphe::Arc;
 
-use crate::{symbol_index::SymbolsDatabase, Change, RootDatabase};
+use crate::{symbol_index::SymbolsDatabase, ChangeWithProcMacros, RootDatabase};
 
 impl RootDatabase {
     pub fn request_cancellation(&mut self) {
@@ -20,7 +20,7 @@ impl RootDatabase {
         self.synthetic_write(Durability::LOW);
     }
 
-    pub fn apply_change(&mut self, change: Change) {
+    pub fn apply_change(&mut self, change: ChangeWithProcMacros) {
         let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered();
         self.request_cancellation();
         tracing::trace!("apply_change {:?}", change);
diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs
index 4ac8a7c4c4..0b5ad7060e 100644
--- a/crates/ide-db/src/helpers.rs
+++ b/crates/ide-db/src/helpers.rs
@@ -64,7 +64,7 @@ pub fn visit_file_defs(
     cb: &mut dyn FnMut(Definition),
 ) {
     let db = sema.db;
-    let module = match sema.file_to_module_def(file_id) {
+    let module = match sema.to_module_def(file_id) {
         Some(it) => it,
         None => return,
     };
diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs
index 3e6cb7476b..a9f7e58de9 100644
--- a/crates/ide-db/src/lib.rs
+++ b/crates/ide-db/src/lib.rs
@@ -44,7 +44,7 @@ pub mod syntax_helpers {
     pub use parser::LexedStr;
 }
 
-pub use hir::Change;
+pub use hir::ChangeWithProcMacros;
 
 use std::{fmt, mem::ManuallyDrop};
 
diff --git a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
index 97b6d4a572..0b0fc66935 100644
--- a/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
+++ b/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
@@ -20,7 +20,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
     let after = Position::after;
 
     let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
-        (pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent)))
+        (pos(token.clone()), make::tokens::whitespace(&" ".repeat(2 * indent)))
     };
     let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| {
         (pos(token.clone()), make::tokens::single_space())
@@ -41,7 +41,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
                 if indent > 0 {
                     mods.push((
                         Position::after(node.clone()),
-                        make::tokens::whitespace(&" ".repeat(4 * indent)),
+                        make::tokens::whitespace(&" ".repeat(2 * indent)),
                     ));
                 }
                 if node.parent().is_some() {
@@ -91,7 +91,10 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
             LIFETIME_IDENT if is_next(is_text, true) => {
                 mods.push(do_ws(after, tok));
             }
-            AS_KW | DYN_KW | IMPL_KW | CONST_KW | MUT_KW => {
+            MUT_KW if is_next(|it| it == SELF_KW, false) => {
+                mods.push(do_ws(after, tok));
+            }
+            AS_KW | DYN_KW | IMPL_KW | CONST_KW => {
                 mods.push(do_ws(after, tok));
             }
             T![;] if is_next(|it| it != R_CURLY, true) => {
diff --git a/crates/ide-diagnostics/Cargo.toml b/crates/ide-diagnostics/Cargo.toml
index 6976804138..509c5a152f 100644
--- a/crates/ide-diagnostics/Cargo.toml
+++ b/crates/ide-diagnostics/Cargo.toml
@@ -20,7 +20,6 @@ tracing.workspace = true
 once_cell = "1.17.0"
 
 # local deps
-profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 text-edit.workspace = true
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index f92ba576d3..09daefd084 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -200,7 +200,7 @@ fn get_default_constructor(
         }
     }
 
-    let krate = ctx.sema.file_to_module_def(d.file.original_file(ctx.sema.db))?.krate();
+    let krate = ctx.sema.to_module_def(d.file.original_file(ctx.sema.db))?.krate();
     let module = krate.root_module();
 
     // Look for a ::new() associated function
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 6c72dbb5ed..9f4368b04e 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -315,7 +315,7 @@ pub fn diagnostics(
         handlers::json_is_not_rust::json_in_items(&sema, &mut res, file_id, &node, config);
     }
 
-    let module = sema.file_to_module_def(file_id);
+    let module = sema.to_module_def(file_id);
 
     let ctx = DiagnosticsContext { config, sema, resolve };
     if module.is_none() {
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index 9eb5a9db62..17c701ad03 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -308,8 +308,8 @@ f$0oo!();
             expect![[r#"
                 foo!
                 fn some_thing() -> u32 {
-                    let a = 0;
-                    a+10
+                  let a = 0;
+                  a+10
                 }"#]],
         );
     }
@@ -342,13 +342,13 @@ fn main() {
             expect![[r#"
                 match_ast!
                 {
-                    if let Some(it) = ast::TraitDef::cast(container.clone()){}
-                    else if let Some(it) = ast::ImplDef::cast(container.clone()){}
-                    else {
-                        {
-                            continue
-                        }
+                  if let Some(it) = ast::TraitDef::cast(container.clone()){}
+                  else if let Some(it) = ast::ImplDef::cast(container.clone()){}
+                  else {
+                    {
+                      continue
                     }
+                  }
                 }"#]],
         );
     }
@@ -397,12 +397,12 @@ fn main() {
             expect![[r#"
                 foo!
                 {
-                    macro_rules! bar {
-                        () => {
-                            42
-                        }
+                  macro_rules! bar {
+                    () => {
+                      42
                     }
-                    42
+                  }
+                  42
                 }"#]],
         );
     }
@@ -482,16 +482,16 @@ struct Foo {}
             expect![[r#"
                 Clone
                 impl < >$crate::clone::Clone for Foo< >where {
-                    fn clone(&self) -> Self {
-                        match self {
-                            Foo{}
-                             => Foo{}
-                            ,
+                  fn clone(&self) -> Self {
+                    match self {
+                      Foo{}
+                       => Foo{}
+                      ,
 
-                            }
-                    }
+                      }
+                  }
 
-                    }"#]],
+                  }"#]],
         );
     }
 
@@ -534,16 +534,16 @@ struct Foo {}
             expect![[r#"
                 Clone
                 impl < >$crate::clone::Clone for Foo< >where {
-                    fn clone(&self) -> Self {
-                        match self {
-                            Foo{}
-                             => Foo{}
-                            ,
+                  fn clone(&self) -> Self {
+                    match self {
+                      Foo{}
+                       => Foo{}
+                      ,
 
-                            }
-                    }
+                      }
+                  }
 
-                    }"#]],
+                  }"#]],
         );
     }
 }
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index a076c7ca9f..4eb4acdf18 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -61,7 +61,7 @@ use std::ffi::OsStr;
 
 use cfg::CfgOptions;
 use fetch_crates::CrateInfo;
-use hir::Change;
+use hir::ChangeWithProcMacros;
 use ide_db::{
     base_db::{
         salsa::{self, ParallelDatabase},
@@ -184,7 +184,7 @@ impl AnalysisHost {
 
     /// Applies changes to the current state of the world. If there are
     /// outstanding snapshots, they will be canceled.
-    pub fn apply_change(&mut self, change: Change) {
+    pub fn apply_change(&mut self, change: ChangeWithProcMacros) {
         self.db.apply_change(change);
     }
 
@@ -239,7 +239,7 @@ impl Analysis {
         file_set.insert(file_id, VfsPath::new_virtual_path("/main.rs".to_owned()));
         let source_root = SourceRoot::new_local(file_set);
 
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.set_roots(vec![source_root]);
         let mut crate_graph = CrateGraph::default();
         // FIXME: cfg options
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs
index ce7a6779e2..f67aea2d5b 100644
--- a/crates/ide/src/parent_module.rs
+++ b/crates/ide/src/parent_module.rs
@@ -48,7 +48,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
             .flat_map(|module| NavigationTarget::from_module_to_decl(db, module))
             .collect(),
         None => sema
-            .file_to_module_defs(position.file_id)
+            .to_module_defs(position.file_id)
             .flat_map(|module| NavigationTarget::from_module_to_decl(db, module))
             .collect(),
     }
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 8c2ae327c7..f78153df38 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -156,7 +156,7 @@ pub(crate) fn will_rename_file(
     new_name_stem: &str,
 ) -> Option<SourceChange> {
     let sema = Semantics::new(db);
-    let module = sema.file_to_module_def(file_id)?;
+    let module = sema.to_module_def(file_id)?;
     let def = Definition::Module(module);
     let mut change = if is_raw_identifier(new_name_stem) {
         def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()?
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 5fe46444ff..ae107a9604 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -178,7 +178,7 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
         }
     });
 
-    sema.file_to_module_defs(file_id)
+    sema.to_module_defs(file_id)
         .map(|it| runnable_mod_outline_definition(&sema, it))
         .for_each(|it| add_opt(it, None));
 
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index d2bd3bab14..dfcbaf54d4 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -223,7 +223,7 @@ fn traverse(
     krate: hir::Crate,
     range_to_highlight: TextRange,
 ) {
-    let is_unlinked = sema.file_to_module_def(file_id).is_none();
+    let is_unlinked = sema.to_module_def(file_id).is_none();
     let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default();
 
     enum AttrOrDerive {
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index 2b5f515c3a..29c1251cce 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -11,7 +11,7 @@ use hir_expand::proc_macro::{
 };
 use ide_db::{
     base_db::{CrateGraph, Env, SourceRoot},
-    prime_caches, Change, FxHashMap, RootDatabase,
+    prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase,
 };
 use itertools::Itertools;
 use proc_macro_api::{MacroDylib, ProcMacroServer};
@@ -314,7 +314,7 @@ fn load_crate_graph(
 
     let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
     let mut db = RootDatabase::new(lru_cap);
-    let mut analysis_change = Change::new();
+    let mut analysis_change = ChangeWithProcMacros::new();
 
     db.enable_proc_attr_macros();
 
diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml
index e74b340126..1f84e3f3af 100644
--- a/crates/parser/Cargo.toml
+++ b/crates/parser/Cargo.toml
@@ -15,6 +15,7 @@ doctest = false
 drop_bomb = "0.1.5"
 ra-ap-rustc_lexer.workspace = true
 limit.workspace = true
+tracing = { workspace = true, optional = true }
 
 [dev-dependencies]
 expect-test = "1.4.0"
@@ -23,6 +24,7 @@ stdx.workspace = true
 sourcegen.workspace = true
 
 [features]
+default = ["tracing"]
 in-rust-tree = []
 
 [lints]
diff --git a/crates/parser/src/lexed_str.rs b/crates/parser/src/lexed_str.rs
index 2da9184693..48e4c8a622 100644
--- a/crates/parser/src/lexed_str.rs
+++ b/crates/parser/src/lexed_str.rs
@@ -31,6 +31,7 @@ struct LexError {
 
 impl<'a> LexedStr<'a> {
     pub fn new(text: &'a str) -> LexedStr<'a> {
+        let _p = tracing::span!(tracing::Level::INFO, "LexedStr::new").entered();
         let mut conv = Converter::new(text);
         if let Some(shebang_len) = rustc_lexer::strip_shebang(text) {
             conv.res.push(SHEBANG, conv.offset);
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index 3ca285e787..86c771c000 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -87,6 +87,7 @@ pub enum TopEntryPoint {
 
 impl TopEntryPoint {
     pub fn parse(&self, input: &Input) -> Output {
+        let _p = tracing::span!(tracing::Level::INFO, "TopEntryPoint::parse", ?self).entered();
         let entry_point: fn(&'_ mut parser::Parser<'_>) = match self {
             TopEntryPoint::SourceFile => grammar::entry::top::source_file,
             TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts,
diff --git a/crates/parser/src/shortcuts.rs b/crates/parser/src/shortcuts.rs
index 57005a6834..680a70997d 100644
--- a/crates/parser/src/shortcuts.rs
+++ b/crates/parser/src/shortcuts.rs
@@ -26,6 +26,7 @@ pub enum StrStep<'a> {
 
 impl LexedStr<'_> {
     pub fn to_input(&self) -> crate::Input {
+        let _p = tracing::span!(tracing::Level::INFO, "LexedStr::to_input").entered();
         let mut res = crate::Input::default();
         let mut was_joint = false;
         for i in 0..self.len() {
diff --git a/crates/proc-macro-api/Cargo.toml b/crates/proc-macro-api/Cargo.toml
index cf01b94c0a..e98d70776c 100644
--- a/crates/proc-macro-api/Cargo.toml
+++ b/crates/proc-macro-api/Cargo.toml
@@ -32,7 +32,6 @@ indexmap = "2.1.0"
 paths.workspace = true
 tt.workspace = true
 stdx.workspace = true
-profile.workspace = true
 text-size.workspace = true
 span.workspace = true
 # Ideally this crate would not depend on salsa things, but we need span information here which wraps
diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs
index 3639981560..a3fdb72a6d 100644
--- a/crates/profile/src/lib.rs
+++ b/crates/profile/src/lib.rs
@@ -23,29 +23,6 @@ pub use countme::Count;
 
 thread_local!(static IN_SCOPE: RefCell<bool> = const { RefCell::new(false) });
 
-/// Allows to check if the current code is within some dynamic scope, can be
-/// useful during debugging to figure out why a function is called.
-pub struct Scope {
-    prev: bool,
-}
-
-impl Scope {
-    #[must_use]
-    pub fn enter() -> Scope {
-        let prev = IN_SCOPE.with(|slot| std::mem::replace(&mut *slot.borrow_mut(), true));
-        Scope { prev }
-    }
-    pub fn is_active() -> bool {
-        IN_SCOPE.with(|slot| *slot.borrow())
-    }
-}
-
-impl Drop for Scope {
-    fn drop(&mut self) {
-        IN_SCOPE.with(|slot| *slot.borrow_mut() = self.prev);
-    }
-}
-
 /// A wrapper around google_cpu_profiler.
 ///
 /// Usage:
diff --git a/crates/project-model/Cargo.toml b/crates/project-model/Cargo.toml
index 3552ed1916..924a4a89e2 100644
--- a/crates/project-model/Cargo.toml
+++ b/crates/project-model/Cargo.toml
@@ -27,7 +27,6 @@ itertools.workspace = true
 base-db.workspace = true
 cfg.workspace = true
 paths.workspace = true
-profile.workspace = true
 stdx.workspace = true
 toolchain.workspace = true
 
@@ -35,4 +34,4 @@ toolchain.workspace = true
 expect-test = "1.4.0"
 
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 7e027c9f92..8762564a8f 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -371,7 +371,7 @@ impl flags::AnalysisStats {
 
             let parse = sema.parse(file_id);
             let file_txt = db.file_text(file_id);
-            let path = vfs.file_path(file_id).as_path().unwrap();
+            let path = vfs.file_path(file_id).as_path().unwrap().to_owned();
 
             for node in parse.syntax().descendants() {
                 let expr = match syntax::ast::Expr::cast(node.clone()) {
@@ -446,7 +446,7 @@ impl flags::AnalysisStats {
                     edit.apply(&mut txt);
 
                     if self.validate_term_search {
-                        std::fs::write(path, txt).unwrap();
+                        std::fs::write(&path, txt).unwrap();
 
                         let res = ws.run_build_scripts(&cargo_config, &|_| ()).unwrap();
                         if let Some(err) = res.error() {
@@ -495,7 +495,7 @@ impl flags::AnalysisStats {
             }
             // Revert file back to original state
             if self.validate_term_search {
-                std::fs::write(path, file_txt.to_string()).unwrap();
+                std::fs::write(&path, file_txt.to_string()).unwrap();
             }
 
             bar.inc(1);
@@ -1077,12 +1077,12 @@ fn location_csv_pat(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, pat_id: Pa
     format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col)
 }
 
-fn expr_syntax_range<'a>(
+fn expr_syntax_range(
     db: &RootDatabase,
-    vfs: &'a Vfs,
+    vfs: &Vfs,
     sm: &BodySourceMap,
     expr_id: ExprId,
-) -> Option<(&'a VfsPath, LineCol, LineCol)> {
+) -> Option<(VfsPath, LineCol, LineCol)> {
     let src = sm.expr_syntax(expr_id);
     if let Ok(src) = src {
         let root = db.parse_or_expand(src.file_id);
@@ -1098,12 +1098,12 @@ fn expr_syntax_range<'a>(
         None
     }
 }
-fn pat_syntax_range<'a>(
+fn pat_syntax_range(
     db: &RootDatabase,
-    vfs: &'a Vfs,
+    vfs: &Vfs,
     sm: &BodySourceMap,
     pat_id: PatId,
-) -> Option<(&'a VfsPath, LineCol, LineCol)> {
+) -> Option<(VfsPath, LineCol, LineCol)> {
     let src = sm.pat_syntax(pat_id);
     if let Ok(src) = src {
         let root = db.parse_or_expand(src.file_id);
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 9bcee6465a..eb47279205 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -7,7 +7,7 @@ use std::{collections::hash_map::Entry, time::Instant};
 
 use crossbeam_channel::{unbounded, Receiver, Sender};
 use flycheck::FlycheckHandle;
-use hir::Change;
+use hir::ChangeWithProcMacros;
 use ide::{Analysis, AnalysisHost, Cancellable, FileId};
 use ide_db::base_db::{CrateId, ProcMacroPaths};
 use load_cargo::SourceRootConfig;
@@ -238,7 +238,7 @@ impl GlobalState {
 
         let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default();
         let (change, modified_rust_files, workspace_structure_change) = {
-            let mut change = Change::new();
+            let mut change = ChangeWithProcMacros::new();
             let mut guard = self.vfs.write();
             let changed_files = guard.0.take_changes();
             if changed_files.is_empty() {
@@ -297,7 +297,7 @@ impl GlobalState {
             let mut bytes = vec![];
             let mut modified_rust_files = vec![];
             for file in changed_files {
-                let vfs_path = vfs.file_path(file.file_id);
+                let vfs_path = &vfs.file_path(file.file_id);
                 if let Some(path) = vfs_path.as_path() {
                     let path = path.to_path_buf();
                     if reload::should_refresh_for_change(&path, file.kind()) {
@@ -481,7 +481,7 @@ impl GlobalStateSnapshot {
     }
 
     pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Url {
-        let mut base = self.vfs_read().file_path(path.anchor).clone();
+        let mut base = self.vfs_read().file_path(path.anchor);
         base.pop();
         let path = base.join(&path.path).unwrap();
         let path = path.as_path().unwrap();
@@ -489,7 +489,7 @@ impl GlobalStateSnapshot {
     }
 
     pub(crate) fn file_id_to_file_path(&self, file_id: FileId) -> vfs::VfsPath {
-        self.vfs_read().file_path(file_id).clone()
+        self.vfs_read().file_path(file_id)
     }
 
     pub(crate) fn cargo_target_for_crate_root(
@@ -497,7 +497,7 @@ impl GlobalStateSnapshot {
         crate_id: CrateId,
     ) -> Option<(&CargoWorkspace, Target)> {
         let file_id = self.analysis.crate_root(crate_id).ok()?;
-        let path = self.vfs_read().file_path(file_id).clone();
+        let path = self.vfs_read().file_path(file_id);
         let path = path.as_path()?;
         self.workspaces.iter().find_map(|ws| match ws {
             ProjectWorkspace::Cargo { cargo, .. } => {
diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 0e005975fb..04a0439542 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/crates/rust-analyzer/src/handlers/request.rs
@@ -2097,7 +2097,7 @@ pub(crate) fn fetch_dependency_list(
         .into_iter()
         .filter_map(|it| {
             let root_file_path = state.file_id_to_file_path(it.root_file_id);
-            crate_path(&root_file_path).and_then(to_url).map(|path| CrateInfoResult {
+            crate_path(root_file_path).and_then(to_url).map(|path| CrateInfoResult {
                 name: it.name,
                 version: it.version,
                 path,
@@ -2118,7 +2118,7 @@ pub(crate) fn fetch_dependency_list(
 /// An `Option` value representing the path to the directory of the crate with the given
 /// name, if such a crate is found. If no crate with the given name is found, this function
 /// returns `None`.
-fn crate_path(root_file_path: &VfsPath) -> Option<VfsPath> {
+fn crate_path(root_file_path: VfsPath) -> Option<VfsPath> {
     let mut current_dir = root_file_path.parent();
     while let Some(path) = current_dir {
         let cargo_toml_path = path.join("../Cargo.toml")?;
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index 9d69217520..008c63c35a 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -10,7 +10,7 @@
 //! in release mode in VS Code. There's however "rust-analyzer: Copy Run Command Line"
 //! which you can use to paste the command in terminal and add `--release` manually.
 
-use hir::Change;
+use hir::ChangeWithProcMacros;
 use ide::{AnalysisHost, CallableSnippets, CompletionConfig, FilePosition, TextSize};
 use ide_db::{
     imports::insert_use::{ImportGranularity, InsertUseConfig},
@@ -55,19 +55,19 @@ fn integrated_highlighting_benchmark() {
         vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
     };
 
+    crate::tracing::hprof::init("*>100");
+
     {
         let _it = stdx::timeit("initial");
         let analysis = host.analysis();
         analysis.highlight_as_html(file_id, false).unwrap();
     }
 
-    crate::tracing::hprof::init("*>100");
-
     {
         let _it = stdx::timeit("change");
         let mut text = host.analysis().file_text(file_id).unwrap().to_string();
         text.push_str("\npub fn _dummy() {}\n");
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.change_file(file_id, Some(Arc::from(text)));
         host.apply_change(change);
     }
@@ -120,7 +120,7 @@ fn integrated_completion_benchmark() {
         let completion_offset =
             patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)")
                 + "sel".len();
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.change_file(file_id, Some(Arc::from(text)));
         host.apply_change(change);
         completion_offset
@@ -163,7 +163,7 @@ fn integrated_completion_benchmark() {
         let completion_offset =
             patch(&mut text, "sel;\ndb.struct_data(self.id)", ";sel;\ndb.struct_data(self.id)")
                 + ";sel".len();
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.change_file(file_id, Some(Arc::from(text)));
         host.apply_change(change);
         completion_offset
@@ -205,7 +205,7 @@ fn integrated_completion_benchmark() {
         let completion_offset =
             patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)")
                 + "self.".len();
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.change_file(file_id, Some(Arc::from(text)));
         host.apply_change(change);
         completion_offset
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index f6bc032c01..95d51baab3 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -16,7 +16,7 @@
 use std::{iter, mem};
 
 use flycheck::{FlycheckConfig, FlycheckHandle};
-use hir::{db::DefDatabase, Change, ProcMacros};
+use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros};
 use ide::CrateId;
 use ide_db::{
     base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version},
@@ -357,7 +357,7 @@ impl GlobalState {
     }
 
     pub(crate) fn set_proc_macros(&mut self, proc_macros: ProcMacros) {
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.set_proc_macros(proc_macros);
         self.analysis_host.apply_change(change);
     }
@@ -548,7 +548,7 @@ impl GlobalState {
 
             ws_to_crate_graph(&self.workspaces, self.config.extra_env(), load)
         };
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         if self.config.expand_proc_macros() {
             change.set_proc_macros(
                 crate_graph
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index a0fd73ee13..9a8d73cf7f 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -27,7 +27,6 @@ tracing.workspace = true
 ra-ap-rustc_lexer.workspace = true
 
 parser.workspace = true
-profile.workspace = true
 stdx.workspace = true
 text-edit.workspace = true
 
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index b755de86d3..e8bb9ee938 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -168,6 +168,7 @@ pub use crate::ast::SourceFile;
 
 impl SourceFile {
     pub fn parse(text: &str) -> Parse<SourceFile> {
+        let _p = tracing::span!(tracing::Level::INFO, "SourceFile::parse").entered();
         let (green, mut errors) = parsing::parse_text(text);
         let root = SyntaxNode::new_root(green.clone());
 
diff --git a/crates/syntax/src/parsing.rs b/crates/syntax/src/parsing.rs
index 1250b5274c..d750476f63 100644
--- a/crates/syntax/src/parsing.rs
+++ b/crates/syntax/src/parsing.rs
@@ -10,6 +10,7 @@ use crate::{syntax_node::GreenNode, SyntaxError, SyntaxTreeBuilder};
 pub(crate) use crate::parsing::reparsing::incremental_reparse;
 
 pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) {
+    let _p = tracing::span!(tracing::Level::INFO, "parse_text").entered();
     let lexed = parser::LexedStr::new(text);
     let parser_input = lexed.to_input();
     let parser_output = parser::TopEntryPoint::SourceFile.parse(&parser_input);
@@ -21,6 +22,7 @@ pub(crate) fn build_tree(
     lexed: parser::LexedStr<'_>,
     parser_output: parser::Output,
 ) -> (GreenNode, Vec<SyntaxError>, bool) {
+    let _p = tracing::span!(tracing::Level::INFO, "build_tree").entered();
     let mut builder = SyntaxTreeBuilder::default();
 
     let is_eof = lexed.intersperse_trivia(&parser_output, &mut |step| match step {
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
index 5c5b26f525..5b3f449eee 100644
--- a/crates/syntax/src/validation.rs
+++ b/crates/syntax/src/validation.rs
@@ -16,6 +16,7 @@ use crate::{
 };
 
 pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
+    let _p = tracing::span!(tracing::Level::INFO, "parser::validate").entered();
     // FIXME:
     // * Add unescape validation of raw string literals and raw byte string literals
     // * Add validation of doc comments are being attached to nodes
diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs
index 824ce39870..34a85818eb 100644
--- a/crates/vfs/src/lib.rs
+++ b/crates/vfs/src/lib.rs
@@ -163,8 +163,8 @@ impl Vfs {
     /// # Panics
     ///
     /// Panics if the id is not present in the `Vfs`.
-    pub fn file_path(&self, file_id: FileId) -> &VfsPath {
-        self.interner.lookup(file_id)
+    pub fn file_path(&self, file_id: FileId) -> VfsPath {
+        self.interner.lookup(file_id).clone()
     }
 
     /// Returns an iterator over the stored ids and their corresponding paths.
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index 3fc63fc7d8..d9c6b6ac45 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -81,9 +81,8 @@ async function getDebugConfiguration(
     if (!editor) return;
 
     const knownEngines: Record<string, DebugConfigProvider> = {
-        "ms-vscode.cpptools": getCCppDebugConfig,
-        "vadimcn.vscode-lldb": getCodeLldbDebugConfig,
-        "webfreak.debug": getNativeDebugConfig,
+        "vadimcn.vscode-lldb": getLldbDebugConfig,
+        "ms-vscode.cpptools": getCppvsDebugConfig,
     };
     const debugOptions = ctx.config.debug;
 
@@ -98,14 +97,12 @@ async function getDebugConfiguration(
     }
 
     if (!debugEngine) {
-        const commandCCpp: string = createCommandLink("ms-vscode.cpptools");
         const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb");
-        const commandNativeDebug: string = createCommandLink("webfreak.debug");
+        const commandCpp: string = createCommandLink("ms-vscode.cpptools");
 
         await vscode.window.showErrorMessage(
             `Install [CodeLLDB](command:${commandCodeLLDB} "Open CodeLLDB")` +
-                `, [C/C++](command:${commandCCpp} "Open C/C++") ` +
-                `or [Native Debug](command:${commandNativeDebug} "Open Native Debug") for debugging.`,
+                ` or [C/C++](command:${commandCpp} "Open C/C++") extension for debugging.`,
         );
         return;
     }
@@ -187,26 +184,7 @@ async function getDebugExecutableInfo(
     return executableInfo;
 }
 
-function getCCppDebugConfig(
-    runnable: ra.Runnable,
-    executable: string,
-    cargoWorkspace: string,
-    env: Record<string, string>,
-    sourceFileMap?: Record<string, string>,
-): vscode.DebugConfiguration {
-    return {
-        type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg",
-        request: "launch",
-        name: runnable.label,
-        program: executable,
-        args: runnable.args.executableArgs,
-        cwd: cargoWorkspace || runnable.args.workspaceRoot,
-        sourceFileMap,
-        env,
-    };
-}
-
-function getCodeLldbDebugConfig(
+function getLldbDebugConfig(
     runnable: ra.Runnable,
     executable: string,
     cargoWorkspace: string,
@@ -226,37 +204,21 @@ function getCodeLldbDebugConfig(
     };
 }
 
-function getNativeDebugConfig(
+function getCppvsDebugConfig(
     runnable: ra.Runnable,
     executable: string,
     cargoWorkspace: string,
     env: Record<string, string>,
-    _sourceFileMap?: Record<string, string>,
+    sourceFileMap?: Record<string, string>,
 ): vscode.DebugConfiguration {
     return {
-        type: "gdb",
+        type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg",
         request: "launch",
         name: runnable.label,
-        target: executable,
-        // See https://github.com/WebFreak001/code-debug/issues/359
-        arguments: quote(runnable.args.executableArgs),
+        program: executable,
+        args: runnable.args.executableArgs,
         cwd: cargoWorkspace || runnable.args.workspaceRoot,
+        sourceFileMap,
         env,
-        valuesFormatting: "prettyPrinters",
     };
 }
-
-// Based on https://github.com/ljharb/shell-quote/blob/main/quote.js
-function quote(xs: string[]) {
-    return xs
-        .map(function (s) {
-            if (/["\s]/.test(s) && !/'/.test(s)) {
-                return "'" + s.replace(/(['\\])/g, "\\$1") + "'";
-            }
-            if (/["'\s]/.test(s)) {
-                return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"';
-            }
-            return s.replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
-        })
-        .join(" ");
-}
diff --git a/lib/lsp-server/src/req_queue.rs b/lib/lsp-server/src/req_queue.rs
index 347a9fb6fb..7b47f5388b 100644
--- a/lib/lsp-server/src/req_queue.rs
+++ b/lib/lsp-server/src/req_queue.rs
@@ -37,7 +37,7 @@ impl<I> Incoming<I> {
     }
 
     pub fn cancel(&mut self, id: RequestId) -> Option<Response> {
-        let _data = self.complete(&id)?;
+        let _data = self.complete(id.clone())?;
         let error = ResponseError {
             code: ErrorCode::RequestCanceled as i32,
             message: "canceled by client".to_owned(),
@@ -46,8 +46,8 @@ impl<I> Incoming<I> {
         Some(Response { id, result: None, error: Some(error) })
     }
 
-    pub fn complete(&mut self, id: &RequestId) -> Option<I> {
-        self.pending.remove(id)
+    pub fn complete(&mut self, id: RequestId) -> Option<I> {
+        self.pending.remove(&id)
     }
 
     pub fn is_completed(&self, id: &RequestId) -> bool {


Test patch:
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 3411133f50..b9ae89cc18 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -6366,8 +6366,8 @@ fn main() { $0V; }
 
             ```rust
             pub const V: i8 = {
-                let e = 123;
-                f(e)
+              let e = 123;
+              f(e)
             }
             ```
         "#]],
@@ -6393,7 +6393,7 @@ fn main() { $0V; }
 
             ```rust
             pub static V: i8 = {
-                let e = 123;
+              let e = 123;
             }
             ```
         "#]],
diff --git a/crates/rust-analyzer/src/cli/rustc_tests.rs b/crates/rust-analyzer/src/cli/rustc_tests.rs
index 9276d241af..7ad87ab97f 100644
--- a/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -5,7 +5,7 @@ use std::thread::Builder;
 use std::time::{Duration, Instant};
 use std::{cell::RefCell, fs::read_to_string, panic::AssertUnwindSafe, path::PathBuf};
 
-use hir::{Change, Crate};
+use hir::{ChangeWithProcMacros, Crate};
 use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig};
 use itertools::Either;
 use profile::StopWatch;
@@ -122,7 +122,7 @@ impl Tester {
             FxHashMap::default()
         };
         let text = read_to_string(&p).unwrap();
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         // Ignore unstable tests, since they move too fast and we do not intend to support all of them.
         let mut ignore_test = text.contains("#![feature");
         // Ignore test with extern crates, as this infra don't support them yet.
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index 58a0e48bc4..ca3007d437 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -7,7 +7,7 @@ use base_db::{
 };
 use cfg::CfgOptions;
 use hir_expand::{
-    change::Change,
+    change::ChangeWithProcMacros,
     db::ExpandDatabase,
     proc_macro::{
         ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacros,
@@ -103,7 +103,7 @@ impl<DB: ExpandDatabase + SourceDatabaseExt + Default + 'static> WithFixture for
 pub struct ChangeFixture {
     pub file_position: Option<(FileId, RangeOrOffset)>,
     pub files: Vec<FileId>,
-    pub change: Change,
+    pub change: ChangeWithProcMacros,
 }
 
 const SOURCE_ROOT_PREFIX: &str = "/";
@@ -149,15 +149,15 @@ impl ChangeFixture {
         for entry in fixture {
             let text = if entry.text.contains(CURSOR_MARKER) {
                 if entry.text.contains(ESCAPED_CURSOR_MARKER) {
-                    entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER).into()
+                    entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER)
                 } else {
                     let (range_or_offset, text) = extract_range_or_offset(&entry.text);
                     assert!(file_position.is_none());
                     file_position = Some((file_id, range_or_offset));
-                    text.into()
+                    text
                 }
             } else {
-                entry.text.as_str().into()
+                entry.text.clone()
             };
 
             let meta = FileMeta::from_fixture(entry, current_source_root_kind);
@@ -195,10 +195,7 @@ impl ChangeFixture {
                 let prev = crates.insert(crate_name.clone(), crate_id);
                 assert!(prev.is_none(), "multiple crates with same name: {}", crate_name);
                 for dep in meta.deps {
-                    let prelude = match &meta.extern_prelude {
-                        Some(v) => v.contains(&dep),
-                        None => true,
-                    };
+                    let prelude = meta.extern_prelude.contains(&dep);
                     let dep = CrateName::normalize_dashes(&dep);
                     crate_deps.push((crate_name.clone(), dep, prelude))
                 }
@@ -209,7 +206,7 @@ impl ChangeFixture {
                 default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
             }
 
-            source_change.change_file(file_id, Some(text));
+            source_change.change_file(file_id, Some(text.into()));
             let path = VfsPath::new_virtual_path(meta.path);
             file_set.insert(file_id, path);
             files.push(file_id);
@@ -320,7 +317,7 @@ impl ChangeFixture {
         };
         roots.push(root);
 
-        let mut change = Change {
+        let mut change = ChangeWithProcMacros {
             source_change,
             proc_macros: proc_macros.is_empty().not().then_some(proc_macros),
             toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()),
@@ -446,7 +443,7 @@ struct FileMeta {
     path: String,
     krate: Option<(String, CrateOrigin, Option<String>)>,
     deps: Vec<String>,
-    extern_prelude: Option<Vec<String>>,
+    extern_prelude: Vec<String>,
     cfg: CfgOptions,
     edition: Edition,
     env: Env,
@@ -476,7 +473,7 @@ impl FileMeta {
         Self {
             path: f.path,
             krate: f.krate.map(|it| parse_crate(it, current_source_root_kind, f.library)),
-            extern_prelude: f.extern_prelude,
+            extern_prelude: f.extern_prelude.unwrap_or_else(|| deps.clone()),
             deps,
             cfg,
             edition: f.edition.map_or(Edition::CURRENT, |v| Edition::from_str(&v).unwrap()),