hir_def/
nameres.rs

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
50pub mod assoc;
51pub mod attr_resolution;
52mod collector;
53pub mod diagnostics;
54mod mod_resolution;
55mod path_resolution;
56pub mod proc_macro;
57
58#[cfg(test)]
59mod tests;
60
61use std::ops::Deref;
62
63use base_db::Crate;
64use hir_expand::{
65    EditionedFileId, ErasedAstId, HirFileId, InFile, MacroCallId, mod_path::ModPath, name::Name,
66    proc_macro::ProcMacroKind,
67};
68use intern::Symbol;
69use itertools::Itertools;
70use la_arena::Arena;
71use rustc_hash::{FxHashMap, FxHashSet};
72use span::{Edition, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID};
73use stdx::format_to;
74use syntax::{AstNode, SmolStr, SyntaxNode, ToSmolStr, ast};
75use triomphe::Arc;
76use tt::TextRange;
77
78use crate::{
79    AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, FxIndexMap,
80    LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
81    db::DefDatabase,
82    item_scope::{BuiltinShadowMode, ItemScope},
83    item_tree::TreeId,
84    nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
85    per_ns::PerNs,
86    visibility::{Visibility, VisibilityExplicitness},
87};
88
89pub use self::path_resolution::ResolvePathResultPrefixInfo;
90
91const PREDEFINED_TOOLS: &[SmolStr] = &[
92    SmolStr::new_static("clippy"),
93    SmolStr::new_static("rustfmt"),
94    SmolStr::new_static("diagnostic"),
95    SmolStr::new_static("miri"),
96    SmolStr::new_static("rust_analyzer"),
97];
98
99/// Parts of the def map that are only needed when analyzing code in the same crate.
100///
101/// There are some data in the def map (e.g. extern prelude) that is only needed when analyzing
102/// things in the same crate (and maybe in the IDE layer), e.g. the extern prelude. If we put
103/// it in the DefMap dependant DefMaps will be invalidated when they change (e.g. when we add
104/// a dependency to the crate). Instead we split them out of the DefMap into a LocalDefMap struct.
105/// `crate_local_def_map()` returns both, and `crate_def_map()` returns only the external-relevant
106/// DefMap.
107#[derive(Debug, PartialEq, Eq, Default)]
108pub struct LocalDefMap {
109    // FIXME: There are probably some other things that could be here, but this is less severe and you
110    // need to be careful with things that block def maps also have.
111    /// The extern prelude which contains all root modules of external crates that are in scope.
112    extern_prelude: FxIndexMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
113}
114
115impl std::hash::Hash for LocalDefMap {
116    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
117        let LocalDefMap { extern_prelude } = self;
118        extern_prelude.len().hash(state);
119        for (name, (crate_root, extern_crate)) in extern_prelude {
120            name.hash(state);
121            crate_root.hash(state);
122            extern_crate.hash(state);
123        }
124    }
125}
126
127impl LocalDefMap {
128    pub(crate) const EMPTY: &Self =
129        &Self { extern_prelude: FxIndexMap::with_hasher(rustc_hash::FxBuildHasher) };
130
131    fn shrink_to_fit(&mut self) {
132        let Self { extern_prelude } = self;
133        extern_prelude.shrink_to_fit();
134    }
135
136    pub(crate) fn extern_prelude(
137        &self,
138    ) -> impl DoubleEndedIterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_
139    {
140        self.extern_prelude.iter().map(|(name, &def)| (name, def))
141    }
142}
143
144/// Contains the results of (early) name resolution.
145///
146/// A `DefMap` stores the module tree and the definitions that are in scope in every module after
147/// item-level macros have been expanded.
148///
149/// Every crate has a primary `DefMap` whose root is the crate's main file (`main.rs`/`lib.rs`),
150/// computed by the `crate_def_map` query. Additionally, every block expression introduces the
151/// opportunity to write arbitrary item and module hierarchies, and thus gets its own `DefMap` that
152/// is computed by the `block_def_map` query.
153#[derive(Debug, PartialEq, Eq)]
154pub struct DefMap {
155    /// The crate this `DefMap` belongs to.
156    krate: Crate,
157    /// When this is a block def map, this will hold the block id of the block and module that
158    /// contains this block.
159    block: Option<BlockInfo>,
160    /// The modules and their data declared in this crate.
161    pub modules: Arena<ModuleData>,
162    /// The prelude module for this crate. This either comes from an import
163    /// marked with the `prelude_import` attribute, or (in the normal case) from
164    /// a dependency (`std` or `core`).
165    /// The prelude is empty for non-block DefMaps (unless `#[prelude_import]` was used,
166    /// but that attribute is nightly and when used in a block, it affects resolution globally
167    /// so we aren't handling this correctly anyways).
168    prelude: Option<(ModuleId, Option<UseId>)>,
169    /// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that
170    /// this contains all kinds of macro, not just `macro_rules!` macro.
171    /// ExternCrateId being None implies it being imported from the general prelude import.
172    macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
173
174    /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
175    /// attributes.
176    // FIXME: Figure out a better way for the IDE layer to resolve these?
177    derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<(Name, MacroId, MacroCallId)>>,
178    /// A mapping from [`hir_expand::MacroDefId`] to [`crate::MacroId`].
179    pub macro_def_to_macro_id: FxHashMap<ErasedAstId, MacroId>,
180
181    /// The diagnostics that need to be emitted for this crate.
182    diagnostics: Vec<DefDiagnostic>,
183
184    /// The crate data that is shared between a crate's def map and all its block def maps.
185    data: Arc<DefMapCrateData>,
186}
187
188/// Data that belongs to a crate which is shared between a crate's def map and all its block def maps.
189#[derive(Clone, Debug, PartialEq, Eq)]
190struct DefMapCrateData {
191    /// Side table for resolving derive helpers.
192    exported_derives: FxHashMap<MacroId, Box<[Name]>>,
193    fn_proc_macro_mapping: FxHashMap<FunctionId, ProcMacroId>,
194
195    /// Custom tool modules registered with `#![register_tool]`.
196    registered_tools: Vec<Symbol>,
197    /// Unstable features of Rust enabled with `#![feature(A, B)]`.
198    unstable_features: FxHashSet<Symbol>,
199    /// #[rustc_coherence_is_core]
200    rustc_coherence_is_core: bool,
201    no_core: bool,
202    no_std: bool,
203
204    edition: Edition,
205    recursion_limit: Option<u32>,
206}
207
208impl DefMapCrateData {
209    fn new(edition: Edition) -> Self {
210        Self {
211            exported_derives: FxHashMap::default(),
212            fn_proc_macro_mapping: FxHashMap::default(),
213            registered_tools: PREDEFINED_TOOLS.iter().map(|it| Symbol::intern(it)).collect(),
214            unstable_features: FxHashSet::default(),
215            rustc_coherence_is_core: false,
216            no_core: false,
217            no_std: false,
218            edition,
219            recursion_limit: None,
220        }
221    }
222
223    fn shrink_to_fit(&mut self) {
224        let Self {
225            exported_derives,
226            fn_proc_macro_mapping,
227            registered_tools,
228            unstable_features,
229            rustc_coherence_is_core: _,
230            no_core: _,
231            no_std: _,
232            edition: _,
233            recursion_limit: _,
234        } = self;
235        exported_derives.shrink_to_fit();
236        fn_proc_macro_mapping.shrink_to_fit();
237        registered_tools.shrink_to_fit();
238        unstable_features.shrink_to_fit();
239    }
240}
241
242/// For `DefMap`s computed for a block expression, this stores its location in the parent map.
243#[derive(Debug, PartialEq, Eq, Clone, Copy)]
244struct BlockInfo {
245    /// The `BlockId` this `DefMap` was created from.
246    block: BlockId,
247    /// The containing module.
248    parent: BlockRelativeModuleId,
249}
250
251#[derive(Debug, PartialEq, Eq, Clone, Copy)]
252struct BlockRelativeModuleId {
253    block: Option<BlockId>,
254    local_id: LocalModuleId,
255}
256
257impl BlockRelativeModuleId {
258    fn def_map(self, db: &dyn DefDatabase, krate: Crate) -> &DefMap {
259        self.into_module(krate).def_map(db)
260    }
261
262    fn into_module(self, krate: Crate) -> ModuleId {
263        ModuleId { krate, block: self.block, local_id: self.local_id }
264    }
265
266    fn is_block_module(self) -> bool {
267        self.block.is_some() && self.local_id == DefMap::ROOT
268    }
269}
270
271impl std::ops::Index<LocalModuleId> for DefMap {
272    type Output = ModuleData;
273    fn index(&self, id: LocalModuleId) -> &ModuleData {
274        &self.modules[id]
275    }
276}
277
278#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
279pub enum ModuleOrigin {
280    CrateRoot {
281        definition: EditionedFileId,
282    },
283    /// Note that non-inline modules, by definition, live inside non-macro file.
284    File {
285        is_mod_rs: bool,
286        declaration: FileAstId<ast::Module>,
287        declaration_tree_id: TreeId,
288        definition: EditionedFileId,
289    },
290    Inline {
291        definition_tree_id: TreeId,
292        definition: FileAstId<ast::Module>,
293    },
294    /// Pseudo-module introduced by a block scope (contains only inner items).
295    BlockExpr {
296        id: BlockId,
297        block: AstId<ast::BlockExpr>,
298    },
299}
300
301impl ModuleOrigin {
302    pub fn declaration(&self) -> Option<AstId<ast::Module>> {
303        match self {
304            &ModuleOrigin::File { declaration, declaration_tree_id, .. } => {
305                Some(AstId::new(declaration_tree_id.file_id(), declaration))
306            }
307            &ModuleOrigin::Inline { definition, definition_tree_id } => {
308                Some(AstId::new(definition_tree_id.file_id(), definition))
309            }
310            ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None,
311        }
312    }
313
314    pub fn file_id(&self) -> Option<EditionedFileId> {
315        match self {
316            ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
317                Some(*definition)
318            }
319            _ => None,
320        }
321    }
322
323    pub fn is_inline(&self) -> bool {
324        match self {
325            ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true,
326            ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false,
327        }
328    }
329
330    /// Returns a node which defines this module.
331    /// That is, a file or a `mod foo {}` with items.
332    pub fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
333        match self {
334            &ModuleOrigin::File { definition: editioned_file_id, .. }
335            | &ModuleOrigin::CrateRoot { definition: editioned_file_id } => {
336                let sf = db.parse(editioned_file_id).tree();
337                InFile::new(editioned_file_id.into(), ModuleSource::SourceFile(sf))
338            }
339            &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
340                definition_tree_id.file_id(),
341                ModuleSource::Module(
342                    AstId::new(definition_tree_id.file_id(), definition).to_node(db),
343                ),
344            ),
345            ModuleOrigin::BlockExpr { block, .. } => {
346                InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db)))
347            }
348        }
349    }
350}
351
352#[derive(Debug, PartialEq, Eq)]
353pub struct ModuleData {
354    /// Where does this module come from?
355    pub origin: ModuleOrigin,
356    /// Declared visibility of this module.
357    pub visibility: Visibility,
358    /// Parent module in the same `DefMap`.
359    ///
360    /// [`None`] for block modules because they are always its `DefMap`'s root.
361    pub parent: Option<LocalModuleId>,
362    pub children: FxIndexMap<Name, LocalModuleId>,
363    pub scope: ItemScope,
364}
365
366#[inline]
367pub fn crate_def_map(db: &dyn DefDatabase, crate_id: Crate) -> &DefMap {
368    crate_local_def_map(db, crate_id).def_map(db)
369}
370
371#[salsa_macros::tracked]
372pub(crate) struct DefMapPair<'db> {
373    #[tracked]
374    #[returns(ref)]
375    pub(crate) def_map: DefMap,
376    #[returns(ref)]
377    pub(crate) local: LocalDefMap,
378}
379
380#[salsa_macros::tracked(returns(ref))]
381pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefMapPair<'_> {
382    let krate = crate_id.data(db);
383    let _p = tracing::info_span!(
384        "crate_def_map_query",
385        name=?crate_id
386            .extra_data(db)
387            .display_name
388            .as_ref()
389            .map(|it| it.crate_name().to_smolstr())
390            .unwrap_or_default()
391    )
392    .entered();
393
394    let module_data = ModuleData::new(
395        ModuleOrigin::CrateRoot { definition: krate.root_file_id(db) },
396        Visibility::Public,
397    );
398
399    let def_map =
400        DefMap::empty(crate_id, Arc::new(DefMapCrateData::new(krate.edition)), module_data, None);
401    let (def_map, local_def_map) = collector::collect_defs(
402        db,
403        def_map,
404        TreeId::new(krate.root_file_id(db).into(), None),
405        None,
406    );
407
408    DefMapPair::new(db, def_map, local_def_map)
409}
410
411#[salsa_macros::tracked(returns(ref))]
412pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap {
413    let BlockLoc { ast_id, module } = block_id.lookup(db);
414
415    let visibility = Visibility::Module(
416        ModuleId { krate: module.krate, local_id: DefMap::ROOT, block: module.block },
417        VisibilityExplicitness::Implicit,
418    );
419    let module_data =
420        ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
421
422    let local_def_map = crate_local_def_map(db, module.krate);
423    let def_map = DefMap::empty(
424        module.krate,
425        local_def_map.def_map(db).data.clone(),
426        module_data,
427        Some(BlockInfo {
428            block: block_id,
429            parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id },
430        }),
431    );
432
433    let (def_map, _) = collector::collect_defs(
434        db,
435        def_map,
436        TreeId::new(ast_id.file_id, Some(block_id)),
437        Some(local_def_map.local(db)),
438    );
439    def_map
440}
441
442impl DefMap {
443    /// The module id of a crate or block root.
444    pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0));
445
446    pub fn edition(&self) -> Edition {
447        self.data.edition
448    }
449
450    fn empty(
451        krate: Crate,
452        crate_data: Arc<DefMapCrateData>,
453        module_data: ModuleData,
454        block: Option<BlockInfo>,
455    ) -> DefMap {
456        let mut modules: Arena<ModuleData> = Arena::default();
457        let root = modules.alloc(module_data);
458        assert_eq!(root, Self::ROOT);
459
460        DefMap {
461            block,
462            modules,
463            krate,
464            prelude: None,
465            macro_use_prelude: FxHashMap::default(),
466            derive_helpers_in_scope: FxHashMap::default(),
467            diagnostics: Vec::new(),
468            data: crate_data,
469            macro_def_to_macro_id: FxHashMap::default(),
470        }
471    }
472    fn shrink_to_fit(&mut self) {
473        // Exhaustive match to require handling new fields.
474        let Self {
475            macro_use_prelude,
476            diagnostics,
477            modules,
478            derive_helpers_in_scope,
479            block: _,
480            krate: _,
481            prelude: _,
482            data: _,
483            macro_def_to_macro_id,
484        } = self;
485
486        macro_def_to_macro_id.shrink_to_fit();
487        macro_use_prelude.shrink_to_fit();
488        diagnostics.shrink_to_fit();
489        modules.shrink_to_fit();
490        derive_helpers_in_scope.shrink_to_fit();
491        for (_, module) in modules.iter_mut() {
492            module.children.shrink_to_fit();
493            module.scope.shrink_to_fit();
494        }
495    }
496}
497
498impl DefMap {
499    pub fn modules_for_file<'a>(
500        &'a self,
501        db: &'a dyn DefDatabase,
502        file_id: FileId,
503    ) -> impl Iterator<Item = LocalModuleId> + 'a {
504        self.modules
505            .iter()
506            .filter(move |(_id, data)| {
507                data.origin.file_id().map(|file_id| file_id.file_id(db)) == Some(file_id)
508            })
509            .map(|(id, _data)| id)
510    }
511
512    pub fn modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_ {
513        self.modules.iter()
514    }
515
516    pub fn derive_helpers_in_scope(
517        &self,
518        id: AstId<ast::Adt>,
519    ) -> Option<&[(Name, MacroId, MacroCallId)]> {
520        self.derive_helpers_in_scope.get(&id.map(|it| it.upcast())).map(Deref::deref)
521    }
522
523    pub fn registered_tools(&self) -> &[Symbol] {
524        &self.data.registered_tools
525    }
526
527    pub fn is_unstable_feature_enabled(&self, feature: &Symbol) -> bool {
528        self.data.unstable_features.contains(feature)
529    }
530
531    pub fn is_rustc_coherence_is_core(&self) -> bool {
532        self.data.rustc_coherence_is_core
533    }
534
535    pub fn is_no_std(&self) -> bool {
536        self.data.no_std || self.data.no_core
537    }
538
539    pub fn is_no_core(&self) -> bool {
540        self.data.no_core
541    }
542
543    pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId> {
544        self.data.fn_proc_macro_mapping.get(&id).copied()
545    }
546
547    pub fn krate(&self) -> Crate {
548        self.krate
549    }
550
551    pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
552        let block = self.block.map(|b| b.block);
553        ModuleId { krate: self.krate, local_id, block }
554    }
555
556    pub fn crate_root(&self) -> CrateRootModuleId {
557        CrateRootModuleId { krate: self.krate }
558    }
559
560    /// This is the same as [`Self::crate_root`] for crate def maps, but for block def maps, it
561    /// returns the root block module.
562    pub fn root_module_id(&self) -> ModuleId {
563        self.module_id(Self::ROOT)
564    }
565
566    /// If this `DefMap` is for a block expression, returns the module containing the block (which
567    /// might again be a block, or a module inside a block).
568    pub fn parent(&self) -> Option<ModuleId> {
569        let BlockRelativeModuleId { block, local_id } = self.block?.parent;
570        Some(ModuleId { krate: self.krate, block, local_id })
571    }
572
573    /// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing
574    /// the block, if `self` corresponds to a block expression.
575    pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
576        match self[local_mod].parent {
577            Some(parent) => Some(self.module_id(parent)),
578            None => {
579                self.block.map(
580                    |BlockInfo { parent: BlockRelativeModuleId { block, local_id }, .. }| {
581                        ModuleId { krate: self.krate, block, local_id }
582                    },
583                )
584            }
585        }
586    }
587
588    /// Get a reference to the def map's diagnostics.
589    pub fn diagnostics(&self) -> &[DefDiagnostic] {
590        self.diagnostics.as_slice()
591    }
592
593    pub fn recursion_limit(&self) -> u32 {
594        // 128 is the default in rustc
595        self.data.recursion_limit.unwrap_or(128)
596    }
597
598    // FIXME: this can use some more human-readable format (ideally, an IR
599    // even), as this should be a great debugging aid.
600    pub fn dump(&self, db: &dyn DefDatabase) -> String {
601        let mut buf = String::new();
602        let mut arc;
603        let mut current_map = self;
604        while let Some(block) = current_map.block {
605            go(&mut buf, db, current_map, "block scope", Self::ROOT);
606            buf.push('\n');
607            arc = block.parent.def_map(db, self.krate);
608            current_map = arc;
609        }
610        go(&mut buf, db, current_map, "crate", Self::ROOT);
611        return buf;
612
613        fn go(
614            buf: &mut String,
615            db: &dyn DefDatabase,
616            map: &DefMap,
617            path: &str,
618            module: LocalModuleId,
619        ) {
620            format_to!(buf, "{}\n", path);
621
622            map.modules[module].scope.dump(db, buf);
623
624            for (name, child) in
625                map.modules[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
626            {
627                let path = format!("{path}::{}", name.display(db, Edition::LATEST));
628                buf.push('\n');
629                go(buf, db, map, &path, *child);
630            }
631        }
632    }
633
634    pub fn dump_block_scopes(&self, db: &dyn DefDatabase) -> String {
635        let mut buf = String::new();
636        let mut arc;
637        let mut current_map = self;
638        while let Some(block) = current_map.block {
639            format_to!(buf, "{:?} in {:?}\n", block.block, block.parent);
640            arc = block.parent.def_map(db, self.krate);
641            current_map = arc;
642        }
643
644        format_to!(buf, "crate scope\n");
645        buf
646    }
647}
648
649impl DefMap {
650    pub(crate) fn block_id(&self) -> Option<BlockId> {
651        self.block.map(|block| block.block)
652    }
653
654    pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
655        self.prelude
656    }
657
658    pub(crate) fn macro_use_prelude(&self) -> &FxHashMap<Name, (MacroId, Option<ExternCrateId>)> {
659        &self.macro_use_prelude
660    }
661
662    pub(crate) fn resolve_path(
663        &self,
664        local_def_map: &LocalDefMap,
665        db: &dyn DefDatabase,
666        original_module: LocalModuleId,
667        path: &ModPath,
668        shadow: BuiltinShadowMode,
669        expected_macro_subns: Option<MacroSubNs>,
670    ) -> (PerNs, Option<usize>) {
671        let res = self.resolve_path_fp_with_macro(
672            local_def_map,
673            db,
674            ResolveMode::Other,
675            original_module,
676            path,
677            shadow,
678            expected_macro_subns,
679        );
680        (res.resolved_def, res.segment_index)
681    }
682
683    /// The first `Option<usize>` points at the `Enum` segment in case of `Enum::Variant`, the second
684    /// points at the unresolved segments.
685    pub(crate) fn resolve_path_locally(
686        &self,
687        local_def_map: &LocalDefMap,
688        db: &dyn DefDatabase,
689        original_module: LocalModuleId,
690        path: &ModPath,
691        shadow: BuiltinShadowMode,
692    ) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
693        let res = self.resolve_path_fp_with_macro_single(
694            local_def_map,
695            db,
696            ResolveMode::Other,
697            original_module,
698            path,
699            shadow,
700            None, // Currently this function isn't used for macro resolution.
701        );
702        (res.resolved_def, res.segment_index, res.prefix_info)
703    }
704
705    /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
706    ///
707    /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
708    /// `None`, iteration continues.
709    pub(crate) fn with_ancestor_maps<T>(
710        &self,
711        db: &dyn DefDatabase,
712        local_mod: LocalModuleId,
713        f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
714    ) -> Option<T> {
715        if let Some(it) = f(self, local_mod) {
716            return Some(it);
717        }
718        let mut block = self.block;
719        while let Some(block_info) = block {
720            let parent = block_info.parent.def_map(db, self.krate);
721            if let Some(it) = f(parent, block_info.parent.local_id) {
722                return Some(it);
723            }
724            block = parent.block;
725        }
726
727        None
728    }
729}
730
731impl ModuleData {
732    pub(crate) fn new(origin: ModuleOrigin, visibility: Visibility) -> Self {
733        ModuleData {
734            origin,
735            visibility,
736            parent: None,
737            children: Default::default(),
738            scope: ItemScope::default(),
739        }
740    }
741
742    /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
743    pub fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
744        self.origin.definition_source(db)
745    }
746
747    /// Same as [`definition_source`] but only returns the file id to prevent parsing the ASt.
748    pub fn definition_source_file_id(&self) -> HirFileId {
749        match self.origin {
750            ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
751                definition.into()
752            }
753            ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id.file_id(),
754            ModuleOrigin::BlockExpr { block, .. } => block.file_id,
755        }
756    }
757
758    pub fn definition_source_range(&self, db: &dyn DefDatabase) -> InFile<TextRange> {
759        match &self.origin {
760            &ModuleOrigin::File { definition, .. } | &ModuleOrigin::CrateRoot { definition } => {
761                InFile::new(
762                    definition.into(),
763                    ErasedAstId::new(definition.into(), ROOT_ERASED_FILE_AST_ID).to_range(db),
764                )
765            }
766            &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
767                definition_tree_id.file_id(),
768                AstId::new(definition_tree_id.file_id(), definition).to_range(db),
769            ),
770            ModuleOrigin::BlockExpr { block, .. } => InFile::new(block.file_id, block.to_range(db)),
771        }
772    }
773
774    /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
775    /// `None` for the crate root or block.
776    pub fn declaration_source(&self, db: &dyn DefDatabase) -> Option<InFile<ast::Module>> {
777        let decl = self.origin.declaration()?;
778        let value = decl.to_node(db);
779        Some(InFile { file_id: decl.file_id, value })
780    }
781
782    /// Returns the range which declares this module, either a `mod foo;` or a `mod foo {}`.
783    /// `None` for the crate root or block.
784    pub fn declaration_source_range(&self, db: &dyn DefDatabase) -> Option<InFile<TextRange>> {
785        let decl = self.origin.declaration()?;
786        Some(InFile { file_id: decl.file_id, value: decl.to_range(db) })
787    }
788}
789
790#[derive(Debug, Clone, PartialEq, Eq)]
791pub enum ModuleSource {
792    SourceFile(ast::SourceFile),
793    Module(ast::Module),
794    BlockExpr(ast::BlockExpr),
795}
796
797impl ModuleSource {
798    pub fn node(&self) -> SyntaxNode {
799        match self {
800            ModuleSource::SourceFile(it) => it.syntax().clone(),
801            ModuleSource::Module(it) => it.syntax().clone(),
802            ModuleSource::BlockExpr(it) => it.syntax().clone(),
803        }
804    }
805}
806
807/// See `sub_namespace_match()`.
808#[derive(Clone, Copy, PartialEq, Eq)]
809pub enum MacroSubNs {
810    /// Function-like macros, suffixed with `!`.
811    Bang,
812    /// Macros inside attributes, i.e. attribute macros and derive macros.
813    Attr,
814}
815
816impl MacroSubNs {
817    fn from_id(db: &dyn DefDatabase, macro_id: MacroId) -> Self {
818        let expander = match macro_id {
819            MacroId::Macro2Id(it) => it.lookup(db).expander,
820            MacroId::MacroRulesId(it) => it.lookup(db).expander,
821            MacroId::ProcMacroId(it) => {
822                return match it.lookup(db).kind {
823                    ProcMacroKind::CustomDerive | ProcMacroKind::Attr => Self::Attr,
824                    ProcMacroKind::Bang => Self::Bang,
825                };
826            }
827        };
828
829        // Eager macros aren't *guaranteed* to be bang macros, but they *are* all bang macros currently.
830        match expander {
831            MacroExpander::Declarative
832            | MacroExpander::BuiltIn(_)
833            | MacroExpander::BuiltInEager(_) => Self::Bang,
834            MacroExpander::BuiltInAttr(_) | MacroExpander::BuiltInDerive(_) => Self::Attr,
835        }
836    }
837}
838
839/// Quoted from [rustc]:
840/// Macro namespace is separated into two sub-namespaces, one for bang macros and
841/// one for attribute-like macros (attributes, derives).
842/// We ignore resolutions from one sub-namespace when searching names in scope for another.
843///
844/// [rustc]: https://github.com/rust-lang/rust/blob/1.69.0/compiler/rustc_resolve/src/macros.rs#L75
845fn sub_namespace_match(candidate: Option<MacroSubNs>, expected: Option<MacroSubNs>) -> bool {
846    match (candidate, expected) {
847        (Some(candidate), Some(expected)) => candidate == expected,
848        _ => true,
849    }
850}