]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/lib.rs
Merge #10701
[rust.git] / crates / hir_def / src / lib.rs
1 //! `hir_def` crate contains everything between macro expansion and type
2 //! inference.
3 //!
4 //! It defines various items (structs, enums, traits) which comprises Rust code,
5 //! as well as an algorithm for resolving paths to such entities.
6 //!
7 //! Note that `hir_def` is a work in progress, so not all of the above is
8 //! actually true.
9
10 #[allow(unused)]
11 macro_rules! eprintln {
12     ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
13 }
14
15 pub mod db;
16
17 pub mod attr;
18 pub mod path;
19 pub mod type_ref;
20 pub mod builtin_type;
21 pub mod builtin_attr;
22 pub mod per_ns;
23 pub mod item_scope;
24
25 pub mod dyn_map;
26 pub mod keys;
27
28 pub mod item_tree;
29 pub mod intern;
30
31 pub mod adt;
32 pub mod data;
33 pub mod generics;
34 pub mod lang_item;
35
36 pub mod expr;
37 pub mod body;
38 pub mod resolver;
39
40 mod trace;
41 pub mod nameres;
42
43 pub mod src;
44 pub mod child_by_source;
45
46 pub mod visibility;
47 pub mod find_path;
48 pub mod import_map;
49
50 #[cfg(test)]
51 mod test_db;
52 #[cfg(test)]
53 mod macro_expansion_tests;
54
55 use std::{
56     hash::{Hash, Hasher},
57     sync::Arc,
58 };
59
60 use attr::Attr;
61 use base_db::{impl_intern_key, salsa, CrateId};
62 use hir_expand::{
63     ast_id_map::FileAstId,
64     eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
65     hygiene::Hygiene,
66     AstId, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
67 };
68 use la_arena::Idx;
69 use nameres::DefMap;
70 use path::ModPath;
71 use stdx::impl_from;
72 use syntax::ast;
73
74 use crate::{
75     adt::VariantData,
76     attr::AttrId,
77     builtin_type::BuiltinType,
78     item_tree::{
79         Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, ModItem, Static, Struct, Trait,
80         TypeAlias, Union,
81     },
82 };
83
84 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
85 pub struct ModuleId {
86     krate: CrateId,
87     /// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the
88     /// `BlockId` of that block expression. If `None`, this module is part of the crate-level
89     /// `DefMap` of `krate`.
90     block: Option<BlockId>,
91     /// The module's ID in its originating `DefMap`.
92     pub local_id: LocalModuleId,
93 }
94
95 impl ModuleId {
96     pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> {
97         match self.block {
98             Some(block) => {
99                 db.block_def_map(block).unwrap_or_else(|| {
100                     // NOTE: This should be unreachable - all `ModuleId`s come from their `DefMap`s,
101                     // so the `DefMap` here must exist.
102                     unreachable!("no `block_def_map` for `ModuleId` {:?}", self);
103                 })
104             }
105             None => db.crate_def_map(self.krate),
106         }
107     }
108
109     pub fn krate(&self) -> CrateId {
110         self.krate
111     }
112
113     pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
114         self.def_map(db).containing_module(self.local_id)
115     }
116
117     pub fn containing_block(&self) -> Option<BlockId> {
118         self.block
119     }
120 }
121
122 /// An ID of a module, **local** to a specific crate
123 pub type LocalModuleId = Idx<nameres::ModuleData>;
124
125 #[derive(Debug)]
126 pub struct ItemLoc<N: ItemTreeNode> {
127     pub container: ModuleId,
128     pub id: ItemTreeId<N>,
129 }
130
131 impl<N: ItemTreeNode> Clone for ItemLoc<N> {
132     fn clone(&self) -> Self {
133         Self { container: self.container, id: self.id }
134     }
135 }
136
137 impl<N: ItemTreeNode> Copy for ItemLoc<N> {}
138
139 impl<N: ItemTreeNode> PartialEq for ItemLoc<N> {
140     fn eq(&self, other: &Self) -> bool {
141         self.container == other.container && self.id == other.id
142     }
143 }
144
145 impl<N: ItemTreeNode> Eq for ItemLoc<N> {}
146
147 impl<N: ItemTreeNode> Hash for ItemLoc<N> {
148     fn hash<H: Hasher>(&self, state: &mut H) {
149         self.container.hash(state);
150         self.id.hash(state);
151     }
152 }
153
154 #[derive(Debug)]
155 pub struct AssocItemLoc<N: ItemTreeNode> {
156     pub container: AssocContainerId,
157     pub id: ItemTreeId<N>,
158 }
159
160 impl<N: ItemTreeNode> Clone for AssocItemLoc<N> {
161     fn clone(&self) -> Self {
162         Self { container: self.container, id: self.id }
163     }
164 }
165
166 impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {}
167
168 impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> {
169     fn eq(&self, other: &Self) -> bool {
170         self.container == other.container && self.id == other.id
171     }
172 }
173
174 impl<N: ItemTreeNode> Eq for AssocItemLoc<N> {}
175
176 impl<N: ItemTreeNode> Hash for AssocItemLoc<N> {
177     fn hash<H: Hasher>(&self, state: &mut H) {
178         self.container.hash(state);
179         self.id.hash(state);
180     }
181 }
182
183 macro_rules! impl_intern {
184     ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
185         impl_intern_key!($id);
186
187         impl Intern for $loc {
188             type ID = $id;
189             fn intern(self, db: &dyn db::DefDatabase) -> $id {
190                 db.$intern(self)
191             }
192         }
193
194         impl Lookup for $id {
195             type Data = $loc;
196             fn lookup(&self, db: &dyn db::DefDatabase) -> $loc {
197                 db.$lookup(*self)
198             }
199         }
200     };
201 }
202
203 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
204 pub struct FunctionId(salsa::InternId);
205 type FunctionLoc = AssocItemLoc<Function>;
206 impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
207
208 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
209 pub struct StructId(salsa::InternId);
210 type StructLoc = ItemLoc<Struct>;
211 impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
212
213 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
214 pub struct UnionId(salsa::InternId);
215 pub type UnionLoc = ItemLoc<Union>;
216 impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
217
218 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
219 pub struct EnumId(salsa::InternId);
220 pub type EnumLoc = ItemLoc<Enum>;
221 impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
222
223 // FIXME: rename to `VariantId`, only enums can ave variants
224 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
225 pub struct EnumVariantId {
226     pub parent: EnumId,
227     pub local_id: LocalEnumVariantId,
228 }
229
230 pub type LocalEnumVariantId = Idx<adt::EnumVariantData>;
231
232 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
233 pub struct FieldId {
234     pub parent: VariantId,
235     pub local_id: LocalFieldId,
236 }
237
238 pub type LocalFieldId = Idx<adt::FieldData>;
239
240 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
241 pub struct ConstId(salsa::InternId);
242 type ConstLoc = AssocItemLoc<Const>;
243 impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
244
245 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
246 pub struct StaticId(salsa::InternId);
247 pub type StaticLoc = ItemLoc<Static>;
248 impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
249
250 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
251 pub struct TraitId(salsa::InternId);
252 pub type TraitLoc = ItemLoc<Trait>;
253 impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
254
255 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
256 pub struct TypeAliasId(salsa::InternId);
257 type TypeAliasLoc = AssocItemLoc<TypeAlias>;
258 impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
259
260 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
261 pub struct ImplId(salsa::InternId);
262 type ImplLoc = ItemLoc<Impl>;
263 impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
264
265 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
266 pub struct BlockId(salsa::InternId);
267 #[derive(Debug, Hash, PartialEq, Eq, Clone)]
268 pub struct BlockLoc {
269     ast_id: AstId<ast::BlockExpr>,
270     /// The containing module.
271     module: ModuleId,
272 }
273 impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
274
275 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
276 pub struct TypeParamId {
277     pub parent: GenericDefId,
278     pub local_id: LocalTypeParamId,
279 }
280
281 pub type LocalTypeParamId = Idx<generics::TypeParamData>;
282
283 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
284 pub struct LifetimeParamId {
285     pub parent: GenericDefId,
286     pub local_id: LocalLifetimeParamId,
287 }
288 pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
289
290 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
291 pub struct ConstParamId {
292     pub parent: GenericDefId,
293     pub local_id: LocalConstParamId,
294 }
295 pub type LocalConstParamId = Idx<generics::ConstParamData>;
296
297 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
298 pub enum AssocContainerId {
299     ModuleId(ModuleId),
300     ImplId(ImplId),
301     TraitId(TraitId),
302 }
303 impl_from!(ModuleId for AssocContainerId);
304
305 /// A Data Type
306 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
307 pub enum AdtId {
308     StructId(StructId),
309     UnionId(UnionId),
310     EnumId(EnumId),
311 }
312 impl_from!(StructId, UnionId, EnumId for AdtId);
313
314 /// A generic param
315 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
316 pub enum GenericParamId {
317     TypeParamId(TypeParamId),
318     LifetimeParamId(LifetimeParamId),
319     ConstParamId(ConstParamId),
320 }
321 impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId);
322
323 /// The defs which can be visible in the module.
324 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
325 pub enum ModuleDefId {
326     ModuleId(ModuleId),
327     FunctionId(FunctionId),
328     AdtId(AdtId),
329     // Can't be directly declared, but can be imported.
330     EnumVariantId(EnumVariantId),
331     ConstId(ConstId),
332     StaticId(StaticId),
333     TraitId(TraitId),
334     TypeAliasId(TypeAliasId),
335     BuiltinType(BuiltinType),
336 }
337 impl_from!(
338     ModuleId,
339     FunctionId,
340     AdtId(StructId, EnumId, UnionId),
341     EnumVariantId,
342     ConstId,
343     StaticId,
344     TraitId,
345     TypeAliasId,
346     BuiltinType
347     for ModuleDefId
348 );
349
350 /// The defs which have a body.
351 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
352 pub enum DefWithBodyId {
353     FunctionId(FunctionId),
354     StaticId(StaticId),
355     ConstId(ConstId),
356 }
357
358 impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
359
360 impl DefWithBodyId {
361     pub fn as_generic_def_id(self) -> Option<GenericDefId> {
362         match self {
363             DefWithBodyId::FunctionId(f) => Some(f.into()),
364             DefWithBodyId::StaticId(_) => None,
365             DefWithBodyId::ConstId(c) => Some(c.into()),
366         }
367     }
368 }
369
370 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
371 pub enum AssocItemId {
372     FunctionId(FunctionId),
373     ConstId(ConstId),
374     TypeAliasId(TypeAliasId),
375 }
376 // FIXME: not every function, ... is actually an assoc item. maybe we should make
377 // sure that you can only turn actual assoc items into AssocItemIds. This would
378 // require not implementing From, and instead having some checked way of
379 // casting them, and somehow making the constructors private, which would be annoying.
380 impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId);
381
382 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
383 pub enum GenericDefId {
384     FunctionId(FunctionId),
385     AdtId(AdtId),
386     TraitId(TraitId),
387     TypeAliasId(TypeAliasId),
388     ImplId(ImplId),
389     // enum variants cannot have generics themselves, but their parent enums
390     // can, and this makes some code easier to write
391     EnumVariantId(EnumVariantId),
392     // consts can have type parameters from their parents (i.e. associated consts of traits)
393     ConstId(ConstId),
394 }
395 impl_from!(
396     FunctionId,
397     AdtId(StructId, EnumId, UnionId),
398     TraitId,
399     TypeAliasId,
400     ImplId,
401     EnumVariantId,
402     ConstId
403     for GenericDefId
404 );
405
406 impl From<AssocItemId> for GenericDefId {
407     fn from(item: AssocItemId) -> Self {
408         match item {
409             AssocItemId::FunctionId(f) => f.into(),
410             AssocItemId::ConstId(c) => c.into(),
411             AssocItemId::TypeAliasId(t) => t.into(),
412         }
413     }
414 }
415
416 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
417 pub enum AttrDefId {
418     ModuleId(ModuleId),
419     FieldId(FieldId),
420     AdtId(AdtId),
421     FunctionId(FunctionId),
422     EnumVariantId(EnumVariantId),
423     StaticId(StaticId),
424     ConstId(ConstId),
425     TraitId(TraitId),
426     TypeAliasId(TypeAliasId),
427     MacroDefId(MacroDefId),
428     ImplId(ImplId),
429     GenericParamId(GenericParamId),
430 }
431
432 impl_from!(
433     ModuleId,
434     FieldId,
435     AdtId(StructId, EnumId, UnionId),
436     EnumVariantId,
437     StaticId,
438     ConstId,
439     FunctionId,
440     TraitId,
441     TypeAliasId,
442     MacroDefId,
443     ImplId,
444     GenericParamId
445     for AttrDefId
446 );
447
448 impl From<AssocContainerId> for AttrDefId {
449     fn from(acid: AssocContainerId) -> Self {
450         match acid {
451             AssocContainerId::ModuleId(mid) => AttrDefId::ModuleId(mid),
452             AssocContainerId::ImplId(iid) => AttrDefId::ImplId(iid),
453             AssocContainerId::TraitId(tid) => AttrDefId::TraitId(tid),
454         }
455     }
456 }
457
458 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
459 pub enum VariantId {
460     EnumVariantId(EnumVariantId),
461     StructId(StructId),
462     UnionId(UnionId),
463 }
464 impl_from!(EnumVariantId, StructId, UnionId for VariantId);
465
466 impl VariantId {
467     pub fn variant_data(self, db: &dyn db::DefDatabase) -> Arc<VariantData> {
468         match self {
469             VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
470             VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
471             VariantId::EnumVariantId(it) => {
472                 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
473             }
474         }
475     }
476
477     pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
478         match self {
479             VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
480             VariantId::StructId(it) => it.lookup(db).id.file_id(),
481             VariantId::UnionId(it) => it.lookup(db).id.file_id(),
482         }
483     }
484
485     pub fn adt_id(self) -> AdtId {
486         match self {
487             VariantId::EnumVariantId(it) => it.parent.into(),
488             VariantId::StructId(it) => it.into(),
489             VariantId::UnionId(it) => it.into(),
490         }
491     }
492 }
493
494 trait Intern {
495     type ID;
496     fn intern(self, db: &dyn db::DefDatabase) -> Self::ID;
497 }
498
499 pub trait Lookup {
500     type Data;
501     fn lookup(&self, db: &dyn db::DefDatabase) -> Self::Data;
502 }
503
504 pub trait HasModule {
505     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId;
506 }
507
508 impl HasModule for AssocContainerId {
509     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
510         match *self {
511             AssocContainerId::ModuleId(it) => it,
512             AssocContainerId::ImplId(it) => it.lookup(db).container,
513             AssocContainerId::TraitId(it) => it.lookup(db).container,
514         }
515     }
516 }
517
518 impl<N: ItemTreeNode> HasModule for AssocItemLoc<N> {
519     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
520         self.container.module(db)
521     }
522 }
523
524 impl HasModule for AdtId {
525     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
526         match self {
527             AdtId::StructId(it) => it.lookup(db).container,
528             AdtId::UnionId(it) => it.lookup(db).container,
529             AdtId::EnumId(it) => it.lookup(db).container,
530         }
531     }
532 }
533
534 impl HasModule for VariantId {
535     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
536         match self {
537             VariantId::EnumVariantId(it) => it.parent.lookup(db).container,
538             VariantId::StructId(it) => it.lookup(db).container,
539             VariantId::UnionId(it) => it.lookup(db).container,
540         }
541     }
542 }
543
544 impl HasModule for DefWithBodyId {
545     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
546         match self {
547             DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
548             DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
549             DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
550         }
551     }
552 }
553
554 impl DefWithBodyId {
555     pub fn as_mod_item(self, db: &dyn db::DefDatabase) -> ModItem {
556         match self {
557             DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
558             DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
559             DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
560         }
561     }
562 }
563
564 impl HasModule for GenericDefId {
565     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
566         match self {
567             GenericDefId::FunctionId(it) => it.lookup(db).module(db),
568             GenericDefId::AdtId(it) => it.module(db),
569             GenericDefId::TraitId(it) => it.lookup(db).container,
570             GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
571             GenericDefId::ImplId(it) => it.lookup(db).container,
572             GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container,
573             GenericDefId::ConstId(it) => it.lookup(db).module(db),
574         }
575     }
576 }
577
578 impl HasModule for TypeAliasId {
579     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
580         self.lookup(db).module(db)
581     }
582 }
583
584 impl HasModule for TraitId {
585     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
586         self.lookup(db).container
587     }
588 }
589
590 impl HasModule for StaticLoc {
591     fn module(&self, _db: &dyn db::DefDatabase) -> ModuleId {
592         self.container
593     }
594 }
595
596 impl ModuleDefId {
597     /// Returns the module containing `self` (or `self`, if `self` is itself a module).
598     ///
599     /// Returns `None` if `self` refers to a primitive type.
600     pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
601         Some(match self {
602             ModuleDefId::ModuleId(id) => *id,
603             ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
604             ModuleDefId::AdtId(id) => id.module(db),
605             ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container,
606             ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
607             ModuleDefId::StaticId(id) => id.lookup(db).container,
608             ModuleDefId::TraitId(id) => id.lookup(db).container,
609             ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
610             ModuleDefId::BuiltinType(_) => return None,
611         })
612     }
613 }
614
615 impl AttrDefId {
616     pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
617         match self {
618             AttrDefId::ModuleId(it) => it.krate,
619             AttrDefId::FieldId(it) => it.parent.module(db).krate,
620             AttrDefId::AdtId(it) => it.module(db).krate,
621             AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
622             AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.krate,
623             AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
624             AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
625             AttrDefId::TraitId(it) => it.lookup(db).container.krate,
626             AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
627             AttrDefId::ImplId(it) => it.lookup(db).container.krate,
628             AttrDefId::GenericParamId(it) => {
629                 match it {
630                     GenericParamId::TypeParamId(it) => it.parent,
631                     GenericParamId::LifetimeParamId(it) => it.parent,
632                     GenericParamId::ConstParamId(it) => it.parent,
633                 }
634                 .module(db)
635                 .krate
636             }
637             // FIXME: `MacroDefId` should store the defining module, then this can implement
638             // `HasModule`
639             AttrDefId::MacroDefId(it) => it.krate,
640         }
641     }
642 }
643
644 /// A helper trait for converting to MacroCallId
645 pub trait AsMacroCall {
646     fn as_call_id(
647         &self,
648         db: &dyn db::DefDatabase,
649         krate: CrateId,
650         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
651     ) -> Option<MacroCallId> {
652         self.as_call_id_with_errors(db, krate, resolver, &mut |_| ()).ok()?.ok()
653     }
654
655     fn as_call_id_with_errors(
656         &self,
657         db: &dyn db::DefDatabase,
658         krate: CrateId,
659         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
660         error_sink: &mut dyn FnMut(mbe::ExpandError),
661     ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro>;
662 }
663
664 impl AsMacroCall for InFile<&ast::MacroCall> {
665     fn as_call_id_with_errors(
666         &self,
667         db: &dyn db::DefDatabase,
668         krate: CrateId,
669         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
670         mut error_sink: &mut dyn FnMut(mbe::ExpandError),
671     ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
672         let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
673         let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
674         let h = Hygiene::new(db.upcast(), self.file_id);
675         let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
676
677         let path = match error_sink
678             .option(path, || mbe::ExpandError::Other("malformed macro invocation".into()))
679         {
680             Ok(path) => path,
681             Err(error) => {
682                 return Ok(Err(error));
683             }
684         };
685
686         macro_call_as_call_id(
687             &AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
688             expands_to,
689             db,
690             krate,
691             resolver,
692             error_sink,
693         )
694     }
695 }
696
697 /// Helper wrapper for `AstId` with `ModPath`
698 #[derive(Clone, Debug, Eq, PartialEq)]
699 struct AstIdWithPath<T: ast::AstNode> {
700     ast_id: AstId<T>,
701     path: path::ModPath,
702 }
703
704 impl<T: ast::AstNode> AstIdWithPath<T> {
705     fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T> {
706         AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path }
707     }
708 }
709
710 #[derive(Debug)]
711 pub struct UnresolvedMacro {
712     pub path: ModPath,
713 }
714
715 fn macro_call_as_call_id(
716     call: &AstIdWithPath<ast::MacroCall>,
717     expand_to: ExpandTo,
718     db: &dyn db::DefDatabase,
719     krate: CrateId,
720     resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
721     error_sink: &mut dyn FnMut(mbe::ExpandError),
722 ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
723     let def: MacroDefId =
724         resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?;
725
726     let res = if let MacroDefKind::BuiltInEager(..) = def.kind {
727         let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
728         let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id);
729
730         expand_eager_macro(
731             db.upcast(),
732             krate,
733             macro_call,
734             def,
735             &|path: ast::Path| resolver(path::ModPath::from_src(db, path, &hygiene)?),
736             error_sink,
737         )
738     } else {
739         Ok(def.as_lazy_macro(
740             db.upcast(),
741             krate,
742             MacroCallKind::FnLike { ast_id: call.ast_id, expand_to },
743         ))
744     };
745     Ok(res)
746 }
747
748 fn derive_macro_as_call_id(
749     item_attr: &AstIdWithPath<ast::Item>,
750     derive_attr: AttrId,
751     db: &dyn db::DefDatabase,
752     krate: CrateId,
753     resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
754 ) -> Result<MacroCallId, UnresolvedMacro> {
755     let def: MacroDefId = resolver(item_attr.path.clone())
756         .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
757     let last_segment = item_attr
758         .path
759         .segments()
760         .last()
761         .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
762     let res = def.as_lazy_macro(
763         db.upcast(),
764         krate,
765         MacroCallKind::Derive {
766             ast_id: item_attr.ast_id,
767             derive_name: last_segment.to_string().into_boxed_str(),
768             derive_attr_index: derive_attr.ast_index,
769         },
770     );
771     Ok(res)
772 }
773
774 fn attr_macro_as_call_id(
775     item_attr: &AstIdWithPath<ast::Item>,
776     macro_attr: &Attr,
777     db: &dyn db::DefDatabase,
778     krate: CrateId,
779     resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
780 ) -> Result<MacroCallId, UnresolvedMacro> {
781     let def: MacroDefId = resolver(item_attr.path.clone())
782         .filter(MacroDefId::is_attribute)
783         .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
784     let last_segment = item_attr
785         .path
786         .segments()
787         .last()
788         .ok_or_else(|| UnresolvedMacro { path: item_attr.path.clone() })?;
789     let mut arg = match &macro_attr.input {
790         Some(input) => match &**input {
791             attr::AttrInput::Literal(_) => Default::default(),
792             attr::AttrInput::TokenTree(tt, map) => (tt.clone(), map.clone()),
793         },
794         None => Default::default(),
795     };
796     // The parentheses are always disposed here.
797     arg.0.delimiter = None;
798
799     let res = def.as_lazy_macro(
800         db.upcast(),
801         krate,
802         MacroCallKind::Attr {
803             ast_id: item_attr.ast_id,
804             attr_name: last_segment.to_string().into_boxed_str(),
805             attr_args: arg,
806             invoc_attr_index: macro_attr.id.ast_index,
807         },
808     );
809     Ok(res)
810 }