From 071fe4e4e921db993de559e9043713e842e4b15b Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Wed, 20 Dec 2023 21:24:20 +0100
Subject: [PATCH 1/4] Move Intern and Lookup traits to hir-expand

---
 crates/hir-def/src/attr.rs     |  21 ++---
 crates/hir-def/src/lib.rs      |  83 ++++++++------------
 crates/hir-expand/src/eager.rs |  11 +--
 crates/hir-expand/src/lib.rs   | 139 ++++++++++++++++++++++-----------
 crates/hir/src/lib.rs          |  10 ++-
 crates/hir/src/symbols.rs      |   5 +-
 6 files changed, 152 insertions(+), 117 deletions(-)

diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index 942b28fc1450..26f76afb1f09 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -637,9 +637,12 @@ impl<'attr> AttrQuery<'attr> {
     }
 }
 
-fn any_has_attrs(
-    db: &dyn DefDatabase,
-    id: impl Lookup<Data = impl HasSource<Value = impl ast::HasAttrs>>,
+fn any_has_attrs<'db>(
+    db: &(dyn DefDatabase + 'db),
+    id: impl Lookup<
+        Database<'db> = dyn DefDatabase + 'db,
+        Data = impl HasSource<Value = impl ast::HasAttrs>,
+    >,
 ) -> InFile<ast::AnyHasAttrs> {
     id.lookup(db).source(db).map(ast::AnyHasAttrs::new)
 }
@@ -650,17 +653,17 @@ fn attrs_from_item_tree<N: ItemTreeNode>(db: &dyn DefDatabase, id: ItemTreeId<N>
     tree.raw_attrs(mod_item.into()).clone()
 }
 
-fn attrs_from_item_tree_loc<N: ItemTreeNode>(
-    db: &dyn DefDatabase,
-    lookup: impl Lookup<Data = ItemLoc<N>>,
+fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>(
+    db: &(dyn DefDatabase + 'db),
+    lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = ItemLoc<N>>,
 ) -> RawAttrs {
     let id = lookup.lookup(db).id;
     attrs_from_item_tree(db, id)
 }
 
-fn attrs_from_item_tree_assoc<N: ItemTreeNode>(
-    db: &dyn DefDatabase,
-    lookup: impl Lookup<Data = AssocItemLoc<N>>,
+fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>(
+    db: &(dyn DefDatabase + 'db),
+    lookup: impl Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>>,
 ) -> RawAttrs {
     let id = lookup.lookup(db).id;
     attrs_from_item_tree(db, id)
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 2baf46073433..9a7d406dfd59 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -72,6 +72,7 @@ use hir_expand::{
     builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
     db::ExpandDatabase,
     eager::expand_eager_macro_input,
+    impl_intern_lookup,
     name::Name,
     proc_macro::{CustomProcMacroExpander, ProcMacroKind},
     AstId, ExpandError, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind,
@@ -84,11 +85,12 @@ use span::Span;
 use stdx::impl_from;
 use syntax::{ast, AstNode};
 
-pub use hir_expand::tt;
+pub use hir_expand::{tt, Intern, Lookup};
 
 use crate::{
     builtin_type::BuiltinType,
     data::adt::VariantData,
+    db::DefDatabase,
     item_tree::{
         Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules,
         Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use,
@@ -102,7 +104,7 @@ pub struct CrateRootModuleId {
 }
 
 impl CrateRootModuleId {
-    pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> {
+    pub fn def_map(&self, db: &dyn DefDatabase) -> Arc<DefMap> {
         db.crate_def_map(self.krate)
     }
 
@@ -164,7 +166,7 @@ pub struct ModuleId {
 }
 
 impl ModuleId {
-    pub fn def_map(self, db: &dyn db::DefDatabase) -> Arc<DefMap> {
+    pub fn def_map(self, db: &dyn DefDatabase) -> Arc<DefMap> {
         match self.block {
             Some(block) => db.block_def_map(block),
             None => db.crate_def_map(self.krate),
@@ -175,7 +177,7 @@ impl ModuleId {
         self.krate
     }
 
-    pub fn name(self, db: &dyn db::DefDatabase) -> Option<Name> {
+    pub fn name(self, db: &dyn DefDatabase) -> Option<Name> {
         let def_map = self.def_map(db);
         let parent = def_map[self.local_id].parent?;
         def_map[parent].children.iter().find_map(|(name, module_id)| {
@@ -187,7 +189,7 @@ impl ModuleId {
         })
     }
 
-    pub fn containing_module(self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
+    pub fn containing_module(self, db: &dyn DefDatabase) -> Option<ModuleId> {
         self.def_map(db).containing_module(self.local_id)
     }
 
@@ -264,20 +266,7 @@ impl<N: ItemTreeNode> Hash for AssocItemLoc<N> {
 macro_rules! impl_intern {
     ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
         impl_intern_key!($id);
-
-        impl Intern for $loc {
-            type ID = $id;
-            fn intern(self, db: &dyn db::DefDatabase) -> $id {
-                db.$intern(self)
-            }
-        }
-
-        impl Lookup for $id {
-            type Data = $loc;
-            fn lookup(&self, db: &dyn db::DefDatabase) -> $loc {
-                db.$lookup(*self)
-            }
-        }
+        impl_intern_lookup!(DefDatabase, $id, $loc, $intern, $lookup);
     };
 }
 
@@ -511,7 +500,7 @@ pub enum MacroId {
 impl_from!(Macro2Id, MacroRulesId, ProcMacroId for MacroId);
 
 impl MacroId {
-    pub fn is_attribute(self, db: &dyn db::DefDatabase) -> bool {
+    pub fn is_attribute(self, db: &dyn DefDatabase) -> bool {
         matches!(self, MacroId::ProcMacroId(it) if it.lookup(db).kind == ProcMacroKind::Attr)
     }
 }
@@ -723,7 +712,7 @@ impl PartialEq for InTypeConstLoc {
 }
 
 impl InTypeConstId {
-    pub fn source(&self, db: &dyn db::DefDatabase) -> ast::ConstArg {
+    pub fn source(&self, db: &dyn DefDatabase) -> ast::ConstArg {
         let src = self.lookup(db).id;
         let file_id = src.file_id;
         let root = &db.parse_or_expand(file_id);
@@ -743,7 +732,7 @@ pub enum GeneralConstId {
 impl_from!(ConstId, ConstBlockId, InTypeConstId for GeneralConstId);
 
 impl GeneralConstId {
-    pub fn generic_def(self, db: &dyn db::DefDatabase) -> Option<GenericDefId> {
+    pub fn generic_def(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
         match self {
             GeneralConstId::ConstId(it) => Some(it.into()),
             GeneralConstId::ConstBlockId(it) => it.lookup(db).parent.as_generic_def_id(),
@@ -751,7 +740,7 @@ impl GeneralConstId {
         }
     }
 
-    pub fn name(self, db: &dyn db::DefDatabase) -> String {
+    pub fn name(self, db: &dyn DefDatabase) -> String {
         match self {
             GeneralConstId::ConstId(const_id) => db
                 .const_data(const_id)
@@ -934,7 +923,7 @@ pub enum VariantId {
 impl_from!(EnumVariantId, StructId, UnionId for VariantId);
 
 impl VariantId {
-    pub fn variant_data(self, db: &dyn db::DefDatabase) -> Arc<VariantData> {
+    pub fn variant_data(self, db: &dyn DefDatabase) -> Arc<VariantData> {
         match self {
             VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
             VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
@@ -944,7 +933,7 @@ impl VariantId {
         }
     }
 
-    pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
+    pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
         match self {
             VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
             VariantId::StructId(it) => it.lookup(db).id.file_id(),
@@ -961,22 +950,12 @@ impl VariantId {
     }
 }
 
-trait Intern {
-    type ID;
-    fn intern(self, db: &dyn db::DefDatabase) -> Self::ID;
-}
-
-pub trait Lookup {
-    type Data;
-    fn lookup(&self, db: &dyn db::DefDatabase) -> Self::Data;
-}
-
 pub trait HasModule {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId;
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId;
 }
 
 impl HasModule for ItemContainerId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         match *self {
             ItemContainerId::ModuleId(it) => it,
             ItemContainerId::ImplId(it) => it.lookup(db).container,
@@ -987,13 +966,13 @@ impl HasModule for ItemContainerId {
 }
 
 impl<N: ItemTreeNode> HasModule for AssocItemLoc<N> {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         self.container.module(db)
     }
 }
 
 impl HasModule for AdtId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         match self {
             AdtId::StructId(it) => it.lookup(db).container,
             AdtId::UnionId(it) => it.lookup(db).container,
@@ -1003,13 +982,13 @@ impl HasModule for AdtId {
 }
 
 impl HasModule for ExternCrateId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         self.lookup(db).container
     }
 }
 
 impl HasModule for VariantId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         match self {
             VariantId::EnumVariantId(it) => it.parent.lookup(db).container,
             VariantId::StructId(it) => it.lookup(db).container,
@@ -1019,7 +998,7 @@ impl HasModule for VariantId {
 }
 
 impl HasModule for MacroId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         match self {
             MacroId::MacroRulesId(it) => it.lookup(db).container,
             MacroId::Macro2Id(it) => it.lookup(db).container,
@@ -1029,7 +1008,7 @@ impl HasModule for MacroId {
 }
 
 impl HasModule for TypeOwnerId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         match self {
             TypeOwnerId::FunctionId(it) => it.lookup(db).module(db),
             TypeOwnerId::StaticId(it) => it.lookup(db).module(db),
@@ -1046,7 +1025,7 @@ impl HasModule for TypeOwnerId {
 }
 
 impl HasModule for DefWithBodyId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         match self {
             DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
             DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
@@ -1058,7 +1037,7 @@ impl HasModule for DefWithBodyId {
 }
 
 impl HasModule for GenericDefId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         match self {
             GenericDefId::FunctionId(it) => it.lookup(db).module(db),
             GenericDefId::AdtId(it) => it.module(db),
@@ -1073,13 +1052,13 @@ impl HasModule for GenericDefId {
 }
 
 impl HasModule for TypeAliasId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         self.lookup(db).module(db)
     }
 }
 
 impl HasModule for TraitId {
-    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
         self.lookup(db).container
     }
 }
@@ -1088,7 +1067,7 @@ impl ModuleDefId {
     /// Returns the module containing `self` (or `self`, if `self` is itself a module).
     ///
     /// Returns `None` if `self` refers to a primitive type.
-    pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
+    pub fn module(&self, db: &dyn DefDatabase) -> Option<ModuleId> {
         Some(match self {
             ModuleDefId::ModuleId(id) => *id,
             ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
@@ -1106,7 +1085,7 @@ impl ModuleDefId {
 }
 
 impl AttrDefId {
-    pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
+    pub fn krate(&self, db: &dyn DefDatabase) -> CrateId {
         match self {
             AttrDefId::ModuleId(it) => it.krate,
             AttrDefId::FieldId(it) => it.parent.module(db).krate,
@@ -1244,7 +1223,7 @@ fn macro_call_as_call_id_with_eager(
     Ok(res)
 }
 
-pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
+pub fn macro_id_to_def_id(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
     match id {
         MacroId::Macro2Id(it) => {
             let loc = it.lookup(db);
@@ -1316,7 +1295,7 @@ pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
 }
 
 fn derive_macro_as_call_id(
-    db: &dyn db::DefDatabase,
+    db: &dyn DefDatabase,
     item_attr: &AstIdWithPath<ast::Adt>,
     derive_attr_index: AttrId,
     derive_pos: u32,
@@ -1341,7 +1320,7 @@ fn derive_macro_as_call_id(
 }
 
 fn attr_macro_as_call_id(
-    db: &dyn db::DefDatabase,
+    db: &dyn DefDatabase,
     item_attr: &AstIdWithPath<ast::Item>,
     macro_attr: &Attr,
     krate: CrateId,
diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs
index fa2100c54b7f..da85c2ec7ac8 100644
--- a/crates/hir-expand/src/eager.rs
+++ b/crates/hir-expand/src/eager.rs
@@ -28,8 +28,8 @@ use crate::{
     db::ExpandDatabase,
     mod_path::ModPath,
     span_map::SpanMapRef,
-    EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, MacroCallId,
-    MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
+    EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, Intern,
+    MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
 };
 
 pub fn expand_eager_macro_input(
@@ -49,13 +49,14 @@ pub fn expand_eager_macro_input(
     // When `lazy_expand` is called, its *parent* file must already exist.
     // Here we store an eager macro id for the argument expanded subtree
     // for that purpose.
-    let arg_id = db.intern_macro_call(MacroCallLoc {
+    let arg_id = MacroCallLoc {
         def,
         krate,
         eager: None,
         kind: MacroCallKind::FnLike { ast_id: call_id, expand_to: ExpandTo::Expr },
         call_site,
-    });
+    }
+    .intern(db);
     let ExpandResult { value: (arg_exp, arg_exp_map), err: parse_err } =
         db.parse_macro_expansion(arg_id.as_macro_file());
 
@@ -94,7 +95,7 @@ pub fn expand_eager_macro_input(
         call_site,
     };
 
-    ExpandResult { value: Some(db.intern_macro_call(loc)), err }
+    ExpandResult { value: Some(loc.intern(db)), err }
 }
 
 fn lazy_expand(
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 1c7e99fdf69f..59796f89f033 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -41,8 +41,9 @@ use crate::{
     builtin_attr_macro::BuiltinAttrExpander,
     builtin_derive_macro::BuiltinDeriveExpander,
     builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
-    db::TokenExpander,
+    db::{ExpandDatabase, TokenExpander},
     fixup::SyntaxFixupUndoInfo,
+    hygiene::SyntaxContextData,
     mod_path::ModPath,
     proc_macro::{CustomProcMacroExpander, ProcMacroKind},
     span_map::{ExpansionSpanMap, SpanMap},
@@ -70,6 +71,56 @@ pub mod tt {
     pub type TokenTree = ::tt::TokenTree<Span>;
 }
 
+#[macro_export]
+macro_rules! impl_intern_lookup {
+    ($db:ident, $id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
+        impl $crate::Intern for $loc {
+            type Database<'db> = dyn $db + 'db;
+            type ID = $id;
+            fn intern<'db>(self, db: &Self::Database<'db>) -> $id {
+                db.$intern(self)
+            }
+        }
+
+        impl $crate::Lookup for $id {
+            type Database<'db> = dyn $db + 'db;
+            type Data = $loc;
+            fn lookup<'db>(&self, db: &Self::Database<'db>) -> $loc {
+                db.$lookup(*self)
+            }
+        }
+    };
+}
+
+// ideally these would be defined in base-db, but the orphan rule doesn't let us
+pub trait Intern {
+    type Database<'db>: ?Sized;
+    type ID;
+    fn intern<'db>(self, db: &Self::Database<'db>) -> Self::ID;
+}
+
+pub trait Lookup {
+    type Database<'db>: ?Sized;
+    type Data;
+    fn lookup<'db>(&self, db: &Self::Database<'db>) -> Self::Data;
+}
+
+impl_intern_lookup!(
+    ExpandDatabase,
+    MacroCallId,
+    MacroCallLoc,
+    intern_macro_call,
+    lookup_intern_macro_call
+);
+
+impl_intern_lookup!(
+    ExpandDatabase,
+    SyntaxContextId,
+    SyntaxContextData,
+    intern_syntax_context,
+    lookup_intern_syntax_context
+);
+
 pub type ExpandResult<T> = ValueResult<T, ExpandError>;
 
 #[derive(Debug, PartialEq, Eq, Clone, Hash)]
@@ -180,36 +231,35 @@ pub enum MacroCallKind {
 
 pub trait HirFileIdExt {
     /// Returns the original file of this macro call hierarchy.
-    fn original_file(self, db: &dyn db::ExpandDatabase) -> FileId;
+    fn original_file(self, db: &dyn ExpandDatabase) -> FileId;
 
     /// Returns the original file of this macro call hierarchy while going into the included file if
     /// one of the calls comes from an `include!``.
-    fn original_file_respecting_includes(self, db: &dyn db::ExpandDatabase) -> FileId;
+    fn original_file_respecting_includes(self, db: &dyn ExpandDatabase) -> FileId;
 
     /// If this is a macro call, returns the syntax node of the very first macro call this file resides in.
-    fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<SyntaxNode>>;
+    fn original_call_node(self, db: &dyn ExpandDatabase) -> Option<InRealFile<SyntaxNode>>;
 
     /// Return expansion information if it is a macro-expansion file
-    fn expansion_info(self, db: &dyn db::ExpandDatabase) -> Option<ExpansionInfo>;
+    fn expansion_info(self, db: &dyn ExpandDatabase) -> Option<ExpansionInfo>;
 
-    fn as_builtin_derive_attr_node(&self, db: &dyn db::ExpandDatabase)
-        -> Option<InFile<ast::Attr>>;
+    fn as_builtin_derive_attr_node(&self, db: &dyn ExpandDatabase) -> Option<InFile<ast::Attr>>;
 }
 
 impl HirFileIdExt for HirFileId {
-    fn original_file(self, db: &dyn db::ExpandDatabase) -> FileId {
+    fn original_file(self, db: &dyn ExpandDatabase) -> FileId {
         let mut file_id = self;
         loop {
             match file_id.repr() {
                 HirFileIdRepr::FileId(id) => break id,
                 HirFileIdRepr::MacroFile(MacroFileId { macro_call_id }) => {
-                    file_id = db.lookup_intern_macro_call(macro_call_id).kind.file_id();
+                    file_id = macro_call_id.lookup(db).kind.file_id();
                 }
             }
         }
     }
 
-    fn original_file_respecting_includes(mut self, db: &dyn db::ExpandDatabase) -> FileId {
+    fn original_file_respecting_includes(mut self, db: &dyn ExpandDatabase) -> FileId {
         loop {
             match self.repr() {
                 HirFileIdRepr::FileId(id) => break id,
@@ -232,7 +282,7 @@ impl HirFileIdExt for HirFileId {
         }
     }
 
-    fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<SyntaxNode>> {
+    fn original_call_node(self, db: &dyn ExpandDatabase) -> Option<InRealFile<SyntaxNode>> {
         let mut call = db.lookup_intern_macro_call(self.macro_file()?.macro_call_id).to_node(db);
         loop {
             match call.file_id.repr() {
@@ -247,14 +297,11 @@ impl HirFileIdExt for HirFileId {
     }
 
     /// Return expansion information if it is a macro-expansion file
-    fn expansion_info(self, db: &dyn db::ExpandDatabase) -> Option<ExpansionInfo> {
+    fn expansion_info(self, db: &dyn ExpandDatabase) -> Option<ExpansionInfo> {
         Some(ExpansionInfo::new(db, self.macro_file()?))
     }
 
-    fn as_builtin_derive_attr_node(
-        &self,
-        db: &dyn db::ExpandDatabase,
-    ) -> Option<InFile<ast::Attr>> {
+    fn as_builtin_derive_attr_node(&self, db: &dyn ExpandDatabase) -> Option<InFile<ast::Attr>> {
         let macro_file = self.macro_file()?;
         let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
         let attr = match loc.def.kind {
@@ -266,32 +313,32 @@ impl HirFileIdExt for HirFileId {
 }
 
 pub trait MacroFileIdExt {
-    fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32;
+    fn expansion_level(self, db: &dyn ExpandDatabase) -> u32;
     /// If this is a macro call, returns the syntax node of the call.
-    fn call_node(self, db: &dyn db::ExpandDatabase) -> InFile<SyntaxNode>;
+    fn call_node(self, db: &dyn ExpandDatabase) -> InFile<SyntaxNode>;
 
-    fn expansion_info(self, db: &dyn db::ExpandDatabase) -> ExpansionInfo;
+    fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo;
 
-    fn is_builtin_derive(&self, db: &dyn db::ExpandDatabase) -> bool;
-    fn is_custom_derive(&self, db: &dyn db::ExpandDatabase) -> bool;
+    fn is_builtin_derive(&self, db: &dyn ExpandDatabase) -> bool;
+    fn is_custom_derive(&self, db: &dyn ExpandDatabase) -> bool;
 
     /// Return whether this file is an include macro
-    fn is_include_macro(&self, db: &dyn db::ExpandDatabase) -> bool;
+    fn is_include_macro(&self, db: &dyn ExpandDatabase) -> bool;
 
-    fn is_eager(&self, db: &dyn db::ExpandDatabase) -> bool;
+    fn is_eager(&self, db: &dyn ExpandDatabase) -> bool;
     /// Return whether this file is an attr macro
-    fn is_attr_macro(&self, db: &dyn db::ExpandDatabase) -> bool;
+    fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool;
 
     /// Return whether this file is the pseudo expansion of the derive attribute.
     /// See [`crate::builtin_attr_macro::derive_attr_expand`].
-    fn is_derive_attr_pseudo_expansion(&self, db: &dyn db::ExpandDatabase) -> bool;
+    fn is_derive_attr_pseudo_expansion(&self, db: &dyn ExpandDatabase) -> bool;
 }
 
 impl MacroFileIdExt for MacroFileId {
-    fn call_node(self, db: &dyn db::ExpandDatabase) -> InFile<SyntaxNode> {
+    fn call_node(self, db: &dyn ExpandDatabase) -> InFile<SyntaxNode> {
         db.lookup_intern_macro_call(self.macro_call_id).to_node(db)
     }
-    fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32 {
+    fn expansion_level(self, db: &dyn ExpandDatabase) -> u32 {
         let mut level = 0;
         let mut macro_file = self;
         loop {
@@ -306,39 +353,39 @@ impl MacroFileIdExt for MacroFileId {
     }
 
     /// Return expansion information if it is a macro-expansion file
-    fn expansion_info(self, db: &dyn db::ExpandDatabase) -> ExpansionInfo {
+    fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo {
         ExpansionInfo::new(db, self)
     }
 
-    fn is_custom_derive(&self, db: &dyn db::ExpandDatabase) -> bool {
+    fn is_custom_derive(&self, db: &dyn ExpandDatabase) -> bool {
         matches!(
             db.lookup_intern_macro_call(self.macro_call_id).def.kind,
             MacroDefKind::ProcMacro(_, ProcMacroKind::CustomDerive, _)
         )
     }
 
-    fn is_builtin_derive(&self, db: &dyn db::ExpandDatabase) -> bool {
+    fn is_builtin_derive(&self, db: &dyn ExpandDatabase) -> bool {
         matches!(
             db.lookup_intern_macro_call(self.macro_call_id).def.kind,
             MacroDefKind::BuiltInDerive(..)
         )
     }
 
-    fn is_include_macro(&self, db: &dyn db::ExpandDatabase) -> bool {
+    fn is_include_macro(&self, db: &dyn ExpandDatabase) -> bool {
         db.lookup_intern_macro_call(self.macro_call_id).def.is_include()
     }
 
-    fn is_eager(&self, db: &dyn db::ExpandDatabase) -> bool {
+    fn is_eager(&self, db: &dyn ExpandDatabase) -> bool {
         let loc: MacroCallLoc = db.lookup_intern_macro_call(self.macro_call_id);
         matches!(loc.def.kind, MacroDefKind::BuiltInEager(..))
     }
 
-    fn is_attr_macro(&self, db: &dyn db::ExpandDatabase) -> bool {
+    fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool {
         let loc: MacroCallLoc = db.lookup_intern_macro_call(self.macro_call_id);
         matches!(loc.kind, MacroCallKind::Attr { .. })
     }
 
-    fn is_derive_attr_pseudo_expansion(&self, db: &dyn db::ExpandDatabase) -> bool {
+    fn is_derive_attr_pseudo_expansion(&self, db: &dyn ExpandDatabase) -> bool {
         let loc: MacroCallLoc = db.lookup_intern_macro_call(self.macro_call_id);
         loc.def.is_attribute_derive()
     }
@@ -347,15 +394,15 @@ impl MacroFileIdExt for MacroFileId {
 impl MacroDefId {
     pub fn as_lazy_macro(
         self,
-        db: &dyn db::ExpandDatabase,
+        db: &dyn ExpandDatabase,
         krate: CrateId,
         kind: MacroCallKind,
         call_site: Span,
     ) -> MacroCallId {
-        db.intern_macro_call(MacroCallLoc { def: self, krate, eager: None, kind, call_site })
+        MacroCallLoc { def: self, krate, eager: None, kind, call_site }.intern(db)
     }
 
-    pub fn definition_range(&self, db: &dyn db::ExpandDatabase) -> InFile<TextRange> {
+    pub fn definition_range(&self, db: &dyn ExpandDatabase) -> InFile<TextRange> {
         match self.kind {
             MacroDefKind::Declarative(id)
             | MacroDefKind::BuiltIn(_, id)
@@ -420,7 +467,7 @@ impl MacroDefId {
 }
 
 impl MacroCallLoc {
-    pub fn span(&self, db: &dyn db::ExpandDatabase) -> Span {
+    pub fn span(&self, db: &dyn ExpandDatabase) -> Span {
         let ast_id = self.kind.erased_ast_id();
         let file_id = self.kind.file_id();
         let range = db.ast_id_map(file_id).get_erased(ast_id).text_range();
@@ -432,7 +479,7 @@ impl MacroCallLoc {
         }
     }
 
-    pub fn to_node(&self, db: &dyn db::ExpandDatabase) -> InFile<SyntaxNode> {
+    pub fn to_node(&self, db: &dyn ExpandDatabase) -> InFile<SyntaxNode> {
         match self.kind {
             MacroCallKind::FnLike { ast_id, .. } => {
                 ast_id.with_value(ast_id.to_node(db).syntax().clone())
@@ -510,7 +557,7 @@ impl MacroCallKind {
     /// Returns the original file range that best describes the location of this macro call.
     ///
     /// Unlike `MacroCallKind::original_call_range`, this also spans the item of attributes and derives.
-    pub fn original_call_range_with_body(self, db: &dyn db::ExpandDatabase) -> FileRange {
+    pub fn original_call_range_with_body(self, db: &dyn ExpandDatabase) -> FileRange {
         let mut kind = self;
         let file_id = loop {
             match kind.file_id().repr() {
@@ -535,7 +582,7 @@ impl MacroCallKind {
     /// Here we try to roughly match what rustc does to improve diagnostics: fn-like macros
     /// get the whole `ast::MacroCall`, attribute macros get the attribute's range, and derives
     /// get only the specific derive that is being referred to.
-    pub fn original_call_range(self, db: &dyn db::ExpandDatabase) -> FileRange {
+    pub fn original_call_range(self, db: &dyn ExpandDatabase) -> FileRange {
         let mut kind = self;
         let file_id = loop {
             match kind.file_id().repr() {
@@ -574,7 +621,7 @@ impl MacroCallKind {
         FileRange { range, file_id }
     }
 
-    fn arg(&self, db: &dyn db::ExpandDatabase) -> InFile<Option<SyntaxNode>> {
+    fn arg(&self, db: &dyn ExpandDatabase) -> InFile<Option<SyntaxNode>> {
         match self {
             MacroCallKind::FnLike { ast_id, .. } => {
                 ast_id.to_in_file_node(db).map(|it| Some(it.token_tree()?.syntax().clone()))
@@ -631,7 +678,7 @@ impl ExpansionInfo {
     /// Looks up the span at the given offset.
     pub fn span_for_offset(
         &self,
-        db: &dyn db::ExpandDatabase,
+        db: &dyn ExpandDatabase,
         offset: TextSize,
     ) -> (FileRange, SyntaxContextId) {
         debug_assert!(self.expanded.value.text_range().contains(offset));
@@ -647,7 +694,7 @@ impl ExpansionInfo {
     /// Maps up the text range out of the expansion hierarchy back into the original file its from.
     pub fn map_node_range_up(
         &self,
-        db: &dyn db::ExpandDatabase,
+        db: &dyn ExpandDatabase,
         range: TextRange,
     ) -> Option<(FileRange, SyntaxContextId)> {
         debug_assert!(self.expanded.value.text_range().contains_range(range));
@@ -677,7 +724,7 @@ impl ExpansionInfo {
     /// Maps up the text range out of the expansion into is macro call.
     pub fn map_range_up_once(
         &self,
-        db: &dyn db::ExpandDatabase,
+        db: &dyn ExpandDatabase,
         token: TextRange,
     ) -> InFile<smallvec::SmallVec<[TextRange; 1]>> {
         debug_assert!(self.expanded.value.text_range().contains_range(token));
@@ -706,7 +753,7 @@ impl ExpansionInfo {
         }
     }
 
-    pub fn new(db: &dyn db::ExpandDatabase, macro_file: MacroFileId) -> ExpansionInfo {
+    pub fn new(db: &dyn ExpandDatabase, macro_file: MacroFileId) -> ExpansionInfo {
         let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
 
         let arg_tt = loc.kind.arg(db);
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ec15aad1c490..f74aeb8a8ffb 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2786,9 +2786,13 @@ impl AsAssocItem for DefWithBody {
     }
 }
 
-fn as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem>
+fn as_assoc_item<'db, ID, DEF, CTOR, AST>(
+    db: &(dyn HirDatabase + 'db),
+    ctor: CTOR,
+    id: ID,
+) -> Option<AssocItem>
 where
-    ID: Lookup<Data = AssocItemLoc<AST>>,
+    ID: Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<AST>>,
     DEF: From<ID>,
     CTOR: FnOnce(DEF) -> AssocItem,
     AST: ItemTreeNode,
@@ -3522,7 +3526,7 @@ impl Impl {
         let src = self.source(db)?;
 
         let macro_file = src.file_id.macro_file()?;
-        let loc = db.lookup_intern_macro_call(macro_file.macro_call_id);
+        let loc = macro_file.macro_call_id.lookup(db.upcast());
         let (derive_attr, derive_index) = match loc.kind {
             MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
                 let module_id = self.id.lookup(db.upcast()).container;
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index a2a30edeb039..ad214e1b80e5 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -2,6 +2,7 @@
 
 use base_db::FileRange;
 use hir_def::{
+    db::DefDatabase,
     item_scope::ItemInNs,
     src::{HasChildSource, HasSource},
     AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId,
@@ -274,9 +275,9 @@ impl<'a> SymbolCollector<'a> {
         }
     }
 
-    fn push_decl<L>(&mut self, id: L, is_assoc: bool)
+    fn push_decl<'db, L>(&mut self, id: L, is_assoc: bool)
     where
-        L: Lookup + Into<ModuleDefId>,
+        L: Lookup<Database<'db> = dyn DefDatabase + 'db> + Into<ModuleDefId>,
         <L as Lookup>::Data: HasSource,
         <<L as Lookup>::Data as HasSource>::Value: HasName,
     {

From 51a9e7831ac573317ee788906676d96de6c5e9f9 Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Thu, 21 Dec 2023 09:18:06 +0100
Subject: [PATCH 2/4] Rename some things and turn macro to macro def into a
 query

---
 crates/hir-def/src/body/lower.rs              | 36 +++++----
 crates/hir-def/src/data.rs                    |  4 +-
 crates/hir-def/src/db.rs                      | 70 ++++++++++++++++-
 crates/hir-def/src/expander.rs                |  6 +-
 crates/hir-def/src/item_scope.rs              | 10 ++-
 crates/hir-def/src/item_tree.rs               | 14 ++--
 crates/hir-def/src/item_tree/lower.rs         |  4 +-
 crates/hir-def/src/item_tree/pretty.rs        |  4 +-
 crates/hir-def/src/lib.rs                     | 75 +------------------
 .../hir-def/src/macro_expansion_tests/mod.rs  |  3 +-
 crates/hir-def/src/nameres.rs                 |  2 +-
 crates/hir-def/src/nameres/attr_resolution.rs |  3 +-
 crates/hir-def/src/nameres/collector.rs       | 40 +++++-----
 crates/hir-expand/src/ast_id_map.rs           | 13 ++++
 crates/hir-expand/src/builtin_derive_macro.rs |  2 +-
 crates/hir-expand/src/builtin_fn_macro.rs     |  4 +-
 crates/hir-expand/src/db.rs                   | 14 ++--
 crates/hir-expand/src/lib.rs                  | 15 +---
 crates/hir/src/lib.rs                         |  3 +-
 crates/hir/src/semantics.rs                   |  3 +-
 crates/hir/src/source_analyzer.rs             |  3 +-
 21 files changed, 165 insertions(+), 163 deletions(-)

diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index c6a909320159..5fe1f0ebd1f7 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -959,20 +959,29 @@ impl ExprCollector<'_> {
         // File containing the macro call. Expansion errors will be attached here.
         let outer_file = self.expander.current_file_id;
 
-        let macro_call_ptr = self.expander.to_source(AstPtr::new(&mcall));
+        let macro_call_ptr = self.expander.to_source(syntax_ptr);
         let module = self.expander.module.local_id;
-        let res = self.expander.enter_expand(self.db, mcall, |path| {
-            self.def_map
-                .resolve_path(
-                    self.db,
-                    module,
-                    &path,
-                    crate::item_scope::BuiltinShadowMode::Other,
-                    Some(MacroSubNs::Bang),
-                )
-                .0
-                .take_macros()
-        });
+
+        let res = match self.def_map.modules[module]
+            .scope
+            .macro_invocations
+            .get(&InFile::new(outer_file, self.ast_id_map.ast_id_for_ptr(syntax_ptr)))
+        {
+            // fast path, macro call is in a block module
+            Some(&call) => Ok(self.expander.enter_expand_id(self.db, call)),
+            None => self.expander.enter_expand(self.db, mcall, |path| {
+                self.def_map
+                    .resolve_path(
+                        self.db,
+                        module,
+                        &path,
+                        crate::item_scope::BuiltinShadowMode::Other,
+                        Some(MacroSubNs::Bang),
+                    )
+                    .0
+                    .take_macros()
+            }),
+        };
 
         let res = match res {
             Ok(res) => res,
@@ -986,7 +995,6 @@ impl ExprCollector<'_> {
                 return collector(self, None);
             }
         };
-
         if record_diagnostics {
             match &res.err {
                 Some(ExpandError::UnresolvedProcMacro(krate)) => {
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index 635d13f24ad8..9c183c9332ba 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -16,7 +16,7 @@ use crate::{
     db::DefDatabase,
     expander::{Expander, Mark},
     item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, TreeId},
-    macro_call_as_call_id, macro_id_to_def_id,
+    macro_call_as_call_id,
     nameres::{
         attr_resolution::ResolvedAttr,
         diagnostics::DefDiagnostic,
@@ -720,7 +720,7 @@ impl<'a> AssocItemCollector<'a> {
                         )
                         .0
                         .take_macros()
-                        .map(|it| macro_id_to_def_id(self.db, it))
+                        .map(|it| self.db.macro_def(it))
                 };
                 match macro_call_as_call_id(
                     self.db.upcast(),
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index 31c1a713031c..d42f4efa1f73 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -1,7 +1,7 @@
 //! Defines database & queries for name resolution.
 use base_db::{salsa, CrateId, SourceDatabase, Upcast};
 use either::Either;
-use hir_expand::{db::ExpandDatabase, HirFileId};
+use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId};
 use intern::Interned;
 use la_arena::ArenaMap;
 use syntax::{ast, AstPtr};
@@ -24,9 +24,9 @@ use crate::{
     AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
     EnumId, EnumLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId,
     FunctionLoc, GenericDefId, ImplId, ImplLoc, InTypeConstId, InTypeConstLoc, LocalEnumVariantId,
-    LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc,
-    StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId, TraitLoc,
-    TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
+    LocalFieldId, Macro2Id, Macro2Loc, MacroId, MacroRulesId, MacroRulesLoc, ProcMacroId,
+    ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitAliasId, TraitAliasLoc, TraitId,
+    TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
 };
 
 #[salsa::query_group(InternDatabaseStorage)]
@@ -110,6 +110,8 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
     #[salsa::invoke(DefMap::block_def_map_query)]
     fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
 
+    fn macro_def(&self, m: MacroId) -> MacroDefId;
+
     // region:data
 
     #[salsa::invoke(StructData::struct_data_query)]
@@ -305,3 +307,63 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
 
     false
 }
+
+fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
+    use hir_expand::InFile;
+
+    use crate::{Lookup, MacroDefKind, MacroExpander};
+
+    let kind = |expander, file_id, m| {
+        let in_file = InFile::new(file_id, m);
+        match expander {
+            MacroExpander::Declarative => MacroDefKind::Declarative(in_file),
+            MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file),
+            MacroExpander::BuiltInAttr(it) => MacroDefKind::BuiltInAttr(it, in_file),
+            MacroExpander::BuiltInDerive(it) => MacroDefKind::BuiltInDerive(it, in_file),
+            MacroExpander::BuiltInEager(it) => MacroDefKind::BuiltInEager(it, in_file),
+        }
+    };
+
+    match id {
+        MacroId::Macro2Id(it) => {
+            let loc = it.lookup(db);
+
+            let item_tree = loc.id.item_tree(db);
+            let makro = &item_tree[loc.id.value];
+            MacroDefId {
+                krate: loc.container.krate,
+                kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()),
+                local_inner: false,
+                allow_internal_unsafe: loc.allow_internal_unsafe,
+            }
+        }
+        MacroId::MacroRulesId(it) => {
+            let loc = it.lookup(db);
+
+            let item_tree = loc.id.item_tree(db);
+            let makro = &item_tree[loc.id.value];
+            MacroDefId {
+                krate: loc.container.krate,
+                kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()),
+                local_inner: loc.local_inner,
+                allow_internal_unsafe: loc.allow_internal_unsafe,
+            }
+        }
+        MacroId::ProcMacroId(it) => {
+            let loc = it.lookup(db);
+
+            let item_tree = loc.id.item_tree(db);
+            let makro = &item_tree[loc.id.value];
+            MacroDefId {
+                krate: loc.container.krate,
+                kind: MacroDefKind::ProcMacro(
+                    loc.expander,
+                    loc.kind,
+                    InFile::new(loc.id.file_id(), makro.ast_id),
+                ),
+                local_inner: false,
+                allow_internal_unsafe: false,
+            }
+        }
+    }
+}
diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs
index 490fd5382cdb..c1936eb18935 100644
--- a/crates/hir-def/src/expander.rs
+++ b/crates/hir-def/src/expander.rs
@@ -11,8 +11,8 @@ use limit::Limit;
 use syntax::{ast, Parse, SyntaxNode};
 
 use crate::{
-    attr::Attrs, db::DefDatabase, lower::LowerCtx, macro_id_to_def_id, path::Path, AsMacroCall,
-    MacroId, ModuleId, UnresolvedMacro,
+    attr::Attrs, db::DefDatabase, lower::LowerCtx, path::Path, AsMacroCall, MacroId, ModuleId,
+    UnresolvedMacro,
 };
 
 #[derive(Debug)]
@@ -58,7 +58,7 @@ impl Expander {
         let result = self.within_limit(db, |this| {
             let macro_call = InFile::new(this.current_file_id, &macro_call);
             match macro_call.as_call_id_with_errors(db.upcast(), this.module.krate(), |path| {
-                resolver(path).map(|it| macro_id_to_def_id(db, it))
+                resolver(path).map(|it| db.macro_def(it))
             }) {
                 Ok(call_id) => call_id,
                 Err(resolve_err) => {
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index ce83cb435e2e..4902f24e2e3a 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -102,8 +102,10 @@ pub struct ItemScope {
     // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
     // be all resolved to the last one defined if shadowing happens.
     legacy_macros: FxHashMap<Name, SmallVec<[MacroId; 1]>>,
-    /// The derive macro invocations in this scope.
+    /// The attribute macro invocations in this scope.
     attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
+    /// The macro invocations in this scope.
+    pub macro_invocations: FxHashMap<AstId<ast::MacroCall>, MacroCallId>,
     /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
     /// paired with the derive macro invocations for the specific attribute.
     derive_macros: FxHashMap<AstId<ast::Adt>, SmallVec<[DeriveMacroInvocation; 1]>>,
@@ -345,6 +347,10 @@ impl ItemScope {
         self.attr_macros.insert(item, call);
     }
 
+    pub(crate) fn add_macro_invoc(&mut self, call: AstId<ast::MacroCall>, call_id: MacroCallId) {
+        self.macro_invocations.insert(call, call_id);
+    }
+
     pub(crate) fn attr_macro_invocs(
         &self,
     ) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
@@ -692,6 +698,7 @@ impl ItemScope {
             use_imports_values,
             use_imports_types,
             use_imports_macros,
+            macro_invocations,
         } = self;
         types.shrink_to_fit();
         values.shrink_to_fit();
@@ -709,6 +716,7 @@ impl ItemScope {
         derive_macros.shrink_to_fit();
         extern_crate_decls.shrink_to_fit();
         use_decls.shrink_to_fit();
+        macro_invocations.shrink_to_fit();
     }
 }
 
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index cf087613bf41..20e4e44339e9 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -29,6 +29,9 @@
 //!
 //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
 //! surface syntax.
+//!
+//! Note that we cannot store [`span::Span`]s inside of this, as typing in an item invalidates its
+//! encompassing span!
 
 mod lower;
 mod pretty;
@@ -281,7 +284,7 @@ struct ItemTreeData {
     mods: Arena<Mod>,
     macro_calls: Arena<MacroCall>,
     macro_rules: Arena<MacroRules>,
-    macro_defs: Arena<MacroDef>,
+    macro_defs: Arena<Macro2>,
 
     vis: ItemVisibilities,
 }
@@ -514,7 +517,7 @@ mod_items! {
     Mod in mods -> ast::Module,
     MacroCall in macro_calls -> ast::MacroCall,
     MacroRules in macro_rules -> ast::MacroRules,
-    MacroDef in macro_defs -> ast::MacroDef,
+    Macro2 in macro_defs -> ast::MacroDef,
 }
 
 macro_rules! impl_index {
@@ -747,6 +750,7 @@ pub struct MacroCall {
     pub path: Interned<ModPath>,
     pub ast_id: FileAstId<ast::MacroCall>,
     pub expand_to: ExpandTo,
+    // FIXME: We need to move this out. It invalidates the item tree when typing inside the macro call.
     pub call_site: Span,
 }
 
@@ -759,7 +763,7 @@ pub struct MacroRules {
 
 /// "Macros 2.0" macro definition.
 #[derive(Debug, Clone, Eq, PartialEq)]
-pub struct MacroDef {
+pub struct Macro2 {
     pub name: Name,
     pub visibility: RawVisibilityId,
     pub ast_id: FileAstId<ast::MacroDef>,
@@ -918,7 +922,7 @@ impl ModItem {
             | ModItem::Impl(_)
             | ModItem::Mod(_)
             | ModItem::MacroRules(_)
-            | ModItem::MacroDef(_) => None,
+            | ModItem::Macro2(_) => None,
             ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
             ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
             ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
@@ -944,7 +948,7 @@ impl ModItem {
             ModItem::Mod(it) => tree[it.index()].ast_id().upcast(),
             ModItem::MacroCall(it) => tree[it.index()].ast_id().upcast(),
             ModItem::MacroRules(it) => tree[it.index()].ast_id().upcast(),
-            ModItem::MacroDef(it) => tree[it.index()].ast_id().upcast(),
+            ModItem::Macro2(it) => tree[it.index()].ast_id().upcast(),
         }
     }
 }
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index d1043a5bd0b3..8e2fafe81b50 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -562,13 +562,13 @@ impl<'a> Ctx<'a> {
         Some(id(self.data().macro_rules.alloc(res)))
     }
 
-    fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> {
+    fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<Macro2>> {
         let name = m.name().map(|it| it.as_name())?;
 
         let ast_id = self.source_ast_id_map.ast_id(m);
         let visibility = self.lower_visibility(m);
 
-        let res = MacroDef { name, ast_id, visibility };
+        let res = Macro2 { name, ast_id, visibility };
         Some(id(self.data().macro_defs.alloc(res)))
     }
 
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 244111d202ce..6d92fce07272 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -464,8 +464,8 @@ impl Printer<'_> {
                 let MacroRules { name, ast_id: _ } = &self.tree[it];
                 wln!(self, "macro_rules! {} {{ ... }}", name.display(self.db.upcast()));
             }
-            ModItem::MacroDef(it) => {
-                let MacroDef { name, visibility, ast_id: _ } = &self.tree[it];
+            ModItem::Macro2(it) => {
+                let Macro2 { name, visibility, ast_id: _ } = &self.tree[it];
                 self.print_visibility(*visibility);
                 wln!(self, "macro {} {{ ... }}", name.display(self.db.upcast()));
             }
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 9a7d406dfd59..37f96df26996 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -92,7 +92,7 @@ use crate::{
     data::adt::VariantData,
     db::DefDatabase,
     item_tree::{
-        Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules,
+        Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
         Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use,
     },
 };
@@ -366,7 +366,7 @@ pub struct Macro2Id(salsa::InternId);
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct Macro2Loc {
     pub container: ModuleId,
-    pub id: ItemTreeId<MacroDef>,
+    pub id: ItemTreeId<Macro2>,
     pub expander: MacroExpander,
     pub allow_internal_unsafe: bool,
 }
@@ -1223,77 +1223,6 @@ fn macro_call_as_call_id_with_eager(
     Ok(res)
 }
 
-pub fn macro_id_to_def_id(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
-    match id {
-        MacroId::Macro2Id(it) => {
-            let loc = it.lookup(db);
-
-            let item_tree = loc.id.item_tree(db);
-            let makro = &item_tree[loc.id.value];
-            let in_file = |m: FileAstId<ast::MacroDef>| InFile::new(loc.id.file_id(), m.upcast());
-            MacroDefId {
-                krate: loc.container.krate,
-                kind: match loc.expander {
-                    MacroExpander::Declarative => MacroDefKind::Declarative(in_file(makro.ast_id)),
-                    MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file(makro.ast_id)),
-                    MacroExpander::BuiltInAttr(it) => {
-                        MacroDefKind::BuiltInAttr(it, in_file(makro.ast_id))
-                    }
-                    MacroExpander::BuiltInDerive(it) => {
-                        MacroDefKind::BuiltInDerive(it, in_file(makro.ast_id))
-                    }
-                    MacroExpander::BuiltInEager(it) => {
-                        MacroDefKind::BuiltInEager(it, in_file(makro.ast_id))
-                    }
-                },
-                local_inner: false,
-                allow_internal_unsafe: loc.allow_internal_unsafe,
-            }
-        }
-        MacroId::MacroRulesId(it) => {
-            let loc = it.lookup(db);
-
-            let item_tree = loc.id.item_tree(db);
-            let makro = &item_tree[loc.id.value];
-            let in_file = |m: FileAstId<ast::MacroRules>| InFile::new(loc.id.file_id(), m.upcast());
-            MacroDefId {
-                krate: loc.container.krate,
-                kind: match loc.expander {
-                    MacroExpander::Declarative => MacroDefKind::Declarative(in_file(makro.ast_id)),
-                    MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file(makro.ast_id)),
-                    MacroExpander::BuiltInAttr(it) => {
-                        MacroDefKind::BuiltInAttr(it, in_file(makro.ast_id))
-                    }
-                    MacroExpander::BuiltInDerive(it) => {
-                        MacroDefKind::BuiltInDerive(it, in_file(makro.ast_id))
-                    }
-                    MacroExpander::BuiltInEager(it) => {
-                        MacroDefKind::BuiltInEager(it, in_file(makro.ast_id))
-                    }
-                },
-                local_inner: loc.local_inner,
-                allow_internal_unsafe: loc.allow_internal_unsafe,
-            }
-        }
-        MacroId::ProcMacroId(it) => {
-            let loc = it.lookup(db);
-
-            let item_tree = loc.id.item_tree(db);
-            let makro = &item_tree[loc.id.value];
-            MacroDefId {
-                krate: loc.container.krate,
-                kind: MacroDefKind::ProcMacro(
-                    loc.expander,
-                    loc.kind,
-                    InFile::new(loc.id.file_id(), makro.ast_id),
-                ),
-                local_inner: false,
-                allow_internal_unsafe: false,
-            }
-        }
-    }
-}
-
 fn derive_macro_as_call_id(
     db: &dyn DefDatabase,
     item_attr: &AstIdWithPath<ast::Adt>,
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index a25f2d292203..ee806361237a 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -36,7 +36,6 @@ use test_fixture::WithFixture;
 
 use crate::{
     db::DefDatabase,
-    macro_id_to_def_id,
     nameres::{DefMap, MacroSubNs, ModuleSource},
     resolver::HasResolver,
     src::HasSource,
@@ -97,7 +96,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
             .as_call_id_with_errors(&db, krate, |path| {
                 resolver
                     .resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang))
-                    .map(|(it, _)| macro_id_to_def_id(&db, it))
+                    .map(|(it, _)| db.macro_def(it))
             })
             .unwrap();
         let macro_call_id = res.value.unwrap();
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 41560c054518..31b87a81e88c 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -100,7 +100,7 @@ pub struct DefMap {
     /// contains this block.
     block: Option<BlockInfo>,
     /// The modules and their data declared in this crate.
-    modules: Arena<ModuleData>,
+    pub modules: Arena<ModuleData>,
     krate: CrateId,
     /// The prelude module for this crate. This either comes from an import
     /// marked with the `prelude_import` attribute, or (in the normal case) from
diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs
index a7abf445918a..6288b8366bf0 100644
--- a/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/crates/hir-def/src/nameres/attr_resolution.rs
@@ -8,7 +8,6 @@ use crate::{
     attr_macro_as_call_id,
     db::DefDatabase,
     item_scope::BuiltinShadowMode,
-    macro_id_to_def_id,
     nameres::path_resolution::ResolveMode,
     path::{ModPath, PathKind},
     AstIdWithPath, LocalModuleId, UnresolvedMacro,
@@ -63,7 +62,7 @@ impl DefMap {
             &ast_id,
             attr,
             self.krate,
-            macro_id_to_def_id(db, def),
+            db.macro_def(def),
         )))
     }
 
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 541edf0845d3..095534058cc0 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -36,9 +36,9 @@ use crate::{
     item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
     item_tree::{
         self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
-        MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
+        Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
     },
-    macro_call_as_call_id, macro_call_as_call_id_with_eager, macro_id_to_def_id,
+    macro_call_as_call_id, macro_call_as_call_id_with_eager,
     nameres::{
         diagnostics::DefDiagnostic,
         mod_resolution::ModDir,
@@ -618,9 +618,7 @@ impl DefCollector<'_> {
         self.define_proc_macro(def.name.clone(), proc_macro_id);
         let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
         if let ProcMacroKind::CustomDerive { helpers } = def.kind {
-            crate_data
-                .exported_derives
-                .insert(macro_id_to_def_id(self.db, proc_macro_id.into()), helpers);
+            crate_data.exported_derives.insert(self.db.macro_def(proc_macro_id.into()), helpers);
         }
         crate_data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
     }
@@ -1131,10 +1129,7 @@ impl DefCollector<'_> {
                     BuiltinShadowMode::Module,
                     Some(subns),
                 );
-                resolved_res
-                    .resolved_def
-                    .take_macros()
-                    .map(|it| (it, macro_id_to_def_id(self.db, it)))
+                resolved_res.resolved_def.take_macros().map(|it| (it, self.db.macro_def(it)))
             };
             let resolver_def_id = |path| resolver(path).map(|(_, it)| it);
 
@@ -1149,6 +1144,9 @@ impl DefCollector<'_> {
                         resolver_def_id,
                     );
                     if let Ok(Some(call_id)) = call_id {
+                        self.def_map.modules[directive.module_id]
+                            .scope
+                            .add_macro_invoc(ast_id.ast_id, call_id);
                         push_resolved(directive, call_id);
 
                         res = ReachedFixedPoint::No;
@@ -1441,10 +1439,7 @@ impl DefCollector<'_> {
                                 BuiltinShadowMode::Module,
                                 Some(MacroSubNs::Bang),
                             );
-                            resolved_res
-                                .resolved_def
-                                .take_macros()
-                                .map(|it| macro_id_to_def_id(self.db, it))
+                            resolved_res.resolved_def.take_macros().map(|it| self.db.macro_def(it))
                         },
                     );
                     if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
@@ -1650,7 +1645,7 @@ impl ModCollector<'_, '_> {
                 ),
                 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container),
                 ModItem::MacroRules(id) => self.collect_macro_rules(id, module),
-                ModItem::MacroDef(id) => self.collect_macro_def(id, module),
+                ModItem::Macro2(id) => self.collect_macro_def(id, module),
                 ModItem::Impl(imp) => {
                     let impl_id =
                         ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) }
@@ -2157,7 +2152,7 @@ impl ModCollector<'_, '_> {
         );
     }
 
-    fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>, module: ModuleId) {
+    fn collect_macro_def(&mut self, id: FileItemTreeId<Macro2>, module: ModuleId) {
         let krate = self.def_collector.def_map.krate;
         let mac = &self.item_tree[id];
         let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
@@ -2225,7 +2220,7 @@ impl ModCollector<'_, '_> {
                 Arc::get_mut(&mut self.def_collector.def_map.data)
                     .unwrap()
                     .exported_derives
-                    .insert(macro_id_to_def_id(self.def_collector.db, macro_id.into()), helpers);
+                    .insert(self.def_collector.db.macro_def(macro_id.into()), helpers);
             }
         }
     }
@@ -2264,7 +2259,7 @@ impl ModCollector<'_, '_> {
                                 Some(MacroSubNs::Bang),
                             )
                         })
-                        .map(|it| macro_id_to_def_id(self.def_collector.db, it))
+                        .map(|it| self.def_collector.db.macro_def(it))
                 })
             },
             |path| {
@@ -2276,7 +2271,7 @@ impl ModCollector<'_, '_> {
                     BuiltinShadowMode::Module,
                     Some(MacroSubNs::Bang),
                 );
-                resolved_res.resolved_def.take_macros().map(|it| macro_id_to_def_id(db, it))
+                resolved_res.resolved_def.take_macros().map(|it| db.macro_def(it))
             },
         ) {
             // FIXME: if there were errors, this mightve been in the eager expansion from an
@@ -2284,10 +2279,13 @@ impl ModCollector<'_, '_> {
             if res.err.is_none() {
                 // Legacy macros need to be expanded immediately, so that any macros they produce
                 // are in scope.
-                if let Some(val) = res.value {
+                if let Some(call_id) = res.value {
+                    self.def_collector.def_map.modules[self.module_id]
+                        .scope
+                        .add_macro_invoc(ast_id.ast_id, call_id);
                     self.def_collector.collect_macro_expansion(
                         self.module_id,
-                        val,
+                        call_id,
                         self.macro_depth + 1,
                         container,
                     );
@@ -2301,7 +2299,7 @@ impl ModCollector<'_, '_> {
         self.def_collector.unresolved_macros.push(MacroDirective {
             module_id: self.module_id,
             depth: self.macro_depth + 1,
-            kind: MacroDirectiveKind::FnLike { ast_id, expand_to: expand_to, call_site },
+            kind: MacroDirectiveKind::FnLike { ast_id, expand_to, call_site },
             container,
         });
     }
diff --git a/crates/hir-expand/src/ast_id_map.rs b/crates/hir-expand/src/ast_id_map.rs
index 2abeaaeec451..d0d229e1319f 100644
--- a/crates/hir-expand/src/ast_id_map.rs
+++ b/crates/hir-expand/src/ast_id_map.rs
@@ -199,6 +199,19 @@ impl AstIdMap {
         FileAstId { raw, covariant: PhantomData }
     }
 
+    pub fn ast_id_for_ptr<N: AstIdNode>(&self, ptr: AstPtr<N>) -> FileAstId<N> {
+        let ptr = ptr.syntax_node_ptr();
+        let hash = hash_ptr(&ptr);
+        match self.map.raw_entry().from_hash(hash, |&idx| self.arena[idx] == ptr) {
+            Some((&raw, &())) => FileAstId { raw, covariant: PhantomData },
+            None => panic!(
+                "Can't find {:?} in AstIdMap:\n{:?}",
+                ptr,
+                self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
+            ),
+        }
+    }
+
     pub fn get<N: AstIdNode>(&self, id: FileAstId<N>) -> AstPtr<N> {
         AstPtr::try_from_raw(self.arena[id.raw].clone()).unwrap()
     }
diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs
index 75720d36f9fd..8f240ef07320 100644
--- a/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/crates/hir-expand/src/builtin_derive_macro.rs
@@ -36,7 +36,7 @@ macro_rules! register_builtin {
                     $( BuiltinDeriveExpander::$trait => $expand, )*
                 };
 
-                let span = db.lookup_intern_macro_call(id).span(db);
+                let span = db.lookup_intern_macro_call(id).call_site;
                 let span = span_with_def_site_ctxt(db, span, id);
                 expander(db, id, span, tt, token_map)
             }
diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs
index 7629d31a2212..2d7531d56d07 100644
--- a/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/crates/hir-expand/src/builtin_fn_macro.rs
@@ -42,7 +42,7 @@ macro_rules! register_builtin {
                     $( BuiltinFnLikeExpander::$kind => $expand, )*
                 };
 
-                let span = db.lookup_intern_macro_call(id).span(db);
+                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)
             }
@@ -59,7 +59,7 @@ macro_rules! register_builtin {
                     $( EagerExpander::$e_kind => $e_expand, )*
                 };
 
-                let span = db.lookup_intern_macro_call(id).span(db);
+                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)
             }
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index dcfa53bfbe2c..df5760724c7f 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -301,16 +301,15 @@ pub fn expand_speculative(
     let mut speculative_expansion = match loc.def.kind {
         MacroDefKind::ProcMacro(expander, ..) => {
             tt.delimiter = tt::Delimiter::invisible_spanned(loc.call_site);
-            let call_site = loc.span(db);
             expander.expand(
                 db,
                 loc.def.krate,
                 loc.krate,
                 &tt,
                 attr_arg.as_ref(),
-                call_site,
-                call_site,
-                call_site,
+                loc.call_site,
+                loc.call_site,
+                loc.call_site,
             )
         }
         MacroDefKind::BuiltInAttr(BuiltinAttrExpander::Derive, _) => {
@@ -782,7 +781,6 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
         _ => None,
     };
 
-    let call_site = loc.span(db);
     let ExpandResult { value: mut tt, err } = expander.expand(
         db,
         loc.def.krate,
@@ -790,10 +788,10 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
         &macro_arg,
         attr_arg,
         // FIXME
-        call_site,
-        call_site,
+        loc.call_site,
+        loc.call_site,
         // FIXME
-        call_site,
+        loc.call_site,
     );
 
     // Set a hard limit for the expanded tt
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 59796f89f033..c3fcbbfcbe73 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -173,7 +173,6 @@ pub struct MacroCallLoc {
     pub call_site: Span,
 }
 
-// FIXME: Might make sense to intern this? Given it's gonna be the same for a bunch of macro calls
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct MacroDefId {
     pub krate: CrateId,
@@ -467,18 +466,6 @@ impl MacroDefId {
 }
 
 impl MacroCallLoc {
-    pub fn span(&self, db: &dyn ExpandDatabase) -> Span {
-        let ast_id = self.kind.erased_ast_id();
-        let file_id = self.kind.file_id();
-        let range = db.ast_id_map(file_id).get_erased(ast_id).text_range();
-        match file_id.repr() {
-            HirFileIdRepr::FileId(file_id) => db.real_span_map(file_id).span_for_range(range),
-            HirFileIdRepr::MacroFile(m) => {
-                db.parse_macro_expansion(m).value.1.span_at(range.start())
-            }
-        }
-    }
-
     pub fn to_node(&self, db: &dyn ExpandDatabase) -> InFile<SyntaxNode> {
         match self.kind {
             MacroCallKind::FnLike { ast_id, .. } => {
@@ -546,7 +533,7 @@ impl MacroCallKind {
         }
     }
 
-    fn erased_ast_id(&self) -> ErasedFileAstId {
+    pub fn erased_ast_id(&self) -> ErasedFileAstId {
         match *self {
             MacroCallKind::FnLike { ast_id: InFile { value, .. }, .. } => value.erase(),
             MacroCallKind::Derive { ast_id: InFile { value, .. }, .. } => value.erase(),
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index f74aeb8a8ffb..85762603ed15 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -47,7 +47,6 @@ use hir_def::{
     item_tree::ItemTreeNode,
     lang_item::LangItemTarget,
     layout::{self, ReprOptions, TargetDataLayout},
-    macro_id_to_def_id,
     nameres::{self, diagnostics::DefDiagnostic},
     path::ImportAlias,
     per_ns::PerNs,
@@ -810,7 +809,7 @@ impl Module {
 }
 
 fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, m: Macro) {
-    let id = macro_id_to_def_id(db.upcast(), m.id);
+    let id = db.macro_def(m.id);
     if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id) {
         if let Some(e) = expander.mac.err() {
             let Some(ast) = id.ast_id().left() else {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 95ed83a49abf..34feb00c9b75 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -13,7 +13,6 @@ use either::Either;
 use hir_def::{
     hir::Expr,
     lower::LowerCtx,
-    macro_id_to_def_id,
     nameres::MacroSubNs,
     resolver::{self, HasResolver, Resolver, TypeNs},
     type_ref::Mutability,
@@ -343,7 +342,7 @@ impl<'db> SemanticsImpl<'db> {
         let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
             resolver
                 .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
-                .map(|(it, _)| macro_id_to_def_id(self.db.upcast(), it))
+                .map(|(it, _)| self.db.macro_def(it))
         })?;
         hir_expand::db::expand_speculative(
             self.db.upcast(),
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index d05118bbc28b..5fbc860a4b30 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -16,7 +16,6 @@ use hir_def::{
     hir::{BindingId, ExprId, Pat, PatId},
     lang_item::LangItem,
     lower::LowerCtx,
-    macro_id_to_def_id,
     nameres::MacroSubNs,
     path::{ModPath, Path, PathKind},
     resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
@@ -773,7 +772,7 @@ impl SourceAnalyzer {
         let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
             self.resolver
                 .resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang))
-                .map(|(it, _)| macro_id_to_def_id(db.upcast(), it))
+                .map(|(it, _)| db.macro_def(it))
         })?;
         // why the 64?
         Some(macro_call_id.as_macro_file()).filter(|it| it.expansion_level(db.upcast()) < 64)

From 7d762d18edb1b05343c7725af54f15ce81cd12de Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Thu, 21 Dec 2023 09:54:47 +0100
Subject: [PATCH 3/4] Record macro def site spans

---
 crates/hir-def/src/db.rs          | 13 +++++++++++--
 crates/hir-expand/src/lib.rs      |  2 +-
 crates/hir-expand/src/span_map.rs |  4 ++++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index d42f4efa1f73..df5e73eff563 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -326,7 +326,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
 
     match id {
         MacroId::Macro2Id(it) => {
-            let loc = it.lookup(db);
+            let loc: Macro2Loc = it.lookup(db);
 
             let item_tree = loc.id.item_tree(db);
             let makro = &item_tree[loc.id.value];
@@ -335,10 +335,13 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()),
                 local_inner: false,
                 allow_internal_unsafe: loc.allow_internal_unsafe,
+                def_site: db
+                    .span_map(loc.id.file_id())
+                    .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
             }
         }
         MacroId::MacroRulesId(it) => {
-            let loc = it.lookup(db);
+            let loc: MacroRulesLoc = it.lookup(db);
 
             let item_tree = loc.id.item_tree(db);
             let makro = &item_tree[loc.id.value];
@@ -347,6 +350,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()),
                 local_inner: loc.local_inner,
                 allow_internal_unsafe: loc.allow_internal_unsafe,
+                def_site: db
+                    .span_map(loc.id.file_id())
+                    .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
             }
         }
         MacroId::ProcMacroId(it) => {
@@ -363,6 +369,9 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
                 ),
                 local_inner: false,
                 allow_internal_unsafe: false,
+                def_site: db
+                    .span_map(loc.id.file_id())
+                    .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
             }
         }
     }
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index c3fcbbfcbe73..22cc426d668b 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -179,7 +179,7 @@ pub struct MacroDefId {
     pub kind: MacroDefKind,
     pub local_inner: bool,
     pub allow_internal_unsafe: bool,
-    // pub def_site: Span,
+    pub def_site: Span,
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs
index f9763cd88666..4ec6e657f9ed 100644
--- a/crates/hir-expand/src/span_map.rs
+++ b/crates/hir-expand/src/span_map.rs
@@ -38,6 +38,10 @@ impl mbe::SpanMapper<Span> for SpanMapRef<'_> {
 impl SpanMap {
     pub fn span_for_range(&self, range: TextRange) -> Span {
         match self {
+            // FIXME: Is it correct for us to only take the span at the start? This feels somewhat
+            // wrong. The context will be right, but the range could be considered wrong. See
+            // https://github.com/rust-lang/rust/issues/23480, we probably want to fetch the span at
+            // the start and end, then merge them like rustc does in `Span::to
             Self::ExpansionSpanMap(span_map) => span_map.span_at(range.start()),
             Self::RealSpanMap(span_map) => span_map.span_for_range(range),
         }

From 1e1113cf5f7318cae702bc31ab5155c24fade6f4 Mon Sep 17 00:00:00 2001
From: Lukas Wirth <lukastw97@gmail.com>
Date: Thu, 21 Dec 2023 10:51:54 +0100
Subject: [PATCH 4/4] Correctly set and mark the proc-macro spans

---
 crates/hir-def/src/db.rs     |  6 +++---
 crates/hir-expand/src/db.rs  | 19 ++++++++++---------
 crates/hir-expand/src/lib.rs |  2 +-
 3 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index df5e73eff563..901c446465d2 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -335,7 +335,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()),
                 local_inner: false,
                 allow_internal_unsafe: loc.allow_internal_unsafe,
-                def_site: db
+                span: db
                     .span_map(loc.id.file_id())
                     .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
             }
@@ -350,7 +350,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
                 kind: kind(loc.expander, loc.id.file_id(), makro.ast_id.upcast()),
                 local_inner: loc.local_inner,
                 allow_internal_unsafe: loc.allow_internal_unsafe,
-                def_site: db
+                span: db
                     .span_map(loc.id.file_id())
                     .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
             }
@@ -369,7 +369,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
                 ),
                 local_inner: false,
                 allow_internal_unsafe: false,
-                def_site: db
+                span: db
                     .span_map(loc.id.file_id())
                     .span_for_range(db.ast_id_map(loc.id.file_id()).get(makro.ast_id).text_range()),
             }
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index df5760724c7f..f7a26e436dee 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -23,7 +23,10 @@ use crate::{
     builtin_attr_macro::pseudo_derive_attr_expansion,
     builtin_fn_macro::EagerExpander,
     fixup::{self, reverse_fixups, SyntaxFixupUndoInfo},
-    hygiene::{apply_mark, SyntaxContextData, Transparency},
+    hygiene::{
+        apply_mark, span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt,
+        SyntaxContextData, Transparency,
+    },
     proc_macro::ProcMacros,
     span_map::{RealSpanMap, SpanMap, SpanMapRef},
     tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander,
@@ -307,9 +310,9 @@ pub fn expand_speculative(
                 loc.krate,
                 &tt,
                 attr_arg.as_ref(),
-                loc.call_site,
-                loc.call_site,
-                loc.call_site,
+                span_with_def_site_ctxt(db, loc.def.span, actual_macro_call),
+                span_with_call_site_ctxt(db, loc.def.span, actual_macro_call),
+                span_with_mixed_site_ctxt(db, loc.def.span, actual_macro_call),
             )
         }
         MacroDefKind::BuiltInAttr(BuiltinAttrExpander::Derive, _) => {
@@ -787,11 +790,9 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
         loc.krate,
         &macro_arg,
         attr_arg,
-        // FIXME
-        loc.call_site,
-        loc.call_site,
-        // FIXME
-        loc.call_site,
+        span_with_def_site_ctxt(db, loc.def.span, id),
+        span_with_call_site_ctxt(db, loc.def.span, id),
+        span_with_mixed_site_ctxt(db, loc.def.span, id),
     );
 
     // Set a hard limit for the expanded tt
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 22cc426d668b..3df62aefaad7 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -179,7 +179,7 @@ pub struct MacroDefId {
     pub kind: MacroDefKind,
     pub local_inner: bool,
     pub allow_internal_unsafe: bool,
-    pub def_site: Span,
+    pub span: Span,
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]