hir_def/
db.rs

1//! Defines database & queries for name resolution.
2use base_db::{Crate, RootQueryDb, SourceDatabase};
3use hir_expand::{
4    EditionedFileId, HirFileId, InFile, Lookup, MacroCallId, MacroDefId, MacroDefKind,
5    db::ExpandDatabase,
6};
7use la_arena::ArenaMap;
8use triomphe::Arc;
9
10use crate::{
11    AssocItemId, AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc,
12    EnumVariantId, EnumVariantLoc, ExternBlockId, ExternBlockLoc, ExternCrateId, ExternCrateLoc,
13    FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalFieldId, Macro2Id, Macro2Loc,
14    MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ProcMacroId,
15    ProcMacroLoc, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId,
16    TypeAliasLoc, UnionId, UnionLoc, UseId, UseLoc, VariantId,
17    attrs::AttrFlags,
18    expr_store::{
19        Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap, scope::ExprScopes,
20    },
21    hir::generics::GenericParams,
22    import_map::ImportMap,
23    item_tree::{ItemTree, file_item_tree_query},
24    nameres::crate_def_map,
25    signatures::{
26        ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
27        StructSignature, TraitSignature, TypeAliasSignature, UnionSignature,
28    },
29    visibility::{self, Visibility},
30};
31
32use salsa::plumbing::AsId;
33
34#[query_group::query_group(InternDatabaseStorage)]
35pub trait InternDatabase: RootQueryDb {
36    // region: items
37    #[salsa::interned]
38    fn intern_use(&self, loc: UseLoc) -> UseId;
39
40    #[salsa::interned]
41    fn intern_extern_crate(&self, loc: ExternCrateLoc) -> ExternCrateId;
42
43    #[salsa::interned]
44    fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
45
46    #[salsa::interned]
47    fn intern_struct(&self, loc: StructLoc) -> StructId;
48
49    #[salsa::interned]
50    fn intern_union(&self, loc: UnionLoc) -> UnionId;
51
52    #[salsa::interned]
53    fn intern_enum(&self, loc: EnumLoc) -> EnumId;
54
55    #[salsa::interned]
56    fn intern_enum_variant(&self, loc: EnumVariantLoc) -> EnumVariantId;
57
58    #[salsa::interned]
59    fn intern_const(&self, loc: ConstLoc) -> ConstId;
60
61    #[salsa::interned]
62    fn intern_static(&self, loc: StaticLoc) -> StaticId;
63
64    #[salsa::interned]
65    fn intern_trait(&self, loc: TraitLoc) -> TraitId;
66
67    #[salsa::interned]
68    fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
69
70    #[salsa::interned]
71    fn intern_impl(&self, loc: ImplLoc) -> ImplId;
72
73    #[salsa::interned]
74    fn intern_extern_block(&self, loc: ExternBlockLoc) -> ExternBlockId;
75
76    #[salsa::interned]
77    fn intern_macro2(&self, loc: Macro2Loc) -> Macro2Id;
78
79    #[salsa::interned]
80    fn intern_proc_macro(&self, loc: ProcMacroLoc) -> ProcMacroId;
81
82    #[salsa::interned]
83    fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId;
84    // endregion: items
85
86    #[salsa::interned]
87    fn intern_block(&self, loc: BlockLoc) -> BlockId;
88}
89
90#[query_group::query_group]
91pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
92    /// Whether to expand procedural macros during name resolution.
93    #[salsa::input]
94    fn expand_proc_attr_macros(&self) -> bool;
95
96    /// Computes an [`ItemTree`] for the given file or macro expansion.
97    #[salsa::invoke(file_item_tree_query)]
98    #[salsa::transparent]
99    fn file_item_tree(&self, file_id: HirFileId) -> &ItemTree;
100
101    /// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution.
102    #[salsa::invoke(macro_def)]
103    fn macro_def(&self, m: MacroId) -> MacroDefId;
104
105    // region:data
106
107    #[salsa::tracked]
108    fn trait_signature(&self, trait_: TraitId) -> Arc<TraitSignature> {
109        self.trait_signature_with_source_map(trait_).0
110    }
111
112    #[salsa::tracked]
113    fn impl_signature(&self, impl_: ImplId) -> Arc<ImplSignature> {
114        self.impl_signature_with_source_map(impl_).0
115    }
116
117    #[salsa::tracked]
118    fn struct_signature(&self, struct_: StructId) -> Arc<StructSignature> {
119        self.struct_signature_with_source_map(struct_).0
120    }
121
122    #[salsa::tracked]
123    fn union_signature(&self, union_: UnionId) -> Arc<UnionSignature> {
124        self.union_signature_with_source_map(union_).0
125    }
126
127    #[salsa::tracked]
128    fn enum_signature(&self, e: EnumId) -> Arc<EnumSignature> {
129        self.enum_signature_with_source_map(e).0
130    }
131
132    #[salsa::tracked]
133    fn const_signature(&self, e: ConstId) -> Arc<ConstSignature> {
134        self.const_signature_with_source_map(e).0
135    }
136
137    #[salsa::tracked]
138    fn static_signature(&self, e: StaticId) -> Arc<StaticSignature> {
139        self.static_signature_with_source_map(e).0
140    }
141
142    #[salsa::tracked]
143    fn function_signature(&self, e: FunctionId) -> Arc<FunctionSignature> {
144        self.function_signature_with_source_map(e).0
145    }
146
147    #[salsa::tracked]
148    fn type_alias_signature(&self, e: TypeAliasId) -> Arc<TypeAliasSignature> {
149        self.type_alias_signature_with_source_map(e).0
150    }
151
152    #[salsa::invoke(TraitSignature::query)]
153    fn trait_signature_with_source_map(
154        &self,
155        trait_: TraitId,
156    ) -> (Arc<TraitSignature>, Arc<ExpressionStoreSourceMap>);
157
158    #[salsa::invoke(ImplSignature::query)]
159    fn impl_signature_with_source_map(
160        &self,
161        impl_: ImplId,
162    ) -> (Arc<ImplSignature>, Arc<ExpressionStoreSourceMap>);
163
164    #[salsa::invoke(StructSignature::query)]
165    fn struct_signature_with_source_map(
166        &self,
167        struct_: StructId,
168    ) -> (Arc<StructSignature>, Arc<ExpressionStoreSourceMap>);
169
170    #[salsa::invoke(UnionSignature::query)]
171    fn union_signature_with_source_map(
172        &self,
173        union_: UnionId,
174    ) -> (Arc<UnionSignature>, Arc<ExpressionStoreSourceMap>);
175
176    #[salsa::invoke(EnumSignature::query)]
177    fn enum_signature_with_source_map(
178        &self,
179        e: EnumId,
180    ) -> (Arc<EnumSignature>, Arc<ExpressionStoreSourceMap>);
181
182    #[salsa::invoke(ConstSignature::query)]
183    fn const_signature_with_source_map(
184        &self,
185        e: ConstId,
186    ) -> (Arc<ConstSignature>, Arc<ExpressionStoreSourceMap>);
187
188    #[salsa::invoke(StaticSignature::query)]
189    fn static_signature_with_source_map(
190        &self,
191        e: StaticId,
192    ) -> (Arc<StaticSignature>, Arc<ExpressionStoreSourceMap>);
193
194    #[salsa::invoke(FunctionSignature::query)]
195    fn function_signature_with_source_map(
196        &self,
197        e: FunctionId,
198    ) -> (Arc<FunctionSignature>, Arc<ExpressionStoreSourceMap>);
199
200    #[salsa::invoke(TypeAliasSignature::query)]
201    fn type_alias_signature_with_source_map(
202        &self,
203        e: TypeAliasId,
204    ) -> (Arc<TypeAliasSignature>, Arc<ExpressionStoreSourceMap>);
205
206    // endregion:data
207
208    #[salsa::invoke(Body::body_with_source_map_query)]
209    #[salsa::lru(512)]
210    fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
211
212    #[salsa::invoke(Body::body_query)]
213    fn body(&self, def: DefWithBodyId) -> Arc<Body>;
214
215    #[salsa::invoke(ExprScopes::expr_scopes_query)]
216    fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
217
218    #[salsa::transparent]
219    #[salsa::invoke(GenericParams::new)]
220    fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>;
221
222    #[salsa::transparent]
223    #[salsa::invoke(GenericParams::generic_params_and_store)]
224    fn generic_params_and_store(
225        &self,
226        def: GenericDefId,
227    ) -> (Arc<GenericParams>, Arc<ExpressionStore>);
228
229    #[salsa::transparent]
230    #[salsa::invoke(GenericParams::generic_params_and_store_and_source_map)]
231    fn generic_params_and_store_and_source_map(
232        &self,
233        def: GenericDefId,
234    ) -> (Arc<GenericParams>, Arc<ExpressionStore>, Arc<ExpressionStoreSourceMap>);
235
236    #[salsa::invoke(ImportMap::import_map_query)]
237    fn import_map(&self, krate: Crate) -> Arc<ImportMap>;
238
239    // region:visibilities
240
241    #[salsa::invoke(visibility::field_visibilities_query)]
242    fn field_visibilities(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Visibility>>;
243
244    #[salsa::invoke(visibility::assoc_visibility_query)]
245    fn assoc_visibility(&self, def: AssocItemId) -> Visibility;
246
247    // endregion:visibilities
248
249    #[salsa::invoke(crate::lang_item::crate_notable_traits)]
250    #[salsa::transparent]
251    fn crate_notable_traits(&self, krate: Crate) -> Option<&[TraitId]>;
252
253    #[salsa::invoke(crate_supports_no_std)]
254    fn crate_supports_no_std(&self, crate_id: Crate) -> bool;
255
256    #[salsa::invoke(include_macro_invoc)]
257    fn include_macro_invoc(&self, crate_id: Crate) -> Arc<[(MacroCallId, EditionedFileId)]>;
258}
259
260// return: macro call id and include file id
261fn include_macro_invoc(
262    db: &dyn DefDatabase,
263    krate: Crate,
264) -> Arc<[(MacroCallId, EditionedFileId)]> {
265    crate_def_map(db, krate)
266        .modules
267        .values()
268        .flat_map(|m| m.scope.iter_macro_invoc())
269        .filter_map(|invoc| {
270            db.lookup_intern_macro_call(*invoc.1)
271                .include_file_id(db, *invoc.1)
272                .map(|x| (*invoc.1, x))
273        })
274        .collect()
275}
276
277fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool {
278    let root_module = crate_def_map(db, crate_id).root_module_id();
279    let attrs = AttrFlags::query(db, AttrDefId::ModuleId(root_module));
280    attrs.contains(AttrFlags::IS_NO_STD)
281}
282
283fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
284    let kind = |expander, file_id, m| {
285        let in_file = InFile::new(file_id, m);
286        match expander {
287            MacroExpander::Declarative { styles } => MacroDefKind::Declarative(in_file, styles),
288            MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(in_file, it),
289            MacroExpander::BuiltInAttr(it) => MacroDefKind::BuiltInAttr(in_file, it),
290            MacroExpander::BuiltInDerive(it) => MacroDefKind::BuiltInDerive(in_file, it),
291            MacroExpander::BuiltInEager(it) => MacroDefKind::BuiltInEager(in_file, it),
292        }
293    };
294
295    match id {
296        MacroId::Macro2Id(it) => {
297            let loc: Macro2Loc = it.lookup(db);
298
299            MacroDefId {
300                krate: loc.container.krate(db),
301                kind: kind(loc.expander, loc.id.file_id, loc.id.value.upcast()),
302                local_inner: false,
303                allow_internal_unsafe: loc.allow_internal_unsafe,
304                edition: loc.edition,
305            }
306        }
307        MacroId::MacroRulesId(it) => {
308            let loc: MacroRulesLoc = it.lookup(db);
309
310            MacroDefId {
311                krate: loc.container.krate(db),
312                kind: kind(loc.expander, loc.id.file_id, loc.id.value.upcast()),
313                local_inner: loc.flags.contains(MacroRulesLocFlags::LOCAL_INNER),
314                allow_internal_unsafe: loc
315                    .flags
316                    .contains(MacroRulesLocFlags::ALLOW_INTERNAL_UNSAFE),
317                edition: loc.edition,
318            }
319        }
320        MacroId::ProcMacroId(it) => {
321            let loc = it.lookup(db);
322
323            MacroDefId {
324                krate: loc.container.krate(db),
325                kind: MacroDefKind::ProcMacro(loc.id, loc.expander, loc.kind),
326                local_inner: false,
327                allow_internal_unsafe: false,
328                edition: loc.edition,
329            }
330        }
331    }
332}