hir_def/
lib.rs

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