]> git.proxmox.com Git - rustc.git/blob - src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / hir-def / src / nameres / collector.rs
1 //! The core of the module-level name resolution algorithm.
2 //!
3 //! `DefCollector::collect` contains the fixed-point iteration loop which
4 //! resolves imports and expands macros.
5
6 use std::{iter, mem};
7
8 use base_db::{CrateId, Edition, FileId};
9 use cfg::{CfgExpr, CfgOptions};
10 use either::Either;
11 use hir_expand::{
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,
19 MacroDefKind,
20 };
21 use itertools::{izip, Itertools};
22 use la_arena::Idx;
23 use limit::Limit;
24 use rustc_hash::{FxHashMap, FxHashSet};
25 use stdx::always;
26 use syntax::{ast, SmolStr};
27
28 use crate::{
29 attr::{Attr, AttrId, Attrs},
30 attr_macro_as_call_id,
31 db::DefDatabase,
32 derive_macro_as_call_id,
33 item_scope::{ImportType, PerNsGlobImports},
34 item_tree::{
35 self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
36 MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
37 },
38 macro_call_as_call_id, macro_id_to_def_id,
39 nameres::{
40 diagnostics::DefDiagnostic,
41 mod_resolution::ModDir,
42 path_resolution::ReachedFixedPoint,
43 proc_macro::{ProcMacroDef, ProcMacroKind},
44 BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
45 },
46 path::{ImportAlias, ModPath, PathKind},
47 per_ns::PerNs,
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,
53 };
54
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);
58
59 pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: TreeId) -> DefMap {
60 let crate_graph = db.crate_graph();
61
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);
69
70 deps.insert(dep.as_name(), dep_root.into());
71
72 if dep.is_prelude() && !tree_id.is_block() {
73 def_map.extern_prelude.insert(dep.as_name(), dep_root);
74 }
75 }
76
77 let cfg_options = &krate.cfg_options;
78 let proc_macros = match &krate.proc_macro {
79 Ok(proc_macros) => {
80 proc_macros
81 .iter()
82 .enumerate()
83 .map(|(idx, it)| {
84 // FIXME: a hacky way to create a Name from string.
85 let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() };
86 (
87 name.as_name(),
88 ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)),
89 )
90 })
91 .collect()
92 }
93 Err(e) => {
94 def_map.proc_macro_loading_error = Some(e.clone().into_boxed_str());
95 Vec::new()
96 }
97 };
98 let is_proc_macro = krate.is_proc_macro;
99
100 let mut collector = DefCollector {
101 db,
102 def_map,
103 deps,
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(),
109 cfg_options,
110 proc_macros,
111 from_glob_import: Default::default(),
112 skip_attrs: Default::default(),
113 is_proc_macro,
114 };
115 if tree_id.is_block() {
116 collector.seed_with_inner(tree_id);
117 } else {
118 collector.seed_with_top_level();
119 }
120 collector.collect();
121 let mut def_map = collector.finish();
122 def_map.shrink_to_fit();
123 def_map
124 }
125
126 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
127 enum PartialResolvedImport {
128 /// None of any namespaces is resolved
129 Unresolved,
130 /// One of namespaces is resolved
131 Indeterminate(PerNs),
132 /// All namespaces are resolved, OR it comes from other crate
133 Resolved(PerNs),
134 }
135
136 impl PartialResolvedImport {
137 fn namespaces(self) -> PerNs {
138 match self {
139 PartialResolvedImport::Unresolved => PerNs::none(),
140 PartialResolvedImport::Indeterminate(ns) | PartialResolvedImport::Resolved(ns) => ns,
141 }
142 }
143 }
144
145 #[derive(Clone, Debug, Eq, PartialEq)]
146 enum ImportSource {
147 Import { id: ItemTreeId<item_tree::Import>, use_tree: Idx<ast::UseTree> },
148 ExternCrate(ItemTreeId<item_tree::ExternCrate>),
149 }
150
151 #[derive(Debug, Eq, PartialEq)]
152 struct Import {
153 path: ModPath,
154 alias: Option<ImportAlias>,
155 visibility: RawVisibility,
156 kind: ImportKind,
157 is_prelude: bool,
158 is_extern_crate: bool,
159 is_macro_use: bool,
160 source: ImportSource,
161 }
162
163 impl Import {
164 fn from_use(
165 db: &dyn DefDatabase,
166 krate: CrateId,
167 tree: &ItemTree,
168 id: ItemTreeId<item_tree::Import>,
169 ) -> Vec<Self> {
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();
174
175 let mut res = Vec::new();
176 it.use_tree.expand(|idx, path, kind, alias| {
177 res.push(Self {
178 path,
179 alias,
180 visibility: visibility.clone(),
181 kind,
182 is_prelude,
183 is_extern_crate: false,
184 is_macro_use: false,
185 source: ImportSource::Import { id, use_tree: idx },
186 });
187 });
188 res
189 }
190
191 fn from_extern_crate(
192 db: &dyn DefDatabase,
193 krate: CrateId,
194 tree: &ItemTree,
195 id: ItemTreeId<item_tree::ExternCrate>,
196 ) -> Self {
197 let it = &tree[id.value];
198 let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
199 let visibility = &tree[it.visibility];
200 Self {
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,
205 is_prelude: false,
206 is_extern_crate: true,
207 is_macro_use: attrs.by_key("macro_use").exists(),
208 source: ImportSource::ExternCrate(id),
209 }
210 }
211 }
212
213 #[derive(Debug, Eq, PartialEq)]
214 struct ImportDirective {
215 module_id: LocalModuleId,
216 import: Import,
217 status: PartialResolvedImport,
218 }
219
220 #[derive(Clone, Debug, Eq, PartialEq)]
221 struct MacroDirective {
222 module_id: LocalModuleId,
223 depth: usize,
224 kind: MacroDirectiveKind,
225 container: ItemContainerId,
226 }
227
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 },
233 }
234
235 /// Walks the tree of module recursively
236 struct DefCollector<'a> {
237 db: &'a dyn DefDatabase,
238 def_map: DefMap,
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
249 /// them).
250 proc_macros: Vec<(Name, ProcMacroExpander)>,
251 is_proc_macro: bool,
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.
256 ///
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>,
260 }
261
262 impl DefCollector<'_> {
263 fn seed_with_top_level(&mut self) {
264 let _p = profile::span("seed_with_top_level");
265
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;
269
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);
273
274 // Process other crate-level attributes.
275 for attr in &*attrs {
276 let attr_name = match attr.path.as_ident() {
277 Some(name) => name,
278 None => continue,
279 };
280
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);
285 }
286 }
287 continue;
288 }
289
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;
293 }
294 continue;
295 }
296
297 if *attr_name == hir_expand::name![feature] {
298 let features =
299 attr.parse_path_comma_token_tree().into_iter().flatten().filter_map(
300 |feat| match feat.segments() {
301 [name] => Some(name.to_smol_str()),
302 _ => None,
303 },
304 );
305 self.def_map.unstable_features.extend(features);
306 }
307
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 {
311 continue;
312 }
313
314 let registered_name = match attr.single_ident_value() {
315 Some(ident) => ident.as_name(),
316 _ => continue,
317 };
318
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);
322 } else {
323 self.def_map.registered_tools.push(registered_name.to_smol_str());
324 cov_mark::hit!(register_tool);
325 }
326 }
327
328 ModCollector {
329 def_collector: self,
330 macro_depth: 0,
331 module_id,
332 tree_id: TreeId::new(file_id.into(), None),
333 item_tree: &item_tree,
334 mod_dir: ModDir::root(),
335 }
336 .collect_in_top_module(item_tree.top_level_items());
337 }
338 }
339
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;
343
344 let is_cfg_enabled = item_tree
345 .top_level_attrs(self.db, self.def_map.krate)
346 .cfg()
347 .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false));
348 if is_cfg_enabled {
349 ModCollector {
350 def_collector: self,
351 macro_depth: 0,
352 module_id,
353 tree_id,
354 item_tree: &item_tree,
355 mod_dir: ModDir::root(),
356 }
357 .collect_in_top_module(item_tree.top_level_items());
358 }
359 }
360
361 fn resolution_loop(&mut self) {
362 let _p = profile::span("DefCollector::resolution_loop");
363
364 // main name resolution fixed-point loop.
365 let mut i = 0;
366 'resolve_attr: loop {
367 'resolve_macros: loop {
368 self.db.unwind_if_cancelled();
369
370 {
371 let _p = profile::span("resolve_imports loop");
372
373 'resolve_imports: loop {
374 if self.resolve_imports() == ReachedFixedPoint::Yes {
375 break 'resolve_imports;
376 }
377 }
378 }
379 if self.resolve_macros() == ReachedFixedPoint::Yes {
380 break 'resolve_macros;
381 }
382
383 i += 1;
384 if FIXED_POINT_LIMIT.check(i).is_err() {
385 tracing::error!("name resolution is stuck");
386 break 'resolve_attr;
387 }
388 }
389
390 if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
391 break 'resolve_attr;
392 }
393 }
394 }
395
396 fn collect(&mut self) {
397 let _p = profile::span("DefCollector::collect");
398
399 self.resolution_loop();
400
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`
404 // correctly
405 let partial_resolved = self.indeterminate_imports.drain(..).map(|directive| {
406 ImportDirective { status: PartialResolvedImport::Unresolved, ..directive }
407 });
408 self.unresolved_imports.extend(partial_resolved);
409 self.resolve_imports();
410
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);
415 }
416 self.unresolved_imports = unresolved_imports;
417
418 if self.is_proc_macro {
419 // A crate exporting procedural macros is not allowed to export anything else.
420 //
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);
428 }
429 }
430
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.
434 ///
435 /// This effectively ignores the fact that the macro is there and just treats the items as
436 /// normal code.
437 ///
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);
442
443 let unresolved_attr =
444 self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive
445 .kind
446 {
447 MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } => {
448 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
449 directive.module_id,
450 MacroCallKind::Attr {
451 ast_id: ast_id.ast_id,
452 attr_args: Default::default(),
453 invoc_attr_index: attr.id.ast_index,
454 is_derive: false,
455 },
456 attr.path().clone(),
457 ));
458
459 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
460
461 Some((idx, directive, *mod_item, *tree))
462 }
463 _ => None,
464 });
465
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();
470 ModCollector {
471 def_collector: self,
472 macro_depth: depth,
473 module_id,
474 tree_id,
475 item_tree,
476 mod_dir,
477 }
478 .collect(&[mod_item], container);
479
480 self.unresolved_macros.swap_remove(pos);
481 // Continue name resolution with the new data.
482 ReachedFixedPoint::No
483 }
484 None => ReachedFixedPoint::Yes,
485 }
486 }
487
488 fn inject_prelude(&mut self, crate_attrs: &Attrs) {
489 // See compiler/rustc_builtin_macros/src/standard_library_imports.rs
490
491 if crate_attrs.by_key("no_core").exists() {
492 // libcore does not get a prelude.
493 return;
494 }
495
496 let krate = if crate_attrs.by_key("no_std").exists() {
497 name![core]
498 } else {
499 let std = name![std];
500 if self.def_map.extern_prelude().any(|(name, _)| *name == std) {
501 std
502 } else {
503 // If `std` does not exist for some reason, fall back to core. This mostly helps
504 // keep r-a's own tests minimal.
505 name![core]
506 }
507 };
508
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],
513 };
514
515 let path_kind = match self.def_map.edition {
516 Edition::Edition2015 => PathKind::Plain,
517 _ => PathKind::Abs,
518 };
519 let path =
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
523 let fallback_path =
524 ModPath::from_segments(path_kind, [krate, name![prelude], name![v1]].into_iter());
525
526 for path in &[path, fallback_path] {
527 let (per_ns, _) = self.def_map.resolve_path(
528 self.db,
529 self.def_map.root,
530 path,
531 BuiltinShadowMode::Other,
532 );
533
534 match per_ns.types {
535 Some((ModuleDefId::ModuleId(m), _)) => {
536 self.def_map.prelude = Some(m);
537 }
538 types => {
539 tracing::debug!(
540 "could not resolve prelude path `{}` to module (resolved to {:?})",
541 path,
542 types
543 );
544 }
545 }
546 }
547 }
548
549 /// Adds a definition of procedural macro `name` to the root module.
550 ///
551 /// # Notes on procedural macro resolution
552 ///
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.
555 ///
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.
559 ///
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(
566 &mut self,
567 def: ProcMacroDef,
568 id: ItemTreeId<item_tree::Function>,
569 fn_id: FunctionId,
570 module_id: ModuleId,
571 ) {
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),
576 };
577
578 let proc_macro_id =
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 {
582 self.def_map
583 .exported_derives
584 .insert(macro_id_to_def_id(self.db, proc_macro_id.into()), helpers);
585 }
586 self.def_map.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
587 }
588
589 /// Define a macro with `macro_rules`.
590 ///
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.
594 ///
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;
600 /// ```
601 ///
602 /// ```rust,compile_fail
603 /// macro_rules! foo { () => {} }
604 /// self::foo!();
605 /// crate::foo!();
606 /// ```
607 ///
608 /// Well, this code compiles, because the plain path `foo` in `use` is searched
609 /// in the legacy textual scope only.
610 /// ```rust
611 /// macro_rules! foo { () => {} }
612 /// use foo as bar;
613 /// ```
614 fn define_macro_rules(
615 &mut self,
616 module_id: LocalModuleId,
617 name: Name,
618 macro_: MacroRulesId,
619 export: bool,
620 ) {
621 // Textual scoping
622 self.define_legacy_macro(module_id, name.clone(), macro_.into());
623
624 // Module scoping
625 // In Rust, `#[macro_export]` macros are unconditionally visible at the
626 // crate root, even if the parent modules is **not** visible.
627 if export {
628 let module_id = self.def_map.root;
629 self.def_map.modules[module_id].scope.declare(macro_.into());
630 self.update(
631 module_id,
632 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
633 Visibility::Public,
634 ImportType::Named,
635 );
636 }
637 }
638
639 /// Define a legacy textual scoped macro in module
640 ///
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) {
647 // Always shadowing
648 self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
649 }
650
651 /// Define a macro 2.0 macro
652 ///
653 /// The scoped of macro 2.0 macro is equal to normal function
654 fn define_macro_def(
655 &mut self,
656 module_id: LocalModuleId,
657 name: Name,
658 macro_: Macro2Id,
659 vis: &RawVisibility,
660 ) {
661 let vis =
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());
664 self.update(
665 module_id,
666 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
667 vis,
668 ImportType::Named,
669 );
670 }
671
672 /// Define a proc macro
673 ///
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());
679 self.update(
680 module_id,
681 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
682 Visibility::Public,
683 ImportType::Named,
684 );
685 }
686
687 /// Import macros from `#[macro_use] extern crate`.
688 fn import_macros_from_extern_crate(
689 &mut self,
690 current_module_id: LocalModuleId,
691 extern_crate: &item_tree::ExternCrate,
692 ) {
693 tracing::debug!(
694 "importing macros from extern crate: {:?} ({:?})",
695 extern_crate,
696 self.def_map.edition,
697 );
698
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);
702 return;
703 }
704
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);
707 }
708 }
709
710 /// Import all exported macros from another crate
711 ///
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);
720 }
721 }
722
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);
727
728 self.unresolved_imports = imports
729 .into_iter()
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;
737 None
738 }
739 PartialResolvedImport::Resolved(_) => {
740 self.record_resolved_import(&directive);
741 res = ReachedFixedPoint::No;
742 None
743 }
744 PartialResolvedImport::Unresolved => Some(directive),
745 }
746 })
747 .collect();
748 res
749 }
750
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 {
755 let name = import
756 .path
757 .as_ident()
758 .expect("extern crate should have been desugared to one-element path");
759
760 let res = self.resolve_extern_crate(name);
761
762 match res {
763 Some(res) => {
764 PartialResolvedImport::Resolved(PerNs::types(res.into(), Visibility::Public))
765 }
766 None => PartialResolvedImport::Unresolved,
767 }
768 } else {
769 let res = self.def_map.resolve_path_fp_with_macro(
770 self.db,
771 ResolveMode::Import,
772 module_id,
773 &import.path,
774 BuiltinShadowMode::Module,
775 );
776
777 let def = res.resolved_def;
778 if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
779 return PartialResolvedImport::Unresolved;
780 }
781
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)),
786 );
787 }
788 }
789
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()
794 {
795 PartialResolvedImport::Resolved(def)
796 } else {
797 PartialResolvedImport::Indeterminate(def)
798 }
799 }
800 }
801
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 {
806 Some(_) => {
807 let def_map = self.def_map.crate_root(self.db).def_map(self.db);
808 def_map.module_id(def_map.root())
809 }
810 None => self.def_map.module_id(self.def_map.root()),
811 };
812 Some(root)
813 } else {
814 self.deps.get(name).copied()
815 }
816 }
817
818 fn record_resolved_import(&mut self, directive: &ImportDirective) {
819 let _p = profile::span("record_resolved_import");
820
821 let module_id = directive.module_id;
822 let import = &directive.import;
823 let mut def = directive.status.namespaces();
824 let vis = self
825 .def_map
826 .resolve_visibility(self.db, module_id, &directive.import.visibility)
827 .unwrap_or(Visibility::Public);
828
829 match import.kind {
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),
836 None => {
837 cov_mark::hit!(bogus_paths);
838 return;
839 }
840 },
841 };
842
843 if import.kind == ImportKind::TypeOnly {
844 def.values = None;
845 def.macros = None;
846 }
847
848 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
849
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
854 {
855 if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name)
856 {
857 self.def_map.extern_prelude.insert(name.clone(), def);
858 }
859 }
860
861 self.update(module_id, &[(name.cloned(), def)], vis, ImportType::Named);
862 }
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;
877
878 // Module scoped macros is included
879 let items = scope
880 .resolutions()
881 // only keep visible names...
882 .map(|(n, res)| {
883 (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
884 })
885 .filter(|(_, res)| !res.is_none())
886 .collect::<Vec<_>>();
887
888 self.update(module_id, &items, vis, ImportType::Glob);
889 } else {
890 // glob import from same crate => we do an initial
891 // import, and then need to propagate any further
892 // additions
893 let def_map;
894 let scope = if m.block == self.def_map.block_id() {
895 &self.def_map[m.local_id].scope
896 } else {
897 def_map = m.def_map(self.db);
898 &def_map[m.local_id].scope
899 };
900
901 // Module scoped macros is included
902 let items = scope
903 .resolutions()
904 // only keep visible names...
905 .map(|(n, res)| {
906 (
907 n,
908 res.filter_visibility(|v| {
909 v.is_visible_from_def_map(
910 self.db,
911 &self.def_map,
912 module_id,
913 )
914 }),
915 )
916 })
917 .filter(|(_, res)| !res.is_none())
918 .collect::<Vec<_>>();
919
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));
925 }
926 }
927 }
928 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
929 cov_mark::hit!(glob_enum);
930 // glob import from enum => just import all the variants
931
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
941 .variants
942 .iter()
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);
947 (Some(name), res)
948 })
949 .collect::<Vec<_>>();
950 self.update(module_id, &resolutions, vis, ImportType::Glob);
951 }
952 Some(d) => {
953 tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
954 }
955 None => {
956 tracing::debug!("glob import {:?} didn't resolve as type", import);
957 }
958 }
959 }
960 }
961 }
962
963 fn update(
964 &mut self,
965 module_id: LocalModuleId,
966 resolutions: &[(Option<Name>, PerNs)],
967 vis: Visibility,
968 import_type: ImportType,
969 ) {
970 self.db.unwind_if_cancelled();
971 self.update_recursive(module_id, resolutions, vis, import_type, 0)
972 }
973
974 fn update_recursive(
975 &mut self,
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
980 vis: Visibility,
981 import_type: ImportType,
982 depth: usize,
983 ) {
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!");
987 }
988 let mut changed = false;
989
990 for (name, res) in resolutions {
991 match name {
992 Some(name) => {
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),
998 import_type,
999 );
1000 }
1001 None => {
1002 let tr = match res.take_types() {
1003 Some(ModuleDefId::TraitId(tr)) => tr,
1004 Some(other) => {
1005 tracing::debug!("non-trait `_` import of {:?}", other);
1006 continue;
1007 }
1008 None => continue,
1009 };
1010 let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
1011 let should_update = match old_vis {
1012 None => true,
1013 Some(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);
1016 });
1017
1018 if max_vis == old_vis {
1019 false
1020 } else {
1021 cov_mark::hit!(upgrade_underscore_visibility);
1022 true
1023 }
1024 }
1025 };
1026
1027 if should_update {
1028 changed = true;
1029 self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
1030 }
1031 }
1032 }
1033 }
1034
1035 if !changed {
1036 return;
1037 }
1038 let glob_imports = self
1039 .glob_imports
1040 .get(&module_id)
1041 .into_iter()
1042 .flatten()
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)
1047 })
1048 .cloned()
1049 .collect::<Vec<_>>();
1050
1051 for (glob_importing_module, glob_import_vis) in glob_imports {
1052 self.update_recursive(
1053 glob_importing_module,
1054 resolutions,
1055 glob_import_vis,
1056 ImportType::Glob,
1057 depth + 1,
1058 );
1059 }
1060 }
1061
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));
1067 };
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(
1072 self.db,
1073 ResolveMode::Other,
1074 directive.module_id,
1075 &path,
1076 BuiltinShadowMode::Module,
1077 );
1078 resolved_res
1079 .resolved_def
1080 .take_macros()
1081 .map(|it| (it, macro_id_to_def_id(self.db, it)))
1082 };
1083 let resolver_def_id = |path| resolver(path).map(|(_, it)| it);
1084
1085 match &directive.kind {
1086 MacroDirectiveKind::FnLike { ast_id, expand_to } => {
1087 let call_id = macro_call_as_call_id(
1088 self.db,
1089 ast_id,
1090 *expand_to,
1091 self.def_map.krate,
1092 &resolver_def_id,
1093 &mut |_err| (),
1094 );
1095 if let Ok(Ok(call_id)) = call_id {
1096 push_resolved(directive, call_id);
1097 res = ReachedFixedPoint::No;
1098 return false;
1099 }
1100 }
1101 MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
1102 let id = derive_macro_as_call_id(
1103 self.db,
1104 ast_id,
1105 *derive_attr,
1106 *derive_pos as u32,
1107 self.def_map.krate,
1108 &resolver,
1109 );
1110
1111 if let Ok((macro_id, def_id, call_id)) = id {
1112 self.def_map.modules[directive.module_id].scope.set_derive_macro_invoc(
1113 ast_id.ast_id,
1114 call_id,
1115 *derive_attr,
1116 *derive_pos,
1117 );
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) {
1122 self.def_map
1123 .derive_helpers_in_scope
1124 .entry(ast_id.ast_id.map(|it| it.upcast()))
1125 .or_default()
1126 .extend(izip!(
1127 helpers.iter().cloned(),
1128 iter::repeat(macro_id),
1129 iter::repeat(call_id),
1130 ));
1131 }
1132 }
1133
1134 push_resolved(directive, call_id);
1135 res = ReachedFixedPoint::No;
1136 return false;
1137 }
1138 }
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;
1142
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);
1147
1148 let item_tree = tree.item_tree(self.db);
1149 ModCollector {
1150 def_collector: collector,
1151 macro_depth: directive.depth,
1152 module_id: directive.module_id,
1153 tree_id: *tree,
1154 item_tree: &item_tree,
1155 mod_dir,
1156 }
1157 .collect(&[*mod_item], directive.container);
1158 res = ReachedFixedPoint::No;
1159 false
1160 };
1161
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);
1169 }
1170 }
1171 }
1172
1173 let def = match resolver_def_id(path.clone()) {
1174 Some(def) if def.is_attribute() => def,
1175 _ => return true,
1176 };
1177 if matches!(
1178 def,
1179 MacroDefId { kind:MacroDefKind::BuiltInAttr(expander, _),.. }
1180 if expander.is_derive()
1181 ) {
1182 // Resolved to `#[derive]`
1183
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(),
1189 _ => {
1190 let diag = DefDiagnostic::invalid_derive_target(
1191 directive.module_id,
1192 ast_id,
1193 attr.id,
1194 );
1195 self.def_map.diagnostics.push(diag);
1196 return recollect_without(self);
1197 }
1198 };
1199 let ast_id = ast_id.with_value(ast_adt_id);
1200
1201 match attr.parse_path_comma_token_tree() {
1202 Some(derive_macros) => {
1203 let mut len = 0;
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 {
1210 ast_id,
1211 derive_attr: attr.id,
1212 derive_pos: idx,
1213 },
1214 container: directive.container,
1215 });
1216 len = idx;
1217 }
1218
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(
1223 self.db,
1224 file_ast_id,
1225 attr,
1226 self.def_map.krate,
1227 def,
1228 true,
1229 );
1230 self.def_map.modules[directive.module_id]
1231 .scope
1232 .init_derive_attribute(ast_id, attr.id, call_id, len + 1);
1233 }
1234 None => {
1235 let diag = DefDiagnostic::malformed_derive(
1236 directive.module_id,
1237 ast_id,
1238 attr.id,
1239 );
1240 self.def_map.diagnostics.push(diag);
1241 }
1242 }
1243
1244 return recollect_without(self);
1245 }
1246
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(
1249 self.db,
1250 file_ast_id,
1251 attr,
1252 self.def_map.krate,
1253 def,
1254 false,
1255 );
1256 let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
1257
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,
1262 loc.kind,
1263 loc.def.krate,
1264 ));
1265 return recollect_without(self);
1266 }
1267
1268 // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
1269 // due to duplicating functions into macro expansions
1270 if matches!(
1271 loc.def.kind,
1272 MacroDefKind::BuiltInAttr(expander, _)
1273 if expander.is_test() || expander.is_bench()
1274 ) {
1275 return recollect_without(self);
1276 }
1277
1278 if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
1279 if exp.is_dummy() {
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,
1286 loc.kind,
1287 loc.def.krate,
1288 ));
1289
1290 return recollect_without(self);
1291 }
1292 }
1293
1294 self.def_map.modules[directive.module_id]
1295 .scope
1296 .add_attr_macro_invoc(ast_id, call_id);
1297
1298 push_resolved(directive, call_id);
1299 res = ReachedFixedPoint::No;
1300 return false;
1301 }
1302 }
1303
1304 true
1305 });
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;
1309
1310 for (module_id, depth, container, macro_call_id) in resolved {
1311 self.collect_macro_expansion(module_id, macro_call_id, depth, container);
1312 }
1313
1314 res
1315 }
1316
1317 fn collect_macro_expansion(
1318 &mut self,
1319 module_id: LocalModuleId,
1320 macro_call_id: MacroCallId,
1321 depth: usize,
1322 container: ItemContainerId,
1323 ) {
1324 if EXPANSION_DEPTH_LIMIT.check(depth).is_err() {
1325 cov_mark::hit!(macro_expansion_overflow);
1326 tracing::warn!("macro expansion is too deep");
1327 return;
1328 }
1329 let file_id = macro_call_id.as_file();
1330
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
1333 // incrementality).
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)
1342 }
1343 _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
1344 };
1345
1346 self.def_map.diagnostics.push(diag);
1347 }
1348
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();
1352 ModCollector {
1353 def_collector: &mut *self,
1354 macro_depth: depth,
1355 tree_id: TreeId::new(file_id, None),
1356 module_id,
1357 item_tree: &item_tree,
1358 mod_dir,
1359 }
1360 .collect(item_tree.top_level_items(), container);
1361 }
1362
1363 fn finish(mut self) -> DefMap {
1364 // Emit diagnostics for all remaining unexpanded macros.
1365
1366 let _p = profile::span("DefCollector::finish");
1367
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(
1372 self.db,
1373 ast_id,
1374 *expand_to,
1375 self.def_map.krate,
1376 |path| {
1377 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1378 self.db,
1379 ResolveMode::Other,
1380 directive.module_id,
1381 &path,
1382 BuiltinShadowMode::Module,
1383 );
1384 resolved_res
1385 .resolved_def
1386 .take_macros()
1387 .map(|it| macro_id_to_def_id(self.db, it))
1388 },
1389 &mut |_| (),
1390 );
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 },
1395 path,
1396 ));
1397 }
1398 }
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,
1406 },
1407 ast_id.path.clone(),
1408 ));
1409 }
1410 // These are diagnosed by `reseed_with_unresolved_attribute`, as that function consumes them
1411 MacroDirectiveKind::Attr { .. } => {}
1412 }
1413 }
1414
1415 // Emit diagnostics for all remaining unresolved imports.
1416
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];
1427
1428 diagnosed_extern_crates.insert(extern_crate.name.clone());
1429
1430 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
1431 directive.module_id,
1432 InFile::new(krate.file_id(), extern_crate.ast_id),
1433 ));
1434 }
1435 }
1436
1437 for directive in &self.unresolved_imports {
1438 if let ImportSource::Import { id: import, use_tree } = directive.import.source {
1439 if matches!(
1440 (directive.import.path.segments().first(), &directive.import.path.kind),
1441 (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate)
1442 ) {
1443 continue;
1444 }
1445
1446 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
1447 directive.module_id,
1448 import,
1449 use_tree,
1450 ));
1451 }
1452 }
1453
1454 self.def_map
1455 }
1456 }
1457
1458 /// Walks a single module, populating defs, imports and macros
1459 struct ModCollector<'a, 'b> {
1460 def_collector: &'a mut DefCollector<'b>,
1461 macro_depth: usize,
1462 module_id: LocalModuleId,
1463 tree_id: TreeId,
1464 item_tree: &'a ItemTree,
1465 mod_dir: ModDir,
1466 }
1467
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())
1472 }
1473
1474 fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
1475 let krate = self.def_collector.def_map.krate;
1476
1477 // Note: don't assert that inserted value is fresh: it's simply not true
1478 // for macros.
1479 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
1480
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);
1486 }
1487 }
1488
1489 // This should be processed eagerly instead of deferred to resolving.
1490 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
1491 // any other items.
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,
1499 krate,
1500 ModItem::from(id).into(),
1501 );
1502 if attrs.by_key("macro_use").exists() {
1503 self.def_collector.import_macros_from_extern_crate(self.module_id, import);
1504 }
1505 }
1506 }
1507 }
1508
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);
1514 continue;
1515 }
1516 }
1517
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.
1521 continue;
1522 }
1523
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;
1527 let update_def =
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(
1531 self.module_id,
1532 &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
1533 vis,
1534 ImportType::Named,
1535 )
1536 };
1537 let resolve_vis = |def_map: &DefMap, visibility| {
1538 def_map
1539 .resolve_visibility(db, self.module_id, visibility)
1540 .unwrap_or(Visibility::Public)
1541 };
1542
1543 match item {
1544 ModItem::Mod(m) => self.collect_module(m, &attrs),
1545 ModItem::Import(import_id) => {
1546 let imports = Import::from_use(
1547 db,
1548 krate,
1549 self.item_tree,
1550 ItemTreeId::new(self.tree_id, import_id),
1551 );
1552 self.def_collector.unresolved_imports.extend(imports.into_iter().map(
1553 |import| ImportDirective {
1554 module_id: self.module_id,
1555 import,
1556 status: PartialResolvedImport::Unresolved,
1557 },
1558 ));
1559 }
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(
1564 db,
1565 krate,
1566 self.item_tree,
1567 ItemTreeId::new(self.tree_id, import_id),
1568 ),
1569 status: PartialResolvedImport::Unresolved,
1570 })
1571 }
1572 ModItem::ExternBlock(block) => self.collect(
1573 &self.item_tree[block].children,
1574 ItemContainerId::ExternBlockId(
1575 ExternBlockLoc {
1576 container: module,
1577 id: ItemTreeId::new(self.tree_id, block),
1578 }
1579 .intern(db),
1580 ),
1581 ),
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) => {
1586 let impl_id =
1587 ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) }
1588 .intern(db);
1589 self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
1590 }
1591 ModItem::Function(id) => {
1592 let it = &self.item_tree[id];
1593 let fn_id =
1594 FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
1595
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(
1602 proc_macro,
1603 ItemTreeId::new(self.tree_id, id),
1604 fn_id,
1605 crate_root,
1606 );
1607 }
1608 }
1609 }
1610
1611 update_def(self.def_collector, fn_id.into(), &it.name, vis, false);
1612 }
1613 ModItem::Struct(id) => {
1614 let it = &self.item_tree[id];
1615
1616 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1617 update_def(
1618 self.def_collector,
1619 StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1620 .intern(db)
1621 .into(),
1622 &it.name,
1623 vis,
1624 !matches!(it.fields, Fields::Record(_)),
1625 );
1626 }
1627 ModItem::Union(id) => {
1628 let it = &self.item_tree[id];
1629
1630 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1631 update_def(
1632 self.def_collector,
1633 UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1634 .intern(db)
1635 .into(),
1636 &it.name,
1637 vis,
1638 false,
1639 );
1640 }
1641 ModItem::Enum(id) => {
1642 let it = &self.item_tree[id];
1643
1644 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1645 update_def(
1646 self.def_collector,
1647 EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1648 .intern(db)
1649 .into(),
1650 &it.name,
1651 vis,
1652 false,
1653 );
1654 }
1655 ModItem::Const(id) => {
1656 let it = &self.item_tree[id];
1657 let const_id =
1658 ConstLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
1659
1660 match &it.name {
1661 Some(name) => {
1662 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1663 update_def(self.def_collector, const_id.into(), name, vis, false);
1664 }
1665 None => {
1666 // const _: T = ...;
1667 self.def_collector.def_map.modules[self.module_id]
1668 .scope
1669 .define_unnamed_const(const_id);
1670 }
1671 }
1672 }
1673 ModItem::Static(id) => {
1674 let it = &self.item_tree[id];
1675
1676 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1677 update_def(
1678 self.def_collector,
1679 StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
1680 .intern(db)
1681 .into(),
1682 &it.name,
1683 vis,
1684 false,
1685 );
1686 }
1687 ModItem::Trait(id) => {
1688 let it = &self.item_tree[id];
1689
1690 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1691 update_def(
1692 self.def_collector,
1693 TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1694 .intern(db)
1695 .into(),
1696 &it.name,
1697 vis,
1698 false,
1699 );
1700 }
1701 ModItem::TypeAlias(id) => {
1702 let it = &self.item_tree[id];
1703
1704 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1705 update_def(
1706 self.def_collector,
1707 TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
1708 .intern(db)
1709 .into(),
1710 &it.name,
1711 vis,
1712 false,
1713 );
1714 }
1715 }
1716 }
1717 }
1718
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),
1729 None,
1730 &self.item_tree[module.visibility],
1731 module_id,
1732 );
1733
1734 if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
1735 {
1736 ModCollector {
1737 def_collector: &mut *self.def_collector,
1738 macro_depth: self.macro_depth,
1739 module_id,
1740 tree_id: self.tree_id,
1741 item_tree: self.item_tree,
1742 mod_dir,
1743 }
1744 .collect_in_top_module(&*items);
1745 if is_macro_use {
1746 self.import_all_legacy_macros(module_id);
1747 }
1748 }
1749 }
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)
1755 {
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)
1761 .cfg()
1762 .map_or(true, |cfg| self.is_cfg_enabled(&cfg));
1763 if is_enabled {
1764 let module_id = self.push_child_module(
1765 module.name.clone(),
1766 ast_id,
1767 Some((file_id, is_mod_rs)),
1768 &self.item_tree[module.visibility],
1769 module_id,
1770 );
1771 ModCollector {
1772 def_collector: self.def_collector,
1773 macro_depth: self.macro_depth,
1774 module_id,
1775 tree_id: TreeId::new(file_id.into(), None),
1776 item_tree: &item_tree,
1777 mod_dir,
1778 }
1779 .collect_in_top_module(item_tree.top_level_items());
1780 let is_macro_use = is_macro_use
1781 || item_tree
1782 .top_level_attrs(db, krate)
1783 .by_key("macro_use")
1784 .exists();
1785 if is_macro_use {
1786 self.import_all_legacy_macros(module_id);
1787 }
1788 }
1789 }
1790 Err(candidates) => {
1791 self.push_child_module(
1792 module.name.clone(),
1793 ast_id,
1794 None,
1795 &self.item_tree[module.visibility],
1796 module_id,
1797 );
1798 self.def_collector.def_map.diagnostics.push(
1799 DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
1800 );
1801 }
1802 };
1803 }
1804 }
1805 }
1806
1807 fn push_child_module(
1808 &mut self,
1809 name: Name,
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;
1816 let vis = 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),
1824 },
1825 Some((definition, is_mod_rs)) => ModuleOrigin::File {
1826 declaration,
1827 definition,
1828 is_mod_rs,
1829 declaration_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
1830 },
1831 };
1832
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() {
1836 for &mac in &mac {
1837 modules[res].scope.define_legacy_macro(name.clone(), mac);
1838 }
1839 }
1840 modules[self.module_id].children.insert(name.clone(), res);
1841
1842 let module = def_map.module_id(res);
1843 let def = ModuleDefId::from(module);
1844
1845 def_map.modules[self.module_id].scope.declare(def);
1846 self.def_collector.update(
1847 self.module_id,
1848 &[(Some(name), PerNs::from_def(def, vis, false))],
1849 vis,
1850 ImportType::Named,
1851 );
1852 res
1853 }
1854
1855 /// Resolves attributes on an item.
1856 ///
1857 /// Returns `Err` when some attributes could not be resolved to builtins and have been
1858 /// registered as unresolved.
1859 ///
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(
1863 &mut self,
1864 attrs: &Attrs,
1865 mod_item: ModItem,
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();
1870 let iter = attrs
1871 .iter()
1872 .dedup_by(|a, b| {
1873 // FIXME: this should not be required, all attributes on an item should have a
1874 // unique ID!
1875 // Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
1876 // #[cfg_attr(not(off), unresolved, unresolved)]
1877 // struct S;
1878 // We should come up with a different way to ID attributes.
1879 a.id == b.id
1880 })
1881 .skip_while(|attr| match ignore_up_to {
1882 Some(id) if attr.id == id => {
1883 ignore_up_to = None;
1884 true
1885 }
1886 Some(_) => true,
1887 None => false,
1888 });
1889
1890 for attr in iter {
1891 if self.def_collector.def_map.is_builtin_or_registered_attr(&attr.path) {
1892 continue;
1893 }
1894 tracing::debug!("non-builtin attribute {}", attr.path);
1895
1896 let ast_id = AstIdWithPath::new(
1897 self.file_id(),
1898 mod_item.ast_id(self.item_tree),
1899 attr.path.as_ref().clone(),
1900 );
1901 self.def_collector.unresolved_macros.push(MacroDirective {
1902 module_id: self.module_id,
1903 depth: self.macro_depth + 1,
1904 kind: MacroDirectiveKind::Attr {
1905 ast_id,
1906 attr: attr.clone(),
1907 mod_item,
1908 tree: self.tree_id,
1909 },
1910 container,
1911 });
1912
1913 return Err(());
1914 }
1915
1916 Ok(())
1917 }
1918
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());
1924
1925 let export_attr = attrs.by_key("macro_export");
1926
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")
1932 }
1933 _ => false,
1934 })
1935 } else {
1936 false
1937 };
1938
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.
1942 let name;
1943 let name = match attrs.by_key("rustc_builtin_macro").string_value() {
1944 Some(it) => {
1945 // FIXME: a hacky way to create a Name from string.
1946 name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
1947 &name
1948 }
1949 None => {
1950 let explicit_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),
1954 _ => None,
1955 }
1956 });
1957 match explicit_name {
1958 Some(ident) => {
1959 name = ident.as_name();
1960 &name
1961 }
1962 None => &mac.name,
1963 }
1964 }
1965 };
1966 match find_builtin_macro(name) {
1967 Some(Either::Left(it)) => MacroExpander::BuiltIn(it),
1968 Some(Either::Right(it)) => MacroExpander::BuiltInEager(it),
1969 None => {
1970 self.def_collector
1971 .def_map
1972 .diagnostics
1973 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1974 return;
1975 }
1976 }
1977 } else {
1978 // Case 2: normal `macro_rules!` macro
1979 MacroExpander::Declarative
1980 };
1981
1982 let macro_id = MacroRulesLoc {
1983 container: module,
1984 id: ItemTreeId::new(self.tree_id, id),
1985 local_inner,
1986 expander,
1987 }
1988 .intern(self.def_collector.db);
1989 self.def_collector.define_macro_rules(
1990 self.module_id,
1991 mac.name.clone(),
1992 macro_id,
1993 is_export,
1994 );
1995 }
1996
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());
2001
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) {
2006 match expander {
2007 Either::Left(it) => MacroExpander::BuiltIn(it),
2008 Either::Right(it) => MacroExpander::BuiltInEager(it),
2009 }
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)
2014 } else {
2015 self.def_collector
2016 .def_map
2017 .diagnostics
2018 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
2019 return;
2020 }
2021 } else {
2022 // Case 2: normal `macro`
2023 MacroExpander::Declarative
2024 };
2025
2026 let macro_id =
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(
2030 self.module_id,
2031 mac.name.clone(),
2032 macro_id,
2033 &self.item_tree[mac.visibility],
2034 );
2035 }
2036
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));
2039
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,
2044 &ast_id,
2045 mac.expand_to,
2046 self.def_collector.def_map.krate,
2047 |path| {
2048 path.as_ident().and_then(|name| {
2049 self.def_collector.def_map.with_ancestor_maps(
2050 self.def_collector.db,
2051 self.module_id,
2052 &mut |map, module| {
2053 map[module]
2054 .scope
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()))
2058 },
2059 )
2060 })
2061 },
2062 &mut |err| {
2063 error.get_or_insert(err);
2064 },
2065 ) {
2066 Ok(Ok(macro_call_id)) => {
2067 // Legacy macros need to be expanded immediately, so that any macros they produce
2068 // are in scope.
2069 self.def_collector.collect_macro_expansion(
2070 self.module_id,
2071 macro_call_id,
2072 self.macro_depth + 1,
2073 container,
2074 );
2075
2076 if let Some(err) = error {
2077 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
2078 self.module_id,
2079 MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
2080 err.to_string(),
2081 ));
2082 }
2083
2084 return;
2085 }
2086 Ok(Err(_)) => {
2087 // Built-in macro failed eager expansion.
2088
2089 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
2090 self.module_id,
2091 MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
2092 error.unwrap().to_string(),
2093 ));
2094 return;
2095 }
2096 Err(UnresolvedMacro { .. }) => (),
2097 }
2098
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 },
2104 container,
2105 });
2106 }
2107
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)
2113 });
2114 }
2115 }
2116
2117 fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
2118 self.def_collector.cfg_options.check(cfg) != Some(false)
2119 }
2120
2121 fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
2122 let ast_id = item.ast_id(self.item_tree);
2123
2124 let ast_id = InFile::new(self.file_id(), ast_id);
2125 self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
2126 self.module_id,
2127 ast_id,
2128 cfg.clone(),
2129 self.def_collector.cfg_options.clone(),
2130 ));
2131 }
2132
2133 fn file_id(&self) -> HirFileId {
2134 self.tree_id.file_id()
2135 }
2136 }
2137
2138 #[cfg(test)]
2139 mod tests {
2140 use crate::{db::DefDatabase, test_db::TestDB};
2141 use base_db::{fixture::WithFixture, SourceDatabase};
2142
2143 use super::*;
2144
2145 fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap {
2146 let mut collector = DefCollector {
2147 db,
2148 def_map,
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,
2160 };
2161 collector.seed_with_top_level();
2162 collector.collect();
2163 collector.def_map
2164 }
2165
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();
2169
2170 let edition = db.crate_graph()[krate].edition;
2171 let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
2172 let def_map =
2173 DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public));
2174 do_collect_defs(&db, def_map)
2175 }
2176
2177 #[test]
2178 fn test_macro_expand_will_stop_1() {
2179 do_resolve(
2180 r#"
2181 macro_rules! foo {
2182 ($($ty:ty)*) => { foo!($($ty)*); }
2183 }
2184 foo!(KABOOM);
2185 "#,
2186 );
2187 do_resolve(
2188 r#"
2189 macro_rules! foo {
2190 ($($ty:ty)*) => { foo!(() $($ty)*); }
2191 }
2192 foo!(KABOOM);
2193 "#,
2194 );
2195 }
2196
2197 #[ignore]
2198 #[test]
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.
2203 //
2204 // We need to find a way to fail this faster.
2205 do_resolve(
2206 r#"
2207 macro_rules! foo {
2208 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
2209 }
2210 foo!(KABOOM);
2211 "#,
2212 );
2213 }
2214 }