• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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