hir_def/
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#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
11
12#[cfg(feature = "in-rust-tree")]
13extern crate rustc_parse_format;
14
15#[cfg(not(feature = "in-rust-tree"))]
16extern crate ra_ap_rustc_parse_format as rustc_parse_format;
17
18extern crate ra_ap_rustc_abi as rustc_abi;
19
20pub mod db;
21
22pub mod attr;
23pub mod builtin_type;
24pub mod item_scope;
25pub mod per_ns;
26
27pub mod signatures;
28
29pub mod dyn_map;
30
31pub mod item_tree;
32
33pub mod lang_item;
34
35pub mod hir;
36pub use self::hir::type_ref;
37pub mod expr_store;
38pub mod resolver;
39
40pub mod nameres;
41
42pub mod src;
43
44pub mod find_path;
45pub mod import_map;
46pub mod visibility;
47
48use intern::{Interned, Symbol, sym};
49pub use rustc_abi as layout;
50use thin_vec::ThinVec;
51use triomphe::Arc;
52
53pub use crate::signatures::LocalFieldId;
54
55#[cfg(test)]
56mod macro_expansion_tests;
57#[cfg(test)]
58mod test_db;
59
60use std::hash::{Hash, Hasher};
61
62use base_db::{Crate, impl_intern_key};
63use hir_expand::{
64    AstId, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
65    MacroDefKind,
66    builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
67    db::ExpandDatabase,
68    eager::expand_eager_macro_input,
69    impl_intern_lookup,
70    mod_path::ModPath,
71    name::Name,
72    proc_macro::{CustomProcMacroExpander, ProcMacroKind},
73};
74use la_arena::Idx;
75use nameres::DefMap;
76use span::{AstIdNode, Edition, FileAstId, SyntaxContext};
77use stdx::impl_from;
78use syntax::{AstNode, ast};
79
80pub use hir_expand::{Intern, Lookup, tt};
81
82use crate::{
83    attr::Attrs,
84    builtin_type::BuiltinType,
85    db::DefDatabase,
86    expr_store::ExpressionStoreSourceMap,
87    hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId},
88    nameres::{
89        LocalDefMap,
90        assoc::{ImplItems, TraitItems},
91        block_def_map, crate_def_map, crate_local_def_map,
92        diagnostics::DefDiagnostics,
93    },
94    signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields},
95};
96
97type FxIndexMap<K, V> = indexmap::IndexMap<K, V, rustc_hash::FxBuildHasher>;
98/// A wrapper around three booleans
99#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
100pub struct FindPathConfig {
101    /// If true, prefer to unconditionally use imports of the `core` and `alloc` crate
102    /// over the std.
103    pub prefer_no_std: bool,
104    /// If true, prefer import paths containing a prelude module.
105    pub prefer_prelude: bool,
106    /// If true, prefer abs path (starting with `::`) where it is available.
107    pub prefer_absolute: bool,
108    /// If true, paths containing `#[unstable]` segments may be returned, but only if if there is no
109    /// stable path. This does not check, whether the item itself that is being imported is `#[unstable]`.
110    pub allow_unstable: bool,
111}
112
113#[derive(Debug)]
114pub struct ItemLoc<N: AstIdNode> {
115    pub container: ModuleId,
116    pub id: AstId<N>,
117}
118
119impl<N: AstIdNode> Clone for ItemLoc<N> {
120    fn clone(&self) -> Self {
121        *self
122    }
123}
124
125impl<N: AstIdNode> Copy for ItemLoc<N> {}
126
127impl<N: AstIdNode> PartialEq for ItemLoc<N> {
128    fn eq(&self, other: &Self) -> bool {
129        self.container == other.container && self.id == other.id
130    }
131}
132
133impl<N: AstIdNode> Eq for ItemLoc<N> {}
134
135impl<N: AstIdNode> Hash for ItemLoc<N> {
136    fn hash<H: Hasher>(&self, state: &mut H) {
137        self.container.hash(state);
138        self.id.hash(state);
139    }
140}
141
142impl<N: AstIdNode> HasModule for ItemLoc<N> {
143    #[inline]
144    fn module(&self, _db: &dyn DefDatabase) -> ModuleId {
145        self.container
146    }
147}
148
149#[derive(Debug)]
150pub struct AssocItemLoc<N: AstIdNode> {
151    // FIXME: Store this as an erased `salsa::Id` to save space
152    pub container: ItemContainerId,
153    pub id: AstId<N>,
154}
155
156impl<N: AstIdNode> Clone for AssocItemLoc<N> {
157    fn clone(&self) -> Self {
158        *self
159    }
160}
161
162impl<N: AstIdNode> Copy for AssocItemLoc<N> {}
163
164impl<N: AstIdNode> PartialEq for AssocItemLoc<N> {
165    fn eq(&self, other: &Self) -> bool {
166        self.container == other.container && self.id == other.id
167    }
168}
169
170impl<N: AstIdNode> Eq for AssocItemLoc<N> {}
171
172impl<N: AstIdNode> Hash for AssocItemLoc<N> {
173    fn hash<H: Hasher>(&self, state: &mut H) {
174        self.container.hash(state);
175        self.id.hash(state);
176    }
177}
178
179impl<N: AstIdNode> HasModule for AssocItemLoc<N> {
180    #[inline]
181    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
182        self.container.module(db)
183    }
184}
185
186pub trait AstIdLoc {
187    type Container;
188    type Ast: AstNode;
189    fn ast_id(&self) -> AstId<Self::Ast>;
190    fn container(&self) -> Self::Container;
191}
192
193impl<N: AstIdNode> AstIdLoc for ItemLoc<N> {
194    type Container = ModuleId;
195    type Ast = N;
196    #[inline]
197    fn ast_id(&self) -> AstId<Self::Ast> {
198        self.id
199    }
200    #[inline]
201    fn container(&self) -> Self::Container {
202        self.container
203    }
204}
205
206impl<N: AstIdNode> AstIdLoc for AssocItemLoc<N> {
207    type Container = ItemContainerId;
208    type Ast = N;
209    #[inline]
210    fn ast_id(&self) -> AstId<Self::Ast> {
211        self.id
212    }
213    #[inline]
214    fn container(&self) -> Self::Container {
215        self.container
216    }
217}
218
219macro_rules! impl_intern {
220    ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => {
221        impl_intern_key!($id, $loc);
222        impl_intern_lookup!(DefDatabase, $id, $loc, $intern, $lookup);
223    };
224}
225
226macro_rules! impl_loc {
227    ($loc:ident, $id:ident: $id_ty:ident, $container:ident: $container_type:ident) => {
228        impl AstIdLoc for $loc {
229            type Container = $container_type;
230            type Ast = ast::$id_ty;
231            fn ast_id(&self) -> AstId<Self::Ast> {
232                self.$id
233            }
234            fn container(&self) -> Self::Container {
235                self.$container
236            }
237        }
238
239        impl HasModule for $loc {
240            #[inline]
241            fn module(&self, db: &dyn DefDatabase) -> ModuleId {
242                self.$container.module(db)
243            }
244        }
245    };
246}
247
248type FunctionLoc = AssocItemLoc<ast::Fn>;
249impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
250
251type StructLoc = ItemLoc<ast::Struct>;
252impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
253
254impl StructId {
255    pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
256        VariantFields::firewall(db, self.into())
257    }
258
259    pub fn fields_with_source_map(
260        self,
261        db: &dyn DefDatabase,
262    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
263        VariantFields::query(db, self.into())
264    }
265}
266
267pub type UnionLoc = ItemLoc<ast::Union>;
268impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
269
270impl UnionId {
271    pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
272        VariantFields::firewall(db, self.into())
273    }
274
275    pub fn fields_with_source_map(
276        self,
277        db: &dyn DefDatabase,
278    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
279        VariantFields::query(db, self.into())
280    }
281}
282
283pub type EnumLoc = ItemLoc<ast::Enum>;
284impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
285
286impl EnumId {
287    #[inline]
288    pub fn enum_variants(self, db: &dyn DefDatabase) -> &EnumVariants {
289        &self.enum_variants_with_diagnostics(db).0
290    }
291
292    #[inline]
293    pub fn enum_variants_with_diagnostics(
294        self,
295        db: &dyn DefDatabase,
296    ) -> &(EnumVariants, Option<ThinVec<InactiveEnumVariantCode>>) {
297        EnumVariants::of(db, self)
298    }
299}
300
301type ConstLoc = AssocItemLoc<ast::Const>;
302impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
303
304pub type StaticLoc = AssocItemLoc<ast::Static>;
305impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
306
307pub type TraitLoc = ItemLoc<ast::Trait>;
308impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
309
310impl TraitId {
311    #[inline]
312    pub fn trait_items(self, db: &dyn DefDatabase) -> &TraitItems {
313        TraitItems::query(db, self)
314    }
315}
316
317type TypeAliasLoc = AssocItemLoc<ast::TypeAlias>;
318impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
319
320type ImplLoc = ItemLoc<ast::Impl>;
321impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
322
323impl ImplId {
324    #[inline]
325    pub fn impl_items(self, db: &dyn DefDatabase) -> &ImplItems {
326        &self.impl_items_with_diagnostics(db).0
327    }
328
329    #[inline]
330    pub fn impl_items_with_diagnostics(self, db: &dyn DefDatabase) -> &(ImplItems, DefDiagnostics) {
331        ImplItems::of(db, self)
332    }
333}
334
335type UseLoc = ItemLoc<ast::Use>;
336impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use);
337
338type ExternCrateLoc = ItemLoc<ast::ExternCrate>;
339impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate);
340
341type ExternBlockLoc = ItemLoc<ast::ExternBlock>;
342impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block);
343
344#[salsa::tracked]
345impl ExternBlockId {
346    #[salsa::tracked]
347    pub fn abi(self, db: &dyn DefDatabase) -> Option<Symbol> {
348        signatures::extern_block_abi(db, self)
349    }
350}
351
352#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
353pub struct EnumVariantLoc {
354    pub id: AstId<ast::Variant>,
355    pub parent: EnumId,
356    pub index: u32,
357}
358impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
359impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
360
361impl EnumVariantId {
362    pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
363        VariantFields::firewall(db, self.into())
364    }
365
366    pub fn fields_with_source_map(
367        self,
368        db: &dyn DefDatabase,
369    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
370        VariantFields::query(db, self.into())
371    }
372}
373
374#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
375pub struct Macro2Loc {
376    pub container: ModuleId,
377    pub id: AstId<ast::MacroDef>,
378    pub expander: MacroExpander,
379    pub allow_internal_unsafe: bool,
380    pub edition: Edition,
381}
382impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2);
383impl_loc!(Macro2Loc, id: MacroDef, container: ModuleId);
384
385#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
386pub struct MacroRulesLoc {
387    pub container: ModuleId,
388    pub id: AstId<ast::MacroRules>,
389    pub expander: MacroExpander,
390    pub flags: MacroRulesLocFlags,
391    pub edition: Edition,
392}
393impl_intern!(MacroRulesId, MacroRulesLoc, intern_macro_rules, lookup_intern_macro_rules);
394impl_loc!(MacroRulesLoc, id: MacroRules, container: ModuleId);
395
396bitflags::bitflags! {
397    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
398    pub struct MacroRulesLocFlags: u8 {
399        const ALLOW_INTERNAL_UNSAFE = 1 << 0;
400        const LOCAL_INNER = 1 << 1;
401    }
402}
403
404#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
405pub enum MacroExpander {
406    Declarative,
407    BuiltIn(BuiltinFnLikeExpander),
408    BuiltInAttr(BuiltinAttrExpander),
409    BuiltInDerive(BuiltinDeriveExpander),
410    BuiltInEager(EagerExpander),
411}
412
413#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
414pub struct ProcMacroLoc {
415    pub container: CrateRootModuleId,
416    pub id: AstId<ast::Fn>,
417    pub expander: CustomProcMacroExpander,
418    pub kind: ProcMacroKind,
419    pub edition: Edition,
420}
421impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_macro);
422impl_loc!(ProcMacroLoc, id: Fn, container: CrateRootModuleId);
423
424#[derive(Debug, Hash, PartialEq, Eq, Clone)]
425pub struct BlockLoc {
426    pub ast_id: AstId<ast::BlockExpr>,
427    /// The containing module.
428    pub module: ModuleId,
429}
430impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
431
432/// A `ModuleId` that is always a crate's root module.
433#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
434pub struct CrateRootModuleId {
435    krate: Crate,
436}
437
438impl CrateRootModuleId {
439    pub fn def_map(self, db: &dyn DefDatabase) -> &DefMap {
440        crate_def_map(db, self.krate)
441    }
442
443    pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (&DefMap, &LocalDefMap) {
444        let def_map = crate_local_def_map(db, self.krate);
445        (def_map.def_map(db), def_map.local(db))
446    }
447
448    pub fn krate(self) -> Crate {
449        self.krate
450    }
451}
452
453impl HasModule for CrateRootModuleId {
454    #[inline]
455    fn module(&self, _db: &dyn DefDatabase) -> ModuleId {
456        ModuleId { krate: self.krate, block: None, local_id: DefMap::ROOT }
457    }
458
459    #[inline]
460    fn krate(&self, _db: &dyn DefDatabase) -> Crate {
461        self.krate
462    }
463}
464
465impl PartialEq<ModuleId> for CrateRootModuleId {
466    fn eq(&self, other: &ModuleId) -> bool {
467        other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate
468    }
469}
470impl PartialEq<CrateRootModuleId> for ModuleId {
471    fn eq(&self, other: &CrateRootModuleId) -> bool {
472        other == self
473    }
474}
475
476impl From<CrateRootModuleId> for ModuleId {
477    fn from(CrateRootModuleId { krate }: CrateRootModuleId) -> Self {
478        ModuleId { krate, block: None, local_id: DefMap::ROOT }
479    }
480}
481
482impl From<CrateRootModuleId> for ModuleDefId {
483    fn from(value: CrateRootModuleId) -> Self {
484        ModuleDefId::ModuleId(value.into())
485    }
486}
487
488impl From<Crate> for CrateRootModuleId {
489    fn from(krate: Crate) -> Self {
490        CrateRootModuleId { krate }
491    }
492}
493
494impl TryFrom<ModuleId> for CrateRootModuleId {
495    type Error = ();
496
497    fn try_from(ModuleId { krate, block, local_id }: ModuleId) -> Result<Self, Self::Error> {
498        if block.is_none() && local_id == DefMap::ROOT {
499            Ok(CrateRootModuleId { krate })
500        } else {
501            Err(())
502        }
503    }
504}
505
506#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
507pub struct ModuleId {
508    krate: Crate,
509    /// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the
510    /// `BlockId` of that block expression. If `None`, this module is part of the crate-level
511    /// `DefMap` of `krate`.
512    block: Option<BlockId>,
513    /// The module's ID in its originating `DefMap`.
514    pub local_id: LocalModuleId,
515}
516
517impl ModuleId {
518    pub fn def_map(self, db: &dyn DefDatabase) -> &DefMap {
519        match self.block {
520            Some(block) => block_def_map(db, block),
521            None => crate_def_map(db, self.krate),
522        }
523    }
524
525    pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (&DefMap, &LocalDefMap) {
526        match self.block {
527            Some(block) => (block_def_map(db, block), self.only_local_def_map(db)),
528            None => {
529                let def_map = crate_local_def_map(db, self.krate);
530                (def_map.def_map(db), def_map.local(db))
531            }
532        }
533    }
534
535    pub(crate) fn only_local_def_map(self, db: &dyn DefDatabase) -> &LocalDefMap {
536        crate_local_def_map(db, self.krate).local(db)
537    }
538
539    pub fn crate_def_map(self, db: &dyn DefDatabase) -> &DefMap {
540        crate_def_map(db, self.krate)
541    }
542
543    pub fn krate(self) -> Crate {
544        self.krate
545    }
546
547    pub fn name(self, db: &dyn DefDatabase) -> Option<Name> {
548        let def_map = self.def_map(db);
549        let parent = def_map[self.local_id].parent?;
550        def_map[parent].children.iter().find_map(|(name, module_id)| {
551            if *module_id == self.local_id { Some(name.clone()) } else { None }
552        })
553    }
554
555    /// Returns the module containing `self`, either the parent `mod`, or the module (or block) containing
556    /// the block, if `self` corresponds to a block expression.
557    pub fn containing_module(self, db: &dyn DefDatabase) -> Option<ModuleId> {
558        self.def_map(db).containing_module(self.local_id)
559    }
560
561    pub fn containing_block(self) -> Option<BlockId> {
562        self.block
563    }
564
565    pub fn is_block_module(self) -> bool {
566        self.block.is_some() && self.local_id == DefMap::ROOT
567    }
568
569    pub fn is_within_block(self) -> bool {
570        self.block.is_some()
571    }
572
573    /// Returns the [`CrateRootModuleId`] for this module if it is the crate root module.
574    pub fn as_crate_root(&self) -> Option<CrateRootModuleId> {
575        if self.local_id == DefMap::ROOT && self.block.is_none() {
576            Some(CrateRootModuleId { krate: self.krate })
577        } else {
578            None
579        }
580    }
581
582    /// Returns the [`CrateRootModuleId`] for this module.
583    pub fn derive_crate_root(&self) -> CrateRootModuleId {
584        CrateRootModuleId { krate: self.krate }
585    }
586
587    /// Whether this module represents the crate root module
588    pub fn is_crate_root(&self) -> bool {
589        self.local_id == DefMap::ROOT && self.block.is_none()
590    }
591}
592
593impl HasModule for ModuleId {
594    #[inline]
595    fn module(&self, _db: &dyn DefDatabase) -> ModuleId {
596        *self
597    }
598}
599
600/// An ID of a module, **local** to a `DefMap`.
601pub type LocalModuleId = Idx<nameres::ModuleData>;
602
603#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
604pub struct FieldId {
605    // FIXME: Store this as an erased `salsa::Id` to save space
606    pub parent: VariantId,
607    pub local_id: LocalFieldId,
608}
609
610#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
611pub struct TupleId(pub u32);
612
613#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
614pub struct TupleFieldId {
615    pub tuple: TupleId,
616    pub index: u32,
617}
618
619#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
620pub struct TypeOrConstParamId {
621    // FIXME: Store this as an erased `salsa::Id` to save space
622    pub parent: GenericDefId,
623    pub local_id: LocalTypeOrConstParamId,
624}
625
626/// A TypeOrConstParamId with an invariant that it actually belongs to a type
627#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
628pub struct TypeParamId(TypeOrConstParamId);
629
630impl TypeParamId {
631    pub fn parent(&self) -> GenericDefId {
632        self.0.parent
633    }
634    pub fn local_id(&self) -> LocalTypeOrConstParamId {
635        self.0.local_id
636    }
637}
638
639impl TypeParamId {
640    /// Caller should check if this toc id really belongs to a type
641    pub fn from_unchecked(it: TypeOrConstParamId) -> Self {
642        Self(it)
643    }
644}
645
646impl From<TypeParamId> for TypeOrConstParamId {
647    fn from(it: TypeParamId) -> Self {
648        it.0
649    }
650}
651
652/// A TypeOrConstParamId with an invariant that it actually belongs to a const
653#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
654pub struct ConstParamId(TypeOrConstParamId);
655
656impl ConstParamId {
657    pub fn parent(&self) -> GenericDefId {
658        self.0.parent
659    }
660    pub fn local_id(&self) -> LocalTypeOrConstParamId {
661        self.0.local_id
662    }
663}
664
665impl ConstParamId {
666    /// Caller should check if this toc id really belongs to a const
667    pub fn from_unchecked(it: TypeOrConstParamId) -> Self {
668        Self(it)
669    }
670}
671
672impl From<ConstParamId> for TypeOrConstParamId {
673    fn from(it: ConstParamId) -> Self {
674        it.0
675    }
676}
677
678#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
679pub struct LifetimeParamId {
680    // FIXME: Store this as an erased `salsa::Id` to save space
681    pub parent: GenericDefId,
682    pub local_id: LocalLifetimeParamId,
683}
684
685#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
686pub enum ItemContainerId {
687    ExternBlockId(ExternBlockId),
688    ModuleId(ModuleId),
689    ImplId(ImplId),
690    TraitId(TraitId),
691}
692impl_from!(ModuleId for ItemContainerId);
693
694/// A Data Type
695#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
696pub enum AdtId {
697    StructId(StructId),
698    UnionId(UnionId),
699    EnumId(EnumId),
700}
701impl_from!(StructId, UnionId, EnumId for AdtId);
702
703/// A macro
704#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
705pub enum MacroId {
706    Macro2Id(Macro2Id),
707    MacroRulesId(MacroRulesId),
708    ProcMacroId(ProcMacroId),
709}
710impl_from!(Macro2Id, MacroRulesId, ProcMacroId for MacroId);
711
712impl MacroId {
713    pub fn is_attribute(self, db: &dyn DefDatabase) -> bool {
714        matches!(self, MacroId::ProcMacroId(it) if it.lookup(db).kind == ProcMacroKind::Attr)
715    }
716}
717
718/// A generic param
719#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
720pub enum GenericParamId {
721    TypeParamId(TypeParamId),
722    ConstParamId(ConstParamId),
723    LifetimeParamId(LifetimeParamId),
724}
725impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId);
726
727/// The defs which can be visible in the module.
728#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
729pub enum ModuleDefId {
730    ModuleId(ModuleId),
731    FunctionId(FunctionId),
732    AdtId(AdtId),
733    // Can't be directly declared, but can be imported.
734    EnumVariantId(EnumVariantId),
735    ConstId(ConstId),
736    StaticId(StaticId),
737    TraitId(TraitId),
738    TypeAliasId(TypeAliasId),
739    BuiltinType(BuiltinType),
740    MacroId(MacroId),
741}
742impl_from!(
743    MacroId(Macro2Id, MacroRulesId, ProcMacroId),
744    ModuleId,
745    FunctionId,
746    AdtId(StructId, EnumId, UnionId),
747    EnumVariantId,
748    ConstId,
749    StaticId,
750    TraitId,
751    TypeAliasId,
752    BuiltinType
753    for ModuleDefId
754);
755
756/// A constant, which might appears as a const item, an anonymous const block in expressions
757/// or patterns, or as a constant in types with const generics.
758#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
759pub enum GeneralConstId {
760    ConstId(ConstId),
761    StaticId(StaticId),
762}
763
764impl_from!(ConstId, StaticId for GeneralConstId);
765
766impl GeneralConstId {
767    pub fn generic_def(self, _db: &dyn DefDatabase) -> Option<GenericDefId> {
768        match self {
769            GeneralConstId::ConstId(it) => Some(it.into()),
770            GeneralConstId::StaticId(it) => Some(it.into()),
771        }
772    }
773
774    pub fn name(self, db: &dyn DefDatabase) -> String {
775        match self {
776            GeneralConstId::StaticId(it) => {
777                db.static_signature(it).name.display(db, Edition::CURRENT).to_string()
778            }
779            GeneralConstId::ConstId(const_id) => {
780                db.const_signature(const_id).name.as_ref().map_or_else(
781                    || "_".to_owned(),
782                    |name| name.display(db, Edition::CURRENT).to_string(),
783                )
784            }
785        }
786    }
787}
788
789/// The defs which have a body (have root expressions for type inference).
790#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
791pub enum DefWithBodyId {
792    FunctionId(FunctionId),
793    StaticId(StaticId),
794    ConstId(ConstId),
795    VariantId(EnumVariantId),
796    // /// All fields of a variant are inference roots
797    // VariantId(VariantId),
798    // /// The signature can contain inference roots in a bunch of places
799    // /// like const parameters or const arguments in paths
800    // This should likely be kept on its own with a separate query
801    // GenericDefId(GenericDefId),
802}
803impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
804
805impl From<EnumVariantId> for DefWithBodyId {
806    fn from(id: EnumVariantId) -> Self {
807        DefWithBodyId::VariantId(id)
808    }
809}
810
811impl DefWithBodyId {
812    pub fn as_generic_def_id(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
813        match self {
814            DefWithBodyId::FunctionId(f) => Some(f.into()),
815            DefWithBodyId::StaticId(s) => Some(s.into()),
816            DefWithBodyId::ConstId(c) => Some(c.into()),
817            DefWithBodyId::VariantId(c) => Some(c.lookup(db).parent.into()),
818        }
819    }
820}
821
822#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, salsa_macros::Supertype)]
823pub enum AssocItemId {
824    FunctionId(FunctionId),
825    ConstId(ConstId),
826    TypeAliasId(TypeAliasId),
827}
828
829// FIXME: not every function, ... is actually an assoc item. maybe we should make
830// sure that you can only turn actual assoc items into AssocItemIds. This would
831// require not implementing From, and instead having some checked way of
832// casting them, and somehow making the constructors private, which would be annoying.
833impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId);
834
835impl From<AssocItemId> for ModuleDefId {
836    fn from(item: AssocItemId) -> Self {
837        match item {
838            AssocItemId::FunctionId(f) => f.into(),
839            AssocItemId::ConstId(c) => c.into(),
840            AssocItemId::TypeAliasId(t) => t.into(),
841        }
842    }
843}
844
845#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
846pub enum GenericDefId {
847    AdtId(AdtId),
848    // consts can have type parameters from their parents (i.e. associated consts of traits)
849    ConstId(ConstId),
850    FunctionId(FunctionId),
851    ImplId(ImplId),
852    // can't actually have generics currently, but they might in the future
853    // More importantly, this completes the set of items that contain type references
854    // which is to be used by the signature expression store in the future.
855    StaticId(StaticId),
856    TraitId(TraitId),
857    TypeAliasId(TypeAliasId),
858}
859impl_from!(
860    AdtId(StructId, EnumId, UnionId),
861    ConstId,
862    FunctionId,
863    ImplId,
864    StaticId,
865    TraitId,
866    TypeAliasId
867    for GenericDefId
868);
869
870impl GenericDefId {
871    pub fn file_id_and_params_of(
872        self,
873        db: &dyn DefDatabase,
874    ) -> (HirFileId, Option<ast::GenericParamList>) {
875        fn file_id_and_params_of_item_loc<Loc>(
876            db: &dyn DefDatabase,
877            def: impl Lookup<Database = dyn DefDatabase, Data = Loc>,
878        ) -> (HirFileId, Option<ast::GenericParamList>)
879        where
880            Loc: src::HasSource,
881            Loc::Value: ast::HasGenericParams,
882        {
883            let src = def.lookup(db).source(db);
884            (src.file_id, ast::HasGenericParams::generic_param_list(&src.value))
885        }
886
887        match self {
888            GenericDefId::FunctionId(it) => file_id_and_params_of_item_loc(db, it),
889            GenericDefId::TypeAliasId(it) => file_id_and_params_of_item_loc(db, it),
890            GenericDefId::AdtId(AdtId::StructId(it)) => file_id_and_params_of_item_loc(db, it),
891            GenericDefId::AdtId(AdtId::UnionId(it)) => file_id_and_params_of_item_loc(db, it),
892            GenericDefId::AdtId(AdtId::EnumId(it)) => file_id_and_params_of_item_loc(db, it),
893            GenericDefId::TraitId(it) => file_id_and_params_of_item_loc(db, it),
894            GenericDefId::ImplId(it) => file_id_and_params_of_item_loc(db, it),
895            GenericDefId::ConstId(it) => (it.lookup(db).id.file_id, None),
896            GenericDefId::StaticId(it) => (it.lookup(db).id.file_id, None),
897        }
898    }
899
900    pub fn assoc_trait_container(self, db: &dyn DefDatabase) -> Option<TraitId> {
901        match match self {
902            GenericDefId::FunctionId(f) => f.lookup(db).container,
903            GenericDefId::TypeAliasId(t) => t.lookup(db).container,
904            GenericDefId::ConstId(c) => c.lookup(db).container,
905            _ => return None,
906        } {
907            ItemContainerId::TraitId(trait_) => Some(trait_),
908            _ => None,
909        }
910    }
911
912    pub fn from_callable(db: &dyn DefDatabase, def: CallableDefId) -> GenericDefId {
913        match def {
914            CallableDefId::FunctionId(f) => f.into(),
915            CallableDefId::StructId(s) => s.into(),
916            CallableDefId::EnumVariantId(e) => e.lookup(db).parent.into(),
917        }
918    }
919}
920
921impl From<AssocItemId> for GenericDefId {
922    fn from(item: AssocItemId) -> Self {
923        match item {
924            AssocItemId::FunctionId(f) => f.into(),
925            AssocItemId::ConstId(c) => c.into(),
926            AssocItemId::TypeAliasId(t) => t.into(),
927        }
928    }
929}
930
931#[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
932pub enum CallableDefId {
933    FunctionId(FunctionId),
934    StructId(StructId),
935    EnumVariantId(EnumVariantId),
936}
937
938impl_from!(FunctionId, StructId, EnumVariantId for CallableDefId);
939impl From<CallableDefId> for ModuleDefId {
940    fn from(def: CallableDefId) -> ModuleDefId {
941        match def {
942            CallableDefId::FunctionId(f) => ModuleDefId::FunctionId(f),
943            CallableDefId::StructId(s) => ModuleDefId::AdtId(AdtId::StructId(s)),
944            CallableDefId::EnumVariantId(e) => ModuleDefId::EnumVariantId(e),
945        }
946    }
947}
948
949impl CallableDefId {
950    pub fn krate(self, db: &dyn DefDatabase) -> Crate {
951        match self {
952            CallableDefId::FunctionId(f) => f.krate(db),
953            CallableDefId::StructId(s) => s.krate(db),
954            CallableDefId::EnumVariantId(e) => e.krate(db),
955        }
956    }
957}
958
959#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
960pub enum AttrDefId {
961    ModuleId(ModuleId),
962    FieldId(FieldId),
963    AdtId(AdtId),
964    FunctionId(FunctionId),
965    EnumVariantId(EnumVariantId),
966    StaticId(StaticId),
967    ConstId(ConstId),
968    TraitId(TraitId),
969    TypeAliasId(TypeAliasId),
970    MacroId(MacroId),
971    ImplId(ImplId),
972    GenericParamId(GenericParamId),
973    ExternBlockId(ExternBlockId),
974    ExternCrateId(ExternCrateId),
975    UseId(UseId),
976}
977
978impl_from!(
979    ModuleId,
980    FieldId,
981    AdtId(StructId, EnumId, UnionId),
982    EnumVariantId,
983    StaticId,
984    ConstId,
985    FunctionId,
986    TraitId,
987    TypeAliasId,
988    MacroId(Macro2Id, MacroRulesId, ProcMacroId),
989    ImplId,
990    GenericParamId,
991    ExternCrateId,
992    UseId
993    for AttrDefId
994);
995
996impl TryFrom<ModuleDefId> for AttrDefId {
997    type Error = ();
998
999    fn try_from(value: ModuleDefId) -> Result<Self, Self::Error> {
1000        match value {
1001            ModuleDefId::ModuleId(it) => Ok(it.into()),
1002            ModuleDefId::FunctionId(it) => Ok(it.into()),
1003            ModuleDefId::AdtId(it) => Ok(it.into()),
1004            ModuleDefId::EnumVariantId(it) => Ok(it.into()),
1005            ModuleDefId::ConstId(it) => Ok(it.into()),
1006            ModuleDefId::StaticId(it) => Ok(it.into()),
1007            ModuleDefId::TraitId(it) => Ok(it.into()),
1008            ModuleDefId::TypeAliasId(it) => Ok(it.into()),
1009            ModuleDefId::MacroId(id) => Ok(id.into()),
1010            ModuleDefId::BuiltinType(_) => Err(()),
1011        }
1012    }
1013}
1014
1015impl From<ItemContainerId> for AttrDefId {
1016    fn from(acid: ItemContainerId) -> Self {
1017        match acid {
1018            ItemContainerId::ModuleId(mid) => AttrDefId::ModuleId(mid),
1019            ItemContainerId::ImplId(iid) => AttrDefId::ImplId(iid),
1020            ItemContainerId::TraitId(tid) => AttrDefId::TraitId(tid),
1021            ItemContainerId::ExternBlockId(id) => AttrDefId::ExternBlockId(id),
1022        }
1023    }
1024}
1025impl From<AssocItemId> for AttrDefId {
1026    fn from(assoc: AssocItemId) -> Self {
1027        match assoc {
1028            AssocItemId::FunctionId(it) => AttrDefId::FunctionId(it),
1029            AssocItemId::ConstId(it) => AttrDefId::ConstId(it),
1030            AssocItemId::TypeAliasId(it) => AttrDefId::TypeAliasId(it),
1031        }
1032    }
1033}
1034impl From<VariantId> for AttrDefId {
1035    fn from(vid: VariantId) -> Self {
1036        match vid {
1037            VariantId::EnumVariantId(id) => id.into(),
1038            VariantId::StructId(id) => id.into(),
1039            VariantId::UnionId(id) => id.into(),
1040        }
1041    }
1042}
1043
1044#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
1045pub enum VariantId {
1046    EnumVariantId(EnumVariantId),
1047    StructId(StructId),
1048    UnionId(UnionId),
1049}
1050impl_from!(EnumVariantId, StructId, UnionId for VariantId);
1051
1052impl VariantId {
1053    pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
1054        VariantFields::firewall(db, self)
1055    }
1056
1057    pub fn fields_with_source_map(
1058        self,
1059        db: &dyn DefDatabase,
1060    ) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>) {
1061        VariantFields::query(db, self)
1062    }
1063
1064    pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
1065        match self {
1066            VariantId::EnumVariantId(it) => it.lookup(db).id.file_id,
1067            VariantId::StructId(it) => it.lookup(db).id.file_id,
1068            VariantId::UnionId(it) => it.lookup(db).id.file_id,
1069        }
1070    }
1071
1072    pub fn adt_id(self, db: &dyn DefDatabase) -> AdtId {
1073        match self {
1074            VariantId::EnumVariantId(it) => it.lookup(db).parent.into(),
1075            VariantId::StructId(it) => it.into(),
1076            VariantId::UnionId(it) => it.into(),
1077        }
1078    }
1079}
1080
1081pub trait HasModule {
1082    /// Returns the enclosing module this thing is defined within.
1083    fn module(&self, db: &dyn DefDatabase) -> ModuleId;
1084    /// Returns the crate this thing is defined within.
1085    #[inline]
1086    #[doc(alias = "crate")]
1087    fn krate(&self, db: &dyn DefDatabase) -> Crate {
1088        self.module(db).krate
1089    }
1090}
1091
1092// In theory this impl should work out for us, but rustc thinks it collides with all the other
1093// manual impls that do not have a ModuleId container...
1094// impl<N, ItemId, Data> HasModule for ItemId
1095// where
1096//     N: ItemTreeNode,
1097//     ItemId: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = Data> + Copy,
1098//     Data: ItemTreeLoc<Id = N, Container = ModuleId>,
1099// {
1100//     #[inline]
1101//     fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1102//         self.lookup(db).container()
1103//     }
1104// }
1105
1106impl<N, ItemId> HasModule for ItemId
1107where
1108    N: AstIdNode,
1109    ItemId: Lookup<Database = dyn DefDatabase, Data = ItemLoc<N>> + Copy,
1110{
1111    #[inline]
1112    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1113        self.lookup(db).container
1114    }
1115}
1116
1117// Technically this does not overlap with the above, but rustc currently forbids this, hence why we
1118// need to write the 3 impls manually instead
1119// impl<N, ItemId> HasModule for ItemId
1120// where
1121//     N: ItemTreeModItemNode,
1122//     ItemId: for<'db> Lookup<Database<'db> = dyn DefDatabase + 'db, Data = AssocItemLoc<N>> + Copy,
1123// {
1124//     #[inline]
1125//     fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1126//         self.lookup(db).container.module(db)
1127//     }
1128// }
1129
1130// region: manual-assoc-has-module-impls
1131#[inline]
1132fn module_for_assoc_item_loc<'db>(
1133    db: &(dyn 'db + DefDatabase),
1134    id: impl Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<impl AstIdNode>>,
1135) -> ModuleId {
1136    id.lookup(db).container.module(db)
1137}
1138
1139impl HasModule for FunctionId {
1140    #[inline]
1141    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1142        module_for_assoc_item_loc(db, *self)
1143    }
1144}
1145
1146impl HasModule for ConstId {
1147    #[inline]
1148    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1149        module_for_assoc_item_loc(db, *self)
1150    }
1151}
1152
1153impl HasModule for StaticId {
1154    #[inline]
1155    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1156        module_for_assoc_item_loc(db, *self)
1157    }
1158}
1159
1160impl HasModule for TypeAliasId {
1161    #[inline]
1162    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1163        module_for_assoc_item_loc(db, *self)
1164    }
1165}
1166// endregion: manual-assoc-has-module-impls
1167
1168impl HasModule for EnumVariantId {
1169    #[inline]
1170    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1171        self.lookup(db).parent.module(db)
1172    }
1173}
1174
1175impl HasModule for MacroRulesId {
1176    #[inline]
1177    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1178        self.lookup(db).container
1179    }
1180}
1181
1182impl HasModule for Macro2Id {
1183    #[inline]
1184    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1185        self.lookup(db).container
1186    }
1187}
1188
1189impl HasModule for ProcMacroId {
1190    #[inline]
1191    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1192        self.lookup(db).container.into()
1193    }
1194}
1195
1196impl HasModule for ItemContainerId {
1197    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1198        match *self {
1199            ItemContainerId::ModuleId(it) => it,
1200            ItemContainerId::ImplId(it) => it.module(db),
1201            ItemContainerId::TraitId(it) => it.module(db),
1202            ItemContainerId::ExternBlockId(it) => it.module(db),
1203        }
1204    }
1205}
1206
1207impl HasModule for AdtId {
1208    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1209        match *self {
1210            AdtId::StructId(it) => it.module(db),
1211            AdtId::UnionId(it) => it.module(db),
1212            AdtId::EnumId(it) => it.module(db),
1213        }
1214    }
1215}
1216
1217impl HasModule for VariantId {
1218    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1219        match *self {
1220            VariantId::EnumVariantId(it) => it.module(db),
1221            VariantId::StructId(it) => it.module(db),
1222            VariantId::UnionId(it) => it.module(db),
1223        }
1224    }
1225}
1226
1227impl HasModule for MacroId {
1228    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1229        match *self {
1230            MacroId::MacroRulesId(it) => it.module(db),
1231            MacroId::Macro2Id(it) => it.module(db),
1232            MacroId::ProcMacroId(it) => it.module(db),
1233        }
1234    }
1235}
1236
1237impl HasModule for DefWithBodyId {
1238    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1239        match self {
1240            DefWithBodyId::FunctionId(it) => it.module(db),
1241            DefWithBodyId::StaticId(it) => it.module(db),
1242            DefWithBodyId::ConstId(it) => it.module(db),
1243            DefWithBodyId::VariantId(it) => it.module(db),
1244        }
1245    }
1246}
1247
1248impl HasModule for GenericDefId {
1249    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1250        match self {
1251            GenericDefId::FunctionId(it) => it.module(db),
1252            GenericDefId::AdtId(it) => it.module(db),
1253            GenericDefId::TraitId(it) => it.module(db),
1254            GenericDefId::TypeAliasId(it) => it.module(db),
1255            GenericDefId::ImplId(it) => it.module(db),
1256            GenericDefId::ConstId(it) => it.module(db),
1257            GenericDefId::StaticId(it) => it.module(db),
1258        }
1259    }
1260}
1261
1262impl HasModule for AttrDefId {
1263    fn module(&self, db: &dyn DefDatabase) -> ModuleId {
1264        match self {
1265            AttrDefId::ModuleId(it) => *it,
1266            AttrDefId::FieldId(it) => it.parent.module(db),
1267            AttrDefId::AdtId(it) => it.module(db),
1268            AttrDefId::FunctionId(it) => it.module(db),
1269            AttrDefId::EnumVariantId(it) => it.module(db),
1270            AttrDefId::StaticId(it) => it.module(db),
1271            AttrDefId::ConstId(it) => it.module(db),
1272            AttrDefId::TraitId(it) => it.module(db),
1273            AttrDefId::TypeAliasId(it) => it.module(db),
1274            AttrDefId::ImplId(it) => it.module(db),
1275            AttrDefId::ExternBlockId(it) => it.module(db),
1276            AttrDefId::GenericParamId(it) => match it {
1277                GenericParamId::TypeParamId(it) => it.parent(),
1278                GenericParamId::ConstParamId(it) => it.parent(),
1279                GenericParamId::LifetimeParamId(it) => it.parent,
1280            }
1281            .module(db),
1282            AttrDefId::MacroId(it) => it.module(db),
1283            AttrDefId::ExternCrateId(it) => it.module(db),
1284            AttrDefId::UseId(it) => it.module(db),
1285        }
1286    }
1287}
1288
1289impl ModuleDefId {
1290    /// Returns the module containing `self` (or `self`, if `self` is itself a module).
1291    ///
1292    /// Returns `None` if `self` refers to a primitive type.
1293    pub fn module(&self, db: &dyn DefDatabase) -> Option<ModuleId> {
1294        Some(match self {
1295            ModuleDefId::ModuleId(id) => *id,
1296            ModuleDefId::FunctionId(id) => id.module(db),
1297            ModuleDefId::AdtId(id) => id.module(db),
1298            ModuleDefId::EnumVariantId(id) => id.module(db),
1299            ModuleDefId::ConstId(id) => id.module(db),
1300            ModuleDefId::StaticId(id) => id.module(db),
1301            ModuleDefId::TraitId(id) => id.module(db),
1302            ModuleDefId::TypeAliasId(id) => id.module(db),
1303            ModuleDefId::MacroId(id) => id.module(db),
1304            ModuleDefId::BuiltinType(_) => return None,
1305        })
1306    }
1307}
1308/// Helper wrapper for `AstId` with `ModPath`
1309#[derive(Clone, Debug, Eq, PartialEq)]
1310struct AstIdWithPath<T: AstIdNode> {
1311    ast_id: AstId<T>,
1312    path: Interned<ModPath>,
1313}
1314
1315impl<T: AstIdNode> AstIdWithPath<T> {
1316    fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: Interned<ModPath>) -> AstIdWithPath<T> {
1317        AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path }
1318    }
1319}
1320
1321pub fn macro_call_as_call_id(
1322    db: &dyn ExpandDatabase,
1323    ast_id: AstId<ast::MacroCall>,
1324    path: &ModPath,
1325    call_site: SyntaxContext,
1326    expand_to: ExpandTo,
1327    krate: Crate,
1328    resolver: impl Fn(&ModPath) -> Option<MacroDefId> + Copy,
1329    eager_callback: &mut dyn FnMut(
1330        InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
1331        MacroCallId,
1332    ),
1333) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
1334    let def = resolver(path).ok_or_else(|| UnresolvedMacro { path: path.clone() })?;
1335
1336    let res = match def.kind {
1337        MacroDefKind::BuiltInEager(..) => expand_eager_macro_input(
1338            db,
1339            krate,
1340            &ast_id.to_node(db),
1341            ast_id,
1342            def,
1343            call_site,
1344            &|path| resolver(path).filter(MacroDefId::is_fn_like),
1345            eager_callback,
1346        ),
1347        _ if def.is_fn_like() => ExpandResult {
1348            value: Some(def.make_call(
1349                db,
1350                krate,
1351                MacroCallKind::FnLike { ast_id, expand_to, eager: None },
1352                call_site,
1353            )),
1354            err: None,
1355        },
1356        _ => return Err(UnresolvedMacro { path: path.clone() }),
1357    };
1358    Ok(res)
1359}
1360
1361#[derive(Debug)]
1362pub struct UnresolvedMacro {
1363    pub path: ModPath,
1364}
1365
1366#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
1367pub struct SyntheticSyntax;
1368
1369// Feature: Completions Attribute
1370// Crate authors can opt their type out of completions in some cases.
1371// This is done with the `#[rust_analyzer::completions(...)]` attribute.
1372//
1373// All completable things support `#[rust_analyzer::completions(ignore_flyimport)]`,
1374// which causes the thing to get excluded from flyimport completion. It will still
1375// be completed when in scope. This is analogous to the setting `rust-analyzer.completion.autoimport.exclude`
1376// with `"type": "always"`.
1377//
1378// In addition, traits support two more modes: `#[rust_analyzer::completions(ignore_flyimport_methods)]`,
1379// which means the trait itself may still be flyimported but its methods won't, and
1380// `#[rust_analyzer::completions(ignore_methods)]`, which means the methods won't be completed even when
1381// the trait is in scope (but the trait itself may still be completed). The methods will still be completed
1382// on `dyn Trait`, `impl Trait` or where the trait is specified in bounds. These modes correspond to
1383// the settings `rust-analyzer.completion.autoimport.exclude` with `"type": "methods"` and
1384// `rust-analyzer.completion.excludeTraits`, respectively.
1385//
1386// Malformed attributes will be ignored without warnings.
1387//
1388// Note that users have no way to override this attribute, so be careful and only include things
1389// users definitely do not want to be completed!
1390
1391/// `#[rust_analyzer::completions(...)]` options.
1392#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1393pub enum Complete {
1394    /// No `#[rust_analyzer::completions(...)]`.
1395    Yes,
1396    /// `#[rust_analyzer::completions(ignore_flyimport)]`.
1397    IgnoreFlyimport,
1398    /// `#[rust_analyzer::completions(ignore_flyimport_methods)]` (on a trait only).
1399    IgnoreFlyimportMethods,
1400    /// `#[rust_analyzer::completions(ignore_methods)]` (on a trait only).
1401    IgnoreMethods,
1402}
1403
1404impl Complete {
1405    pub fn extract(is_trait: bool, attrs: &Attrs) -> Complete {
1406        let mut do_not_complete = Complete::Yes;
1407        for ra_attr in attrs.rust_analyzer_tool() {
1408            let segments = ra_attr.path.segments();
1409            if segments.len() != 2 {
1410                continue;
1411            }
1412            let action = segments[1].symbol();
1413            if *action == sym::completions {
1414                match ra_attr.token_tree_value().map(|tt| tt.token_trees().flat_tokens()) {
1415                    Some([tt::TokenTree::Leaf(tt::Leaf::Ident(ident))]) => {
1416                        if ident.sym == sym::ignore_flyimport {
1417                            do_not_complete = Complete::IgnoreFlyimport;
1418                        } else if is_trait {
1419                            if ident.sym == sym::ignore_methods {
1420                                do_not_complete = Complete::IgnoreMethods;
1421                            } else if ident.sym == sym::ignore_flyimport_methods {
1422                                do_not_complete = Complete::IgnoreFlyimportMethods;
1423                            }
1424                        }
1425                    }
1426                    _ => {}
1427                }
1428            }
1429        }
1430        do_not_complete
1431    }
1432
1433    #[inline]
1434    pub fn for_trait_item(trait_attr: Complete, item_attr: Complete) -> Complete {
1435        match (trait_attr, item_attr) {
1436            (
1437                Complete::IgnoreFlyimportMethods
1438                | Complete::IgnoreFlyimport
1439                | Complete::IgnoreMethods,
1440                _,
1441            ) => Complete::IgnoreFlyimport,
1442            _ => item_attr,
1443        }
1444    }
1445}