1 //! This module implements import-resolution/macro expansion algorithm.
2 //!
3 //! The result of this module is `DefMap`: a data structure which contains:
4 //!
5 //! * a tree of modules for the crate
6 //! * for each module, a set of items visible in the module (directly declared
7 //! or imported)
8 //!
9 //! Note that `DefMap` contains fully macro expanded code.
10 //!
11 //! Computing `DefMap` can be partitioned into several logically
12 //! independent "phases". The phases are mutually recursive though, there's no
13 //! strict ordering.
14 //!
15 //! ## Collecting RawItems
16 //!
17 //! This happens in the `raw` module, which parses a single source file into a
18 //! set of top-level items. Nested imports are desugared to flat imports in this
19 //! phase. Macro calls are represented as a triple of (Path, Option<Name>,
20 //! TokenTree).
21 //!
22 //! ## Collecting Modules
23 //!
24 //! This happens in the `collector` module. In this phase, we recursively walk
25 //! tree of modules, collect raw items from submodules, populate module scopes
26 //! with defined items (so, we assign item ids in this phase) and record the set
27 //! of unresolved imports and macros.
28 //!
29 //! While we walk tree of modules, we also record macro_rules definitions and
30 //! expand calls to macro_rules defined macros.
31 //!
32 //! ## Resolving Imports
33 //!
34 //! We maintain a list of currently unresolved imports. On every iteration, we
35 //! try to resolve some imports from this list. If the import is resolved, we
36 //! record it, by adding an item to current module scope and, if necessary, by
37 //! recursively populating glob imports.
38 //!
39 //! ## Resolving Macros
40 //!
41 //! macro_rules from the same crate use a global mutable namespace. We expand
42 //! them immediately, when we collect modules.
43 //!
44 //! Macros from other crates (including proc-macros) can be used with
45 //! `foo::bar!` syntax. We handle them similarly to imports. There's a list of
46 //! unexpanded macros. On every iteration, we try to resolve each macro call
47 //! path and, upon success, we run macro expansion and "collect module" phase on
48 //! the result
49
50 pub mod attr_resolution;
51 pub mod proc_macro;
52 pub mod diagnostics;
53 mod collector;
54 mod mod_resolution;
55 mod path_resolution;
56
57 #[cfg(test)]
58 mod tests;
59
60 use std::{cmp::Ord, ops::Deref};
61
62 use base_db::{CrateId, Edition, FileId, ProcMacroKind};
63 use hir_expand::{name::Name, InFile, MacroCallId, MacroDefId};
64 use itertools::Itertools;
65 use la_arena::Arena;
66 use profile::Count;
67 use rustc_hash::{FxHashMap, FxHashSet};
68 use stdx::format_to;
69 use syntax::{ast, SmolStr};
70 use triomphe::Arc;
71
72 use crate::{
73 db::DefDatabase,
74 item_scope::{BuiltinShadowMode, ItemScope},
75 item_tree::{ItemTreeId, Mod, TreeId},
76 nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
77 path::ModPath,
78 per_ns::PerNs,
79 visibility::Visibility,
80 AstId, BlockId, BlockLoc, CrateRootModuleId, FunctionId, LocalModuleId, Lookup, MacroExpander,
81 MacroId, ModuleId, ProcMacroId,
82 };
83
84 /// Contains the results of (early) name resolution.
85 ///
86 /// A `DefMap` stores the module tree and the definitions that are in scope in every module after
87 /// item-level macros have been expanded.
88 ///
89 /// Every crate has a primary `DefMap` whose root is the crate's main file (`main.rs`/`lib.rs`),
90 /// computed by the `crate_def_map` query. Additionally, every block expression introduces the
91 /// opportunity to write arbitrary item and module hierarchies, and thus gets its own `DefMap` that
92 /// is computed by the `block_def_map` query.
93 #[derive(Debug, PartialEq, Eq)]
94 pub struct DefMap {
95 _c: Count<Self>,
96 /// When this is a block def map, this will hold the block id of the the block and module that
97 /// contains this block.
98 block: Option<BlockInfo>,
99 /// The modules and their data declared in this crate.
100 modules: Arena<ModuleData>,
101 krate: CrateId,
102 /// The prelude module for this crate. This either comes from an import
103 /// marked with the `prelude_import` attribute, or (in the normal case) from
104 /// a dependency (`std` or `core`).
105 /// The prelude is empty for non-block DefMaps (unless `#[prelude_import]` was used,
106 /// but that attribute is nightly and when used in a block, it affects resolution globally
107 /// so we aren't handling this correctly anyways).
108 prelude: Option<ModuleId>,
109 /// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that
110 /// this contains all kinds of macro, not just `macro_rules!` macro.
111 macro_use_prelude: FxHashMap<Name, MacroId>,
112
113 /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
114 /// attributes.
115 derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<(Name, MacroId, MacroCallId)>>,
116
117 /// The diagnostics that need to be emitted for this crate.
118 diagnostics: Vec<DefDiagnostic>,
119
120 /// The crate data that is shared between a crate's def map and all its block def maps.
121 data: Arc<DefMapCrateData>,
122 }
123
124 /// Data that belongs to a crate which is shared between a crate's def map and all its block def maps.
125 #[derive(Clone, Debug, PartialEq, Eq)]
126 struct DefMapCrateData {
127 /// The extern prelude which contains all root modules of external crates that are in scope.
128 extern_prelude: FxHashMap<Name, CrateRootModuleId>,
129
130 /// Side table for resolving derive helpers.
131 exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
132 fn_proc_macro_mapping: FxHashMap<FunctionId, ProcMacroId>,
133 /// The error that occurred when failing to load the proc-macro dll.
134 proc_macro_loading_error: Option<Box<str>>,
135
136 /// Custom attributes registered with `#![register_attr]`.
137 registered_attrs: Vec<SmolStr>,
138 /// Custom tool modules registered with `#![register_tool]`.
139 registered_tools: Vec<SmolStr>,
140 /// Unstable features of Rust enabled with `#![feature(A, B)]`.
141 unstable_features: FxHashSet<SmolStr>,
142 /// #[rustc_coherence_is_core]
143 rustc_coherence_is_core: bool,
144 no_core: bool,
145 no_std: bool,
146
147 edition: Edition,
148 recursion_limit: Option<u32>,
149 }
150
151 impl DefMapCrateData {
shrink_to_fit(&mut self)152 fn shrink_to_fit(&mut self) {
153 let Self {
154 extern_prelude,
155 exported_derives,
156 fn_proc_macro_mapping,
157 registered_attrs,
158 registered_tools,
159 unstable_features,
160 proc_macro_loading_error: _,
161 rustc_coherence_is_core: _,
162 no_core: _,
163 no_std: _,
164 edition: _,
165 recursion_limit: _,
166 } = self;
167 extern_prelude.shrink_to_fit();
168 exported_derives.shrink_to_fit();
169 fn_proc_macro_mapping.shrink_to_fit();
170 registered_attrs.shrink_to_fit();
171 registered_tools.shrink_to_fit();
172 unstable_features.shrink_to_fit();
173 }
174 }
175
176 /// For `DefMap`s computed for a block expression, this stores its location in the parent map.
177 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
178 struct BlockInfo {
179 /// The `BlockId` this `DefMap` was created from.
180 block: BlockId,
181 /// The containing module.
182 parent: BlockRelativeModuleId,
183 }
184
185 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
186 struct BlockRelativeModuleId {
187 block: Option<BlockId>,
188 local_id: LocalModuleId,
189 }
190
191 impl BlockRelativeModuleId {
def_map(self, db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap>192 fn def_map(self, db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
193 self.into_module(krate).def_map(db)
194 }
195
into_module(self, krate: CrateId) -> ModuleId196 fn into_module(self, krate: CrateId) -> ModuleId {
197 ModuleId { krate, block: self.block, local_id: self.local_id }
198 }
199 }
200
201 impl std::ops::Index<LocalModuleId> for DefMap {
202 type Output = ModuleData;
index(&self, id: LocalModuleId) -> &ModuleData203 fn index(&self, id: LocalModuleId) -> &ModuleData {
204 &self.modules[id]
205 }
206 }
207
208 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
209 pub enum ModuleOrigin {
210 CrateRoot {
211 definition: FileId,
212 },
213 /// Note that non-inline modules, by definition, live inside non-macro file.
214 File {
215 is_mod_rs: bool,
216 declaration: AstId<ast::Module>,
217 declaration_tree_id: ItemTreeId<Mod>,
218 definition: FileId,
219 },
220 Inline {
221 definition_tree_id: ItemTreeId<Mod>,
222 definition: AstId<ast::Module>,
223 },
224 /// Pseudo-module introduced by a block scope (contains only inner items).
225 BlockExpr {
226 block: AstId<ast::BlockExpr>,
227 },
228 }
229
230 impl ModuleOrigin {
declaration(&self) -> Option<AstId<ast::Module>>231 pub fn declaration(&self) -> Option<AstId<ast::Module>> {
232 match self {
233 ModuleOrigin::File { declaration: module, .. }
234 | ModuleOrigin::Inline { definition: module, .. } => Some(*module),
235 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None,
236 }
237 }
238
file_id(&self) -> Option<FileId>239 pub fn file_id(&self) -> Option<FileId> {
240 match self {
241 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
242 Some(*definition)
243 }
244 _ => None,
245 }
246 }
247
is_inline(&self) -> bool248 pub fn is_inline(&self) -> bool {
249 match self {
250 ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true,
251 ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false,
252 }
253 }
254
255 /// Returns a node which defines this module.
256 /// That is, a file or a `mod foo {}` with items.
definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource>257 fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
258 match self {
259 ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
260 let file_id = *definition;
261 let sf = db.parse(file_id).tree();
262 InFile::new(file_id.into(), ModuleSource::SourceFile(sf))
263 }
264 ModuleOrigin::Inline { definition, .. } => InFile::new(
265 definition.file_id,
266 ModuleSource::Module(definition.to_node(db.upcast())),
267 ),
268 ModuleOrigin::BlockExpr { block } => {
269 InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast())))
270 }
271 }
272 }
273 }
274
275 #[derive(Debug, PartialEq, Eq)]
276 pub struct ModuleData {
277 /// Where does this module come from?
278 pub origin: ModuleOrigin,
279 /// Declared visibility of this module.
280 pub visibility: Visibility,
281 /// Always [`None`] for block modules
282 pub parent: Option<LocalModuleId>,
283 pub children: FxHashMap<Name, LocalModuleId>,
284 pub scope: ItemScope,
285 }
286
287 impl DefMap {
288 /// The module id of a crate or block root.
289 pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0));
290
crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap>291 pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
292 let _p = profile::span("crate_def_map_query").detail(|| {
293 db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string()
294 });
295
296 let crate_graph = db.crate_graph();
297
298 let edition = crate_graph[krate].edition;
299 let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id };
300 let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public));
301 let def_map = collector::collect_defs(
302 db,
303 def_map,
304 TreeId::new(crate_graph[krate].root_file_id.into(), None),
305 );
306
307 Arc::new(def_map)
308 }
309
block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap>310 pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
311 let block: BlockLoc = db.lookup_intern_block(block_id);
312
313 let tree_id = TreeId::new(block.ast_id.file_id, Some(block_id));
314
315 let parent_map = block.module.def_map(db);
316 let krate = block.module.krate;
317 let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
318 // NB: we use `None` as block here, which would be wrong for implicit
319 // modules declared by blocks with items. At the moment, we don't use
320 // this visibility for anything outside IDE, so that's probably OK.
321 let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
322 let module_data =
323 ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility);
324
325 let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data);
326 def_map.data = parent_map.data.clone();
327 def_map.block = Some(BlockInfo {
328 block: block_id,
329 parent: BlockRelativeModuleId {
330 block: block.module.block,
331 local_id: block.module.local_id,
332 },
333 });
334
335 let def_map = collector::collect_defs(db, def_map, tree_id);
336 Arc::new(def_map)
337 }
338
empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap339 fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap {
340 let mut modules: Arena<ModuleData> = Arena::default();
341 let root = modules.alloc(module_data);
342 assert_eq!(root, Self::ROOT);
343
344 DefMap {
345 _c: Count::new(),
346 block: None,
347 modules,
348 krate,
349 prelude: None,
350 macro_use_prelude: FxHashMap::default(),
351 derive_helpers_in_scope: FxHashMap::default(),
352 diagnostics: Vec::new(),
353 data: Arc::new(DefMapCrateData {
354 extern_prelude: FxHashMap::default(),
355 exported_derives: FxHashMap::default(),
356 fn_proc_macro_mapping: FxHashMap::default(),
357 proc_macro_loading_error: None,
358 registered_attrs: Vec::new(),
359 registered_tools: Vec::new(),
360 unstable_features: FxHashSet::default(),
361 rustc_coherence_is_core: false,
362 no_core: false,
363 no_std: false,
364 edition,
365 recursion_limit: None,
366 }),
367 }
368 }
369
modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_370 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
371 self.modules
372 .iter()
373 .filter(move |(_id, data)| data.origin.file_id() == Some(file_id))
374 .map(|(id, _data)| id)
375 }
376
modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_377 pub fn modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_ {
378 self.modules.iter()
379 }
380
derive_helpers_in_scope( &self, id: AstId<ast::Adt>, ) -> Option<&[(Name, MacroId, MacroCallId)]>381 pub fn derive_helpers_in_scope(
382 &self,
383 id: AstId<ast::Adt>,
384 ) -> Option<&[(Name, MacroId, MacroCallId)]> {
385 self.derive_helpers_in_scope.get(&id.map(|it| it.upcast())).map(Deref::deref)
386 }
387
registered_tools(&self) -> &[SmolStr]388 pub fn registered_tools(&self) -> &[SmolStr] {
389 &self.data.registered_tools
390 }
391
registered_attrs(&self) -> &[SmolStr]392 pub fn registered_attrs(&self) -> &[SmolStr] {
393 &self.data.registered_attrs
394 }
395
is_unstable_feature_enabled(&self, feature: &str) -> bool396 pub fn is_unstable_feature_enabled(&self, feature: &str) -> bool {
397 self.data.unstable_features.contains(feature)
398 }
399
is_rustc_coherence_is_core(&self) -> bool400 pub fn is_rustc_coherence_is_core(&self) -> bool {
401 self.data.rustc_coherence_is_core
402 }
403
is_no_std(&self) -> bool404 pub fn is_no_std(&self) -> bool {
405 self.data.no_std || self.data.no_core
406 }
407
fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId>408 pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId> {
409 self.data.fn_proc_macro_mapping.get(&id).copied()
410 }
411
proc_macro_loading_error(&self) -> Option<&str>412 pub fn proc_macro_loading_error(&self) -> Option<&str> {
413 self.data.proc_macro_loading_error.as_deref()
414 }
415
krate(&self) -> CrateId416 pub fn krate(&self) -> CrateId {
417 self.krate
418 }
419
block_id(&self) -> Option<BlockId>420 pub(crate) fn block_id(&self) -> Option<BlockId> {
421 self.block.map(|block| block.block)
422 }
423
prelude(&self) -> Option<ModuleId>424 pub(crate) fn prelude(&self) -> Option<ModuleId> {
425 self.prelude
426 }
427
extern_prelude(&self) -> impl Iterator<Item = (&Name, ModuleId)> + '_428 pub(crate) fn extern_prelude(&self) -> impl Iterator<Item = (&Name, ModuleId)> + '_ {
429 self.data.extern_prelude.iter().map(|(name, &def)| (name, def.into()))
430 }
431
macro_use_prelude(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_432 pub(crate) fn macro_use_prelude(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ {
433 self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
434 }
435
module_id(&self, local_id: LocalModuleId) -> ModuleId436 pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
437 let block = self.block.map(|b| b.block);
438 ModuleId { krate: self.krate, local_id, block }
439 }
440
crate_root(&self) -> CrateRootModuleId441 pub fn crate_root(&self) -> CrateRootModuleId {
442 CrateRootModuleId { krate: self.krate }
443 }
444
resolve_path( &self, db: &dyn DefDatabase, original_module: LocalModuleId, path: &ModPath, shadow: BuiltinShadowMode, expected_macro_subns: Option<MacroSubNs>, ) -> (PerNs, Option<usize>)445 pub(crate) fn resolve_path(
446 &self,
447 db: &dyn DefDatabase,
448 original_module: LocalModuleId,
449 path: &ModPath,
450 shadow: BuiltinShadowMode,
451 expected_macro_subns: Option<MacroSubNs>,
452 ) -> (PerNs, Option<usize>) {
453 let res = self.resolve_path_fp_with_macro(
454 db,
455 ResolveMode::Other,
456 original_module,
457 path,
458 shadow,
459 expected_macro_subns,
460 );
461 (res.resolved_def, res.segment_index)
462 }
463
resolve_path_locally( &self, db: &dyn DefDatabase, original_module: LocalModuleId, path: &ModPath, shadow: BuiltinShadowMode, ) -> (PerNs, Option<usize>)464 pub(crate) fn resolve_path_locally(
465 &self,
466 db: &dyn DefDatabase,
467 original_module: LocalModuleId,
468 path: &ModPath,
469 shadow: BuiltinShadowMode,
470 ) -> (PerNs, Option<usize>) {
471 let res = self.resolve_path_fp_with_macro_single(
472 db,
473 ResolveMode::Other,
474 original_module,
475 path,
476 shadow,
477 None, // Currently this function isn't used for macro resolution.
478 );
479 (res.resolved_def, res.segment_index)
480 }
481
482 /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
483 ///
484 /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
485 /// `None`, iteration continues.
with_ancestor_maps<T>( &self, db: &dyn DefDatabase, local_mod: LocalModuleId, f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>, ) -> Option<T>486 pub(crate) fn with_ancestor_maps<T>(
487 &self,
488 db: &dyn DefDatabase,
489 local_mod: LocalModuleId,
490 f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
491 ) -> Option<T> {
492 if let Some(it) = f(self, local_mod) {
493 return Some(it);
494 }
495 let mut block = self.block;
496 while let Some(block_info) = block {
497 let parent = block_info.parent.def_map(db, self.krate);
498 if let Some(it) = f(&parent, block_info.parent.local_id) {
499 return Some(it);
500 }
501 block = parent.block;
502 }
503
504 None
505 }
506
507 /// If this `DefMap` is for a block expression, returns the module containing the block (which
508 /// might again be a block, or a module inside a block).
parent(&self) -> Option<ModuleId>509 pub fn parent(&self) -> Option<ModuleId> {
510 let BlockRelativeModuleId { block, local_id } = self.block?.parent;
511 Some(ModuleId { krate: self.krate, block, local_id })
512 }
513
514 /// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing
515 /// the block, if `self` corresponds to a block expression.
containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId>516 pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
517 match self[local_mod].parent {
518 Some(parent) => Some(self.module_id(parent)),
519 None => {
520 self.block.map(
521 |BlockInfo { parent: BlockRelativeModuleId { block, local_id }, .. }| {
522 ModuleId { krate: self.krate, block, local_id }
523 },
524 )
525 }
526 }
527 }
528
529 // FIXME: this can use some more human-readable format (ideally, an IR
530 // even), as this should be a great debugging aid.
dump(&self, db: &dyn DefDatabase) -> String531 pub fn dump(&self, db: &dyn DefDatabase) -> String {
532 let mut buf = String::new();
533 let mut arc;
534 let mut current_map = self;
535 while let Some(block) = current_map.block {
536 go(&mut buf, db, current_map, "block scope", Self::ROOT);
537 buf.push('\n');
538 arc = block.parent.def_map(db, self.krate);
539 current_map = &arc;
540 }
541 go(&mut buf, db, current_map, "crate", Self::ROOT);
542 return buf;
543
544 fn go(
545 buf: &mut String,
546 db: &dyn DefDatabase,
547 map: &DefMap,
548 path: &str,
549 module: LocalModuleId,
550 ) {
551 format_to!(buf, "{}\n", path);
552
553 map.modules[module].scope.dump(db.upcast(), buf);
554
555 for (name, child) in
556 map.modules[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
557 {
558 let path = format!("{path}::{}", name.display(db.upcast()));
559 buf.push('\n');
560 go(buf, db, map, &path, *child);
561 }
562 }
563 }
564
dump_block_scopes(&self, db: &dyn DefDatabase) -> String565 pub fn dump_block_scopes(&self, db: &dyn DefDatabase) -> String {
566 let mut buf = String::new();
567 let mut arc;
568 let mut current_map = self;
569 while let Some(block) = current_map.block {
570 format_to!(buf, "{:?} in {:?}\n", block.block, block.parent);
571 arc = block.parent.def_map(db, self.krate);
572 current_map = &arc;
573 }
574
575 format_to!(buf, "crate scope\n");
576 buf
577 }
578
shrink_to_fit(&mut self)579 fn shrink_to_fit(&mut self) {
580 // Exhaustive match to require handling new fields.
581 let Self {
582 _c: _,
583 macro_use_prelude,
584 diagnostics,
585 modules,
586 derive_helpers_in_scope,
587 block: _,
588 krate: _,
589 prelude: _,
590 data: _,
591 } = self;
592
593 macro_use_prelude.shrink_to_fit();
594 diagnostics.shrink_to_fit();
595 modules.shrink_to_fit();
596 derive_helpers_in_scope.shrink_to_fit();
597 for (_, module) in modules.iter_mut() {
598 module.children.shrink_to_fit();
599 module.scope.shrink_to_fit();
600 }
601 }
602
603 /// Get a reference to the def map's diagnostics.
diagnostics(&self) -> &[DefDiagnostic]604 pub fn diagnostics(&self) -> &[DefDiagnostic] {
605 self.diagnostics.as_slice()
606 }
607
recursion_limit(&self) -> Option<u32>608 pub fn recursion_limit(&self) -> Option<u32> {
609 self.data.recursion_limit
610 }
611 }
612
613 impl ModuleData {
new(origin: ModuleOrigin, visibility: Visibility) -> Self614 pub(crate) fn new(origin: ModuleOrigin, visibility: Visibility) -> Self {
615 ModuleData {
616 origin,
617 visibility,
618 parent: None,
619 children: FxHashMap::default(),
620 scope: ItemScope::default(),
621 }
622 }
623
624 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource>625 pub fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
626 self.origin.definition_source(db)
627 }
628
629 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
630 /// `None` for the crate root or block.
declaration_source(&self, db: &dyn DefDatabase) -> Option<InFile<ast::Module>>631 pub fn declaration_source(&self, db: &dyn DefDatabase) -> Option<InFile<ast::Module>> {
632 let decl = self.origin.declaration()?;
633 let value = decl.to_node(db.upcast());
634 Some(InFile { file_id: decl.file_id, value })
635 }
636 }
637
638 #[derive(Debug, Clone, PartialEq, Eq)]
639 pub enum ModuleSource {
640 SourceFile(ast::SourceFile),
641 Module(ast::Module),
642 BlockExpr(ast::BlockExpr),
643 }
644
645 /// See `sub_namespace_match()`.
646 #[derive(Clone, Copy, PartialEq, Eq)]
647 pub enum MacroSubNs {
648 /// Function-like macros, suffixed with `!`.
649 Bang,
650 /// Macros inside attributes, i.e. attribute macros and derive macros.
651 Attr,
652 }
653
654 impl MacroSubNs {
from_id(db: &dyn DefDatabase, macro_id: MacroId) -> Self655 fn from_id(db: &dyn DefDatabase, macro_id: MacroId) -> Self {
656 let expander = match macro_id {
657 MacroId::Macro2Id(it) => it.lookup(db).expander,
658 MacroId::MacroRulesId(it) => it.lookup(db).expander,
659 MacroId::ProcMacroId(it) => {
660 return match it.lookup(db).kind {
661 ProcMacroKind::CustomDerive | ProcMacroKind::Attr => Self::Attr,
662 ProcMacroKind::FuncLike => Self::Bang,
663 };
664 }
665 };
666
667 // Eager macros aren't *guaranteed* to be bang macros, but they *are* all bang macros currently.
668 match expander {
669 MacroExpander::Declarative
670 | MacroExpander::BuiltIn(_)
671 | MacroExpander::BuiltInEager(_) => Self::Bang,
672 MacroExpander::BuiltInAttr(_) | MacroExpander::BuiltInDerive(_) => Self::Attr,
673 }
674 }
675 }
676
677 /// Quoted from [rustc]:
678 /// Macro namespace is separated into two sub-namespaces, one for bang macros and
679 /// one for attribute-like macros (attributes, derives).
680 /// We ignore resolutions from one sub-namespace when searching names in scope for another.
681 ///
682 /// [rustc]: https://github.com/rust-lang/rust/blob/1.69.0/compiler/rustc_resolve/src/macros.rs#L75
sub_namespace_match(candidate: Option<MacroSubNs>, expected: Option<MacroSubNs>) -> bool683 fn sub_namespace_match(candidate: Option<MacroSubNs>, expected: Option<MacroSubNs>) -> bool {
684 match (candidate, expected) {
685 (Some(candidate), Some(expected)) => candidate == expected,
686 _ => true,
687 }
688 }
689