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