]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / hir-def / src / nameres / collector.rs
CommitLineData
064997fb
FG
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
6use std::{iter, mem};
7
8use base_db::{CrateId, Edition, FileId};
9use cfg::{CfgExpr, CfgOptions};
10use either::Either;
11use 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};
21use itertools::{izip, Itertools};
22use la_arena::Idx;
23use limit::Limit;
24use rustc_hash::{FxHashMap, FxHashSet};
25use stdx::always;
26use syntax::{ast, SmolStr};
27
28use 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,
f25598a0 43 proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
064997fb
FG
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
55static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
56static EXPANSION_DEPTH_LIMIT: Limit = Limit::new(128);
57static FIXED_POINT_LIMIT: Limit = Limit::new(8192);
58
59pub(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
f25598a0 70 deps.insert(dep.as_name(), dep_root);
064997fb
FG
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)]
127enum 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
136impl 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)]
146enum 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)]
152struct 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
163impl 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)]
214struct ImportDirective {
487cf647 215 /// The module this import directive is in.
064997fb
FG
216 module_id: LocalModuleId,
217 import: Import,
218 status: PartialResolvedImport,
219}
220
221#[derive(Clone, Debug, Eq, PartialEq)]
222struct MacroDirective {
223 module_id: LocalModuleId,
224 depth: usize,
225 kind: MacroDirectiveKind,
226 container: ItemContainerId,
227}
228
229#[derive(Clone, Debug, Eq, PartialEq)]
230enum MacroDirectiveKind {
231 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo },
232 Derive { ast_id: AstIdWithPath<ast::Adt>, derive_attr: AttrId, derive_pos: usize },
233 Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem, tree: TreeId },
234}
235
236/// Walks the tree of module recursively
237struct DefCollector<'a> {
238 db: &'a dyn DefDatabase,
239 def_map: DefMap,
240 deps: FxHashMap<Name, ModuleId>,
241 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
242 unresolved_imports: Vec<ImportDirective>,
243 indeterminate_imports: Vec<ImportDirective>,
244 unresolved_macros: Vec<MacroDirective>,
245 mod_dirs: FxHashMap<LocalModuleId, ModDir>,
246 cfg_options: &'a CfgOptions,
247 /// List of procedural macros defined by this crate. This is read from the dynamic library
248 /// built by the build system, and is the list of proc. macros we can actually expand. It is
249 /// empty when proc. macro support is disabled (in which case we still do name resolution for
250 /// them).
251 proc_macros: Vec<(Name, ProcMacroExpander)>,
252 is_proc_macro: bool,
253 from_glob_import: PerNsGlobImports,
254 /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute.
255 /// This map is used to skip all attributes up to and including the one that failed to resolve,
256 /// in order to not expand them twice.
257 ///
258 /// This also stores the attributes to skip when we resolve derive helpers and non-macro
259 /// non-builtin attributes in general.
260 skip_attrs: FxHashMap<InFile<ModItem>, AttrId>,
261}
262
263impl DefCollector<'_> {
264 fn seed_with_top_level(&mut self) {
265 let _p = profile::span("seed_with_top_level");
266
267 let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
268 let item_tree = self.db.file_item_tree(file_id.into());
269 let module_id = self.def_map.root;
270
271 let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
272 if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
273 self.inject_prelude(&attrs);
274
275 // Process other crate-level attributes.
276 for attr in &*attrs {
277 let attr_name = match attr.path.as_ident() {
278 Some(name) => name,
279 None => continue,
280 };
281
282 if *attr_name == hir_expand::name![recursion_limit] {
283 if let Some(limit) = attr.string_value() {
284 if let Ok(limit) = limit.parse() {
285 self.def_map.recursion_limit = Some(limit);
286 }
287 }
288 continue;
289 }
290
291 if *attr_name == hir_expand::name![crate_type] {
292 if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
293 self.is_proc_macro = true;
294 }
295 continue;
296 }
297
f2b60f7d
FG
298 if *attr_name == hir_expand::name![feature] {
299 let features =
300 attr.parse_path_comma_token_tree().into_iter().flatten().filter_map(
301 |feat| match feat.segments() {
302 [name] => Some(name.to_smol_str()),
303 _ => None,
304 },
305 );
306 self.def_map.unstable_features.extend(features);
307 }
308
064997fb
FG
309 let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
310 || *attr_name == hir_expand::name![register_tool];
311 if !attr_is_register_like {
312 continue;
313 }
314
315 let registered_name = match attr.single_ident_value() {
316 Some(ident) => ident.as_name(),
317 _ => continue,
318 };
319
320 if *attr_name == hir_expand::name![register_attr] {
321 self.def_map.registered_attrs.push(registered_name.to_smol_str());
322 cov_mark::hit!(register_attr);
323 } else {
324 self.def_map.registered_tools.push(registered_name.to_smol_str());
325 cov_mark::hit!(register_tool);
326 }
327 }
328
329 ModCollector {
330 def_collector: self,
331 macro_depth: 0,
332 module_id,
333 tree_id: TreeId::new(file_id.into(), None),
334 item_tree: &item_tree,
335 mod_dir: ModDir::root(),
336 }
337 .collect_in_top_module(item_tree.top_level_items());
338 }
339 }
340
341 fn seed_with_inner(&mut self, tree_id: TreeId) {
342 let item_tree = tree_id.item_tree(self.db);
343 let module_id = self.def_map.root;
344
345 let is_cfg_enabled = item_tree
346 .top_level_attrs(self.db, self.def_map.krate)
347 .cfg()
348 .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false));
349 if is_cfg_enabled {
350 ModCollector {
351 def_collector: self,
352 macro_depth: 0,
353 module_id,
354 tree_id,
355 item_tree: &item_tree,
356 mod_dir: ModDir::root(),
357 }
358 .collect_in_top_module(item_tree.top_level_items());
359 }
360 }
361
362 fn resolution_loop(&mut self) {
363 let _p = profile::span("DefCollector::resolution_loop");
364
365 // main name resolution fixed-point loop.
366 let mut i = 0;
367 'resolve_attr: loop {
368 'resolve_macros: loop {
369 self.db.unwind_if_cancelled();
370
371 {
372 let _p = profile::span("resolve_imports loop");
373
374 'resolve_imports: loop {
375 if self.resolve_imports() == ReachedFixedPoint::Yes {
376 break 'resolve_imports;
377 }
378 }
379 }
380 if self.resolve_macros() == ReachedFixedPoint::Yes {
381 break 'resolve_macros;
382 }
383
384 i += 1;
385 if FIXED_POINT_LIMIT.check(i).is_err() {
386 tracing::error!("name resolution is stuck");
387 break 'resolve_attr;
388 }
389 }
390
391 if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
392 break 'resolve_attr;
393 }
394 }
395 }
396
397 fn collect(&mut self) {
398 let _p = profile::span("DefCollector::collect");
399
400 self.resolution_loop();
401
402 // Resolve all indeterminate resolved imports again
403 // As some of the macros will expand newly import shadowing partial resolved imports
404 // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
405 // correctly
406 let partial_resolved = self.indeterminate_imports.drain(..).map(|directive| {
407 ImportDirective { status: PartialResolvedImport::Unresolved, ..directive }
408 });
409 self.unresolved_imports.extend(partial_resolved);
410 self.resolve_imports();
411
412 let unresolved_imports = mem::take(&mut self.unresolved_imports);
413 // show unresolved imports in completion, etc
414 for directive in &unresolved_imports {
415 self.record_resolved_import(directive);
416 }
417 self.unresolved_imports = unresolved_imports;
418
419 if self.is_proc_macro {
420 // A crate exporting procedural macros is not allowed to export anything else.
421 //
422 // Additionally, while the proc macro entry points must be `pub`, they are not publicly
423 // exported in type/value namespace. This function reduces the visibility of all items
424 // in the crate root that aren't proc macros.
425 let root = self.def_map.root;
426 let module_id = self.def_map.module_id(root);
427 let root = &mut self.def_map.modules[root];
428 root.scope.censor_non_proc_macros(module_id);
429 }
430 }
431
432 /// When the fixed-point loop reaches a stable state, we might still have
433 /// some unresolved attributes left over. This takes one of them, and feeds
434 /// the item it's applied to back into name resolution.
435 ///
436 /// This effectively ignores the fact that the macro is there and just treats the items as
437 /// normal code.
438 ///
439 /// This improves UX for unresolved attributes, and replicates the
440 /// behavior before we supported proc. attribute macros.
441 fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
442 cov_mark::hit!(unresolved_attribute_fallback);
443
444 let unresolved_attr =
445 self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive
446 .kind
447 {
448 MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } => {
449 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
450 directive.module_id,
451 MacroCallKind::Attr {
452 ast_id: ast_id.ast_id,
453 attr_args: Default::default(),
454 invoc_attr_index: attr.id.ast_index,
455 is_derive: false,
456 },
457 attr.path().clone(),
458 ));
459
460 self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
461
462 Some((idx, directive, *mod_item, *tree))
463 }
464 _ => None,
465 });
466
467 match unresolved_attr {
468 Some((pos, &MacroDirective { module_id, depth, container, .. }, mod_item, tree_id)) => {
469 let item_tree = &tree_id.item_tree(self.db);
470 let mod_dir = self.mod_dirs[&module_id].clone();
471 ModCollector {
472 def_collector: self,
473 macro_depth: depth,
474 module_id,
475 tree_id,
476 item_tree,
477 mod_dir,
478 }
479 .collect(&[mod_item], container);
480
481 self.unresolved_macros.swap_remove(pos);
482 // Continue name resolution with the new data.
483 ReachedFixedPoint::No
484 }
485 None => ReachedFixedPoint::Yes,
486 }
487 }
488
489 fn inject_prelude(&mut self, crate_attrs: &Attrs) {
490 // See compiler/rustc_builtin_macros/src/standard_library_imports.rs
491
492 if crate_attrs.by_key("no_core").exists() {
493 // libcore does not get a prelude.
494 return;
495 }
496
497 let krate = if crate_attrs.by_key("no_std").exists() {
498 name![core]
499 } else {
500 let std = name![std];
501 if self.def_map.extern_prelude().any(|(name, _)| *name == std) {
502 std
503 } else {
504 // If `std` does not exist for some reason, fall back to core. This mostly helps
505 // keep r-a's own tests minimal.
506 name![core]
507 }
508 };
509
510 let edition = match self.def_map.edition {
511 Edition::Edition2015 => name![rust_2015],
512 Edition::Edition2018 => name![rust_2018],
513 Edition::Edition2021 => name![rust_2021],
514 };
515
f2b60f7d
FG
516 let path_kind = match self.def_map.edition {
517 Edition::Edition2015 => PathKind::Plain,
518 _ => PathKind::Abs,
064997fb
FG
519 };
520 let path =
521 ModPath::from_segments(path_kind, [krate.clone(), name![prelude], edition].into_iter());
522 // Fall back to the older `std::prelude::v1` for compatibility with Rust <1.52.0
523 // FIXME remove this fallback
524 let fallback_path =
525 ModPath::from_segments(path_kind, [krate, name![prelude], name![v1]].into_iter());
526
527 for path in &[path, fallback_path] {
528 let (per_ns, _) = self.def_map.resolve_path(
529 self.db,
530 self.def_map.root,
531 path,
532 BuiltinShadowMode::Other,
533 );
534
535 match per_ns.types {
536 Some((ModuleDefId::ModuleId(m), _)) => {
537 self.def_map.prelude = Some(m);
2b03887a 538 break;
064997fb
FG
539 }
540 types => {
541 tracing::debug!(
542 "could not resolve prelude path `{}` to module (resolved to {:?})",
543 path,
544 types
545 );
546 }
547 }
548 }
549 }
550
551 /// Adds a definition of procedural macro `name` to the root module.
552 ///
553 /// # Notes on procedural macro resolution
554 ///
555 /// Procedural macro functionality is provided by the build system: It has to build the proc
556 /// macro and pass the resulting dynamic library to rust-analyzer.
557 ///
558 /// When procedural macro support is enabled, the list of proc macros exported by a crate is
559 /// known before we resolve names in the crate. This list is stored in `self.proc_macros` and is
560 /// derived from the dynamic library.
561 ///
562 /// However, we *also* would like to be able to at least *resolve* macros on our own, without
563 /// help by the build system. So, when the macro isn't found in `self.proc_macros`, we instead
564 /// use a dummy expander that always errors. This comes with the drawback of macros potentially
565 /// going out of sync with what the build system sees (since we resolve using VFS state, but
566 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
567 fn export_proc_macro(
568 &mut self,
569 def: ProcMacroDef,
570 id: ItemTreeId<item_tree::Function>,
571 fn_id: FunctionId,
572 module_id: ModuleId,
573 ) {
574 let kind = def.kind.to_basedb_kind();
575 let (expander, kind) = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
576 Some(&(_, expander)) => (expander, kind),
577 None => (ProcMacroExpander::dummy(self.def_map.krate), kind),
578 };
579
580 let proc_macro_id =
581 ProcMacroLoc { container: module_id, id, expander, kind }.intern(self.db);
582 self.define_proc_macro(def.name.clone(), proc_macro_id);
583 if let ProcMacroKind::CustomDerive { helpers } = def.kind {
584 self.def_map
585 .exported_derives
586 .insert(macro_id_to_def_id(self.db, proc_macro_id.into()), helpers);
587 }
588 self.def_map.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
589 }
590
591 /// Define a macro with `macro_rules`.
592 ///
593 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
594 /// then it is also defined in the root module scope.
595 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
596 ///
597 /// It is surprising that the macro will never be in the current module scope.
598 /// These code fails with "unresolved import/macro",
599 /// ```rust,compile_fail
600 /// mod m { macro_rules! foo { () => {} } }
601 /// use m::foo as bar;
602 /// ```
603 ///
604 /// ```rust,compile_fail
605 /// macro_rules! foo { () => {} }
606 /// self::foo!();
607 /// crate::foo!();
608 /// ```
609 ///
610 /// Well, this code compiles, because the plain path `foo` in `use` is searched
611 /// in the legacy textual scope only.
612 /// ```rust
613 /// macro_rules! foo { () => {} }
614 /// use foo as bar;
615 /// ```
616 fn define_macro_rules(
617 &mut self,
618 module_id: LocalModuleId,
619 name: Name,
620 macro_: MacroRulesId,
621 export: bool,
622 ) {
623 // Textual scoping
624 self.define_legacy_macro(module_id, name.clone(), macro_.into());
625
626 // Module scoping
627 // In Rust, `#[macro_export]` macros are unconditionally visible at the
628 // crate root, even if the parent modules is **not** visible.
629 if export {
630 let module_id = self.def_map.root;
631 self.def_map.modules[module_id].scope.declare(macro_.into());
632 self.update(
633 module_id,
634 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
635 Visibility::Public,
636 ImportType::Named,
637 );
638 }
639 }
640
641 /// Define a legacy textual scoped macro in module
642 ///
643 /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
644 /// It will clone all macros from parent legacy scope, whose definition is prior to
645 /// the definition of current module.
646 /// And also, `macro_use` on a module will import all legacy macros visible inside to
647 /// current legacy scope, with possible shadowing.
648 fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroId) {
649 // Always shadowing
650 self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
651 }
652
653 /// Define a macro 2.0 macro
654 ///
655 /// The scoped of macro 2.0 macro is equal to normal function
656 fn define_macro_def(
657 &mut self,
658 module_id: LocalModuleId,
659 name: Name,
660 macro_: Macro2Id,
661 vis: &RawVisibility,
662 ) {
663 let vis =
664 self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
665 self.def_map.modules[module_id].scope.declare(macro_.into());
666 self.update(
667 module_id,
668 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
669 vis,
670 ImportType::Named,
671 );
672 }
673
674 /// Define a proc macro
675 ///
676 /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
677 /// And unconditionally exported.
678 fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) {
679 let module_id = self.def_map.root;
680 self.def_map.modules[module_id].scope.declare(macro_.into());
681 self.update(
682 module_id,
683 &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
684 Visibility::Public,
685 ImportType::Named,
686 );
687 }
688
689 /// Import macros from `#[macro_use] extern crate`.
690 fn import_macros_from_extern_crate(
691 &mut self,
692 current_module_id: LocalModuleId,
693 extern_crate: &item_tree::ExternCrate,
694 ) {
695 tracing::debug!(
696 "importing macros from extern crate: {:?} ({:?})",
697 extern_crate,
698 self.def_map.edition,
699 );
700
701 if let Some(m) = self.resolve_extern_crate(&extern_crate.name) {
702 if m == self.def_map.module_id(current_module_id) {
703 cov_mark::hit!(ignore_macro_use_extern_crate_self);
704 return;
705 }
706
707 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
708 self.import_all_macros_exported(current_module_id, m.krate);
709 }
710 }
711
712 /// Import all exported macros from another crate
713 ///
714 /// Exported macros are just all macros in the root module scope.
715 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
716 /// created by `use` in the root module, ignoring the visibility of `use`.
717 fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
718 let def_map = self.db.crate_def_map(krate);
719 for (name, def) in def_map[def_map.root].scope.macros() {
720 // `#[macro_use]` brings macros into legacy scope. Yes, even non-`macro_rules!` macros.
721 self.define_legacy_macro(current_module_id, name.clone(), def);
722 }
723 }
724
725 /// Tries to resolve every currently unresolved import.
726 fn resolve_imports(&mut self) -> ReachedFixedPoint {
727 let mut res = ReachedFixedPoint::Yes;
728 let imports = mem::take(&mut self.unresolved_imports);
729
730 self.unresolved_imports = imports
731 .into_iter()
732 .filter_map(|mut directive| {
733 directive.status = self.resolve_import(directive.module_id, &directive.import);
734 match directive.status {
735 PartialResolvedImport::Indeterminate(_) => {
736 self.record_resolved_import(&directive);
737 self.indeterminate_imports.push(directive);
738 res = ReachedFixedPoint::No;
739 None
740 }
741 PartialResolvedImport::Resolved(_) => {
742 self.record_resolved_import(&directive);
743 res = ReachedFixedPoint::No;
744 None
745 }
746 PartialResolvedImport::Unresolved => Some(directive),
747 }
748 })
749 .collect();
750 res
751 }
752
753 fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport {
754 let _p = profile::span("resolve_import").detail(|| format!("{}", import.path));
755 tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
756 if import.is_extern_crate {
757 let name = import
758 .path
759 .as_ident()
760 .expect("extern crate should have been desugared to one-element path");
761
762 let res = self.resolve_extern_crate(name);
763
764 match res {
765 Some(res) => {
766 PartialResolvedImport::Resolved(PerNs::types(res.into(), Visibility::Public))
767 }
768 None => PartialResolvedImport::Unresolved,
769 }
770 } else {
771 let res = self.def_map.resolve_path_fp_with_macro(
772 self.db,
773 ResolveMode::Import,
774 module_id,
775 &import.path,
776 BuiltinShadowMode::Module,
777 );
778
779 let def = res.resolved_def;
780 if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
781 return PartialResolvedImport::Unresolved;
782 }
783
784 if let Some(krate) = res.krate {
785 if krate != self.def_map.krate {
786 return PartialResolvedImport::Resolved(
787 def.filter_visibility(|v| matches!(v, Visibility::Public)),
788 );
789 }
790 }
791
792 // Check whether all namespace is resolved
793 if def.take_types().is_some()
794 && def.take_values().is_some()
795 && def.take_macros().is_some()
796 {
797 PartialResolvedImport::Resolved(def)
798 } else {
799 PartialResolvedImport::Indeterminate(def)
800 }
801 }
802 }
803
804 fn resolve_extern_crate(&self, name: &Name) -> Option<ModuleId> {
805 if *name == name!(self) {
806 cov_mark::hit!(extern_crate_self_as);
807 let root = match self.def_map.block {
808 Some(_) => {
809 let def_map = self.def_map.crate_root(self.db).def_map(self.db);
810 def_map.module_id(def_map.root())
811 }
812 None => self.def_map.module_id(self.def_map.root()),
813 };
814 Some(root)
815 } else {
816 self.deps.get(name).copied()
817 }
818 }
819
820 fn record_resolved_import(&mut self, directive: &ImportDirective) {
821 let _p = profile::span("record_resolved_import");
822
823 let module_id = directive.module_id;
824 let import = &directive.import;
825 let mut def = directive.status.namespaces();
826 let vis = self
827 .def_map
828 .resolve_visibility(self.db, module_id, &directive.import.visibility)
829 .unwrap_or(Visibility::Public);
830
831 match import.kind {
832 ImportKind::Plain | ImportKind::TypeOnly => {
833 let name = match &import.alias {
834 Some(ImportAlias::Alias(name)) => Some(name),
835 Some(ImportAlias::Underscore) => None,
836 None => match import.path.segments().last() {
837 Some(last_segment) => Some(last_segment),
838 None => {
839 cov_mark::hit!(bogus_paths);
840 return;
841 }
842 },
843 };
844
845 if import.kind == ImportKind::TypeOnly {
846 def.values = None;
847 def.macros = None;
848 }
849
850 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
851
852 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
f2b60f7d
FG
853 if import.is_extern_crate
854 && self.def_map.block.is_none()
855 && module_id == self.def_map.root
856 {
064997fb
FG
857 if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name)
858 {
859 self.def_map.extern_prelude.insert(name.clone(), def);
860 }
861 }
862
863 self.update(module_id, &[(name.cloned(), def)], vis, ImportType::Named);
864 }
865 ImportKind::Glob => {
866 tracing::debug!("glob import: {:?}", import);
867 match def.take_types() {
868 Some(ModuleDefId::ModuleId(m)) => {
869 if import.is_prelude {
870 // Note: This dodgily overrides the injected prelude. The rustc
871 // implementation seems to work the same though.
872 cov_mark::hit!(std_prelude);
873 self.def_map.prelude = Some(m);
874 } else if m.krate != self.def_map.krate {
875 cov_mark::hit!(glob_across_crates);
876 // glob import from other crate => we can just import everything once
877 let item_map = m.def_map(self.db);
878 let scope = &item_map[m.local_id].scope;
879
880 // Module scoped macros is included
881 let items = scope
882 .resolutions()
883 // only keep visible names...
884 .map(|(n, res)| {
885 (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
886 })
887 .filter(|(_, res)| !res.is_none())
888 .collect::<Vec<_>>();
889
890 self.update(module_id, &items, vis, ImportType::Glob);
891 } else {
892 // glob import from same crate => we do an initial
893 // import, and then need to propagate any further
894 // additions
895 let def_map;
896 let scope = if m.block == self.def_map.block_id() {
897 &self.def_map[m.local_id].scope
898 } else {
899 def_map = m.def_map(self.db);
900 &def_map[m.local_id].scope
901 };
902
903 // Module scoped macros is included
904 let items = scope
905 .resolutions()
906 // only keep visible names...
907 .map(|(n, res)| {
908 (
909 n,
910 res.filter_visibility(|v| {
911 v.is_visible_from_def_map(
912 self.db,
913 &self.def_map,
914 module_id,
915 )
916 }),
917 )
918 })
919 .filter(|(_, res)| !res.is_none())
920 .collect::<Vec<_>>();
921
922 self.update(module_id, &items, vis, ImportType::Glob);
923 // record the glob import in case we add further items
924 let glob = self.glob_imports.entry(m.local_id).or_default();
925 if !glob.iter().any(|(mid, _)| *mid == module_id) {
926 glob.push((module_id, vis));
927 }
928 }
929 }
930 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
931 cov_mark::hit!(glob_enum);
932 // glob import from enum => just import all the variants
933
934 // XXX: urgh, so this works by accident! Here, we look at
935 // the enum data, and, in theory, this might require us to
936 // look back at the crate_def_map, creating a cycle. For
937 // example, `enum E { crate::some_macro!(); }`. Luckily, the
938 // only kind of macro that is allowed inside enum is a
939 // `cfg_macro`, and we don't need to run name resolution for
940 // it, but this is sheer luck!
941 let enum_data = self.db.enum_data(e);
942 let resolutions = enum_data
943 .variants
944 .iter()
945 .map(|(local_id, variant_data)| {
946 let name = variant_data.name.clone();
947 let variant = EnumVariantId { parent: e, local_id };
948 let res = PerNs::both(variant.into(), variant.into(), vis);
949 (Some(name), res)
950 })
951 .collect::<Vec<_>>();
952 self.update(module_id, &resolutions, vis, ImportType::Glob);
953 }
954 Some(d) => {
955 tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
956 }
957 None => {
958 tracing::debug!("glob import {:?} didn't resolve as type", import);
959 }
960 }
961 }
962 }
963 }
964
965 fn update(
966 &mut self,
487cf647 967 // The module for which `resolutions` have been resolve
064997fb
FG
968 module_id: LocalModuleId,
969 resolutions: &[(Option<Name>, PerNs)],
487cf647 970 // Visibility this import will have
064997fb
FG
971 vis: Visibility,
972 import_type: ImportType,
973 ) {
974 self.db.unwind_if_cancelled();
975 self.update_recursive(module_id, resolutions, vis, import_type, 0)
976 }
977
978 fn update_recursive(
979 &mut self,
487cf647 980 // The module for which `resolutions` have been resolve
064997fb
FG
981 module_id: LocalModuleId,
982 resolutions: &[(Option<Name>, PerNs)],
983 // All resolutions are imported with this visibility; the visibilities in
984 // the `PerNs` values are ignored and overwritten
985 vis: Visibility,
986 import_type: ImportType,
987 depth: usize,
988 ) {
989 if GLOB_RECURSION_LIMIT.check(depth).is_err() {
990 // prevent stack overflows (but this shouldn't be possible)
991 panic!("infinite recursion in glob imports!");
992 }
993 let mut changed = false;
994
995 for (name, res) in resolutions {
996 match name {
997 Some(name) => {
998 let scope = &mut self.def_map.modules[module_id].scope;
999 changed |= scope.push_res_with_import(
1000 &mut self.from_glob_import,
1001 (module_id, name.clone()),
1002 res.with_visibility(vis),
1003 import_type,
1004 );
1005 }
1006 None => {
1007 let tr = match res.take_types() {
1008 Some(ModuleDefId::TraitId(tr)) => tr,
1009 Some(other) => {
1010 tracing::debug!("non-trait `_` import of {:?}", other);
1011 continue;
1012 }
1013 None => continue,
1014 };
1015 let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
1016 let should_update = match old_vis {
1017 None => true,
1018 Some(old_vis) => {
1019 let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| {
f25598a0 1020 panic!("`Tr as _` imports with unrelated visibilities {old_vis:?} and {vis:?} (trait {tr:?})");
064997fb
FG
1021 });
1022
1023 if max_vis == old_vis {
1024 false
1025 } else {
1026 cov_mark::hit!(upgrade_underscore_visibility);
1027 true
1028 }
1029 }
1030 };
1031
1032 if should_update {
1033 changed = true;
1034 self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
1035 }
1036 }
1037 }
1038 }
1039
1040 if !changed {
1041 return;
1042 }
1043 let glob_imports = self
1044 .glob_imports
1045 .get(&module_id)
1046 .into_iter()
1047 .flatten()
1048 .filter(|(glob_importing_module, _)| {
1049 // we know all resolutions have the same visibility (`vis`), so we
1050 // just need to check that once
1051 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
1052 })
1053 .cloned()
1054 .collect::<Vec<_>>();
1055
1056 for (glob_importing_module, glob_import_vis) in glob_imports {
1057 self.update_recursive(
1058 glob_importing_module,
1059 resolutions,
1060 glob_import_vis,
1061 ImportType::Glob,
1062 depth + 1,
1063 );
1064 }
1065 }
1066
1067 fn resolve_macros(&mut self) -> ReachedFixedPoint {
1068 let mut macros = mem::take(&mut self.unresolved_macros);
1069 let mut resolved = Vec::new();
1070 let mut push_resolved = |directive: &MacroDirective, call_id| {
1071 resolved.push((directive.module_id, directive.depth, directive.container, call_id));
1072 };
1073 let mut res = ReachedFixedPoint::Yes;
1074 macros.retain(|directive| {
1075 let resolver = |path| {
1076 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1077 self.db,
1078 ResolveMode::Other,
1079 directive.module_id,
1080 &path,
1081 BuiltinShadowMode::Module,
1082 );
1083 resolved_res
1084 .resolved_def
1085 .take_macros()
1086 .map(|it| (it, macro_id_to_def_id(self.db, it)))
1087 };
1088 let resolver_def_id = |path| resolver(path).map(|(_, it)| it);
1089
1090 match &directive.kind {
1091 MacroDirectiveKind::FnLike { ast_id, expand_to } => {
1092 let call_id = macro_call_as_call_id(
1093 self.db,
1094 ast_id,
1095 *expand_to,
1096 self.def_map.krate,
f25598a0 1097 resolver_def_id,
064997fb
FG
1098 &mut |_err| (),
1099 );
1100 if let Ok(Ok(call_id)) = call_id {
1101 push_resolved(directive, call_id);
1102 res = ReachedFixedPoint::No;
1103 return false;
1104 }
1105 }
1106 MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
1107 let id = derive_macro_as_call_id(
1108 self.db,
1109 ast_id,
1110 *derive_attr,
1111 *derive_pos as u32,
1112 self.def_map.krate,
f25598a0 1113 resolver,
064997fb
FG
1114 );
1115
1116 if let Ok((macro_id, def_id, call_id)) = id {
1117 self.def_map.modules[directive.module_id].scope.set_derive_macro_invoc(
1118 ast_id.ast_id,
1119 call_id,
1120 *derive_attr,
1121 *derive_pos,
1122 );
1123 // Record its helper attributes.
1124 if def_id.krate != self.def_map.krate {
1125 let def_map = self.db.crate_def_map(def_id.krate);
1126 if let Some(helpers) = def_map.exported_derives.get(&def_id) {
1127 self.def_map
1128 .derive_helpers_in_scope
1129 .entry(ast_id.ast_id.map(|it| it.upcast()))
1130 .or_default()
1131 .extend(izip!(
1132 helpers.iter().cloned(),
1133 iter::repeat(macro_id),
1134 iter::repeat(call_id),
1135 ));
1136 }
1137 }
1138
1139 push_resolved(directive, call_id);
1140 res = ReachedFixedPoint::No;
1141 return false;
1142 }
1143 }
1144 MacroDirectiveKind::Attr { ast_id: file_ast_id, mod_item, attr, tree } => {
1145 let &AstIdWithPath { ast_id, ref path } = file_ast_id;
1146 let file_id = ast_id.file_id;
1147
1148 let mut recollect_without = |collector: &mut Self| {
1149 // Remove the original directive since we resolved it.
1150 let mod_dir = collector.mod_dirs[&directive.module_id].clone();
1151 collector.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
1152
1153 let item_tree = tree.item_tree(self.db);
1154 ModCollector {
1155 def_collector: collector,
1156 macro_depth: directive.depth,
1157 module_id: directive.module_id,
1158 tree_id: *tree,
1159 item_tree: &item_tree,
1160 mod_dir,
1161 }
1162 .collect(&[*mod_item], directive.container);
1163 res = ReachedFixedPoint::No;
1164 false
1165 };
1166
1167 if let Some(ident) = path.as_ident() {
1168 if let Some(helpers) = self.def_map.derive_helpers_in_scope.get(&ast_id) {
1169 if helpers.iter().any(|(it, ..)| it == ident) {
1170 cov_mark::hit!(resolved_derive_helper);
1171 // Resolved to derive helper. Collect the item's attributes again,
1172 // starting after the derive helper.
1173 return recollect_without(self);
1174 }
1175 }
1176 }
1177
1178 let def = match resolver_def_id(path.clone()) {
1179 Some(def) if def.is_attribute() => def,
1180 _ => return true,
1181 };
1182 if matches!(
1183 def,
1184 MacroDefId { kind:MacroDefKind::BuiltInAttr(expander, _),.. }
1185 if expander.is_derive()
1186 ) {
1187 // Resolved to `#[derive]`
1188
1189 let item_tree = tree.item_tree(self.db);
1190 let ast_adt_id: FileAstId<ast::Adt> = match *mod_item {
1191 ModItem::Struct(strukt) => item_tree[strukt].ast_id().upcast(),
1192 ModItem::Union(union) => item_tree[union].ast_id().upcast(),
1193 ModItem::Enum(enum_) => item_tree[enum_].ast_id().upcast(),
1194 _ => {
1195 let diag = DefDiagnostic::invalid_derive_target(
1196 directive.module_id,
1197 ast_id,
1198 attr.id,
1199 );
1200 self.def_map.diagnostics.push(diag);
1201 return recollect_without(self);
1202 }
1203 };
1204 let ast_id = ast_id.with_value(ast_adt_id);
1205
1206 match attr.parse_path_comma_token_tree() {
1207 Some(derive_macros) => {
1208 let mut len = 0;
1209 for (idx, path) in derive_macros.enumerate() {
1210 let ast_id = AstIdWithPath::new(file_id, ast_id.value, path);
1211 self.unresolved_macros.push(MacroDirective {
1212 module_id: directive.module_id,
1213 depth: directive.depth + 1,
1214 kind: MacroDirectiveKind::Derive {
1215 ast_id,
1216 derive_attr: attr.id,
1217 derive_pos: idx,
1218 },
1219 container: directive.container,
1220 });
1221 len = idx;
1222 }
1223
1224 // We treat the #[derive] macro as an attribute call, but we do not resolve it for nameres collection.
1225 // This is just a trick to be able to resolve the input to derives as proper paths.
1226 // Check the comment in [`builtin_attr_macro`].
1227 let call_id = attr_macro_as_call_id(
1228 self.db,
1229 file_ast_id,
1230 attr,
1231 self.def_map.krate,
1232 def,
1233 true,
1234 );
1235 self.def_map.modules[directive.module_id]
1236 .scope
1237 .init_derive_attribute(ast_id, attr.id, call_id, len + 1);
1238 }
1239 None => {
1240 let diag = DefDiagnostic::malformed_derive(
1241 directive.module_id,
1242 ast_id,
1243 attr.id,
1244 );
1245 self.def_map.diagnostics.push(diag);
1246 }
1247 }
1248
1249 return recollect_without(self);
1250 }
1251
1252 // Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
1253 let call_id = attr_macro_as_call_id(
1254 self.db,
1255 file_ast_id,
1256 attr,
1257 self.def_map.krate,
1258 def,
1259 false,
1260 );
1261 let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
1262
1263 // If proc attribute macro expansion is disabled, skip expanding it here
1264 if !self.db.enable_proc_attr_macros() {
1265 self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
1266 directive.module_id,
1267 loc.kind,
1268 loc.def.krate,
1269 ));
1270 return recollect_without(self);
1271 }
1272
1273 // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
1274 // due to duplicating functions into macro expansions
1275 if matches!(
1276 loc.def.kind,
1277 MacroDefKind::BuiltInAttr(expander, _)
1278 if expander.is_test() || expander.is_bench()
1279 ) {
1280 return recollect_without(self);
1281 }
1282
1283 if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
1284 if exp.is_dummy() {
1285 // If there's no expander for the proc macro (e.g.
1286 // because proc macros are disabled, or building the
1287 // proc macro crate failed), report this and skip
1288 // expansion like we would if it was disabled
1289 self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
1290 directive.module_id,
1291 loc.kind,
1292 loc.def.krate,
1293 ));
1294
1295 return recollect_without(self);
1296 }
1297 }
1298
1299 self.def_map.modules[directive.module_id]
1300 .scope
1301 .add_attr_macro_invoc(ast_id, call_id);
1302
1303 push_resolved(directive, call_id);
1304 res = ReachedFixedPoint::No;
1305 return false;
1306 }
1307 }
1308
1309 true
1310 });
1311 // Attribute resolution can add unresolved macro invocations, so concatenate the lists.
1312 macros.extend(mem::take(&mut self.unresolved_macros));
1313 self.unresolved_macros = macros;
1314
1315 for (module_id, depth, container, macro_call_id) in resolved {
1316 self.collect_macro_expansion(module_id, macro_call_id, depth, container);
1317 }
1318
1319 res
1320 }
1321
1322 fn collect_macro_expansion(
1323 &mut self,
1324 module_id: LocalModuleId,
1325 macro_call_id: MacroCallId,
1326 depth: usize,
1327 container: ItemContainerId,
1328 ) {
1329 if EXPANSION_DEPTH_LIMIT.check(depth).is_err() {
1330 cov_mark::hit!(macro_expansion_overflow);
1331 tracing::warn!("macro expansion is too deep");
1332 return;
1333 }
1334 let file_id = macro_call_id.as_file();
1335
1336 // First, fetch the raw expansion result for purposes of error reporting. This goes through
1337 // `macro_expand_error` to avoid depending on the full expansion result (to improve
1338 // incrementality).
1339 let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
1340 let err = self.db.macro_expand_error(macro_call_id);
1341 if let Some(err) = err {
1342 let diag = match err {
1343 hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
1344 always!(krate == loc.def.krate);
1345 // Missing proc macros are non-fatal, so they are handled specially.
1346 DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone(), loc.def.krate)
1347 }
f25598a0 1348 _ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()),
064997fb
FG
1349 };
1350
1351 self.def_map.diagnostics.push(diag);
1352 }
1353
1354 // Then, fetch and process the item tree. This will reuse the expansion result from above.
1355 let item_tree = self.db.file_item_tree(file_id);
1356 let mod_dir = self.mod_dirs[&module_id].clone();
1357 ModCollector {
1358 def_collector: &mut *self,
1359 macro_depth: depth,
1360 tree_id: TreeId::new(file_id, None),
1361 module_id,
1362 item_tree: &item_tree,
1363 mod_dir,
1364 }
1365 .collect(item_tree.top_level_items(), container);
1366 }
1367
1368 fn finish(mut self) -> DefMap {
1369 // Emit diagnostics for all remaining unexpanded macros.
1370
1371 let _p = profile::span("DefCollector::finish");
1372
1373 for directive in &self.unresolved_macros {
1374 match &directive.kind {
1375 MacroDirectiveKind::FnLike { ast_id, expand_to } => {
1376 let macro_call_as_call_id = macro_call_as_call_id(
1377 self.db,
1378 ast_id,
1379 *expand_to,
1380 self.def_map.krate,
1381 |path| {
1382 let resolved_res = self.def_map.resolve_path_fp_with_macro(
1383 self.db,
1384 ResolveMode::Other,
1385 directive.module_id,
1386 &path,
1387 BuiltinShadowMode::Module,
1388 );
1389 resolved_res
1390 .resolved_def
1391 .take_macros()
1392 .map(|it| macro_id_to_def_id(self.db, it))
1393 },
1394 &mut |_| (),
1395 );
1396 if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
1397 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1398 directive.module_id,
1399 MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: *expand_to },
1400 path,
1401 ));
1402 }
1403 }
1404 MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
1405 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
1406 directive.module_id,
1407 MacroCallKind::Derive {
1408 ast_id: ast_id.ast_id,
1409 derive_attr_index: derive_attr.ast_index,
1410 derive_index: *derive_pos as u32,
1411 },
1412 ast_id.path.clone(),
1413 ));
1414 }
1415 // These are diagnosed by `reseed_with_unresolved_attribute`, as that function consumes them
1416 MacroDirectiveKind::Attr { .. } => {}
1417 }
1418 }
1419
1420 // Emit diagnostics for all remaining unresolved imports.
1421
1422 // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
1423 // resolve. We first emit diagnostics for unresolved extern crates and collect the missing
1424 // crate names. Then we emit diagnostics for unresolved imports, but only if the import
1425 // doesn't start with an unresolved crate's name. Due to renaming and reexports, this is a
1426 // heuristic, but it works in practice.
1427 let mut diagnosed_extern_crates = FxHashSet::default();
1428 for directive in &self.unresolved_imports {
1429 if let ImportSource::ExternCrate(krate) = directive.import.source {
1430 let item_tree = krate.item_tree(self.db);
1431 let extern_crate = &item_tree[krate.value];
1432
1433 diagnosed_extern_crates.insert(extern_crate.name.clone());
1434
1435 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
1436 directive.module_id,
1437 InFile::new(krate.file_id(), extern_crate.ast_id),
1438 ));
1439 }
1440 }
1441
1442 for directive in &self.unresolved_imports {
1443 if let ImportSource::Import { id: import, use_tree } = directive.import.source {
1444 if matches!(
1445 (directive.import.path.segments().first(), &directive.import.path.kind),
1446 (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate)
1447 ) {
1448 continue;
1449 }
1450
1451 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
1452 directive.module_id,
1453 import,
1454 use_tree,
1455 ));
1456 }
1457 }
1458
1459 self.def_map
1460 }
1461}
1462
1463/// Walks a single module, populating defs, imports and macros
1464struct ModCollector<'a, 'b> {
1465 def_collector: &'a mut DefCollector<'b>,
1466 macro_depth: usize,
1467 module_id: LocalModuleId,
1468 tree_id: TreeId,
1469 item_tree: &'a ItemTree,
1470 mod_dir: ModDir,
1471}
1472
1473impl ModCollector<'_, '_> {
1474 fn collect_in_top_module(&mut self, items: &[ModItem]) {
1475 let module = self.def_collector.def_map.module_id(self.module_id);
1476 self.collect(items, module.into())
1477 }
1478
1479 fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
1480 let krate = self.def_collector.def_map.krate;
1481
1482 // Note: don't assert that inserted value is fresh: it's simply not true
1483 // for macros.
1484 self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
1485
1486 // Prelude module is always considered to be `#[macro_use]`.
1487 if let Some(prelude_module) = self.def_collector.def_map.prelude {
1488 if prelude_module.krate != krate {
1489 cov_mark::hit!(prelude_is_macro_use);
1490 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
1491 }
1492 }
1493
1494 // This should be processed eagerly instead of deferred to resolving.
1495 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
1496 // any other items.
1497 for &item in items {
1498 let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
1499 if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
1500 if let ModItem::ExternCrate(id) = item {
1501 let import = &self.item_tree[id];
1502 let attrs = self.item_tree.attrs(
1503 self.def_collector.db,
1504 krate,
1505 ModItem::from(id).into(),
1506 );
1507 if attrs.by_key("macro_use").exists() {
1508 self.def_collector.import_macros_from_extern_crate(self.module_id, import);
1509 }
1510 }
1511 }
1512 }
1513
1514 for &item in items {
1515 let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
1516 if let Some(cfg) = attrs.cfg() {
1517 if !self.is_cfg_enabled(&cfg) {
1518 self.emit_unconfigured_diagnostic(item, &cfg);
1519 continue;
1520 }
1521 }
1522
1523 if let Err(()) = self.resolve_attributes(&attrs, item, container) {
1524 // Do not process the item. It has at least one non-builtin attribute, so the
1525 // fixed-point algorithm is required to resolve the rest of them.
1526 continue;
1527 }
1528
1529 let db = self.def_collector.db;
1530 let module = self.def_collector.def_map.module_id(self.module_id);
1531 let def_map = &mut self.def_collector.def_map;
1532 let update_def =
1533 |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
1534 def_collector.def_map.modules[self.module_id].scope.declare(id);
1535 def_collector.update(
1536 self.module_id,
1537 &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
1538 vis,
1539 ImportType::Named,
1540 )
1541 };
1542 let resolve_vis = |def_map: &DefMap, visibility| {
1543 def_map
1544 .resolve_visibility(db, self.module_id, visibility)
1545 .unwrap_or(Visibility::Public)
1546 };
1547
1548 match item {
1549 ModItem::Mod(m) => self.collect_module(m, &attrs),
1550 ModItem::Import(import_id) => {
1551 let imports = Import::from_use(
1552 db,
1553 krate,
1554 self.item_tree,
1555 ItemTreeId::new(self.tree_id, import_id),
1556 );
1557 self.def_collector.unresolved_imports.extend(imports.into_iter().map(
1558 |import| ImportDirective {
1559 module_id: self.module_id,
1560 import,
1561 status: PartialResolvedImport::Unresolved,
1562 },
1563 ));
1564 }
1565 ModItem::ExternCrate(import_id) => {
1566 self.def_collector.unresolved_imports.push(ImportDirective {
1567 module_id: self.module_id,
1568 import: Import::from_extern_crate(
1569 db,
1570 krate,
1571 self.item_tree,
1572 ItemTreeId::new(self.tree_id, import_id),
1573 ),
1574 status: PartialResolvedImport::Unresolved,
1575 })
1576 }
1577 ModItem::ExternBlock(block) => self.collect(
1578 &self.item_tree[block].children,
1579 ItemContainerId::ExternBlockId(
1580 ExternBlockLoc {
1581 container: module,
1582 id: ItemTreeId::new(self.tree_id, block),
1583 }
1584 .intern(db),
1585 ),
1586 ),
1587 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container),
1588 ModItem::MacroRules(id) => self.collect_macro_rules(id, module),
1589 ModItem::MacroDef(id) => self.collect_macro_def(id, module),
1590 ModItem::Impl(imp) => {
1591 let impl_id =
1592 ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) }
1593 .intern(db);
1594 self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
1595 }
1596 ModItem::Function(id) => {
1597 let it = &self.item_tree[id];
1598 let fn_id =
1599 FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
1600
1601 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1602 if self.def_collector.is_proc_macro {
1603 if self.module_id == def_map.root {
1604 if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) {
1605 let crate_root = def_map.module_id(def_map.root);
1606 self.def_collector.export_proc_macro(
1607 proc_macro,
1608 ItemTreeId::new(self.tree_id, id),
1609 fn_id,
1610 crate_root,
1611 );
1612 }
1613 }
1614 }
1615
1616 update_def(self.def_collector, fn_id.into(), &it.name, vis, false);
1617 }
1618 ModItem::Struct(id) => {
1619 let it = &self.item_tree[id];
1620
1621 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1622 update_def(
1623 self.def_collector,
1624 StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1625 .intern(db)
1626 .into(),
1627 &it.name,
1628 vis,
1629 !matches!(it.fields, Fields::Record(_)),
1630 );
1631 }
1632 ModItem::Union(id) => {
1633 let it = &self.item_tree[id];
1634
1635 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1636 update_def(
1637 self.def_collector,
1638 UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1639 .intern(db)
1640 .into(),
1641 &it.name,
1642 vis,
1643 false,
1644 );
1645 }
1646 ModItem::Enum(id) => {
1647 let it = &self.item_tree[id];
1648
1649 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1650 update_def(
1651 self.def_collector,
1652 EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1653 .intern(db)
1654 .into(),
1655 &it.name,
1656 vis,
1657 false,
1658 );
1659 }
1660 ModItem::Const(id) => {
1661 let it = &self.item_tree[id];
1662 let const_id =
1663 ConstLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
1664
1665 match &it.name {
1666 Some(name) => {
1667 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1668 update_def(self.def_collector, const_id.into(), name, vis, false);
1669 }
1670 None => {
1671 // const _: T = ...;
1672 self.def_collector.def_map.modules[self.module_id]
1673 .scope
1674 .define_unnamed_const(const_id);
1675 }
1676 }
1677 }
1678 ModItem::Static(id) => {
1679 let it = &self.item_tree[id];
1680
1681 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1682 update_def(
1683 self.def_collector,
1684 StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
1685 .intern(db)
1686 .into(),
1687 &it.name,
1688 vis,
1689 false,
1690 );
1691 }
1692 ModItem::Trait(id) => {
1693 let it = &self.item_tree[id];
1694
1695 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1696 update_def(
1697 self.def_collector,
1698 TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
1699 .intern(db)
1700 .into(),
1701 &it.name,
1702 vis,
1703 false,
1704 );
1705 }
1706 ModItem::TypeAlias(id) => {
1707 let it = &self.item_tree[id];
1708
1709 let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
1710 update_def(
1711 self.def_collector,
1712 TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
1713 .intern(db)
1714 .into(),
1715 &it.name,
1716 vis,
1717 false,
1718 );
1719 }
1720 }
1721 }
1722 }
1723
1724 fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
1725 let path_attr = attrs.by_key("path").string_value();
1726 let is_macro_use = attrs.by_key("macro_use").exists();
1727 let module = &self.item_tree[module_id];
1728 match &module.kind {
1729 // inline module, just recurse
1730 ModKind::Inline { items } => {
1731 let module_id = self.push_child_module(
1732 module.name.clone(),
1733 AstId::new(self.file_id(), module.ast_id),
1734 None,
1735 &self.item_tree[module.visibility],
1736 module_id,
1737 );
1738
1739 if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
1740 {
1741 ModCollector {
1742 def_collector: &mut *self.def_collector,
1743 macro_depth: self.macro_depth,
1744 module_id,
1745 tree_id: self.tree_id,
1746 item_tree: self.item_tree,
1747 mod_dir,
1748 }
1749 .collect_in_top_module(&*items);
1750 if is_macro_use {
1751 self.import_all_legacy_macros(module_id);
1752 }
1753 }
1754 }
1755 // out of line module, resolve, parse and recurse
1756 ModKind::Outline => {
1757 let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id);
1758 let db = self.def_collector.db;
1759 match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr)
1760 {
1761 Ok((file_id, is_mod_rs, mod_dir)) => {
1762 let item_tree = db.file_item_tree(file_id.into());
1763 let krate = self.def_collector.def_map.krate;
1764 let is_enabled = item_tree
1765 .top_level_attrs(db, krate)
1766 .cfg()
1767 .map_or(true, |cfg| self.is_cfg_enabled(&cfg));
1768 if is_enabled {
1769 let module_id = self.push_child_module(
1770 module.name.clone(),
1771 ast_id,
1772 Some((file_id, is_mod_rs)),
1773 &self.item_tree[module.visibility],
1774 module_id,
1775 );
1776 ModCollector {
1777 def_collector: self.def_collector,
1778 macro_depth: self.macro_depth,
1779 module_id,
1780 tree_id: TreeId::new(file_id.into(), None),
1781 item_tree: &item_tree,
1782 mod_dir,
1783 }
1784 .collect_in_top_module(item_tree.top_level_items());
1785 let is_macro_use = is_macro_use
1786 || item_tree
1787 .top_level_attrs(db, krate)
1788 .by_key("macro_use")
1789 .exists();
1790 if is_macro_use {
1791 self.import_all_legacy_macros(module_id);
1792 }
1793 }
1794 }
1795 Err(candidates) => {
1796 self.push_child_module(
1797 module.name.clone(),
1798 ast_id,
1799 None,
1800 &self.item_tree[module.visibility],
1801 module_id,
1802 );
1803 self.def_collector.def_map.diagnostics.push(
1804 DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
1805 );
1806 }
1807 };
1808 }
1809 }
1810 }
1811
1812 fn push_child_module(
1813 &mut self,
1814 name: Name,
1815 declaration: AstId<ast::Module>,
1816 definition: Option<(FileId, bool)>,
1817 visibility: &crate::visibility::RawVisibility,
1818 mod_tree_id: FileItemTreeId<Mod>,
1819 ) -> LocalModuleId {
1820 let def_map = &mut self.def_collector.def_map;
1821 let vis = def_map
1822 .resolve_visibility(self.def_collector.db, self.module_id, visibility)
1823 .unwrap_or(Visibility::Public);
1824 let modules = &mut def_map.modules;
1825 let origin = match definition {
1826 None => ModuleOrigin::Inline {
1827 definition: declaration,
1828 definition_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
1829 },
1830 Some((definition, is_mod_rs)) => ModuleOrigin::File {
1831 declaration,
1832 definition,
1833 is_mod_rs,
1834 declaration_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
1835 },
1836 };
1837
1838 let res = modules.alloc(ModuleData::new(origin, vis));
1839 modules[res].parent = Some(self.module_id);
1840 for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
1841 for &mac in &mac {
1842 modules[res].scope.define_legacy_macro(name.clone(), mac);
1843 }
1844 }
1845 modules[self.module_id].children.insert(name.clone(), res);
1846
1847 let module = def_map.module_id(res);
1848 let def = ModuleDefId::from(module);
1849
1850 def_map.modules[self.module_id].scope.declare(def);
1851 self.def_collector.update(
1852 self.module_id,
1853 &[(Some(name), PerNs::from_def(def, vis, false))],
1854 vis,
1855 ImportType::Named,
1856 );
1857 res
1858 }
1859
1860 /// Resolves attributes on an item.
1861 ///
1862 /// Returns `Err` when some attributes could not be resolved to builtins and have been
1863 /// registered as unresolved.
1864 ///
1865 /// If `ignore_up_to` is `Some`, attributes preceding and including that attribute will be
1866 /// assumed to be resolved already.
1867 fn resolve_attributes(
1868 &mut self,
1869 attrs: &Attrs,
1870 mod_item: ModItem,
1871 container: ItemContainerId,
1872 ) -> Result<(), ()> {
1873 let mut ignore_up_to =
1874 self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied();
1875 let iter = attrs
1876 .iter()
1877 .dedup_by(|a, b| {
1878 // FIXME: this should not be required, all attributes on an item should have a
1879 // unique ID!
1880 // Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
1881 // #[cfg_attr(not(off), unresolved, unresolved)]
1882 // struct S;
1883 // We should come up with a different way to ID attributes.
1884 a.id == b.id
1885 })
1886 .skip_while(|attr| match ignore_up_to {
1887 Some(id) if attr.id == id => {
1888 ignore_up_to = None;
1889 true
1890 }
1891 Some(_) => true,
1892 None => false,
1893 });
1894
1895 for attr in iter {
1896 if self.def_collector.def_map.is_builtin_or_registered_attr(&attr.path) {
1897 continue;
1898 }
1899 tracing::debug!("non-builtin attribute {}", attr.path);
1900
1901 let ast_id = AstIdWithPath::new(
1902 self.file_id(),
1903 mod_item.ast_id(self.item_tree),
1904 attr.path.as_ref().clone(),
1905 );
1906 self.def_collector.unresolved_macros.push(MacroDirective {
1907 module_id: self.module_id,
1908 depth: self.macro_depth + 1,
1909 kind: MacroDirectiveKind::Attr {
1910 ast_id,
1911 attr: attr.clone(),
1912 mod_item,
1913 tree: self.tree_id,
1914 },
1915 container,
1916 });
1917
1918 return Err(());
1919 }
1920
1921 Ok(())
1922 }
1923
1924 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>, module: ModuleId) {
1925 let krate = self.def_collector.def_map.krate;
1926 let mac = &self.item_tree[id];
1927 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1928 let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
1929
1930 let export_attr = attrs.by_key("macro_export");
1931
1932 let is_export = export_attr.exists();
1933 let local_inner = if is_export {
1934 export_attr.tt_values().flat_map(|it| &it.token_trees).any(|it| match it {
1935 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
1936 ident.text.contains("local_inner_macros")
1937 }
1938 _ => false,
1939 })
1940 } else {
1941 false
1942 };
1943
1944 // Case 1: builtin macros
1945 let expander = if attrs.by_key("rustc_builtin_macro").exists() {
1946 // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
1947 let name;
1948 let name = match attrs.by_key("rustc_builtin_macro").string_value() {
1949 Some(it) => {
1950 // FIXME: a hacky way to create a Name from string.
1951 name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
1952 &name
1953 }
1954 None => {
1955 let explicit_name =
1956 attrs.by_key("rustc_builtin_macro").tt_values().next().and_then(|tt| {
1957 match tt.token_trees.first() {
1958 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name),
1959 _ => None,
1960 }
1961 });
1962 match explicit_name {
1963 Some(ident) => {
1964 name = ident.as_name();
1965 &name
1966 }
1967 None => &mac.name,
1968 }
1969 }
1970 };
1971 match find_builtin_macro(name) {
1972 Some(Either::Left(it)) => MacroExpander::BuiltIn(it),
1973 Some(Either::Right(it)) => MacroExpander::BuiltInEager(it),
1974 None => {
1975 self.def_collector
1976 .def_map
1977 .diagnostics
1978 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
1979 return;
1980 }
1981 }
1982 } else {
1983 // Case 2: normal `macro_rules!` macro
1984 MacroExpander::Declarative
1985 };
1986
1987 let macro_id = MacroRulesLoc {
1988 container: module,
1989 id: ItemTreeId::new(self.tree_id, id),
1990 local_inner,
1991 expander,
1992 }
1993 .intern(self.def_collector.db);
1994 self.def_collector.define_macro_rules(
1995 self.module_id,
1996 mac.name.clone(),
1997 macro_id,
1998 is_export,
1999 );
2000 }
2001
2002 fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>, module: ModuleId) {
2003 let krate = self.def_collector.def_map.krate;
2004 let mac = &self.item_tree[id];
2005 let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
2006
2007 // Case 1: builtin macros
f25598a0 2008 let mut helpers_opt = None;
064997fb
FG
2009 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
2010 let expander = if attrs.by_key("rustc_builtin_macro").exists() {
2011 if let Some(expander) = find_builtin_macro(&mac.name) {
2012 match expander {
2013 Either::Left(it) => MacroExpander::BuiltIn(it),
2014 Either::Right(it) => MacroExpander::BuiltInEager(it),
2015 }
2016 } else if let Some(expander) = find_builtin_derive(&mac.name) {
f25598a0
FG
2017 if let Some(attr) = attrs.by_key("rustc_builtin_macro").tt_values().next() {
2018 // NOTE: The item *may* have both `#[rustc_builtin_macro]` and `#[proc_macro_derive]`,
2019 // in which case rustc ignores the helper attributes from the latter, but it
2020 // "doesn't make sense in practice" (see rust-lang/rust#87027).
2021 if let Some((name, helpers)) =
2022 parse_macro_name_and_helper_attrs(&attr.token_trees)
2023 {
2024 // NOTE: rustc overrides the name if the macro name if it's different from the
2025 // macro name, but we assume it isn't as there's no such case yet. FIXME if
2026 // the following assertion fails.
2027 stdx::always!(
2028 name == mac.name,
2029 "built-in macro {} has #[rustc_builtin_macro] which declares different name {}",
2030 mac.name,
2031 name
2032 );
2033 helpers_opt = Some(helpers);
2034 }
2035 }
064997fb
FG
2036 MacroExpander::BuiltInDerive(expander)
2037 } else if let Some(expander) = find_builtin_attr(&mac.name) {
2038 MacroExpander::BuiltInAttr(expander)
2039 } else {
2040 self.def_collector
2041 .def_map
2042 .diagnostics
2043 .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
2044 return;
2045 }
2046 } else {
2047 // Case 2: normal `macro`
2048 MacroExpander::Declarative
2049 };
2050
2051 let macro_id =
2052 Macro2Loc { container: module, id: ItemTreeId::new(self.tree_id, id), expander }
2053 .intern(self.def_collector.db);
2054 self.def_collector.define_macro_def(
2055 self.module_id,
2056 mac.name.clone(),
2057 macro_id,
2058 &self.item_tree[mac.visibility],
2059 );
f25598a0
FG
2060 if let Some(helpers) = helpers_opt {
2061 self.def_collector
2062 .def_map
2063 .exported_derives
2064 .insert(macro_id_to_def_id(self.def_collector.db, macro_id.into()), helpers);
2065 }
064997fb
FG
2066 }
2067
2068 fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
2069 let ast_id = AstIdWithPath::new(self.file_id(), mac.ast_id, ModPath::clone(&mac.path));
2070
2071 // Case 1: try to resolve in legacy scope and expand macro_rules
2072 let mut error = None;
2073 match macro_call_as_call_id(
2074 self.def_collector.db,
2075 &ast_id,
2076 mac.expand_to,
2077 self.def_collector.def_map.krate,
2078 |path| {
2079 path.as_ident().and_then(|name| {
2080 self.def_collector.def_map.with_ancestor_maps(
2081 self.def_collector.db,
2082 self.module_id,
2083 &mut |map, module| {
2084 map[module]
2085 .scope
2086 .get_legacy_macro(name)
2087 .and_then(|it| it.last())
f25598a0 2088 .map(|&it| macro_id_to_def_id(self.def_collector.db, it))
064997fb
FG
2089 },
2090 )
2091 })
2092 },
2093 &mut |err| {
2094 error.get_or_insert(err);
2095 },
2096 ) {
2097 Ok(Ok(macro_call_id)) => {
2098 // Legacy macros need to be expanded immediately, so that any macros they produce
2099 // are in scope.
2100 self.def_collector.collect_macro_expansion(
2101 self.module_id,
2102 macro_call_id,
2103 self.macro_depth + 1,
2104 container,
2105 );
2106
2107 if let Some(err) = error {
2108 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
2109 self.module_id,
2110 MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
2111 err.to_string(),
2112 ));
2113 }
2114
2115 return;
2116 }
2117 Ok(Err(_)) => {
2118 // Built-in macro failed eager expansion.
2119
2120 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
2121 self.module_id,
2122 MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
2123 error.unwrap().to_string(),
2124 ));
2125 return;
2126 }
2127 Err(UnresolvedMacro { .. }) => (),
2128 }
2129
2130 // Case 2: resolve in module scope, expand during name resolution.
2131 self.def_collector.unresolved_macros.push(MacroDirective {
2132 module_id: self.module_id,
2133 depth: self.macro_depth + 1,
2134 kind: MacroDirectiveKind::FnLike { ast_id, expand_to: mac.expand_to },
2135 container,
2136 });
2137 }
2138
2139 fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
2140 let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
2141 for (name, macs) in macros {
2142 macs.last().map(|&mac| {
2143 self.def_collector.define_legacy_macro(self.module_id, name.clone(), mac)
2144 });
2145 }
2146 }
2147
2148 fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
2149 self.def_collector.cfg_options.check(cfg) != Some(false)
2150 }
2151
2152 fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
2153 let ast_id = item.ast_id(self.item_tree);
2154
2b03887a 2155 let ast_id = InFile::new(self.file_id(), ast_id.upcast());
064997fb
FG
2156 self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
2157 self.module_id,
2158 ast_id,
2159 cfg.clone(),
2160 self.def_collector.cfg_options.clone(),
2161 ));
2162 }
2163
2164 fn file_id(&self) -> HirFileId {
2165 self.tree_id.file_id()
2166 }
2167}
2168
2169#[cfg(test)]
2170mod tests {
2171 use crate::{db::DefDatabase, test_db::TestDB};
2172 use base_db::{fixture::WithFixture, SourceDatabase};
2173
2174 use super::*;
2175
2176 fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap {
2177 let mut collector = DefCollector {
2178 db,
2179 def_map,
2180 deps: FxHashMap::default(),
2181 glob_imports: FxHashMap::default(),
2182 unresolved_imports: Vec::new(),
2183 indeterminate_imports: Vec::new(),
2184 unresolved_macros: Vec::new(),
2185 mod_dirs: FxHashMap::default(),
2186 cfg_options: &CfgOptions::default(),
2187 proc_macros: Default::default(),
2188 from_glob_import: Default::default(),
2189 skip_attrs: Default::default(),
2190 is_proc_macro: false,
2191 };
2192 collector.seed_with_top_level();
2193 collector.collect();
2194 collector.def_map
2195 }
2196
2197 fn do_resolve(not_ra_fixture: &str) -> DefMap {
2198 let (db, file_id) = TestDB::with_single_file(not_ra_fixture);
2199 let krate = db.test_crate();
2200
2201 let edition = db.crate_graph()[krate].edition;
2202 let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
2203 let def_map =
2204 DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public));
2205 do_collect_defs(&db, def_map)
2206 }
2207
2208 #[test]
2209 fn test_macro_expand_will_stop_1() {
2210 do_resolve(
2211 r#"
2212macro_rules! foo {
2213 ($($ty:ty)*) => { foo!($($ty)*); }
2214}
2215foo!(KABOOM);
2216"#,
2217 );
2218 do_resolve(
2219 r#"
2220macro_rules! foo {
2221 ($($ty:ty)*) => { foo!(() $($ty)*); }
2222}
2223foo!(KABOOM);
2224"#,
2225 );
2226 }
2227
2228 #[ignore]
2229 #[test]
2230 fn test_macro_expand_will_stop_2() {
2231 // FIXME: this test does succeed, but takes quite a while: 90 seconds in
2232 // the release mode. That's why the argument is not an ra_fixture --
2233 // otherwise injection highlighting gets stuck.
2234 //
2235 // We need to find a way to fail this faster.
2236 do_resolve(
2237 r#"
2238macro_rules! foo {
2239 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
2240}
2241foo!(KABOOM);
2242"#,
2243 );
2244 }
2245}