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>, +fn any_has_attrs<'db>( + db: &(dyn DefDatabase + 'db), + id: impl Lookup< + Database<'db> = dyn DefDatabase + 'db, + Data = impl HasSource, + >, ) -> InFile { id.lookup(db).source(db).map(ast::AnyHasAttrs::new) } @@ -650,17 +653,17 @@ fn attrs_from_item_tree(db: &dyn DefDatabase, id: ItemTreeId tree.raw_attrs(mod_item.into()).clone() } -fn attrs_from_item_tree_loc( - db: &dyn DefDatabase, - lookup: impl Lookup>, +fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( + db: &(dyn DefDatabase + 'db), + lookup: impl Lookup = dyn DefDatabase + 'db, Data = ItemLoc>, ) -> RawAttrs { let id = lookup.lookup(db).id; attrs_from_item_tree(db, id) } -fn attrs_from_item_tree_assoc( - db: &dyn DefDatabase, - lookup: impl Lookup>, +fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>( + db: &(dyn DefDatabase + 'db), + lookup: impl Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, ) -> RawAttrs { let id = lookup.lookup(db).id; attrs_from_item_tree(db, id) 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..901c446465d2 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 Arc; + fn macro_def(&self, m: MacroId) -> MacroDefId; + // region:data #[salsa::invoke(StructData::struct_data_query)] @@ -305,3 +307,72 @@ 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: Macro2Loc = 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, + 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()), + } + } + MacroId::MacroRulesId(it) => { + let loc: MacroRulesLoc = 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, + 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()), + } + } + 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, + 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-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, ¯o_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>, - /// The derive macro invocations in this scope. + /// The attribute macro invocations in this scope. attr_macros: FxHashMap, MacroCallId>, + /// The macro invocations in this scope. + pub macro_invocations: FxHashMap, 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, 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, call_id: MacroCallId) { + self.macro_invocations.insert(call, call_id); + } + pub(crate) fn attr_macro_invocs( &self, ) -> impl Iterator, 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, macro_calls: Arena, macro_rules: Arena, - macro_defs: Arena, + macro_defs: Arena, 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, pub ast_id: FileAstId, 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, @@ -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> { + fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option> { 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 2baf46073433..37f96df26996 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,13 +85,14 @@ 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, + Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, 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 { + pub fn def_map(&self, db: &dyn DefDatabase) -> Arc { 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 { + pub fn def_map(self, db: &dyn DefDatabase) -> Arc { 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 { + pub fn name(self, db: &dyn DefDatabase) -> Option { 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 { + pub fn containing_module(self, db: &dyn DefDatabase) -> Option { self.def_map(db).containing_module(self.local_id) } @@ -264,20 +266,7 @@ impl Hash for AssocItemLoc { 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); }; } @@ -377,7 +366,7 @@ pub struct Macro2Id(salsa::InternId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Macro2Loc { pub container: ModuleId, - pub id: ItemTreeId, + pub id: ItemTreeId, pub expander: MacroExpander, pub allow_internal_unsafe: bool, } @@ -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 { + pub fn generic_def(self, db: &dyn DefDatabase) -> Option { 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 { + pub fn variant_data(self, db: &dyn DefDatabase) -> Arc { 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 HasModule for AssocItemLoc { - 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 { + pub fn module(&self, db: &dyn DefDatabase) -> Option { 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,79 +1223,8 @@ fn macro_call_as_call_id_with_eager( Ok(res) } -pub fn macro_id_to_def_id(db: &dyn db::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| 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| 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 db::DefDatabase, + db: &dyn DefDatabase, item_attr: &AstIdWithPath, derive_attr_index: AttrId, derive_pos: u32, @@ -1341,7 +1249,7 @@ fn derive_macro_as_call_id( } fn attr_macro_as_call_id( - db: &dyn db::DefDatabase, + db: &dyn DefDatabase, item_attr: &AstIdWithPath, macro_attr: &Attr, krate: CrateId, 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, /// The modules and their data declared in this crate. - modules: Arena, + pub modules: Arena, 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 a80d8d0428b8..090d83483904 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, @@ -620,9 +620,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); } @@ -1133,10 +1131,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); @@ -1151,6 +1146,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; @@ -1443,10 +1441,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 { @@ -1652,7 +1647,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) } @@ -2159,7 +2154,7 @@ impl ModCollector<'_, '_> { ); } - fn collect_macro_def(&mut self, id: FileItemTreeId, module: ModuleId) { + fn collect_macro_def(&mut self, id: FileItemTreeId, 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()); @@ -2227,7 +2222,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); } } } @@ -2266,7 +2261,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| { @@ -2278,7 +2273,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 @@ -2286,10 +2281,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, ); @@ -2303,7 +2301,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(&self, ptr: AstPtr) -> FileAstId { + 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::>(), + ), + } + } + pub fn get(&self, id: FileAstId) -> AstPtr { 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..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, @@ -301,16 +304,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, + 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, _) => { @@ -782,18 +784,15 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult None, }; - let call_site = loc.span(db); let ExpandResult { value: mut tt, err } = expander.expand( db, loc.def.krate, loc.krate, ¯o_arg, attr_arg, - // FIXME - call_site, - call_site, - // FIXME - 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/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..3df62aefaad7 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; } +#[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 = ValueResult; #[derive(Debug, PartialEq, Eq, Clone, Hash)] @@ -122,14 +173,13 @@ 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, 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)] @@ -180,36 +230,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>; + fn original_call_node(self, db: &dyn ExpandDatabase) -> Option>; /// Return expansion information if it is a macro-expansion file - fn expansion_info(self, db: &dyn db::ExpandDatabase) -> Option; + fn expansion_info(self, db: &dyn ExpandDatabase) -> Option; - fn as_builtin_derive_attr_node(&self, db: &dyn db::ExpandDatabase) - -> Option>; + fn as_builtin_derive_attr_node(&self, db: &dyn ExpandDatabase) -> Option>; } 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 +281,7 @@ impl HirFileIdExt for HirFileId { } } - fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option> { + fn original_call_node(self, db: &dyn ExpandDatabase) -> Option> { 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 +296,11 @@ impl HirFileIdExt for HirFileId { } /// Return expansion information if it is a macro-expansion file - fn expansion_info(self, db: &dyn db::ExpandDatabase) -> Option { + fn expansion_info(self, db: &dyn ExpandDatabase) -> Option { Some(ExpansionInfo::new(db, self.macro_file()?)) } - fn as_builtin_derive_attr_node( - &self, - db: &dyn db::ExpandDatabase, - ) -> Option> { + fn as_builtin_derive_attr_node(&self, db: &dyn ExpandDatabase) -> Option> { 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 +312,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; + fn call_node(self, db: &dyn ExpandDatabase) -> InFile; - 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 { + fn call_node(self, db: &dyn ExpandDatabase) -> InFile { 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 +352,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 +393,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 { + pub fn definition_range(&self, db: &dyn ExpandDatabase) -> InFile { match self.kind { MacroDefKind::Declarative(id) | MacroDefKind::BuiltIn(_, id) @@ -420,19 +466,7 @@ impl MacroDefId { } impl MacroCallLoc { - pub fn span(&self, db: &dyn db::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 db::ExpandDatabase) -> InFile { + pub fn to_node(&self, db: &dyn ExpandDatabase) -> InFile { match self.kind { MacroCallKind::FnLike { ast_id, .. } => { ast_id.with_value(ast_id.to_node(db).syntax().clone()) @@ -499,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(), @@ -510,7 +544,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 +569,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 +608,7 @@ impl MacroCallKind { FileRange { range, file_id } } - fn arg(&self, db: &dyn db::ExpandDatabase) -> InFile> { + fn arg(&self, db: &dyn ExpandDatabase) -> InFile> { match self { MacroCallKind::FnLike { ast_id, .. } => { ast_id.to_in_file_node(db).map(|it| Some(it.token_tree()?.syntax().clone())) @@ -631,7 +665,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 +681,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 +711,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> { debug_assert!(self.expanded.value.text_range().contains_range(token)); @@ -706,7 +740,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-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 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), } diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ec15aad1c490..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, 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 { @@ -2786,9 +2785,13 @@ impl AsAssocItem for DefWithBody { } } -fn as_assoc_item(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option +fn as_assoc_item<'db, ID, DEF, CTOR, AST>( + db: &(dyn HirDatabase + 'db), + ctor: CTOR, + id: ID, +) -> Option where - ID: Lookup>, + ID: Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, DEF: From, CTOR: FnOnce(DEF) -> AssocItem, AST: ItemTreeNode, @@ -3522,7 +3525,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/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) 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(&mut self, id: L, is_assoc: bool) + fn push_decl<'db, L>(&mut self, id: L, is_assoc: bool) where - L: Lookup + Into, + L: Lookup = dyn DefDatabase + 'db> + Into, ::Data: HasSource, <::Data as HasSource>::Value: HasName, {