]>
Commit | Line | Data |
---|---|---|
064997fb FG |
1 | //! Defines database & queries for name resolution. |
2 | use std::sync::Arc; | |
3 | ||
4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; | |
5 | use either::Either; | |
6 | use hir_expand::{db::AstDatabase, HirFileId}; | |
9ffffee4 | 7 | use intern::Interned; |
064997fb | 8 | use la_arena::ArenaMap; |
9ffffee4 | 9 | use syntax::{ast, AstPtr}; |
064997fb FG |
10 | |
11 | use crate::{ | |
12 | adt::{EnumData, StructData}, | |
13 | attr::{Attrs, AttrsWithOwner}, | |
14 | body::{scope::ExprScopes, Body, BodySourceMap}, | |
15 | data::{ | |
16 | ConstData, FunctionData, ImplData, Macro2Data, MacroRulesData, ProcMacroData, StaticData, | |
17 | TraitData, TypeAliasData, | |
18 | }, | |
19 | generics::GenericParams, | |
20 | import_map::ImportMap, | |
064997fb | 21 | item_tree::{AttrOwner, ItemTree}, |
9ffffee4 | 22 | lang_item::{LangItem, LangItemTarget, LangItems}, |
f2b60f7d | 23 | nameres::{diagnostics::DefDiagnostic, DefMap}, |
064997fb FG |
24 | visibility::{self, Visibility}, |
25 | AttrDefId, BlockId, BlockLoc, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, ExternBlockId, | |
26 | ExternBlockLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, LocalEnumVariantId, | |
27 | LocalFieldId, Macro2Id, Macro2Loc, MacroRulesId, MacroRulesLoc, ProcMacroId, ProcMacroLoc, | |
28 | StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, | |
29 | UnionId, UnionLoc, VariantId, | |
30 | }; | |
31 | ||
32 | #[salsa::query_group(InternDatabaseStorage)] | |
33 | pub trait InternDatabase: SourceDatabase { | |
34 | #[salsa::interned] | |
35 | fn intern_function(&self, loc: FunctionLoc) -> FunctionId; | |
36 | #[salsa::interned] | |
37 | fn intern_struct(&self, loc: StructLoc) -> StructId; | |
38 | #[salsa::interned] | |
39 | fn intern_union(&self, loc: UnionLoc) -> UnionId; | |
40 | #[salsa::interned] | |
41 | fn intern_enum(&self, loc: EnumLoc) -> EnumId; | |
42 | #[salsa::interned] | |
43 | fn intern_const(&self, loc: ConstLoc) -> ConstId; | |
44 | #[salsa::interned] | |
45 | fn intern_static(&self, loc: StaticLoc) -> StaticId; | |
46 | #[salsa::interned] | |
47 | fn intern_trait(&self, loc: TraitLoc) -> TraitId; | |
48 | #[salsa::interned] | |
49 | fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; | |
50 | #[salsa::interned] | |
51 | fn intern_impl(&self, loc: ImplLoc) -> ImplId; | |
52 | #[salsa::interned] | |
53 | fn intern_extern_block(&self, loc: ExternBlockLoc) -> ExternBlockId; | |
54 | #[salsa::interned] | |
55 | fn intern_block(&self, loc: BlockLoc) -> BlockId; | |
56 | #[salsa::interned] | |
57 | fn intern_macro2(&self, loc: Macro2Loc) -> Macro2Id; | |
58 | #[salsa::interned] | |
59 | fn intern_proc_macro(&self, loc: ProcMacroLoc) -> ProcMacroId; | |
60 | #[salsa::interned] | |
61 | fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId; | |
62 | } | |
63 | ||
64 | #[salsa::query_group(DefDatabaseStorage)] | |
65 | pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |
66 | #[salsa::input] | |
67 | fn enable_proc_attr_macros(&self) -> bool; | |
68 | ||
69 | #[salsa::invoke(ItemTree::file_item_tree_query)] | |
70 | fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>; | |
71 | ||
72 | #[salsa::invoke(crate_def_map_wait)] | |
73 | #[salsa::transparent] | |
74 | fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>; | |
75 | ||
76 | #[salsa::invoke(DefMap::crate_def_map_query)] | |
77 | fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>; | |
78 | ||
79 | /// Computes the block-level `DefMap`, returning `None` when `block` doesn't contain any inner | |
80 | /// items directly. | |
81 | /// | |
82 | /// For example: | |
83 | /// | |
84 | /// ``` | |
85 | /// fn f() { // (0) | |
86 | /// { // (1) | |
87 | /// fn inner() {} | |
88 | /// } | |
89 | /// } | |
90 | /// ``` | |
91 | /// | |
92 | /// The `block_def_map` for block 0 would return `None`, while `block_def_map` of block 1 would | |
93 | /// return a `DefMap` containing `inner`. | |
94 | #[salsa::invoke(DefMap::block_def_map_query)] | |
95 | fn block_def_map(&self, block: BlockId) -> Option<Arc<DefMap>>; | |
96 | ||
97 | #[salsa::invoke(StructData::struct_data_query)] | |
98 | fn struct_data(&self, id: StructId) -> Arc<StructData>; | |
99 | ||
2b03887a FG |
100 | #[salsa::invoke(StructData::struct_data_with_diagnostics_query)] |
101 | fn struct_data_with_diagnostics(&self, id: StructId) | |
102 | -> (Arc<StructData>, Arc<[DefDiagnostic]>); | |
103 | ||
064997fb FG |
104 | #[salsa::invoke(StructData::union_data_query)] |
105 | fn union_data(&self, id: UnionId) -> Arc<StructData>; | |
106 | ||
2b03887a FG |
107 | #[salsa::invoke(StructData::union_data_with_diagnostics_query)] |
108 | fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc<StructData>, Arc<[DefDiagnostic]>); | |
109 | ||
064997fb FG |
110 | #[salsa::invoke(EnumData::enum_data_query)] |
111 | fn enum_data(&self, e: EnumId) -> Arc<EnumData>; | |
112 | ||
2b03887a FG |
113 | #[salsa::invoke(EnumData::enum_data_with_diagnostics_query)] |
114 | fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc<EnumData>, Arc<[DefDiagnostic]>); | |
115 | ||
064997fb FG |
116 | #[salsa::invoke(ImplData::impl_data_query)] |
117 | fn impl_data(&self, e: ImplId) -> Arc<ImplData>; | |
118 | ||
f2b60f7d | 119 | #[salsa::invoke(ImplData::impl_data_with_diagnostics_query)] |
2b03887a | 120 | fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<[DefDiagnostic]>); |
f2b60f7d | 121 | |
064997fb FG |
122 | #[salsa::invoke(TraitData::trait_data_query)] |
123 | fn trait_data(&self, e: TraitId) -> Arc<TraitData>; | |
124 | ||
f2b60f7d | 125 | #[salsa::invoke(TraitData::trait_data_with_diagnostics_query)] |
2b03887a | 126 | fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, Arc<[DefDiagnostic]>); |
f2b60f7d | 127 | |
064997fb FG |
128 | #[salsa::invoke(TypeAliasData::type_alias_data_query)] |
129 | fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>; | |
130 | ||
131 | #[salsa::invoke(FunctionData::fn_data_query)] | |
132 | fn function_data(&self, func: FunctionId) -> Arc<FunctionData>; | |
133 | ||
134 | #[salsa::invoke(ConstData::const_data_query)] | |
135 | fn const_data(&self, konst: ConstId) -> Arc<ConstData>; | |
136 | ||
137 | #[salsa::invoke(StaticData::static_data_query)] | |
138 | fn static_data(&self, konst: StaticId) -> Arc<StaticData>; | |
139 | ||
140 | #[salsa::invoke(Macro2Data::macro2_data_query)] | |
141 | fn macro2_data(&self, makro: Macro2Id) -> Arc<Macro2Data>; | |
142 | ||
143 | #[salsa::invoke(MacroRulesData::macro_rules_data_query)] | |
144 | fn macro_rules_data(&self, makro: MacroRulesId) -> Arc<MacroRulesData>; | |
145 | ||
146 | #[salsa::invoke(ProcMacroData::proc_macro_data_query)] | |
147 | fn proc_macro_data(&self, makro: ProcMacroId) -> Arc<ProcMacroData>; | |
148 | ||
149 | #[salsa::invoke(Body::body_with_source_map_query)] | |
150 | fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); | |
151 | ||
152 | #[salsa::invoke(Body::body_query)] | |
153 | fn body(&self, def: DefWithBodyId) -> Arc<Body>; | |
154 | ||
155 | #[salsa::invoke(ExprScopes::expr_scopes_query)] | |
156 | fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; | |
157 | ||
158 | #[salsa::invoke(GenericParams::generic_params_query)] | |
159 | fn generic_params(&self, def: GenericDefId) -> Interned<GenericParams>; | |
160 | ||
161 | #[salsa::invoke(Attrs::variants_attrs_query)] | |
162 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; | |
163 | ||
164 | #[salsa::invoke(Attrs::fields_attrs_query)] | |
165 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; | |
166 | ||
167 | #[salsa::invoke(crate::attr::variants_attrs_source_map)] | |
168 | fn variants_attrs_source_map( | |
169 | &self, | |
170 | def: EnumId, | |
171 | ) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>; | |
172 | ||
173 | #[salsa::invoke(crate::attr::fields_attrs_source_map)] | |
174 | fn fields_attrs_source_map( | |
175 | &self, | |
176 | def: VariantId, | |
177 | ) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>>; | |
178 | ||
179 | #[salsa::invoke(AttrsWithOwner::attrs_query)] | |
180 | fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; | |
181 | ||
182 | #[salsa::invoke(LangItems::crate_lang_items_query)] | |
183 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; | |
184 | ||
185 | #[salsa::invoke(LangItems::lang_item_query)] | |
9ffffee4 | 186 | fn lang_item(&self, start_crate: CrateId, item: LangItem) -> Option<LangItemTarget>; |
064997fb FG |
187 | |
188 | #[salsa::invoke(ImportMap::import_map_query)] | |
189 | fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; | |
190 | ||
191 | #[salsa::invoke(visibility::field_visibilities_query)] | |
192 | fn field_visibilities(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Visibility>>; | |
193 | ||
194 | // FIXME: unify function_visibility and const_visibility? | |
195 | #[salsa::invoke(visibility::function_visibility_query)] | |
196 | fn function_visibility(&self, def: FunctionId) -> Visibility; | |
197 | ||
198 | #[salsa::invoke(visibility::const_visibility_query)] | |
199 | fn const_visibility(&self, def: ConstId) -> Visibility; | |
200 | ||
201 | #[salsa::transparent] | |
202 | fn crate_limits(&self, crate_id: CrateId) -> CrateLimits; | |
203 | ||
204 | fn crate_supports_no_std(&self, crate_id: CrateId) -> bool; | |
205 | } | |
206 | ||
207 | fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> { | |
208 | let _p = profile::span("crate_def_map:wait"); | |
209 | db.crate_def_map_query(krate) | |
210 | } | |
211 | ||
212 | pub struct CrateLimits { | |
213 | /// The maximum depth for potentially infinitely-recursive compile-time operations like macro expansion or auto-dereference. | |
214 | pub recursion_limit: u32, | |
215 | } | |
216 | ||
217 | fn crate_limits(db: &dyn DefDatabase, crate_id: CrateId) -> CrateLimits { | |
218 | let def_map = db.crate_def_map(crate_id); | |
219 | ||
220 | CrateLimits { | |
221 | // 128 is the default in rustc. | |
222 | recursion_limit: def_map.recursion_limit().unwrap_or(128), | |
223 | } | |
224 | } | |
225 | ||
226 | fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool { | |
227 | let file = db.crate_graph()[crate_id].root_file_id; | |
228 | let item_tree = db.file_item_tree(file.into()); | |
229 | let attrs = item_tree.raw_attrs(AttrOwner::TopLevel); | |
230 | for attr in &**attrs { | |
231 | match attr.path().as_ident().and_then(|id| id.as_text()) { | |
232 | Some(ident) if ident == "no_std" => return true, | |
233 | Some(ident) if ident == "cfg_attr" => {} | |
234 | _ => continue, | |
235 | } | |
236 | ||
237 | // This is a `cfg_attr`; check if it could possibly expand to `no_std`. | |
238 | // Syntax is: `#[cfg_attr(condition(cfg, style), attr0, attr1, <...>)]` | |
239 | let tt = match attr.token_tree_value() { | |
240 | Some(tt) => &tt.token_trees, | |
241 | None => continue, | |
242 | }; | |
243 | ||
244 | let segments = tt.split(|tt| match tt { | |
245 | tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => true, | |
246 | _ => false, | |
247 | }); | |
248 | for output in segments.skip(1) { | |
249 | match output { | |
250 | [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "no_std" => { | |
251 | return true | |
252 | } | |
253 | _ => {} | |
254 | } | |
255 | } | |
256 | } | |
257 | ||
258 | false | |
259 | } |