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