1 //! The core of the module-level name resolution algorithm.
3 //! `DefCollector::collect` contains the fixed-point iteration loop which
4 //! resolves imports and expands macros.
8 use base_db
::{CrateId, Edition, FileId}
;
9 use cfg
::{CfgExpr, CfgOptions}
;
12 ast_id_map
::FileAstId
,
13 builtin_attr_macro
::find_builtin_attr
,
14 builtin_derive_macro
::find_builtin_derive
,
15 builtin_fn_macro
::find_builtin_macro
,
16 name
::{name, AsName, Name}
,
17 proc_macro
::ProcMacroExpander
,
18 ExpandTo
, HirFileId
, InFile
, MacroCallId
, MacroCallKind
, MacroCallLoc
, MacroDefId
,
21 use itertools
::{izip, Itertools}
;
24 use rustc_hash
::{FxHashMap, FxHashSet}
;
26 use syntax
::{ast, SmolStr}
;
29 attr
::{Attr, AttrId, Attrs}
,
30 attr_macro_as_call_id
,
32 derive_macro_as_call_id
,
33 item_scope
::{ImportType, PerNsGlobImports}
,
35 self, Fields
, FileItemTreeId
, ImportKind
, ItemTree
, ItemTreeId
, ItemTreeNode
, MacroCall
,
36 MacroDef
, MacroRules
, Mod
, ModItem
, ModKind
, TreeId
,
38 macro_call_as_call_id
, macro_id_to_def_id
,
40 diagnostics
::DefDiagnostic
,
41 mod_resolution
::ModDir
,
42 path_resolution
::ReachedFixedPoint
,
43 proc_macro
::{ProcMacroDef, ProcMacroKind}
,
44 BuiltinShadowMode
, DefMap
, ModuleData
, ModuleOrigin
, ResolveMode
,
46 path
::{ImportAlias, ModPath, PathKind}
,
48 visibility
::{RawVisibility, Visibility}
,
49 AdtId
, AstId
, AstIdWithPath
, ConstLoc
, EnumLoc
, EnumVariantId
, ExternBlockLoc
, FunctionId
,
50 FunctionLoc
, ImplLoc
, Intern
, ItemContainerId
, LocalModuleId
, Macro2Id
, Macro2Loc
,
51 MacroExpander
, MacroId
, MacroRulesId
, MacroRulesLoc
, ModuleDefId
, ModuleId
, ProcMacroId
,
52 ProcMacroLoc
, StaticLoc
, StructLoc
, TraitLoc
, TypeAliasLoc
, UnionLoc
, UnresolvedMacro
,
55 static GLOB_RECURSION_LIMIT
: Limit
= Limit
::new(100);
56 static EXPANSION_DEPTH_LIMIT
: Limit
= Limit
::new(128);
57 static FIXED_POINT_LIMIT
: Limit
= Limit
::new(8192);
59 pub(super) fn collect_defs(db
: &dyn DefDatabase
, mut def_map
: DefMap
, tree_id
: TreeId
) -> DefMap
{
60 let crate_graph
= db
.crate_graph();
62 let mut deps
= FxHashMap
::default();
63 // populate external prelude and dependency list
64 let krate
= &crate_graph
[def_map
.krate
];
65 for dep
in &krate
.dependencies
{
66 tracing
::debug
!("crate dep {:?} -> {:?}", dep
.name
, dep
.crate_id
);
67 let dep_def_map
= db
.crate_def_map(dep
.crate_id
);
68 let dep_root
= dep_def_map
.module_id(dep_def_map
.root
);
70 deps
.insert(dep
.as_name(), dep_root
.into());
72 if dep
.is_prelude() && !tree_id
.is_block() {
73 def_map
.extern_prelude
.insert(dep
.as_name(), dep_root
);
77 let cfg_options
= &krate
.cfg_options
;
78 let proc_macros
= match &krate
.proc_macro
{
84 // FIXME: a hacky way to create a Name from string.
85 let name
= tt
::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() }
;
88 ProcMacroExpander
::new(def_map
.krate
, base_db
::ProcMacroId(idx
as u32)),
94 def_map
.proc_macro_loading_error
= Some(e
.clone().into_boxed_str());
98 let is_proc_macro
= krate
.is_proc_macro
;
100 let mut collector
= DefCollector
{
104 glob_imports
: FxHashMap
::default(),
105 unresolved_imports
: Vec
::new(),
106 indeterminate_imports
: Vec
::new(),
107 unresolved_macros
: Vec
::new(),
108 mod_dirs
: FxHashMap
::default(),
111 from_glob_import
: Default
::default(),
112 skip_attrs
: Default
::default(),
115 if tree_id
.is_block() {
116 collector
.seed_with_inner(tree_id
);
118 collector
.seed_with_top_level();
121 let mut def_map
= collector
.finish();
122 def_map
.shrink_to_fit();
126 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
127 enum PartialResolvedImport
{
128 /// None of any namespaces is resolved
130 /// One of namespaces is resolved
131 Indeterminate(PerNs
),
132 /// All namespaces are resolved, OR it comes from other crate
136 impl PartialResolvedImport
{
137 fn namespaces(self) -> PerNs
{
139 PartialResolvedImport
::Unresolved
=> PerNs
::none(),
140 PartialResolvedImport
::Indeterminate(ns
) | PartialResolvedImport
::Resolved(ns
) => ns
,
145 #[derive(Clone, Debug, Eq, PartialEq)]
147 Import { id: ItemTreeId<item_tree::Import>, use_tree: Idx<ast::UseTree> }
,
148 ExternCrate(ItemTreeId
<item_tree
::ExternCrate
>),
151 #[derive(Debug, Eq, PartialEq)]
154 alias
: Option
<ImportAlias
>,
155 visibility
: RawVisibility
,
158 is_extern_crate
: bool
,
160 source
: ImportSource
,
165 db
: &dyn DefDatabase
,
168 id
: ItemTreeId
<item_tree
::Import
>,
170 let it
= &tree
[id
.value
];
171 let attrs
= &tree
.attrs(db
, krate
, ModItem
::from(id
.value
).into());
172 let visibility
= &tree
[it
.visibility
];
173 let is_prelude
= attrs
.by_key("prelude_import").exists();
175 let mut res
= Vec
::new();
176 it
.use_tree
.expand(|idx
, path
, kind
, alias
| {
180 visibility
: visibility
.clone(),
183 is_extern_crate
: false,
185 source
: ImportSource
::Import { id, use_tree: idx }
,
191 fn from_extern_crate(
192 db
: &dyn DefDatabase
,
195 id
: ItemTreeId
<item_tree
::ExternCrate
>,
197 let it
= &tree
[id
.value
];
198 let attrs
= &tree
.attrs(db
, krate
, ModItem
::from(id
.value
).into());
199 let visibility
= &tree
[it
.visibility
];
201 path
: ModPath
::from_segments(PathKind
::Plain
, iter
::once(it
.name
.clone())),
202 alias
: it
.alias
.clone(),
203 visibility
: visibility
.clone(),
204 kind
: ImportKind
::Plain
,
206 is_extern_crate
: true,
207 is_macro_use
: attrs
.by_key("macro_use").exists(),
208 source
: ImportSource
::ExternCrate(id
),
213 #[derive(Debug, Eq, PartialEq)]
214 struct ImportDirective
{
215 module_id
: LocalModuleId
,
217 status
: PartialResolvedImport
,
220 #[derive(Clone, Debug, Eq, PartialEq)]
221 struct MacroDirective
{
222 module_id
: LocalModuleId
,
224 kind
: MacroDirectiveKind
,
225 container
: ItemContainerId
,
228 #[derive(Clone, Debug, Eq, PartialEq)]
229 enum MacroDirectiveKind
{
230 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo }
,
231 Derive { ast_id: AstIdWithPath<ast::Adt>, derive_attr: AttrId, derive_pos: usize }
,
232 Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem, tree: TreeId }
,
235 /// Walks the tree of module recursively
236 struct DefCollector
<'a
> {
237 db
: &'a
dyn DefDatabase
,
239 deps
: FxHashMap
<Name
, ModuleId
>,
240 glob_imports
: FxHashMap
<LocalModuleId
, Vec
<(LocalModuleId
, Visibility
)>>,
241 unresolved_imports
: Vec
<ImportDirective
>,
242 indeterminate_imports
: Vec
<ImportDirective
>,
243 unresolved_macros
: Vec
<MacroDirective
>,
244 mod_dirs
: FxHashMap
<LocalModuleId
, ModDir
>,
245 cfg_options
: &'a CfgOptions
,
246 /// List of procedural macros defined by this crate. This is read from the dynamic library
247 /// built by the build system, and is the list of proc. macros we can actually expand. It is
248 /// empty when proc. macro support is disabled (in which case we still do name resolution for
250 proc_macros
: Vec
<(Name
, ProcMacroExpander
)>,
252 from_glob_import
: PerNsGlobImports
,
253 /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute.
254 /// This map is used to skip all attributes up to and including the one that failed to resolve,
255 /// in order to not expand them twice.
257 /// This also stores the attributes to skip when we resolve derive helpers and non-macro
258 /// non-builtin attributes in general.
259 skip_attrs
: FxHashMap
<InFile
<ModItem
>, AttrId
>,
262 impl DefCollector
<'_
> {
263 fn seed_with_top_level(&mut self) {
264 let _p
= profile
::span("seed_with_top_level");
266 let file_id
= self.db
.crate_graph()[self.def_map
.krate
].root_file_id
;
267 let item_tree
= self.db
.file_item_tree(file_id
.into());
268 let module_id
= self.def_map
.root
;
270 let attrs
= item_tree
.top_level_attrs(self.db
, self.def_map
.krate
);
271 if attrs
.cfg().map_or(true, |cfg
| self.cfg_options
.check(&cfg
) != Some(false)) {
272 self.inject_prelude(&attrs
);
274 // Process other crate-level attributes.
275 for attr
in &*attrs
{
276 let attr_name
= match attr
.path
.as_ident() {
281 if *attr_name
== hir_expand
::name
![recursion_limit
] {
282 if let Some(limit
) = attr
.string_value() {
283 if let Ok(limit
) = limit
.parse() {
284 self.def_map
.recursion_limit
= Some(limit
);
290 if *attr_name
== hir_expand
::name
![crate_type
] {
291 if let Some("proc-macro") = attr
.string_value().map(SmolStr
::as_str
) {
292 self.is_proc_macro
= true;
297 if *attr_name
== hir_expand
::name
![feature
] {
299 attr
.parse_path_comma_token_tree().into_iter().flatten().filter_map(
300 |feat
| match feat
.segments() {
301 [name
] => Some(name
.to_smol_str()),
305 self.def_map
.unstable_features
.extend(features
);
308 let attr_is_register_like
= *attr_name
== hir_expand
::name
![register_attr
]
309 || *attr_name
== hir_expand
::name
![register_tool
];
310 if !attr_is_register_like
{
314 let registered_name
= match attr
.single_ident_value() {
315 Some(ident
) => ident
.as_name(),
319 if *attr_name
== hir_expand
::name
![register_attr
] {
320 self.def_map
.registered_attrs
.push(registered_name
.to_smol_str());
321 cov_mark
::hit
!(register_attr
);
323 self.def_map
.registered_tools
.push(registered_name
.to_smol_str());
324 cov_mark
::hit
!(register_tool
);
332 tree_id
: TreeId
::new(file_id
.into(), None
),
333 item_tree
: &item_tree
,
334 mod_dir
: ModDir
::root(),
336 .collect_in_top_module(item_tree
.top_level_items());
340 fn seed_with_inner(&mut self, tree_id
: TreeId
) {
341 let item_tree
= tree_id
.item_tree(self.db
);
342 let module_id
= self.def_map
.root
;
344 let is_cfg_enabled
= item_tree
345 .top_level_attrs(self.db
, self.def_map
.krate
)
347 .map_or(true, |cfg
| self.cfg_options
.check(&cfg
) != Some(false));
354 item_tree
: &item_tree
,
355 mod_dir
: ModDir
::root(),
357 .collect_in_top_module(item_tree
.top_level_items());
361 fn resolution_loop(&mut self) {
362 let _p
= profile
::span("DefCollector::resolution_loop");
364 // main name resolution fixed-point loop.
366 'resolve_attr
: loop {
367 'resolve_macros
: loop {
368 self.db
.unwind_if_cancelled();
371 let _p
= profile
::span("resolve_imports loop");
373 'resolve_imports
: loop {
374 if self.resolve_imports() == ReachedFixedPoint
::Yes
{
375 break 'resolve_imports
;
379 if self.resolve_macros() == ReachedFixedPoint
::Yes
{
380 break 'resolve_macros
;
384 if FIXED_POINT_LIMIT
.check(i
).is_err() {
385 tracing
::error
!("name resolution is stuck");
390 if self.reseed_with_unresolved_attribute() == ReachedFixedPoint
::Yes
{
396 fn collect(&mut self) {
397 let _p
= profile
::span("DefCollector::collect");
399 self.resolution_loop();
401 // Resolve all indeterminate resolved imports again
402 // As some of the macros will expand newly import shadowing partial resolved imports
403 // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
405 let partial_resolved
= self.indeterminate_imports
.drain(..).map(|directive
| {
406 ImportDirective { status: PartialResolvedImport::Unresolved, ..directive }
408 self.unresolved_imports
.extend(partial_resolved
);
409 self.resolve_imports();
411 let unresolved_imports
= mem
::take(&mut self.unresolved_imports
);
412 // show unresolved imports in completion, etc
413 for directive
in &unresolved_imports
{
414 self.record_resolved_import(directive
);
416 self.unresolved_imports
= unresolved_imports
;
418 if self.is_proc_macro
{
419 // A crate exporting procedural macros is not allowed to export anything else.
421 // Additionally, while the proc macro entry points must be `pub`, they are not publicly
422 // exported in type/value namespace. This function reduces the visibility of all items
423 // in the crate root that aren't proc macros.
424 let root
= self.def_map
.root
;
425 let module_id
= self.def_map
.module_id(root
);
426 let root
= &mut self.def_map
.modules
[root
];
427 root
.scope
.censor_non_proc_macros(module_id
);
431 /// When the fixed-point loop reaches a stable state, we might still have
432 /// some unresolved attributes left over. This takes one of them, and feeds
433 /// the item it's applied to back into name resolution.
435 /// This effectively ignores the fact that the macro is there and just treats the items as
438 /// This improves UX for unresolved attributes, and replicates the
439 /// behavior before we supported proc. attribute macros.
440 fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint
{
441 cov_mark
::hit
!(unresolved_attribute_fallback
);
443 let unresolved_attr
=
444 self.unresolved_macros
.iter().enumerate().find_map(|(idx
, directive
)| match &directive
447 MacroDirectiveKind
::Attr { ast_id, mod_item, attr, tree }
=> {
448 self.def_map
.diagnostics
.push(DefDiagnostic
::unresolved_macro_call(
450 MacroCallKind
::Attr
{
451 ast_id
: ast_id
.ast_id
,
452 attr_args
: Default
::default(),
453 invoc_attr_index
: attr
.id
.ast_index
,
459 self.skip_attrs
.insert(ast_id
.ast_id
.with_value(*mod_item
), attr
.id
);
461 Some((idx
, directive
, *mod_item
, *tree
))
466 match unresolved_attr
{
467 Some((pos
, &MacroDirective { module_id, depth, container, .. }
, mod_item
, tree_id
)) => {
468 let item_tree
= &tree_id
.item_tree(self.db
);
469 let mod_dir
= self.mod_dirs
[&module_id
].clone();
478 .collect(&[mod_item
], container
);
480 self.unresolved_macros
.swap_remove(pos
);
481 // Continue name resolution with the new data.
482 ReachedFixedPoint
::No
484 None
=> ReachedFixedPoint
::Yes
,
488 fn inject_prelude(&mut self, crate_attrs
: &Attrs
) {
489 // See compiler/rustc_builtin_macros/src/standard_library_imports.rs
491 if crate_attrs
.by_key("no_core").exists() {
492 // libcore does not get a prelude.
496 let krate
= if crate_attrs
.by_key("no_std").exists() {
499 let std
= name
![std
];
500 if self.def_map
.extern_prelude().any(|(name
, _
)| *name
== std
) {
503 // If `std` does not exist for some reason, fall back to core. This mostly helps
504 // keep r-a's own tests minimal.
509 let edition
= match self.def_map
.edition
{
510 Edition
::Edition2015
=> name
![rust_2015
],
511 Edition
::Edition2018
=> name
![rust_2018
],
512 Edition
::Edition2021
=> name
![rust_2021
],
515 let path_kind
= match self.def_map
.edition
{
516 Edition
::Edition2015
=> PathKind
::Plain
,
520 ModPath
::from_segments(path_kind
, [krate
.clone(), name
![prelude
], edition
].into_iter());
521 // Fall back to the older `std::prelude::v1` for compatibility with Rust <1.52.0
522 // FIXME remove this fallback
524 ModPath
::from_segments(path_kind
, [krate
, name
![prelude
], name
![v1
]].into_iter());
526 for path
in &[path
, fallback_path
] {
527 let (per_ns
, _
) = self.def_map
.resolve_path(
531 BuiltinShadowMode
::Other
,
535 Some((ModuleDefId
::ModuleId(m
), _
)) => {
536 self.def_map
.prelude
= Some(m
);
540 "could not resolve prelude path `{}` to module (resolved to {:?})",
549 /// Adds a definition of procedural macro `name` to the root module.
551 /// # Notes on procedural macro resolution
553 /// Procedural macro functionality is provided by the build system: It has to build the proc
554 /// macro and pass the resulting dynamic library to rust-analyzer.
556 /// When procedural macro support is enabled, the list of proc macros exported by a crate is
557 /// known before we resolve names in the crate. This list is stored in `self.proc_macros` and is
558 /// derived from the dynamic library.
560 /// However, we *also* would like to be able to at least *resolve* macros on our own, without
561 /// help by the build system. So, when the macro isn't found in `self.proc_macros`, we instead
562 /// use a dummy expander that always errors. This comes with the drawback of macros potentially
563 /// going out of sync with what the build system sees (since we resolve using VFS state, but
564 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
565 fn export_proc_macro(
568 id
: ItemTreeId
<item_tree
::Function
>,
572 let kind
= def
.kind
.to_basedb_kind();
573 let (expander
, kind
) = match self.proc_macros
.iter().find(|(n
, _
)| n
== &def
.name
) {
574 Some(&(_
, expander
)) => (expander
, kind
),
575 None
=> (ProcMacroExpander
::dummy(self.def_map
.krate
), kind
),
579 ProcMacroLoc { container: module_id, id, expander, kind }
.intern(self.db
);
580 self.define_proc_macro(def
.name
.clone(), proc_macro_id
);
581 if let ProcMacroKind
::CustomDerive { helpers }
= def
.kind
{
584 .insert(macro_id_to_def_id(self.db
, proc_macro_id
.into()), helpers
);
586 self.def_map
.fn_proc_macro_mapping
.insert(fn_id
, proc_macro_id
);
589 /// Define a macro with `macro_rules`.
591 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
592 /// then it is also defined in the root module scope.
593 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
595 /// It is surprising that the macro will never be in the current module scope.
596 /// These code fails with "unresolved import/macro",
597 /// ```rust,compile_fail
598 /// mod m { macro_rules! foo { () => {} } }
599 /// use m::foo as bar;
602 /// ```rust,compile_fail
603 /// macro_rules! foo { () => {} }
608 /// Well, this code compiles, because the plain path `foo` in `use` is searched
609 /// in the legacy textual scope only.
611 /// macro_rules! foo { () => {} }
614 fn define_macro_rules(
616 module_id
: LocalModuleId
,
618 macro_
: MacroRulesId
,
622 self.define_legacy_macro(module_id
, name
.clone(), macro_
.into());
625 // In Rust, `#[macro_export]` macros are unconditionally visible at the
626 // crate root, even if the parent modules is **not** visible.
628 let module_id
= self.def_map
.root
;
629 self.def_map
.modules
[module_id
].scope
.declare(macro_
.into());
632 &[(Some(name
), PerNs
::macros(macro_
.into(), Visibility
::Public
))],
639 /// Define a legacy textual scoped macro in module
641 /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
642 /// It will clone all macros from parent legacy scope, whose definition is prior to
643 /// the definition of current module.
644 /// And also, `macro_use` on a module will import all legacy macros visible inside to
645 /// current legacy scope, with possible shadowing.
646 fn define_legacy_macro(&mut self, module_id
: LocalModuleId
, name
: Name
, mac
: MacroId
) {
648 self.def_map
.modules
[module_id
].scope
.define_legacy_macro(name
, mac
);
651 /// Define a macro 2.0 macro
653 /// The scoped of macro 2.0 macro is equal to normal function
656 module_id
: LocalModuleId
,
662 self.def_map
.resolve_visibility(self.db
, module_id
, vis
).unwrap_or(Visibility
::Public
);
663 self.def_map
.modules
[module_id
].scope
.declare(macro_
.into());
666 &[(Some(name
), PerNs
::macros(macro_
.into(), Visibility
::Public
))],
672 /// Define a proc macro
674 /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
675 /// And unconditionally exported.
676 fn define_proc_macro(&mut self, name
: Name
, macro_
: ProcMacroId
) {
677 let module_id
= self.def_map
.root
;
678 self.def_map
.modules
[module_id
].scope
.declare(macro_
.into());
681 &[(Some(name
), PerNs
::macros(macro_
.into(), Visibility
::Public
))],
687 /// Import macros from `#[macro_use] extern crate`.
688 fn import_macros_from_extern_crate(
690 current_module_id
: LocalModuleId
,
691 extern_crate
: &item_tree
::ExternCrate
,
694 "importing macros from extern crate: {:?} ({:?})",
696 self.def_map
.edition
,
699 if let Some(m
) = self.resolve_extern_crate(&extern_crate
.name
) {
700 if m
== self.def_map
.module_id(current_module_id
) {
701 cov_mark
::hit
!(ignore_macro_use_extern_crate_self
);
705 cov_mark
::hit
!(macro_rules_from_other_crates_are_visible_with_macro_use
);
706 self.import_all_macros_exported(current_module_id
, m
.krate
);
710 /// Import all exported macros from another crate
712 /// Exported macros are just all macros in the root module scope.
713 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
714 /// created by `use` in the root module, ignoring the visibility of `use`.
715 fn import_all_macros_exported(&mut self, current_module_id
: LocalModuleId
, krate
: CrateId
) {
716 let def_map
= self.db
.crate_def_map(krate
);
717 for (name
, def
) in def_map
[def_map
.root
].scope
.macros() {
718 // `#[macro_use]` brings macros into legacy scope. Yes, even non-`macro_rules!` macros.
719 self.define_legacy_macro(current_module_id
, name
.clone(), def
);
723 /// Tries to resolve every currently unresolved import.
724 fn resolve_imports(&mut self) -> ReachedFixedPoint
{
725 let mut res
= ReachedFixedPoint
::Yes
;
726 let imports
= mem
::take(&mut self.unresolved_imports
);
728 self.unresolved_imports
= imports
730 .filter_map(|mut directive
| {
731 directive
.status
= self.resolve_import(directive
.module_id
, &directive
.import
);
732 match directive
.status
{
733 PartialResolvedImport
::Indeterminate(_
) => {
734 self.record_resolved_import(&directive
);
735 self.indeterminate_imports
.push(directive
);
736 res
= ReachedFixedPoint
::No
;
739 PartialResolvedImport
::Resolved(_
) => {
740 self.record_resolved_import(&directive
);
741 res
= ReachedFixedPoint
::No
;
744 PartialResolvedImport
::Unresolved
=> Some(directive
),
751 fn resolve_import(&self, module_id
: LocalModuleId
, import
: &Import
) -> PartialResolvedImport
{
752 let _p
= profile
::span("resolve_import").detail(|| format
!("{}", import
.path
));
753 tracing
::debug
!("resolving import: {:?} ({:?})", import
, self.def_map
.edition
);
754 if import
.is_extern_crate
{
758 .expect("extern crate should have been desugared to one-element path");
760 let res
= self.resolve_extern_crate(name
);
764 PartialResolvedImport
::Resolved(PerNs
::types(res
.into(), Visibility
::Public
))
766 None
=> PartialResolvedImport
::Unresolved
,
769 let res
= self.def_map
.resolve_path_fp_with_macro(
774 BuiltinShadowMode
::Module
,
777 let def
= res
.resolved_def
;
778 if res
.reached_fixedpoint
== ReachedFixedPoint
::No
|| def
.is_none() {
779 return PartialResolvedImport
::Unresolved
;
782 if let Some(krate
) = res
.krate
{
783 if krate
!= self.def_map
.krate
{
784 return PartialResolvedImport
::Resolved(
785 def
.filter_visibility(|v
| matches
!(v
, Visibility
::Public
)),
790 // Check whether all namespace is resolved
791 if def
.take_types().is_some()
792 && def
.take_values().is_some()
793 && def
.take_macros().is_some()
795 PartialResolvedImport
::Resolved(def
)
797 PartialResolvedImport
::Indeterminate(def
)
802 fn resolve_extern_crate(&self, name
: &Name
) -> Option
<ModuleId
> {
803 if *name
== name
!(self) {
804 cov_mark
::hit
!(extern_crate_self_as
);
805 let root
= match self.def_map
.block
{
807 let def_map
= self.def_map
.crate_root(self.db
).def_map(self.db
);
808 def_map
.module_id(def_map
.root())
810 None
=> self.def_map
.module_id(self.def_map
.root()),
814 self.deps
.get(name
).copied()
818 fn record_resolved_import(&mut self, directive
: &ImportDirective
) {
819 let _p
= profile
::span("record_resolved_import");
821 let module_id
= directive
.module_id
;
822 let import
= &directive
.import
;
823 let mut def
= directive
.status
.namespaces();
826 .resolve_visibility(self.db
, module_id
, &directive
.import
.visibility
)
827 .unwrap_or(Visibility
::Public
);
830 ImportKind
::Plain
| ImportKind
::TypeOnly
=> {
831 let name
= match &import
.alias
{
832 Some(ImportAlias
::Alias(name
)) => Some(name
),
833 Some(ImportAlias
::Underscore
) => None
,
834 None
=> match import
.path
.segments().last() {
835 Some(last_segment
) => Some(last_segment
),
837 cov_mark
::hit
!(bogus_paths
);
843 if import
.kind
== ImportKind
::TypeOnly
{
848 tracing
::debug
!("resolved import {:?} ({:?}) to {:?}", name
, import
, def
);
850 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
851 if import
.is_extern_crate
852 && self.def_map
.block
.is_none()
853 && module_id
== self.def_map
.root
855 if let (Some(ModuleDefId
::ModuleId(def
)), Some(name
)) = (def
.take_types(), name
)
857 self.def_map
.extern_prelude
.insert(name
.clone(), def
);
861 self.update(module_id
, &[(name
.cloned(), def
)], vis
, ImportType
::Named
);
863 ImportKind
::Glob
=> {
864 tracing
::debug
!("glob import: {:?}", import
);
865 match def
.take_types() {
866 Some(ModuleDefId
::ModuleId(m
)) => {
867 if import
.is_prelude
{
868 // Note: This dodgily overrides the injected prelude. The rustc
869 // implementation seems to work the same though.
870 cov_mark
::hit
!(std_prelude
);
871 self.def_map
.prelude
= Some(m
);
872 } else if m
.krate
!= self.def_map
.krate
{
873 cov_mark
::hit
!(glob_across_crates
);
874 // glob import from other crate => we can just import everything once
875 let item_map
= m
.def_map(self.db
);
876 let scope
= &item_map
[m
.local_id
].scope
;
878 // Module scoped macros is included
881 // only keep visible names...
883 (n
, res
.filter_visibility(|v
| v
.is_visible_from_other_crate()))
885 .filter(|(_
, res
)| !res
.is_none())
886 .collect
::<Vec
<_
>>();
888 self.update(module_id
, &items
, vis
, ImportType
::Glob
);
890 // glob import from same crate => we do an initial
891 // import, and then need to propagate any further
894 let scope
= if m
.block
== self.def_map
.block_id() {
895 &self.def_map
[m
.local_id
].scope
897 def_map
= m
.def_map(self.db
);
898 &def_map
[m
.local_id
].scope
901 // Module scoped macros is included
904 // only keep visible names...
908 res
.filter_visibility(|v
| {
909 v
.is_visible_from_def_map(
917 .filter(|(_
, res
)| !res
.is_none())
918 .collect
::<Vec
<_
>>();
920 self.update(module_id
, &items
, vis
, ImportType
::Glob
);
921 // record the glob import in case we add further items
922 let glob
= self.glob_imports
.entry(m
.local_id
).or_default();
923 if !glob
.iter().any(|(mid
, _
)| *mid
== module_id
) {
924 glob
.push((module_id
, vis
));
928 Some(ModuleDefId
::AdtId(AdtId
::EnumId(e
))) => {
929 cov_mark
::hit
!(glob_enum
);
930 // glob import from enum => just import all the variants
932 // XXX: urgh, so this works by accident! Here, we look at
933 // the enum data, and, in theory, this might require us to
934 // look back at the crate_def_map, creating a cycle. For
935 // example, `enum E { crate::some_macro!(); }`. Luckily, the
936 // only kind of macro that is allowed inside enum is a
937 // `cfg_macro`, and we don't need to run name resolution for
938 // it, but this is sheer luck!
939 let enum_data
= self.db
.enum_data(e
);
940 let resolutions
= enum_data
943 .map(|(local_id
, variant_data
)| {
944 let name
= variant_data
.name
.clone();
945 let variant
= EnumVariantId { parent: e, local_id }
;
946 let res
= PerNs
::both(variant
.into(), variant
.into(), vis
);
949 .collect
::<Vec
<_
>>();
950 self.update(module_id
, &resolutions
, vis
, ImportType
::Glob
);
953 tracing
::debug
!("glob import {:?} from non-module/enum {:?}", import
, d
);
956 tracing
::debug
!("glob import {:?} didn't resolve as type", import
);
965 module_id
: LocalModuleId
,
966 resolutions
: &[(Option
<Name
>, PerNs
)],
968 import_type
: ImportType
,
970 self.db
.unwind_if_cancelled();
971 self.update_recursive(module_id
, resolutions
, vis
, import_type
, 0)
976 module_id
: LocalModuleId
,
977 resolutions
: &[(Option
<Name
>, PerNs
)],
978 // All resolutions are imported with this visibility; the visibilities in
979 // the `PerNs` values are ignored and overwritten
981 import_type
: ImportType
,
984 if GLOB_RECURSION_LIMIT
.check(depth
).is_err() {
985 // prevent stack overflows (but this shouldn't be possible)
986 panic
!("infinite recursion in glob imports!");
988 let mut changed
= false;
990 for (name
, res
) in resolutions
{
993 let scope
= &mut self.def_map
.modules
[module_id
].scope
;
994 changed
|= scope
.push_res_with_import(
995 &mut self.from_glob_import
,
996 (module_id
, name
.clone()),
997 res
.with_visibility(vis
),
1002 let tr
= match res
.take_types() {
1003 Some(ModuleDefId
::TraitId(tr
)) => tr
,
1005 tracing
::debug
!("non-trait `_` import of {:?}", other
);
1010 let old_vis
= self.def_map
.modules
[module_id
].scope
.unnamed_trait_vis(tr
);
1011 let should_update
= match old_vis
{
1014 let max_vis
= old_vis
.max(vis
, &self.def_map
).unwrap_or_else(|| {
1015 panic
!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis
, vis
, tr
);
1018 if max_vis
== old_vis
{
1021 cov_mark
::hit
!(upgrade_underscore_visibility
);
1029 self.def_map
.modules
[module_id
].scope
.push_unnamed_trait(tr
, vis
);
1038 let glob_imports
= self
1043 .filter(|(glob_importing_module
, _
)| {
1044 // we know all resolutions have the same visibility (`vis`), so we
1045 // just need to check that once
1046 vis
.is_visible_from_def_map(self.db
, &self.def_map
, *glob_importing_module
)
1049 .collect
::<Vec
<_
>>();
1051 for (glob_importing_module
, glob_import_vis
) in glob_imports
{
1052 self.update_recursive(
1053 glob_importing_module
,
1062 fn resolve_macros(&mut self) -> ReachedFixedPoint
{
1063 let mut macros
= mem
::take(&mut self.unresolved_macros
);
1064 let mut resolved
= Vec
::new();
1065 let mut push_resolved
= |directive
: &MacroDirective
, call_id
| {
1066 resolved
.push((directive
.module_id
, directive
.depth
, directive
.container
, call_id
));
1068 let mut res
= ReachedFixedPoint
::Yes
;
1069 macros
.retain(|directive
| {
1070 let resolver
= |path
| {
1071 let resolved_res
= self.def_map
.resolve_path_fp_with_macro(
1074 directive
.module_id
,
1076 BuiltinShadowMode
::Module
,
1081 .map(|it
| (it
, macro_id_to_def_id(self.db
, it
)))
1083 let resolver_def_id
= |path
| resolver(path
).map(|(_
, it
)| it
);
1085 match &directive
.kind
{
1086 MacroDirectiveKind
::FnLike { ast_id, expand_to }
=> {
1087 let call_id
= macro_call_as_call_id(
1095 if let Ok(Ok(call_id
)) = call_id
{
1096 push_resolved(directive
, call_id
);
1097 res
= ReachedFixedPoint
::No
;
1101 MacroDirectiveKind
::Derive { ast_id, derive_attr, derive_pos }
=> {
1102 let id
= derive_macro_as_call_id(
1111 if let Ok((macro_id
, def_id
, call_id
)) = id
{
1112 self.def_map
.modules
[directive
.module_id
].scope
.set_derive_macro_invoc(
1118 // Record its helper attributes.
1119 if def_id
.krate
!= self.def_map
.krate
{
1120 let def_map
= self.db
.crate_def_map(def_id
.krate
);
1121 if let Some(helpers
) = def_map
.exported_derives
.get(&def_id
) {
1123 .derive_helpers_in_scope
1124 .entry(ast_id
.ast_id
.map(|it
| it
.upcast()))
1127 helpers
.iter().cloned(),
1128 iter
::repeat(macro_id
),
1129 iter
::repeat(call_id
),
1134 push_resolved(directive
, call_id
);
1135 res
= ReachedFixedPoint
::No
;
1139 MacroDirectiveKind
::Attr { ast_id: file_ast_id, mod_item, attr, tree }
=> {
1140 let &AstIdWithPath { ast_id, ref path }
= file_ast_id
;
1141 let file_id
= ast_id
.file_id
;
1143 let mut recollect_without
= |collector
: &mut Self| {
1144 // Remove the original directive since we resolved it.
1145 let mod_dir
= collector
.mod_dirs
[&directive
.module_id
].clone();
1146 collector
.skip_attrs
.insert(InFile
::new(file_id
, *mod_item
), attr
.id
);
1148 let item_tree
= tree
.item_tree(self.db
);
1150 def_collector
: collector
,
1151 macro_depth
: directive
.depth
,
1152 module_id
: directive
.module_id
,
1154 item_tree
: &item_tree
,
1157 .collect(&[*mod_item
], directive
.container
);
1158 res
= ReachedFixedPoint
::No
;
1162 if let Some(ident
) = path
.as_ident() {
1163 if let Some(helpers
) = self.def_map
.derive_helpers_in_scope
.get(&ast_id
) {
1164 if helpers
.iter().any(|(it
, ..)| it
== ident
) {
1165 cov_mark
::hit
!(resolved_derive_helper
);
1166 // Resolved to derive helper. Collect the item's attributes again,
1167 // starting after the derive helper.
1168 return recollect_without(self);
1173 let def
= match resolver_def_id(path
.clone()) {
1174 Some(def
) if def
.is_attribute() => def
,
1179 MacroDefId { kind:MacroDefKind::BuiltInAttr(expander, _),.. }
1180 if expander
.is_derive()
1182 // Resolved to `#[derive]`
1184 let item_tree
= tree
.item_tree(self.db
);
1185 let ast_adt_id
: FileAstId
<ast
::Adt
> = match *mod_item
{
1186 ModItem
::Struct(strukt
) => item_tree
[strukt
].ast_id().upcast(),
1187 ModItem
::Union(union) => item_tree
[union].ast_id().upcast(),
1188 ModItem
::Enum(enum_
) => item_tree
[enum_
].ast_id().upcast(),
1190 let diag
= DefDiagnostic
::invalid_derive_target(
1191 directive
.module_id
,
1195 self.def_map
.diagnostics
.push(diag
);
1196 return recollect_without(self);
1199 let ast_id
= ast_id
.with_value(ast_adt_id
);
1201 match attr
.parse_path_comma_token_tree() {
1202 Some(derive_macros
) => {
1204 for (idx
, path
) in derive_macros
.enumerate() {
1205 let ast_id
= AstIdWithPath
::new(file_id
, ast_id
.value
, path
);
1206 self.unresolved_macros
.push(MacroDirective
{
1207 module_id
: directive
.module_id
,
1208 depth
: directive
.depth
+ 1,
1209 kind
: MacroDirectiveKind
::Derive
{
1211 derive_attr
: attr
.id
,
1214 container
: directive
.container
,
1219 // We treat the #[derive] macro as an attribute call, but we do not resolve it for nameres collection.
1220 // This is just a trick to be able to resolve the input to derives as proper paths.
1221 // Check the comment in [`builtin_attr_macro`].
1222 let call_id
= attr_macro_as_call_id(
1230 self.def_map
.modules
[directive
.module_id
]
1232 .init_derive_attribute(ast_id
, attr
.id
, call_id
, len
+ 1);
1235 let diag
= DefDiagnostic
::malformed_derive(
1236 directive
.module_id
,
1240 self.def_map
.diagnostics
.push(diag
);
1244 return recollect_without(self);
1247 // Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
1248 let call_id
= attr_macro_as_call_id(
1256 let loc
: MacroCallLoc
= self.db
.lookup_intern_macro_call(call_id
);
1258 // If proc attribute macro expansion is disabled, skip expanding it here
1259 if !self.db
.enable_proc_attr_macros() {
1260 self.def_map
.diagnostics
.push(DefDiagnostic
::unresolved_proc_macro(
1261 directive
.module_id
,
1265 return recollect_without(self);
1268 // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
1269 // due to duplicating functions into macro expansions
1272 MacroDefKind
::BuiltInAttr(expander
, _
)
1273 if expander
.is_test() || expander
.is_bench()
1275 return recollect_without(self);
1278 if let MacroDefKind
::ProcMacro(exp
, ..) = loc
.def
.kind
{
1280 // If there's no expander for the proc macro (e.g.
1281 // because proc macros are disabled, or building the
1282 // proc macro crate failed), report this and skip
1283 // expansion like we would if it was disabled
1284 self.def_map
.diagnostics
.push(DefDiagnostic
::unresolved_proc_macro(
1285 directive
.module_id
,
1290 return recollect_without(self);
1294 self.def_map
.modules
[directive
.module_id
]
1296 .add_attr_macro_invoc(ast_id
, call_id
);
1298 push_resolved(directive
, call_id
);
1299 res
= ReachedFixedPoint
::No
;
1306 // Attribute resolution can add unresolved macro invocations, so concatenate the lists.
1307 macros
.extend(mem
::take(&mut self.unresolved_macros
));
1308 self.unresolved_macros
= macros
;
1310 for (module_id
, depth
, container
, macro_call_id
) in resolved
{
1311 self.collect_macro_expansion(module_id
, macro_call_id
, depth
, container
);
1317 fn collect_macro_expansion(
1319 module_id
: LocalModuleId
,
1320 macro_call_id
: MacroCallId
,
1322 container
: ItemContainerId
,
1324 if EXPANSION_DEPTH_LIMIT
.check(depth
).is_err() {
1325 cov_mark
::hit
!(macro_expansion_overflow
);
1326 tracing
::warn
!("macro expansion is too deep");
1329 let file_id
= macro_call_id
.as_file();
1331 // First, fetch the raw expansion result for purposes of error reporting. This goes through
1332 // `macro_expand_error` to avoid depending on the full expansion result (to improve
1334 let loc
: MacroCallLoc
= self.db
.lookup_intern_macro_call(macro_call_id
);
1335 let err
= self.db
.macro_expand_error(macro_call_id
);
1336 if let Some(err
) = err
{
1337 let diag
= match err
{
1338 hir_expand
::ExpandError
::UnresolvedProcMacro(krate
) => {
1339 always
!(krate
== loc
.def
.krate
);
1340 // Missing proc macros are non-fatal, so they are handled specially.
1341 DefDiagnostic
::unresolved_proc_macro(module_id
, loc
.kind
.clone(), loc
.def
.krate
)
1343 _
=> DefDiagnostic
::macro_error(module_id
, loc
.kind
.clone(), err
.to_string()),
1346 self.def_map
.diagnostics
.push(diag
);
1349 // Then, fetch and process the item tree. This will reuse the expansion result from above.
1350 let item_tree
= self.db
.file_item_tree(file_id
);
1351 let mod_dir
= self.mod_dirs
[&module_id
].clone();
1353 def_collector
: &mut *self,
1355 tree_id
: TreeId
::new(file_id
, None
),
1357 item_tree
: &item_tree
,
1360 .collect(item_tree
.top_level_items(), container
);
1363 fn finish(mut self) -> DefMap
{
1364 // Emit diagnostics for all remaining unexpanded macros.
1366 let _p
= profile
::span("DefCollector::finish");
1368 for directive
in &self.unresolved_macros
{
1369 match &directive
.kind
{
1370 MacroDirectiveKind
::FnLike { ast_id, expand_to }
=> {
1371 let macro_call_as_call_id
= macro_call_as_call_id(
1377 let resolved_res
= self.def_map
.resolve_path_fp_with_macro(
1380 directive
.module_id
,
1382 BuiltinShadowMode
::Module
,
1387 .map(|it
| macro_id_to_def_id(self.db
, it
))
1391 if let Err(UnresolvedMacro { path }
) = macro_call_as_call_id
{
1392 self.def_map
.diagnostics
.push(DefDiagnostic
::unresolved_macro_call(
1393 directive
.module_id
,
1394 MacroCallKind
::FnLike { ast_id: ast_id.ast_id, expand_to: *expand_to }
,
1399 MacroDirectiveKind
::Derive { ast_id, derive_attr, derive_pos }
=> {
1400 self.def_map
.diagnostics
.push(DefDiagnostic
::unresolved_macro_call(
1401 directive
.module_id
,
1402 MacroCallKind
::Derive
{
1403 ast_id
: ast_id
.ast_id
,
1404 derive_attr_index
: derive_attr
.ast_index
,
1405 derive_index
: *derive_pos
as u32,
1407 ast_id
.path
.clone(),
1410 // These are diagnosed by `reseed_with_unresolved_attribute`, as that function consumes them
1411 MacroDirectiveKind
::Attr { .. }
=> {}
1415 // Emit diagnostics for all remaining unresolved imports.
1417 // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
1418 // resolve. We first emit diagnostics for unresolved extern crates and collect the missing
1419 // crate names. Then we emit diagnostics for unresolved imports, but only if the import
1420 // doesn't start with an unresolved crate's name. Due to renaming and reexports, this is a
1421 // heuristic, but it works in practice.
1422 let mut diagnosed_extern_crates
= FxHashSet
::default();
1423 for directive
in &self.unresolved_imports
{
1424 if let ImportSource
::ExternCrate(krate
) = directive
.import
.source
{
1425 let item_tree
= krate
.item_tree(self.db
);
1426 let extern_crate
= &item_tree
[krate
.value
];
1428 diagnosed_extern_crates
.insert(extern_crate
.name
.clone());
1430 self.def_map
.diagnostics
.push(DefDiagnostic
::unresolved_extern_crate(
1431 directive
.module_id
,
1432 InFile
::new(krate
.file_id(), extern_crate
.ast_id
),
1437 for directive
in &self.unresolved_imports
{
1438 if let ImportSource
::Import { id: import, use_tree }
= directive
.import
.source
{
1440 (directive
.import
.path
.segments().first(), &directive
.import
.path
.kind
),
1441 (Some(krate
), PathKind
::Plain
| PathKind
::Abs
) if diagnosed_extern_crates
.contains(krate
)
1446 self.def_map
.diagnostics
.push(DefDiagnostic
::unresolved_import(
1447 directive
.module_id
,
1458 /// Walks a single module, populating defs, imports and macros
1459 struct ModCollector
<'a
, 'b
> {
1460 def_collector
: &'a
mut DefCollector
<'b
>,
1462 module_id
: LocalModuleId
,
1464 item_tree
: &'a ItemTree
,
1468 impl ModCollector
<'_
, '_
> {
1469 fn collect_in_top_module(&mut self, items
: &[ModItem
]) {
1470 let module
= self.def_collector
.def_map
.module_id(self.module_id
);
1471 self.collect(items
, module
.into())
1474 fn collect(&mut self, items
: &[ModItem
], container
: ItemContainerId
) {
1475 let krate
= self.def_collector
.def_map
.krate
;
1477 // Note: don't assert that inserted value is fresh: it's simply not true
1479 self.def_collector
.mod_dirs
.insert(self.module_id
, self.mod_dir
.clone());
1481 // Prelude module is always considered to be `#[macro_use]`.
1482 if let Some(prelude_module
) = self.def_collector
.def_map
.prelude
{
1483 if prelude_module
.krate
!= krate
{
1484 cov_mark
::hit
!(prelude_is_macro_use
);
1485 self.def_collector
.import_all_macros_exported(self.module_id
, prelude_module
.krate
);
1489 // This should be processed eagerly instead of deferred to resolving.
1490 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
1492 for &item
in items
{
1493 let attrs
= self.item_tree
.attrs(self.def_collector
.db
, krate
, item
.into());
1494 if attrs
.cfg().map_or(true, |cfg
| self.is_cfg_enabled(&cfg
)) {
1495 if let ModItem
::ExternCrate(id
) = item
{
1496 let import
= &self.item_tree
[id
];
1497 let attrs
= self.item_tree
.attrs(
1498 self.def_collector
.db
,
1500 ModItem
::from(id
).into(),
1502 if attrs
.by_key("macro_use").exists() {
1503 self.def_collector
.import_macros_from_extern_crate(self.module_id
, import
);
1509 for &item
in items
{
1510 let attrs
= self.item_tree
.attrs(self.def_collector
.db
, krate
, item
.into());
1511 if let Some(cfg
) = attrs
.cfg() {
1512 if !self.is_cfg_enabled(&cfg
) {
1513 self.emit_unconfigured_diagnostic(item
, &cfg
);
1518 if let Err(()) = self.resolve_attributes(&attrs
, item
, container
) {
1519 // Do not process the item. It has at least one non-builtin attribute, so the
1520 // fixed-point algorithm is required to resolve the rest of them.
1524 let db
= self.def_collector
.db
;
1525 let module
= self.def_collector
.def_map
.module_id(self.module_id
);
1526 let def_map
= &mut self.def_collector
.def_map
;
1528 |def_collector
: &mut DefCollector
<'_
>, id
, name
: &Name
, vis
, has_constructor
| {
1529 def_collector
.def_map
.modules
[self.module_id
].scope
.declare(id
);
1530 def_collector
.update(
1532 &[(Some(name
.clone()), PerNs
::from_def(id
, vis
, has_constructor
))],
1537 let resolve_vis
= |def_map
: &DefMap
, visibility
| {
1539 .resolve_visibility(db
, self.module_id
, visibility
)
1540 .unwrap_or(Visibility
::Public
)
1544 ModItem
::Mod(m
) => self.collect_module(m
, &attrs
),
1545 ModItem
::Import(import_id
) => {
1546 let imports
= Import
::from_use(
1550 ItemTreeId
::new(self.tree_id
, import_id
),
1552 self.def_collector
.unresolved_imports
.extend(imports
.into_iter().map(
1553 |import
| ImportDirective
{
1554 module_id
: self.module_id
,
1556 status
: PartialResolvedImport
::Unresolved
,
1560 ModItem
::ExternCrate(import_id
) => {
1561 self.def_collector
.unresolved_imports
.push(ImportDirective
{
1562 module_id
: self.module_id
,
1563 import
: Import
::from_extern_crate(
1567 ItemTreeId
::new(self.tree_id
, import_id
),
1569 status
: PartialResolvedImport
::Unresolved
,
1572 ModItem
::ExternBlock(block
) => self.collect(
1573 &self.item_tree
[block
].children
,
1574 ItemContainerId
::ExternBlockId(
1577 id
: ItemTreeId
::new(self.tree_id
, block
),
1582 ModItem
::MacroCall(mac
) => self.collect_macro_call(&self.item_tree
[mac
], container
),
1583 ModItem
::MacroRules(id
) => self.collect_macro_rules(id
, module
),
1584 ModItem
::MacroDef(id
) => self.collect_macro_def(id
, module
),
1585 ModItem
::Impl(imp
) => {
1587 ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) }
1589 self.def_collector
.def_map
.modules
[self.module_id
].scope
.define_impl(impl_id
)
1591 ModItem
::Function(id
) => {
1592 let it
= &self.item_tree
[id
];
1594 FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }
.intern(db
);
1596 let vis
= resolve_vis(def_map
, &self.item_tree
[it
.visibility
]);
1597 if self.def_collector
.is_proc_macro
{
1598 if self.module_id
== def_map
.root
{
1599 if let Some(proc_macro
) = attrs
.parse_proc_macro_decl(&it
.name
) {
1600 let crate_root
= def_map
.module_id(def_map
.root
);
1601 self.def_collector
.export_proc_macro(
1603 ItemTreeId
::new(self.tree_id
, id
),
1611 update_def(self.def_collector
, fn_id
.into(), &it
.name
, vis
, false);
1613 ModItem
::Struct(id
) => {
1614 let it
= &self.item_tree
[id
];
1616 let vis
= resolve_vis(def_map
, &self.item_tree
[it
.visibility
]);
1619 StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1624 !matches
!(it
.fields
, Fields
::Record(_
)),
1627 ModItem
::Union(id
) => {
1628 let it
= &self.item_tree
[id
];
1630 let vis
= resolve_vis(def_map
, &self.item_tree
[it
.visibility
]);
1633 UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1641 ModItem
::Enum(id
) => {
1642 let it
= &self.item_tree
[id
];
1644 let vis
= resolve_vis(def_map
, &self.item_tree
[it
.visibility
]);
1647 EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1655 ModItem
::Const(id
) => {
1656 let it
= &self.item_tree
[id
];
1658 ConstLoc { container, id: ItemTreeId::new(self.tree_id, id) }
.intern(db
);
1662 let vis
= resolve_vis(def_map
, &self.item_tree
[it
.visibility
]);
1663 update_def(self.def_collector
, const_id
.into(), name
, vis
, false);
1666 // const _: T = ...;
1667 self.def_collector
.def_map
.modules
[self.module_id
]
1669 .define_unnamed_const(const_id
);
1673 ModItem
::Static(id
) => {
1674 let it
= &self.item_tree
[id
];
1676 let vis
= resolve_vis(def_map
, &self.item_tree
[it
.visibility
]);
1679 StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
1687 ModItem
::Trait(id
) => {
1688 let it
= &self.item_tree
[id
];
1690 let vis
= resolve_vis(def_map
, &self.item_tree
[it
.visibility
]);
1693 TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1701 ModItem
::TypeAlias(id
) => {
1702 let it
= &self.item_tree
[id
];
1704 let vis
= resolve_vis(def_map
, &self.item_tree
[it
.visibility
]);
1707 TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
1719 fn collect_module(&mut self, module_id
: FileItemTreeId
<Mod
>, attrs
: &Attrs
) {
1720 let path_attr
= attrs
.by_key("path").string_value();
1721 let is_macro_use
= attrs
.by_key("macro_use").exists();
1722 let module
= &self.item_tree
[module_id
];
1723 match &module
.kind
{
1724 // inline module, just recurse
1725 ModKind
::Inline { items }
=> {
1726 let module_id
= self.push_child_module(
1727 module
.name
.clone(),
1728 AstId
::new(self.file_id(), module
.ast_id
),
1730 &self.item_tree
[module
.visibility
],
1734 if let Some(mod_dir
) = self.mod_dir
.descend_into_definition(&module
.name
, path_attr
)
1737 def_collector
: &mut *self.def_collector
,
1738 macro_depth
: self.macro_depth
,
1740 tree_id
: self.tree_id
,
1741 item_tree
: self.item_tree
,
1744 .collect_in_top_module(&*items
);
1746 self.import_all_legacy_macros(module_id
);
1750 // out of line module, resolve, parse and recurse
1751 ModKind
::Outline
=> {
1752 let ast_id
= AstId
::new(self.tree_id
.file_id(), module
.ast_id
);
1753 let db
= self.def_collector
.db
;
1754 match self.mod_dir
.resolve_declaration(db
, self.file_id(), &module
.name
, path_attr
)
1756 Ok((file_id
, is_mod_rs
, mod_dir
)) => {
1757 let item_tree
= db
.file_item_tree(file_id
.into());
1758 let krate
= self.def_collector
.def_map
.krate
;
1759 let is_enabled
= item_tree
1760 .top_level_attrs(db
, krate
)
1762 .map_or(true, |cfg
| self.is_cfg_enabled(&cfg
));
1764 let module_id
= self.push_child_module(
1765 module
.name
.clone(),
1767 Some((file_id
, is_mod_rs
)),
1768 &self.item_tree
[module
.visibility
],
1772 def_collector
: self.def_collector
,
1773 macro_depth
: self.macro_depth
,
1775 tree_id
: TreeId
::new(file_id
.into(), None
),
1776 item_tree
: &item_tree
,
1779 .collect_in_top_module(item_tree
.top_level_items());
1780 let is_macro_use
= is_macro_use
1782 .top_level_attrs(db
, krate
)
1783 .by_key("macro_use")
1786 self.import_all_legacy_macros(module_id
);
1790 Err(candidates
) => {
1791 self.push_child_module(
1792 module
.name
.clone(),
1795 &self.item_tree
[module
.visibility
],
1798 self.def_collector
.def_map
.diagnostics
.push(
1799 DefDiagnostic
::unresolved_module(self.module_id
, ast_id
, candidates
),
1807 fn push_child_module(
1810 declaration
: AstId
<ast
::Module
>,
1811 definition
: Option
<(FileId
, bool
)>,
1812 visibility
: &crate::visibility
::RawVisibility
,
1813 mod_tree_id
: FileItemTreeId
<Mod
>,
1814 ) -> LocalModuleId
{
1815 let def_map
= &mut self.def_collector
.def_map
;
1817 .resolve_visibility(self.def_collector
.db
, self.module_id
, visibility
)
1818 .unwrap_or(Visibility
::Public
);
1819 let modules
= &mut def_map
.modules
;
1820 let origin
= match definition
{
1821 None
=> ModuleOrigin
::Inline
{
1822 definition
: declaration
,
1823 definition_tree_id
: ItemTreeId
::new(self.tree_id
, mod_tree_id
),
1825 Some((definition
, is_mod_rs
)) => ModuleOrigin
::File
{
1829 declaration_tree_id
: ItemTreeId
::new(self.tree_id
, mod_tree_id
),
1833 let res
= modules
.alloc(ModuleData
::new(origin
, vis
));
1834 modules
[res
].parent
= Some(self.module_id
);
1835 for (name
, mac
) in modules
[self.module_id
].scope
.collect_legacy_macros() {
1837 modules
[res
].scope
.define_legacy_macro(name
.clone(), mac
);
1840 modules
[self.module_id
].children
.insert(name
.clone(), res
);
1842 let module
= def_map
.module_id(res
);
1843 let def
= ModuleDefId
::from(module
);
1845 def_map
.modules
[self.module_id
].scope
.declare(def
);
1846 self.def_collector
.update(
1848 &[(Some(name
), PerNs
::from_def(def
, vis
, false))],
1855 /// Resolves attributes on an item.
1857 /// Returns `Err` when some attributes could not be resolved to builtins and have been
1858 /// registered as unresolved.
1860 /// If `ignore_up_to` is `Some`, attributes preceding and including that attribute will be
1861 /// assumed to be resolved already.
1862 fn resolve_attributes(
1866 container
: ItemContainerId
,
1867 ) -> Result
<(), ()> {
1868 let mut ignore_up_to
=
1869 self.def_collector
.skip_attrs
.get(&InFile
::new(self.file_id(), mod_item
)).copied();
1873 // FIXME: this should not be required, all attributes on an item should have a
1875 // Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
1876 // #[cfg_attr(not(off), unresolved, unresolved)]
1878 // We should come up with a different way to ID attributes.
1881 .skip_while(|attr
| match ignore_up_to
{
1882 Some(id
) if attr
.id
== id
=> {
1883 ignore_up_to
= None
;
1891 if self.def_collector
.def_map
.is_builtin_or_registered_attr(&attr
.path
) {
1894 tracing
::debug
!("non-builtin attribute {}", attr
.path
);
1896 let ast_id
= AstIdWithPath
::new(
1898 mod_item
.ast_id(self.item_tree
),
1899 attr
.path
.as_ref().clone(),
1901 self.def_collector
.unresolved_macros
.push(MacroDirective
{
1902 module_id
: self.module_id
,
1903 depth
: self.macro_depth
+ 1,
1904 kind
: MacroDirectiveKind
::Attr
{
1919 fn collect_macro_rules(&mut self, id
: FileItemTreeId
<MacroRules
>, module
: ModuleId
) {
1920 let krate
= self.def_collector
.def_map
.krate
;
1921 let mac
= &self.item_tree
[id
];
1922 let attrs
= self.item_tree
.attrs(self.def_collector
.db
, krate
, ModItem
::from(id
).into());
1923 let ast_id
= InFile
::new(self.file_id(), mac
.ast_id
.upcast());
1925 let export_attr
= attrs
.by_key("macro_export");
1927 let is_export
= export_attr
.exists();
1928 let local_inner
= if is_export
{
1929 export_attr
.tt_values().flat_map(|it
| &it
.token_trees
).any(|it
| match it
{
1930 tt
::TokenTree
::Leaf(tt
::Leaf
::Ident(ident
)) => {
1931 ident
.text
.contains("local_inner_macros")
1939 // Case 1: builtin macros
1940 let expander
= if attrs
.by_key("rustc_builtin_macro").exists() {
1941 // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
1943 let name
= match attrs
.by_key("rustc_builtin_macro").string_value() {
1945 // FIXME: a hacky way to create a Name from string.
1946 name
= tt
::Ident { text: it.clone(), id: tt::TokenId::unspecified() }
.as_name();
1951 attrs
.by_key("rustc_builtin_macro").tt_values().next().and_then(|tt
| {
1952 match tt
.token_trees
.first() {
1953 Some(tt
::TokenTree
::Leaf(tt
::Leaf
::Ident(name
))) => Some(name
),
1957 match explicit_name
{
1959 name
= ident
.as_name();
1966 match find_builtin_macro(name
) {
1967 Some(Either
::Left(it
)) => MacroExpander
::BuiltIn(it
),
1968 Some(Either
::Right(it
)) => MacroExpander
::BuiltInEager(it
),
1973 .push(DefDiagnostic
::unimplemented_builtin_macro(self.module_id
, ast_id
));
1978 // Case 2: normal `macro_rules!` macro
1979 MacroExpander
::Declarative
1982 let macro_id
= MacroRulesLoc
{
1984 id
: ItemTreeId
::new(self.tree_id
, id
),
1988 .intern(self.def_collector
.db
);
1989 self.def_collector
.define_macro_rules(
1997 fn collect_macro_def(&mut self, id
: FileItemTreeId
<MacroDef
>, module
: ModuleId
) {
1998 let krate
= self.def_collector
.def_map
.krate
;
1999 let mac
= &self.item_tree
[id
];
2000 let ast_id
= InFile
::new(self.file_id(), mac
.ast_id
.upcast());
2002 // Case 1: builtin macros
2003 let attrs
= self.item_tree
.attrs(self.def_collector
.db
, krate
, ModItem
::from(id
).into());
2004 let expander
= if attrs
.by_key("rustc_builtin_macro").exists() {
2005 if let Some(expander
) = find_builtin_macro(&mac
.name
) {
2007 Either
::Left(it
) => MacroExpander
::BuiltIn(it
),
2008 Either
::Right(it
) => MacroExpander
::BuiltInEager(it
),
2010 } else if let Some(expander
) = find_builtin_derive(&mac
.name
) {
2011 MacroExpander
::BuiltInDerive(expander
)
2012 } else if let Some(expander
) = find_builtin_attr(&mac
.name
) {
2013 MacroExpander
::BuiltInAttr(expander
)
2018 .push(DefDiagnostic
::unimplemented_builtin_macro(self.module_id
, ast_id
));
2022 // Case 2: normal `macro`
2023 MacroExpander
::Declarative
2027 Macro2Loc { container: module, id: ItemTreeId::new(self.tree_id, id), expander }
2028 .intern(self.def_collector
.db
);
2029 self.def_collector
.define_macro_def(
2033 &self.item_tree
[mac
.visibility
],
2037 fn collect_macro_call(&mut self, mac
: &MacroCall
, container
: ItemContainerId
) {
2038 let ast_id
= AstIdWithPath
::new(self.file_id(), mac
.ast_id
, ModPath
::clone(&mac
.path
));
2040 // Case 1: try to resolve in legacy scope and expand macro_rules
2041 let mut error
= None
;
2042 match macro_call_as_call_id(
2043 self.def_collector
.db
,
2046 self.def_collector
.def_map
.krate
,
2048 path
.as_ident().and_then(|name
| {
2049 self.def_collector
.def_map
.with_ancestor_maps(
2050 self.def_collector
.db
,
2052 &mut |map
, module
| {
2055 .get_legacy_macro(name
)
2056 .and_then(|it
| it
.last())
2057 .map(|&it
| macro_id_to_def_id(self.def_collector
.db
, it
.into()))
2063 error
.get_or_insert(err
);
2066 Ok(Ok(macro_call_id
)) => {
2067 // Legacy macros need to be expanded immediately, so that any macros they produce
2069 self.def_collector
.collect_macro_expansion(
2072 self.macro_depth
+ 1,
2076 if let Some(err
) = error
{
2077 self.def_collector
.def_map
.diagnostics
.push(DefDiagnostic
::macro_error(
2079 MacroCallKind
::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to }
,
2087 // Built-in macro failed eager expansion.
2089 self.def_collector
.def_map
.diagnostics
.push(DefDiagnostic
::macro_error(
2091 MacroCallKind
::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to }
,
2092 error
.unwrap().to_string(),
2096 Err(UnresolvedMacro { .. }
) => (),
2099 // Case 2: resolve in module scope, expand during name resolution.
2100 self.def_collector
.unresolved_macros
.push(MacroDirective
{
2101 module_id
: self.module_id
,
2102 depth
: self.macro_depth
+ 1,
2103 kind
: MacroDirectiveKind
::FnLike { ast_id, expand_to: mac.expand_to }
,
2108 fn import_all_legacy_macros(&mut self, module_id
: LocalModuleId
) {
2109 let macros
= self.def_collector
.def_map
[module_id
].scope
.collect_legacy_macros();
2110 for (name
, macs
) in macros
{
2111 macs
.last().map(|&mac
| {
2112 self.def_collector
.define_legacy_macro(self.module_id
, name
.clone(), mac
)
2117 fn is_cfg_enabled(&self, cfg
: &CfgExpr
) -> bool
{
2118 self.def_collector
.cfg_options
.check(cfg
) != Some(false)
2121 fn emit_unconfigured_diagnostic(&mut self, item
: ModItem
, cfg
: &CfgExpr
) {
2122 let ast_id
= item
.ast_id(self.item_tree
);
2124 let ast_id
= InFile
::new(self.file_id(), ast_id
);
2125 self.def_collector
.def_map
.diagnostics
.push(DefDiagnostic
::unconfigured_code(
2129 self.def_collector
.cfg_options
.clone(),
2133 fn file_id(&self) -> HirFileId
{
2134 self.tree_id
.file_id()
2140 use crate::{db::DefDatabase, test_db::TestDB}
;
2141 use base_db
::{fixture::WithFixture, SourceDatabase}
;
2145 fn do_collect_defs(db
: &dyn DefDatabase
, def_map
: DefMap
) -> DefMap
{
2146 let mut collector
= DefCollector
{
2149 deps
: FxHashMap
::default(),
2150 glob_imports
: FxHashMap
::default(),
2151 unresolved_imports
: Vec
::new(),
2152 indeterminate_imports
: Vec
::new(),
2153 unresolved_macros
: Vec
::new(),
2154 mod_dirs
: FxHashMap
::default(),
2155 cfg_options
: &CfgOptions
::default(),
2156 proc_macros
: Default
::default(),
2157 from_glob_import
: Default
::default(),
2158 skip_attrs
: Default
::default(),
2159 is_proc_macro
: false,
2161 collector
.seed_with_top_level();
2162 collector
.collect();
2166 fn do_resolve(not_ra_fixture
: &str) -> DefMap
{
2167 let (db
, file_id
) = TestDB
::with_single_file(not_ra_fixture
);
2168 let krate
= db
.test_crate();
2170 let edition
= db
.crate_graph()[krate
].edition
;
2171 let module_origin
= ModuleOrigin
::CrateRoot { definition: file_id }
;
2173 DefMap
::empty(krate
, edition
, ModuleData
::new(module_origin
, Visibility
::Public
));
2174 do_collect_defs(&db
, def_map
)
2178 fn test_macro_expand_will_stop_1() {
2182 ($($ty:ty)*) => { foo!($($ty)*); }
2190 ($($ty:ty)*) => { foo!(() $($ty)*); }
2199 fn test_macro_expand_will_stop_2() {
2200 // FIXME: this test does succeed, but takes quite a while: 90 seconds in
2201 // the release mode. That's why the argument is not an ra_fixture --
2202 // otherwise injection highlighting gets stuck.
2204 // We need to find a way to fail this faster.
2208 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }