Skip to main content

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