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