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