]> git.lizzy.rs Git - rust.git/blob - crates/ra_hir_def/src/nameres/collector.rs
Revert "Merge #2629"
[rust.git] / crates / ra_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 hir_expand::{
7     builtin_derive::find_builtin_derive,
8     builtin_macro::find_builtin_macro,
9     name::{name, AsName, Name},
10     HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
11 };
12 use ra_cfg::CfgOptions;
13 use ra_db::{CrateId, FileId};
14 use ra_syntax::ast;
15 use rustc_hash::FxHashMap;
16 use test_utils::tested_by;
17
18 use crate::{
19     attr::Attrs,
20     db::DefDatabase,
21     item_scope::Resolution,
22     nameres::{
23         diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
24         raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
25     },
26     path::{ModPath, PathKind},
27     per_ns::PerNs,
28     AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
29     LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc,
30     TypeAliasLoc, UnionLoc,
31 };
32
33 pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
34     let crate_graph = db.crate_graph();
35
36     // populate external prelude
37     for dep in crate_graph.dependencies(def_map.krate) {
38         let dep_def_map = db.crate_def_map(dep.crate_id);
39         log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
40         def_map.extern_prelude.insert(
41             dep.as_name(),
42             ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(),
43         );
44
45         // look for the prelude
46         // If the dependency defines a prelude, we overwrite an already defined
47         // prelude. This is necessary to import the "std" prelude if a crate
48         // depends on both "core" and "std".
49         let dep_def_map = db.crate_def_map(dep.crate_id);
50         if dep_def_map.prelude.is_some() {
51             def_map.prelude = dep_def_map.prelude;
52         }
53     }
54
55     let cfg_options = crate_graph.cfg_options(def_map.krate);
56
57     let mut collector = DefCollector {
58         db,
59         def_map,
60         glob_imports: FxHashMap::default(),
61         unresolved_imports: Vec::new(),
62         resolved_imports: Vec::new(),
63
64         unexpanded_macros: Vec::new(),
65         unexpanded_attribute_macros: Vec::new(),
66         mod_dirs: FxHashMap::default(),
67         cfg_options,
68     };
69     collector.collect();
70     collector.finish()
71 }
72
73 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
74 enum PartialResolvedImport {
75     /// None of any namespaces is resolved
76     Unresolved,
77     /// One of namespaces is resolved
78     Indeterminate(PerNs),
79     /// All namespaces are resolved, OR it is came from other crate
80     Resolved(PerNs),
81 }
82
83 impl PartialResolvedImport {
84     fn namespaces(&self) -> PerNs {
85         match self {
86             PartialResolvedImport::Unresolved => PerNs::none(),
87             PartialResolvedImport::Indeterminate(ns) => *ns,
88             PartialResolvedImport::Resolved(ns) => *ns,
89         }
90     }
91 }
92
93 #[derive(Clone, Debug, Eq, PartialEq)]
94 struct ImportDirective {
95     module_id: LocalModuleId,
96     import_id: LocalImportId,
97     import: raw::ImportData,
98     status: PartialResolvedImport,
99 }
100
101 #[derive(Clone, Debug, Eq, PartialEq)]
102 struct MacroDirective {
103     module_id: LocalModuleId,
104     ast_id: AstId<ast::MacroCall>,
105     path: ModPath,
106     legacy: Option<MacroCallId>,
107 }
108
109 /// Walks the tree of module recursively
110 struct DefCollector<'a, DB> {
111     db: &'a DB,
112     def_map: CrateDefMap,
113     glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>,
114     unresolved_imports: Vec<ImportDirective>,
115     resolved_imports: Vec<ImportDirective>,
116     unexpanded_macros: Vec<MacroDirective>,
117     unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, ModPath)>,
118     mod_dirs: FxHashMap<LocalModuleId, ModDir>,
119     cfg_options: &'a CfgOptions,
120 }
121
122 impl<DB> DefCollector<'_, DB>
123 where
124     DB: DefDatabase,
125 {
126     fn collect(&mut self) {
127         let crate_graph = self.db.crate_graph();
128         let file_id = crate_graph.crate_root(self.def_map.krate);
129         let raw_items = self.db.raw_items(file_id.into());
130         let module_id = self.def_map.root;
131         self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
132         ModCollector {
133             def_collector: &mut *self,
134             module_id,
135             file_id: file_id.into(),
136             raw_items: &raw_items,
137             mod_dir: ModDir::root(),
138         }
139         .collect(raw_items.items());
140
141         // main name resolution fixed-point loop.
142         let mut i = 0;
143         loop {
144             self.db.check_canceled();
145             self.resolve_imports();
146
147             match self.resolve_macros() {
148                 ReachedFixedPoint::Yes => break,
149                 ReachedFixedPoint::No => i += 1,
150             }
151             if i == 1000 {
152                 log::error!("name resolution is stuck");
153                 break;
154             }
155         }
156
157         // Resolve all indeterminate resolved imports again
158         // As some of the macros will expand newly import shadowing partial resolved imports
159         // FIXME: We maybe could skip this, if we handle the Indetermine imports in `resolve_imports`
160         // correctly
161         let partial_resolved = self.resolved_imports.iter().filter_map(|directive| {
162             if let PartialResolvedImport::Indeterminate(_) = directive.status {
163                 let mut directive = directive.clone();
164                 directive.status = PartialResolvedImport::Unresolved;
165                 Some(directive)
166             } else {
167                 None
168             }
169         });
170         self.unresolved_imports.extend(partial_resolved);
171         self.resolve_imports();
172
173         let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
174         // show unresolved imports in completion, etc
175         for directive in unresolved_imports {
176             self.record_resolved_import(&directive)
177         }
178     }
179
180     /// Define a macro with `macro_rules`.
181     ///
182     /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
183     /// then it is also defined in the root module scope.
184     /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
185     ///
186     /// It is surprising that the macro will never be in the current module scope.
187     /// These code fails with "unresolved import/macro",
188     /// ```rust,compile_fail
189     /// mod m { macro_rules! foo { () => {} } }
190     /// use m::foo as bar;
191     /// ```
192     ///
193     /// ```rust,compile_fail
194     /// macro_rules! foo { () => {} }
195     /// self::foo!();
196     /// crate::foo!();
197     /// ```
198     ///
199     /// Well, this code compiles, because the plain path `foo` in `use` is searched
200     /// in the legacy textual scope only.
201     /// ```rust
202     /// macro_rules! foo { () => {} }
203     /// use foo as bar;
204     /// ```
205     fn define_macro(
206         &mut self,
207         module_id: LocalModuleId,
208         name: Name,
209         macro_: MacroDefId,
210         export: bool,
211     ) {
212         // Textual scoping
213         self.define_legacy_macro(module_id, name.clone(), macro_);
214
215         // Module scoping
216         // In Rust, `#[macro_export]` macros are unconditionally visible at the
217         // crate root, even if the parent modules is **not** visible.
218         if export {
219             self.update(
220                 self.def_map.root,
221                 None,
222                 &[(name, Resolution { def: PerNs::macros(macro_), import: None })],
223             );
224         }
225     }
226
227     /// Define a legacy textual scoped macro in module
228     ///
229     /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
230     /// It will clone all macros from parent legacy scope, whose definition is prior to
231     /// the definition of current module.
232     /// And also, `macro_use` on a module will import all legacy macros visible inside to
233     /// current legacy scope, with possible shadowing.
234     fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) {
235         // Always shadowing
236         self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
237     }
238
239     /// Import macros from `#[macro_use] extern crate`.
240     fn import_macros_from_extern_crate(
241         &mut self,
242         current_module_id: LocalModuleId,
243         import: &raw::ImportData,
244     ) {
245         log::debug!(
246             "importing macros from extern crate: {:?} ({:?})",
247             import,
248             self.def_map.edition,
249         );
250
251         let res = self.def_map.resolve_name_in_extern_prelude(
252             &import
253                 .path
254                 .as_ident()
255                 .expect("extern crate should have been desugared to one-element path"),
256         );
257
258         if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
259             tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
260             self.import_all_macros_exported(current_module_id, m.krate);
261         }
262     }
263
264     /// Import all exported macros from another crate
265     ///
266     /// Exported macros are just all macros in the root module scope.
267     /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
268     /// created by `use` in the root module, ignoring the visibility of `use`.
269     fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
270         let def_map = self.db.crate_def_map(krate);
271         for (name, def) in def_map[def_map.root].scope.macros() {
272             // `macro_use` only bring things into legacy scope.
273             self.define_legacy_macro(current_module_id, name.clone(), def);
274         }
275     }
276
277     /// Import resolution
278     ///
279     /// This is a fix point algorithm. We resolve imports until no forward
280     /// progress in resolving imports is made
281     fn resolve_imports(&mut self) {
282         let mut n_previous_unresolved = self.unresolved_imports.len() + 1;
283
284         while self.unresolved_imports.len() < n_previous_unresolved {
285             n_previous_unresolved = self.unresolved_imports.len();
286             let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
287             for mut directive in imports {
288                 directive.status = self.resolve_import(directive.module_id, &directive.import);
289
290                 match directive.status {
291                     PartialResolvedImport::Indeterminate(_) => {
292                         self.record_resolved_import(&directive);
293                         // FIXME: For avoid performance regression,
294                         // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved)
295                         self.resolved_imports.push(directive)
296                     }
297                     PartialResolvedImport::Resolved(_) => {
298                         self.record_resolved_import(&directive);
299                         self.resolved_imports.push(directive)
300                     }
301                     PartialResolvedImport::Unresolved => {
302                         self.unresolved_imports.push(directive);
303                     }
304                 }
305             }
306         }
307     }
308
309     fn resolve_import(
310         &self,
311         module_id: LocalModuleId,
312         import: &raw::ImportData,
313     ) -> PartialResolvedImport {
314         log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
315         if import.is_extern_crate {
316             let res = self.def_map.resolve_name_in_extern_prelude(
317                 &import
318                     .path
319                     .as_ident()
320                     .expect("extern crate should have been desugared to one-element path"),
321             );
322             PartialResolvedImport::Resolved(res)
323         } else {
324             let res = self.def_map.resolve_path_fp_with_macro(
325                 self.db,
326                 ResolveMode::Import,
327                 module_id,
328                 &import.path,
329                 BuiltinShadowMode::Module,
330             );
331
332             let def = res.resolved_def;
333             if res.reached_fixedpoint == ReachedFixedPoint::No {
334                 return PartialResolvedImport::Unresolved;
335             }
336
337             if let Some(krate) = res.krate {
338                 if krate != self.def_map.krate {
339                     return PartialResolvedImport::Resolved(def);
340                 }
341             }
342
343             // Check whether all namespace is resolved
344             if def.take_types().is_some()
345                 && def.take_values().is_some()
346                 && def.take_macros().is_some()
347             {
348                 PartialResolvedImport::Resolved(def)
349             } else {
350                 PartialResolvedImport::Indeterminate(def)
351             }
352         }
353     }
354
355     fn record_resolved_import(&mut self, directive: &ImportDirective) {
356         let module_id = directive.module_id;
357         let import_id = directive.import_id;
358         let import = &directive.import;
359         let def = directive.status.namespaces();
360
361         if import.is_glob {
362             log::debug!("glob import: {:?}", import);
363             match def.take_types() {
364                 Some(ModuleDefId::ModuleId(m)) => {
365                     if import.is_prelude {
366                         tested_by!(std_prelude);
367                         self.def_map.prelude = Some(m);
368                     } else if m.krate != self.def_map.krate {
369                         tested_by!(glob_across_crates);
370                         // glob import from other crate => we can just import everything once
371                         let item_map = self.db.crate_def_map(m.krate);
372                         let scope = &item_map[m.local_id].scope;
373
374                         // Module scoped macros is included
375                         let items = scope.collect_resolutions();
376
377                         self.update(module_id, Some(import_id), &items);
378                     } else {
379                         // glob import from same crate => we do an initial
380                         // import, and then need to propagate any further
381                         // additions
382                         let scope = &self.def_map[m.local_id].scope;
383
384                         // Module scoped macros is included
385                         let items = scope.collect_resolutions();
386
387                         self.update(module_id, Some(import_id), &items);
388                         // record the glob import in case we add further items
389                         let glob = self.glob_imports.entry(m.local_id).or_default();
390                         if !glob.iter().any(|it| *it == (module_id, import_id)) {
391                             glob.push((module_id, import_id));
392                         }
393                     }
394                 }
395                 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
396                     tested_by!(glob_enum);
397                     // glob import from enum => just import all the variants
398                     let enum_data = self.db.enum_data(e);
399                     let resolutions = enum_data
400                         .variants
401                         .iter()
402                         .map(|(local_id, variant_data)| {
403                             let name = variant_data.name.clone();
404                             let variant = EnumVariantId { parent: e, local_id };
405                             let res = Resolution {
406                                 def: PerNs::both(variant.into(), variant.into()),
407                                 import: Some(import_id),
408                             };
409                             (name, res)
410                         })
411                         .collect::<Vec<_>>();
412                     self.update(module_id, Some(import_id), &resolutions);
413                 }
414                 Some(d) => {
415                     log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
416                 }
417                 None => {
418                     log::debug!("glob import {:?} didn't resolve as type", import);
419                 }
420             }
421         } else {
422             match import.path.segments.last() {
423                 Some(last_segment) => {
424                     let name = import.alias.clone().unwrap_or_else(|| last_segment.clone());
425                     log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
426
427                     // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
428                     if import.is_extern_crate && module_id == self.def_map.root {
429                         if let Some(def) = def.take_types() {
430                             self.def_map.extern_prelude.insert(name.clone(), def);
431                         }
432                     }
433
434                     let resolution = Resolution { def, import: Some(import_id) };
435                     self.update(module_id, Some(import_id), &[(name, resolution)]);
436                 }
437                 None => tested_by!(bogus_paths),
438             }
439         }
440     }
441
442     fn update(
443         &mut self,
444         module_id: LocalModuleId,
445         import: Option<LocalImportId>,
446         resolutions: &[(Name, Resolution)],
447     ) {
448         self.update_recursive(module_id, import, resolutions, 0)
449     }
450
451     fn update_recursive(
452         &mut self,
453         module_id: LocalModuleId,
454         import: Option<LocalImportId>,
455         resolutions: &[(Name, Resolution)],
456         depth: usize,
457     ) {
458         if depth > 100 {
459             // prevent stack overflows (but this shouldn't be possible)
460             panic!("infinite recursion in glob imports!");
461         }
462         let scope = &mut self.def_map.modules[module_id].scope;
463         let mut changed = false;
464         for (name, res) in resolutions {
465             changed |= scope.push_res(name.clone(), res, import);
466         }
467
468         if !changed {
469             return;
470         }
471         let glob_imports = self
472             .glob_imports
473             .get(&module_id)
474             .into_iter()
475             .flat_map(|v| v.iter())
476             .cloned()
477             .collect::<Vec<_>>();
478         for (glob_importing_module, glob_import) in glob_imports {
479             // We pass the glob import so that the tracked import in those modules is that glob import
480             self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1);
481         }
482     }
483
484     fn resolve_macros(&mut self) -> ReachedFixedPoint {
485         let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
486         let mut attribute_macros =
487             std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
488         let mut resolved = Vec::new();
489         let mut res = ReachedFixedPoint::Yes;
490         macros.retain(|directive| {
491             if let Some(call_id) = directive.legacy {
492                 res = ReachedFixedPoint::No;
493                 resolved.push((directive.module_id, call_id));
494                 return false;
495             }
496
497             let resolved_res = self.def_map.resolve_path_fp_with_macro(
498                 self.db,
499                 ResolveMode::Other,
500                 directive.module_id,
501                 &directive.path,
502                 BuiltinShadowMode::Module,
503             );
504
505             if let Some(def) = resolved_res.resolved_def.take_macros() {
506                 let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id));
507                 resolved.push((directive.module_id, call_id));
508                 res = ReachedFixedPoint::No;
509                 return false;
510             }
511
512             true
513         });
514         attribute_macros.retain(|(module_id, ast_id, path)| {
515             let resolved_res = self.resolve_attribute_macro(path);
516
517             if let Some(def) = resolved_res {
518                 let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id));
519                 resolved.push((*module_id, call_id));
520                 res = ReachedFixedPoint::No;
521                 return false;
522             }
523
524             true
525         });
526
527         self.unexpanded_macros = macros;
528         self.unexpanded_attribute_macros = attribute_macros;
529
530         for (module_id, macro_call_id) in resolved {
531             self.collect_macro_expansion(module_id, macro_call_id);
532         }
533
534         res
535     }
536
537     fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> {
538         // FIXME this is currently super hacky, just enough to support the
539         // built-in derives
540         if let Some(name) = path.as_ident() {
541             // FIXME this should actually be handled with the normal name
542             // resolution; the std lib defines built-in stubs for the derives,
543             // but these are new-style `macro`s, which we don't support yet
544             if let Some(def_id) = find_builtin_derive(name) {
545                 return Some(def_id);
546             }
547         }
548         None
549     }
550
551     fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) {
552         let file_id: HirFileId = macro_call_id.as_file();
553         let raw_items = self.db.raw_items(file_id);
554         let mod_dir = self.mod_dirs[&module_id].clone();
555         ModCollector {
556             def_collector: &mut *self,
557             file_id,
558             module_id,
559             raw_items: &raw_items,
560             mod_dir,
561         }
562         .collect(raw_items.items());
563     }
564
565     fn finish(self) -> CrateDefMap {
566         self.def_map
567     }
568 }
569
570 /// Walks a single module, populating defs, imports and macros
571 struct ModCollector<'a, D> {
572     def_collector: D,
573     module_id: LocalModuleId,
574     file_id: HirFileId,
575     raw_items: &'a raw::RawItems,
576     mod_dir: ModDir,
577 }
578
579 impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
580 where
581     DB: DefDatabase,
582 {
583     fn collect(&mut self, items: &[raw::RawItem]) {
584         // Note: don't assert that inserted value is fresh: it's simply not true
585         // for macros.
586         self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
587
588         // Prelude module is always considered to be `#[macro_use]`.
589         if let Some(prelude_module) = self.def_collector.def_map.prelude {
590             if prelude_module.krate != self.def_collector.def_map.krate {
591                 tested_by!(prelude_is_macro_use);
592                 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
593             }
594         }
595
596         // This should be processed eagerly instead of deferred to resolving.
597         // `#[macro_use] extern crate` is hoisted to imports macros before collecting
598         // any other items.
599         for item in items {
600             if self.is_cfg_enabled(&item.attrs) {
601                 if let raw::RawItemKind::Import(import_id) = item.kind {
602                     let import = self.raw_items[import_id].clone();
603                     if import.is_extern_crate && import.is_macro_use {
604                         self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
605                     }
606                 }
607             }
608         }
609
610         for item in items {
611             if self.is_cfg_enabled(&item.attrs) {
612                 match item.kind {
613                     raw::RawItemKind::Module(m) => {
614                         self.collect_module(&self.raw_items[m], &item.attrs)
615                     }
616                     raw::RawItemKind::Import(import_id) => {
617                         self.def_collector.unresolved_imports.push(ImportDirective {
618                             module_id: self.module_id,
619                             import_id,
620                             import: self.raw_items[import_id].clone(),
621                             status: PartialResolvedImport::Unresolved,
622                         })
623                     }
624                     raw::RawItemKind::Def(def) => {
625                         self.define_def(&self.raw_items[def], &item.attrs)
626                     }
627                     raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
628                     raw::RawItemKind::Impl(imp) => {
629                         let module = ModuleId {
630                             krate: self.def_collector.def_map.krate,
631                             local_id: self.module_id,
632                         };
633                         let container = ContainerId::ModuleId(module);
634                         let ast_id = self.raw_items[imp].ast_id;
635                         let impl_id =
636                             ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
637                                 .intern(self.def_collector.db);
638                         self.def_collector.def_map.modules[self.module_id]
639                             .scope
640                             .define_impl(impl_id)
641                     }
642                 }
643             }
644         }
645     }
646
647     fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
648         let path_attr = attrs.by_key("path").string_value();
649         let is_macro_use = attrs.by_key("macro_use").exists();
650         match module {
651             // inline module, just recurse
652             raw::ModuleData::Definition { name, items, ast_id } => {
653                 let module_id =
654                     self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
655
656                 ModCollector {
657                     def_collector: &mut *self.def_collector,
658                     module_id,
659                     file_id: self.file_id,
660                     raw_items: self.raw_items,
661                     mod_dir: self.mod_dir.descend_into_definition(name, path_attr),
662                 }
663                 .collect(&*items);
664                 if is_macro_use {
665                     self.import_all_legacy_macros(module_id);
666                 }
667             }
668             // out of line module, resolve, parse and recurse
669             raw::ModuleData::Declaration { name, ast_id } => {
670                 let ast_id = AstId::new(self.file_id, *ast_id);
671                 match self.mod_dir.resolve_declaration(
672                     self.def_collector.db,
673                     self.file_id,
674                     name,
675                     path_attr,
676                 ) {
677                     Ok((file_id, mod_dir)) => {
678                         let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
679                         let raw_items = self.def_collector.db.raw_items(file_id.into());
680                         ModCollector {
681                             def_collector: &mut *self.def_collector,
682                             module_id,
683                             file_id: file_id.into(),
684                             raw_items: &raw_items,
685                             mod_dir,
686                         }
687                         .collect(raw_items.items());
688                         if is_macro_use {
689                             self.import_all_legacy_macros(module_id);
690                         }
691                     }
692                     Err(candidate) => self.def_collector.def_map.diagnostics.push(
693                         DefDiagnostic::UnresolvedModule {
694                             module: self.module_id,
695                             declaration: ast_id,
696                             candidate,
697                         },
698                     ),
699                 };
700             }
701         }
702     }
703
704     fn push_child_module(
705         &mut self,
706         name: Name,
707         declaration: AstId<ast::Module>,
708         definition: Option<FileId>,
709     ) -> LocalModuleId {
710         let modules = &mut self.def_collector.def_map.modules;
711         let res = modules.alloc(ModuleData::default());
712         modules[res].parent = Some(self.module_id);
713         modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
714         for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
715             modules[res].scope.define_legacy_macro(name, mac)
716         }
717         modules[self.module_id].children.insert(name.clone(), res);
718         let resolution = Resolution {
719             def: PerNs::types(
720                 ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(),
721             ),
722             import: None,
723         };
724         self.def_collector.update(self.module_id, None, &[(name, resolution)]);
725         res
726     }
727
728     fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) {
729         let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
730         // FIXME: check attrs to see if this is an attribute macro invocation;
731         // in which case we don't add the invocation, just a single attribute
732         // macro invocation
733
734         self.collect_derives(attrs, def);
735
736         let name = def.name.clone();
737         let container = ContainerId::ModuleId(module);
738         let def: PerNs = match def.kind {
739             raw::DefKind::Function(ast_id) => {
740                 let def = FunctionLoc {
741                     container: container.into(),
742                     ast_id: AstId::new(self.file_id, ast_id),
743                 }
744                 .intern(self.def_collector.db);
745
746                 PerNs::values(def.into())
747             }
748             raw::DefKind::Struct(ast_id) => {
749                 let def = StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
750                     .intern(self.def_collector.db);
751                 PerNs::both(def.into(), def.into())
752             }
753             raw::DefKind::Union(ast_id) => {
754                 let def = UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
755                     .intern(self.def_collector.db);
756                 PerNs::both(def.into(), def.into())
757             }
758             raw::DefKind::Enum(ast_id) => {
759                 let def = EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
760                     .intern(self.def_collector.db);
761                 PerNs::types(def.into())
762             }
763             raw::DefKind::Const(ast_id) => {
764                 let def = ConstLoc {
765                     container: container.into(),
766                     ast_id: AstId::new(self.file_id, ast_id),
767                 }
768                 .intern(self.def_collector.db);
769
770                 PerNs::values(def.into())
771             }
772             raw::DefKind::Static(ast_id) => {
773                 let def = StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
774                     .intern(self.def_collector.db);
775
776                 PerNs::values(def.into())
777             }
778             raw::DefKind::Trait(ast_id) => {
779                 let def = TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
780                     .intern(self.def_collector.db);
781
782                 PerNs::types(def.into())
783             }
784             raw::DefKind::TypeAlias(ast_id) => {
785                 let def = TypeAliasLoc {
786                     container: container.into(),
787                     ast_id: AstId::new(self.file_id, ast_id),
788                 }
789                 .intern(self.def_collector.db);
790
791                 PerNs::types(def.into())
792             }
793         };
794         let resolution = Resolution { def, import: None };
795         self.def_collector.update(self.module_id, None, &[(name, resolution)])
796     }
797
798     fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
799         for derive_subtree in attrs.by_key("derive").tt_values() {
800             // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
801             for tt in &derive_subtree.token_trees {
802                 let ident = match &tt {
803                     tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
804                     tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
805                     _ => continue, // anything else would be an error (which we currently ignore)
806                 };
807                 let path = ModPath::from_tt_ident(ident);
808
809                 let ast_id = AstId::new(self.file_id, def.kind.ast_id());
810                 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path));
811             }
812         }
813     }
814
815     fn collect_macro(&mut self, mac: &raw::MacroData) {
816         let ast_id = AstId::new(self.file_id, mac.ast_id);
817
818         // Case 0: builtin macros
819         if mac.builtin {
820             if let Some(name) = &mac.name {
821                 let krate = self.def_collector.def_map.krate;
822                 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
823                     self.def_collector.define_macro(
824                         self.module_id,
825                         name.clone(),
826                         macro_id,
827                         mac.export,
828                     );
829                     return;
830                 }
831             }
832         }
833
834         // Case 1: macro rules, define a macro in crate-global mutable scope
835         if is_macro_rules(&mac.path) {
836             if let Some(name) = &mac.name {
837                 let macro_id = MacroDefId {
838                     ast_id: Some(ast_id),
839                     krate: Some(self.def_collector.def_map.krate),
840                     kind: MacroDefKind::Declarative,
841                 };
842                 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
843             }
844             return;
845         }
846
847         // Case 2: try to resolve in legacy scope and expand macro_rules
848         if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
849             self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
850         }) {
851             let macro_call_id =
852                 macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id));
853
854             self.def_collector.unexpanded_macros.push(MacroDirective {
855                 module_id: self.module_id,
856                 path: mac.path.clone(),
857                 ast_id,
858                 legacy: Some(macro_call_id),
859             });
860
861             return;
862         }
863
864         // Case 3: resolve in module scope, expand during name resolution.
865         // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
866         let mut path = mac.path.clone();
867         if path.is_ident() {
868             path.kind = PathKind::Super(0);
869         }
870
871         self.def_collector.unexpanded_macros.push(MacroDirective {
872             module_id: self.module_id,
873             path,
874             ast_id,
875             legacy: None,
876         });
877     }
878
879     fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
880         let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
881         for (name, macro_) in macros {
882             self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
883         }
884     }
885
886     fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
887         // FIXME: handle cfg_attr :-)
888         attrs
889             .by_key("cfg")
890             .tt_values()
891             .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
892     }
893 }
894
895 fn is_macro_rules(path: &ModPath) -> bool {
896     path.as_ident() == Some(&name![macro_rules])
897 }
898
899 #[cfg(test)]
900 mod tests {
901     use crate::{db::DefDatabase, test_db::TestDB};
902     use ra_arena::Arena;
903     use ra_db::{fixture::WithFixture, SourceDatabase};
904
905     use super::*;
906
907     fn do_collect_defs(db: &impl DefDatabase, def_map: CrateDefMap) -> CrateDefMap {
908         let mut collector = DefCollector {
909             db,
910             def_map,
911             glob_imports: FxHashMap::default(),
912             unresolved_imports: Vec::new(),
913             resolved_imports: Vec::new(),
914             unexpanded_macros: Vec::new(),
915             unexpanded_attribute_macros: Vec::new(),
916             mod_dirs: FxHashMap::default(),
917             cfg_options: &CfgOptions::default(),
918         };
919         collector.collect();
920         collector.def_map
921     }
922
923     fn do_resolve(code: &str) -> CrateDefMap {
924         let (db, _file_id) = TestDB::with_single_file(&code);
925         let krate = db.test_crate();
926
927         let def_map = {
928             let edition = db.crate_graph().edition(krate);
929             let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
930             let root = modules.alloc(ModuleData::default());
931             CrateDefMap {
932                 krate,
933                 edition,
934                 extern_prelude: FxHashMap::default(),
935                 prelude: None,
936                 root,
937                 modules,
938                 diagnostics: Vec::new(),
939             }
940         };
941         do_collect_defs(&db, def_map)
942     }
943
944     #[test]
945     fn test_macro_expand_will_stop() {
946         do_resolve(
947             r#"
948         macro_rules! foo {
949             ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }
950         }
951 foo!(KABOOM);
952         "#,
953         );
954     }
955 }