1 //! `hir_def` crate contains everything between macro expansion and type
4 //! It defines various items (structs, enums, traits) which comprises Rust code,
5 //! as well as an algorithm for resolving paths to such entities.
7 //! Note that `hir_def` is a work in progress, so not all of the above is
11 macro_rules! eprintln {
12 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
44 pub mod child_by_source;
53 mod macro_expansion_tests;
61 use base_db::{impl_intern_key, salsa, CrateId, ProcMacroKind};
63 ast_id_map::FileAstId,
64 builtin_attr_macro::BuiltinAttrExpander,
65 builtin_derive_macro::BuiltinDeriveExpander,
66 builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
67 eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
69 proc_macro::ProcMacroExpander,
70 AstId, ExpandError, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
71 MacroDefKind, UnresolvedMacro,
73 use item_tree::ExternBlock;
82 builtin_type::BuiltinType,
84 Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem,
85 Static, Struct, Trait, TypeAlias, Union,
89 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
92 /// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the
93 /// `BlockId` of that block expression. If `None`, this module is part of the crate-level
94 /// `DefMap` of `krate`.
95 block: Option<BlockId>,
96 /// The module's ID in its originating `DefMap`.
97 pub local_id: LocalModuleId,
101 pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> {
104 db.block_def_map(block).unwrap_or_else(|| {
105 // NOTE: This should be unreachable - all `ModuleId`s come from their `DefMap`s,
106 // so the `DefMap` here must exist.
107 unreachable!("no `block_def_map` for `ModuleId` {:?}", self);
110 None => db.crate_def_map(self.krate),
114 pub fn krate(&self) -> CrateId {
118 pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
119 self.def_map(db).containing_module(self.local_id)
122 pub fn containing_block(&self) -> Option<BlockId> {
127 /// An ID of a module, **local** to a specific crate
128 pub type LocalModuleId = Idx<nameres::ModuleData>;
131 pub struct ItemLoc<N: ItemTreeNode> {
132 pub container: ModuleId,
133 pub id: ItemTreeId<N>,
136 impl<N: ItemTreeNode> Clone for ItemLoc<N> {
137 fn clone(&self) -> Self {
138 Self { container: self.container, id: self.id }
142 impl<N: ItemTreeNode> Copy for ItemLoc<N> {}
144 impl<N: ItemTreeNode> PartialEq for ItemLoc<N> {
145 fn eq(&self, other: &Self) -> bool {
146 self.container == other.container && self.id == other.id
150 impl<N: ItemTreeNode> Eq for ItemLoc<N> {}
152 impl<N: ItemTreeNode> Hash for ItemLoc<N> {
153 fn hash<H: Hasher>(&self, state: &mut H) {
154 self.container.hash(state);
160 pub struct AssocItemLoc<N: ItemTreeNode> {
161 pub container: ItemContainerId,
162 pub id: ItemTreeId<N>,
165 impl<N: ItemTreeNode> Clone for AssocItemLoc<N> {
166 fn clone(&self) -> Self {
167 Self { container: self.container, id: self.id }
171 impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {}
173 impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> {
174 fn eq(&self, other: &Self) -> bool {
175 self.container == other.container && self.id == other.id
179 impl<N: ItemTreeNode> Eq for AssocItemLoc<N> {}
181 impl<N: ItemTreeNode> Hash for AssocItemLoc<N> {
182 fn hash<H: Hasher>(&self, state: &mut H) {
183 self.container.hash(state);
188 macro_rules! impl_intern {
189 ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
190 impl_intern_key!($id);
192 impl Intern for $loc {
194 fn intern(self, db: &dyn db::DefDatabase) -> $id {
199 impl Lookup for $id {
201 fn lookup(&self, db: &dyn db::DefDatabase) -> $loc {
208 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
209 pub struct FunctionId(salsa::InternId);
210 type FunctionLoc = AssocItemLoc<Function>;
211 impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
213 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
214 pub struct StructId(salsa::InternId);
215 type StructLoc = ItemLoc<Struct>;
216 impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
218 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
219 pub struct UnionId(salsa::InternId);
220 pub type UnionLoc = ItemLoc<Union>;
221 impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
223 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
224 pub struct EnumId(salsa::InternId);
225 pub type EnumLoc = ItemLoc<Enum>;
226 impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
228 // FIXME: rename to `VariantId`, only enums can ave variants
229 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
230 pub struct EnumVariantId {
232 pub local_id: LocalEnumVariantId,
235 pub type LocalEnumVariantId = Idx<adt::EnumVariantData>;
237 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
239 pub parent: VariantId,
240 pub local_id: LocalFieldId,
243 pub type LocalFieldId = Idx<adt::FieldData>;
245 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
246 pub struct ConstId(salsa::InternId);
247 type ConstLoc = AssocItemLoc<Const>;
248 impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
250 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
251 pub struct StaticId(salsa::InternId);
252 pub type StaticLoc = AssocItemLoc<Static>;
253 impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
255 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
256 pub struct TraitId(salsa::InternId);
257 pub type TraitLoc = ItemLoc<Trait>;
258 impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
260 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
261 pub struct TypeAliasId(salsa::InternId);
262 type TypeAliasLoc = AssocItemLoc<TypeAlias>;
263 impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
265 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
266 pub struct ImplId(salsa::InternId);
267 type ImplLoc = ItemLoc<Impl>;
268 impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
270 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
271 pub struct ExternBlockId(salsa::InternId);
272 type ExternBlockLoc = ItemLoc<ExternBlock>;
273 impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block);
275 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
276 pub enum MacroExpander {
278 BuiltIn(BuiltinFnLikeExpander),
279 BuiltInAttr(BuiltinAttrExpander),
280 BuiltInDerive(BuiltinDeriveExpander),
281 BuiltInEager(EagerExpander),
284 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
285 pub struct Macro2Id(salsa::InternId);
286 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
287 pub struct Macro2Loc {
288 pub container: ModuleId,
289 pub id: ItemTreeId<MacroDef>,
290 pub expander: MacroExpander,
292 impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2);
294 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
295 pub struct MacroRulesId(salsa::InternId);
296 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
297 pub struct MacroRulesLoc {
298 pub container: ModuleId,
299 pub id: ItemTreeId<MacroRules>,
300 pub local_inner: bool,
301 pub expander: MacroExpander,
303 impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules);
305 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
306 pub struct ProcMacroId(salsa::InternId);
307 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
308 pub struct ProcMacroLoc {
309 // FIXME: this should be a crate? or just a crate-root module
310 pub container: ModuleId,
311 pub id: ItemTreeId<Function>,
312 pub expander: ProcMacroExpander,
313 pub kind: ProcMacroKind,
315 impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro);
317 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
318 pub struct BlockId(salsa::InternId);
319 #[derive(Debug, Hash, PartialEq, Eq, Clone)]
320 pub struct BlockLoc {
321 ast_id: AstId<ast::BlockExpr>,
322 /// The containing module.
325 impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
327 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
328 pub struct TypeOrConstParamId {
329 pub parent: GenericDefId,
330 pub local_id: LocalTypeOrConstParamId,
333 /// A TypeOrConstParamId with an invariant that it actually belongs to a type
334 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
335 pub struct TypeParamId(TypeOrConstParamId);
338 pub fn parent(&self) -> GenericDefId {
341 pub fn local_id(&self) -> LocalTypeOrConstParamId {
347 /// Caller should check if this toc id really belongs to a type
348 pub fn from_unchecked(x: TypeOrConstParamId) -> Self {
353 impl From<TypeParamId> for TypeOrConstParamId {
354 fn from(x: TypeParamId) -> Self {
359 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
360 /// A TypeOrConstParamId with an invariant that it actually belongs to a const
361 pub struct ConstParamId(TypeOrConstParamId);
364 pub fn parent(&self) -> GenericDefId {
367 pub fn local_id(&self) -> LocalTypeOrConstParamId {
373 /// Caller should check if this toc id really belongs to a const
374 pub fn from_unchecked(x: TypeOrConstParamId) -> Self {
379 impl From<ConstParamId> for TypeOrConstParamId {
380 fn from(x: ConstParamId) -> Self {
385 pub type LocalTypeOrConstParamId = Idx<generics::TypeOrConstParamData>;
387 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
388 pub struct LifetimeParamId {
389 pub parent: GenericDefId,
390 pub local_id: LocalLifetimeParamId,
392 pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
394 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
395 pub enum ItemContainerId {
396 ExternBlockId(ExternBlockId),
401 impl_from!(ModuleId for ItemContainerId);
404 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
410 impl_from!(StructId, UnionId, EnumId for AdtId);
413 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
416 MacroRulesId(MacroRulesId),
417 ProcMacroId(ProcMacroId),
419 impl_from!(Macro2Id, MacroRulesId, ProcMacroId for MacroId);
422 pub fn is_attribute(self, db: &dyn db::DefDatabase) -> bool {
424 MacroId::ProcMacroId(it) => it.lookup(db).kind == ProcMacroKind::Attr,
431 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
432 pub enum GenericParamId {
433 TypeParamId(TypeParamId),
434 ConstParamId(ConstParamId),
435 LifetimeParamId(LifetimeParamId),
437 impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId);
439 /// The defs which can be visible in the module.
440 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
441 pub enum ModuleDefId {
443 FunctionId(FunctionId),
445 // Can't be directly declared, but can be imported.
446 EnumVariantId(EnumVariantId),
450 TypeAliasId(TypeAliasId),
451 BuiltinType(BuiltinType),
455 MacroId(Macro2Id, MacroRulesId, ProcMacroId),
458 AdtId(StructId, EnumId, UnionId),
468 /// The defs which have a body.
469 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
470 pub enum DefWithBodyId {
471 FunctionId(FunctionId),
476 impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
479 pub fn as_generic_def_id(self) -> Option<GenericDefId> {
481 DefWithBodyId::FunctionId(f) => Some(f.into()),
482 DefWithBodyId::StaticId(_) => None,
483 DefWithBodyId::ConstId(c) => Some(c.into()),
488 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
489 pub enum AssocItemId {
490 FunctionId(FunctionId),
492 TypeAliasId(TypeAliasId),
494 // FIXME: not every function, ... is actually an assoc item. maybe we should make
495 // sure that you can only turn actual assoc items into AssocItemIds. This would
496 // require not implementing From, and instead having some checked way of
497 // casting them, and somehow making the constructors private, which would be annoying.
498 impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId);
500 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
501 pub enum GenericDefId {
502 FunctionId(FunctionId),
505 TypeAliasId(TypeAliasId),
507 // enum variants cannot have generics themselves, but their parent enums
508 // can, and this makes some code easier to write
509 EnumVariantId(EnumVariantId),
510 // consts can have type parameters from their parents (i.e. associated consts of traits)
515 AdtId(StructId, EnumId, UnionId),
524 impl From<AssocItemId> for GenericDefId {
525 fn from(item: AssocItemId) -> Self {
527 AssocItemId::FunctionId(f) => f.into(),
528 AssocItemId::ConstId(c) => c.into(),
529 AssocItemId::TypeAliasId(t) => t.into(),
534 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
539 FunctionId(FunctionId),
540 EnumVariantId(EnumVariantId),
544 TypeAliasId(TypeAliasId),
547 GenericParamId(GenericParamId),
548 ExternBlockId(ExternBlockId),
554 AdtId(StructId, EnumId, UnionId),
561 MacroId(Macro2Id, MacroRulesId, ProcMacroId),
567 impl From<ItemContainerId> for AttrDefId {
568 fn from(acid: ItemContainerId) -> Self {
570 ItemContainerId::ModuleId(mid) => AttrDefId::ModuleId(mid),
571 ItemContainerId::ImplId(iid) => AttrDefId::ImplId(iid),
572 ItemContainerId::TraitId(tid) => AttrDefId::TraitId(tid),
573 ItemContainerId::ExternBlockId(id) => AttrDefId::ExternBlockId(id),
578 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
580 EnumVariantId(EnumVariantId),
584 impl_from!(EnumVariantId, StructId, UnionId for VariantId);
587 pub fn variant_data(self, db: &dyn db::DefDatabase) -> Arc<VariantData> {
589 VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
590 VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
591 VariantId::EnumVariantId(it) => {
592 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
597 pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
599 VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
600 VariantId::StructId(it) => it.lookup(db).id.file_id(),
601 VariantId::UnionId(it) => it.lookup(db).id.file_id(),
605 pub fn adt_id(self) -> AdtId {
607 VariantId::EnumVariantId(it) => it.parent.into(),
608 VariantId::StructId(it) => it.into(),
609 VariantId::UnionId(it) => it.into(),
616 fn intern(self, db: &dyn db::DefDatabase) -> Self::ID;
621 fn lookup(&self, db: &dyn db::DefDatabase) -> Self::Data;
624 pub trait HasModule {
625 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId;
628 impl HasModule for ItemContainerId {
629 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
631 ItemContainerId::ModuleId(it) => it,
632 ItemContainerId::ImplId(it) => it.lookup(db).container,
633 ItemContainerId::TraitId(it) => it.lookup(db).container,
634 ItemContainerId::ExternBlockId(it) => it.lookup(db).container,
639 impl<N: ItemTreeNode> HasModule for AssocItemLoc<N> {
640 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
641 self.container.module(db)
645 impl HasModule for AdtId {
646 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
648 AdtId::StructId(it) => it.lookup(db).container,
649 AdtId::UnionId(it) => it.lookup(db).container,
650 AdtId::EnumId(it) => it.lookup(db).container,
655 impl HasModule for VariantId {
656 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
658 VariantId::EnumVariantId(it) => it.parent.lookup(db).container,
659 VariantId::StructId(it) => it.lookup(db).container,
660 VariantId::UnionId(it) => it.lookup(db).container,
665 impl HasModule for MacroId {
666 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
668 MacroId::MacroRulesId(it) => it.lookup(db).container,
669 MacroId::Macro2Id(it) => it.lookup(db).container,
670 MacroId::ProcMacroId(it) => it.lookup(db).container,
675 impl HasModule for DefWithBodyId {
676 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
678 DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
679 DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
680 DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
686 pub fn as_mod_item(self, db: &dyn db::DefDatabase) -> ModItem {
688 DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
689 DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
690 DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
695 impl HasModule for GenericDefId {
696 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
698 GenericDefId::FunctionId(it) => it.lookup(db).module(db),
699 GenericDefId::AdtId(it) => it.module(db),
700 GenericDefId::TraitId(it) => it.lookup(db).container,
701 GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
702 GenericDefId::ImplId(it) => it.lookup(db).container,
703 GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container,
704 GenericDefId::ConstId(it) => it.lookup(db).module(db),
709 impl HasModule for TypeAliasId {
710 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
711 self.lookup(db).module(db)
715 impl HasModule for TraitId {
716 fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
717 self.lookup(db).container
722 /// Returns the module containing `self` (or `self`, if `self` is itself a module).
724 /// Returns `None` if `self` refers to a primitive type.
725 pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
727 ModuleDefId::ModuleId(id) => *id,
728 ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
729 ModuleDefId::AdtId(id) => id.module(db),
730 ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container,
731 ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
732 ModuleDefId::StaticId(id) => id.lookup(db).module(db),
733 ModuleDefId::TraitId(id) => id.lookup(db).container,
734 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
735 ModuleDefId::MacroId(id) => id.module(db),
736 ModuleDefId::BuiltinType(_) => return None,
742 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
744 AttrDefId::ModuleId(it) => it.krate,
745 AttrDefId::FieldId(it) => it.parent.module(db).krate,
746 AttrDefId::AdtId(it) => it.module(db).krate,
747 AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
748 AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.krate,
749 AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
750 AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
751 AttrDefId::TraitId(it) => it.lookup(db).container.krate,
752 AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
753 AttrDefId::ImplId(it) => it.lookup(db).container.krate,
754 AttrDefId::ExternBlockId(it) => it.lookup(db).container.krate,
755 AttrDefId::GenericParamId(it) => {
757 GenericParamId::TypeParamId(it) => it.parent(),
758 GenericParamId::ConstParamId(it) => it.parent(),
759 GenericParamId::LifetimeParamId(it) => it.parent,
764 AttrDefId::MacroId(it) => it.module(db).krate,
769 /// A helper trait for converting to MacroCallId
770 pub trait AsMacroCall {
773 db: &dyn db::DefDatabase,
775 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
776 ) -> Option<MacroCallId> {
777 self.as_call_id_with_errors(db, krate, resolver, &mut |_| ()).ok()?.ok()
780 fn as_call_id_with_errors(
782 db: &dyn db::DefDatabase,
784 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
785 error_sink: &mut dyn FnMut(ExpandError),
786 ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro>;
789 impl AsMacroCall for InFile<&ast::MacroCall> {
790 fn as_call_id_with_errors(
792 db: &dyn db::DefDatabase,
794 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
795 mut error_sink: &mut dyn FnMut(ExpandError),
796 ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
797 let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
798 let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
799 let h = Hygiene::new(db.upcast(), self.file_id);
801 self.value.path().and_then(|path| path::ModPath::from_src(db.upcast(), path, &h));
803 let path = match error_sink
804 .option(path, || ExpandError::Other("malformed macro invocation".into()))
808 return Ok(Err(error));
812 macro_call_as_call_id(
814 &AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
823 /// Helper wrapper for `AstId` with `ModPath`
824 #[derive(Clone, Debug, Eq, PartialEq)]
825 struct AstIdWithPath<T: ast::AstNode> {
830 impl<T: ast::AstNode> AstIdWithPath<T> {
831 fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T> {
832 AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path }
836 fn macro_call_as_call_id(
837 db: &dyn db::DefDatabase,
838 call: &AstIdWithPath<ast::MacroCall>,
841 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
842 error_sink: &mut dyn FnMut(ExpandError),
843 ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
845 resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?;
847 let res = if let MacroDefKind::BuiltInEager(..) = def.kind {
848 let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
850 expand_eager_macro(db.upcast(), krate, macro_call, def, &resolver, error_sink)?
852 Ok(def.as_lazy_macro(
855 MacroCallKind::FnLike { ast_id: call.ast_id, expand_to },
861 pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
863 MacroId::Macro2Id(it) => {
864 let loc = it.lookup(db);
866 let item_tree = loc.id.item_tree(db);
867 let makro = &item_tree[loc.id.value];
868 let in_file = |m: FileAstId<ast::MacroDef>| InFile::new(loc.id.file_id(), m.upcast());
870 krate: loc.container.krate,
871 kind: match loc.expander {
872 MacroExpander::Declarative => MacroDefKind::Declarative(in_file(makro.ast_id)),
873 MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file(makro.ast_id)),
874 MacroExpander::BuiltInAttr(it) => {
875 MacroDefKind::BuiltInAttr(it, in_file(makro.ast_id))
877 MacroExpander::BuiltInDerive(it) => {
878 MacroDefKind::BuiltInDerive(it, in_file(makro.ast_id))
880 MacroExpander::BuiltInEager(it) => {
881 MacroDefKind::BuiltInEager(it, in_file(makro.ast_id))
887 MacroId::MacroRulesId(it) => {
888 let loc = it.lookup(db);
890 let item_tree = loc.id.item_tree(db);
891 let makro = &item_tree[loc.id.value];
892 let in_file = |m: FileAstId<ast::MacroRules>| InFile::new(loc.id.file_id(), m.upcast());
894 krate: loc.container.krate,
895 kind: match loc.expander {
896 MacroExpander::Declarative => MacroDefKind::Declarative(in_file(makro.ast_id)),
897 MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(it, in_file(makro.ast_id)),
898 MacroExpander::BuiltInAttr(it) => {
899 MacroDefKind::BuiltInAttr(it, in_file(makro.ast_id))
901 MacroExpander::BuiltInDerive(it) => {
902 MacroDefKind::BuiltInDerive(it, in_file(makro.ast_id))
904 MacroExpander::BuiltInEager(it) => {
905 MacroDefKind::BuiltInEager(it, in_file(makro.ast_id))
908 local_inner: loc.local_inner,
911 MacroId::ProcMacroId(it) => {
912 let loc = it.lookup(db);
914 let item_tree = loc.id.item_tree(db);
915 let makro = &item_tree[loc.id.value];
917 krate: loc.container.krate,
918 kind: MacroDefKind::ProcMacro(
921 InFile::new(loc.id.file_id(), makro.ast_id),
929 fn derive_macro_as_call_id(
930 db: &dyn db::DefDatabase,
931 item_attr: &AstIdWithPath<ast::Adt>,
935 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
936 ) -> Result<MacroCallId, UnresolvedMacro> {
937 let def: MacroDefId = resolver(item_attr.path.clone())
938 .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
939 let res = def.as_lazy_macro(
942 MacroCallKind::Derive {
943 ast_id: item_attr.ast_id,
944 derive_index: derive_pos,
945 derive_attr_index: derive_attr.ast_index,
951 fn attr_macro_as_call_id(
952 db: &dyn db::DefDatabase,
953 item_attr: &AstIdWithPath<ast::Item>,
959 let mut arg = match macro_attr.input.as_deref() {
960 Some(attr::AttrInput::TokenTree(tt, map)) => (tt.clone(), map.clone()),
961 _ => Default::default(),
964 // The parentheses are always disposed here.
965 arg.0.delimiter = None;
967 let res = def.as_lazy_macro(
970 MacroCallKind::Attr {
971 ast_id: item_attr.ast_id,
972 attr_args: Arc::new(arg),
973 invoc_attr_index: macro_attr.id.ast_index,