]> git.lizzy.rs Git - rust.git/blob - crates/ra_hir_def/src/nameres/collector.rs
Fix typos
[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, macro_: MacroDefId) {
235         // Always shadowing
236         self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
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
376                             .items
377                             .iter()
378                             .map(|(name, res)| (name.clone(), res.clone()))
379                             .collect::<Vec<_>>();
380
381                         self.update(module_id, Some(import_id), &items);
382                     } else {
383                         // glob import from same crate => we do an initial
384                         // import, and then need to propagate any further
385                         // additions
386                         let scope = &self.def_map[m.local_id].scope;
387
388                         // Module scoped macros is included
389                         let items = scope
390                             .items
391                             .iter()
392                             .map(|(name, res)| (name.clone(), res.clone()))
393                             .collect::<Vec<_>>();
394
395                         self.update(module_id, Some(import_id), &items);
396                         // record the glob import in case we add further items
397                         let glob = self.glob_imports.entry(m.local_id).or_default();
398                         if !glob.iter().any(|it| *it == (module_id, import_id)) {
399                             glob.push((module_id, import_id));
400                         }
401                     }
402                 }
403                 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
404                     tested_by!(glob_enum);
405                     // glob import from enum => just import all the variants
406                     let enum_data = self.db.enum_data(e);
407                     let resolutions = enum_data
408                         .variants
409                         .iter()
410                         .filter_map(|(local_id, variant_data)| {
411                             let name = variant_data.name.clone();
412                             let variant = EnumVariantId { parent: e, local_id };
413                             let res = Resolution {
414                                 def: PerNs::both(variant.into(), variant.into()),
415                                 import: Some(import_id),
416                             };
417                             Some((name, res))
418                         })
419                         .collect::<Vec<_>>();
420                     self.update(module_id, Some(import_id), &resolutions);
421                 }
422                 Some(d) => {
423                     log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
424                 }
425                 None => {
426                     log::debug!("glob import {:?} didn't resolve as type", import);
427                 }
428             }
429         } else {
430             match import.path.segments.last() {
431                 Some(last_segment) => {
432                     let name = import.alias.clone().unwrap_or_else(|| last_segment.clone());
433                     log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
434
435                     // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
436                     if import.is_extern_crate && module_id == self.def_map.root {
437                         if let Some(def) = def.take_types() {
438                             self.def_map.extern_prelude.insert(name.clone(), def);
439                         }
440                     }
441
442                     let resolution = Resolution { def, import: Some(import_id) };
443                     self.update(module_id, Some(import_id), &[(name, resolution)]);
444                 }
445                 None => tested_by!(bogus_paths),
446             }
447         }
448     }
449
450     fn update(
451         &mut self,
452         module_id: LocalModuleId,
453         import: Option<LocalImportId>,
454         resolutions: &[(Name, Resolution)],
455     ) {
456         self.update_recursive(module_id, import, resolutions, 0)
457     }
458
459     fn update_recursive(
460         &mut self,
461         module_id: LocalModuleId,
462         import: Option<LocalImportId>,
463         resolutions: &[(Name, Resolution)],
464         depth: usize,
465     ) {
466         if depth > 100 {
467             // prevent stack overflows (but this shouldn't be possible)
468             panic!("infinite recursion in glob imports!");
469         }
470         let module_items = &mut self.def_map.modules[module_id].scope;
471         let mut changed = false;
472         for (name, res) in resolutions {
473             let existing = module_items.items.entry(name.clone()).or_default();
474
475             if existing.def.types.is_none() && res.def.types.is_some() {
476                 existing.def.types = res.def.types;
477                 existing.import = import.or(res.import);
478                 changed = true;
479             }
480             if existing.def.values.is_none() && res.def.values.is_some() {
481                 existing.def.values = res.def.values;
482                 existing.import = import.or(res.import);
483                 changed = true;
484             }
485             if existing.def.macros.is_none() && res.def.macros.is_some() {
486                 existing.def.macros = res.def.macros;
487                 existing.import = import.or(res.import);
488                 changed = true;
489             }
490
491             if existing.def.is_none()
492                 && res.def.is_none()
493                 && existing.import.is_none()
494                 && res.import.is_some()
495             {
496                 existing.import = res.import;
497             }
498         }
499
500         if !changed {
501             return;
502         }
503         let glob_imports = self
504             .glob_imports
505             .get(&module_id)
506             .into_iter()
507             .flat_map(|v| v.iter())
508             .cloned()
509             .collect::<Vec<_>>();
510         for (glob_importing_module, glob_import) in glob_imports {
511             // We pass the glob import so that the tracked import in those modules is that glob import
512             self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1);
513         }
514     }
515
516     fn resolve_macros(&mut self) -> ReachedFixedPoint {
517         let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
518         let mut attribute_macros =
519             std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new());
520         let mut resolved = Vec::new();
521         let mut res = ReachedFixedPoint::Yes;
522         macros.retain(|directive| {
523             if let Some(call_id) = directive.legacy {
524                 res = ReachedFixedPoint::No;
525                 resolved.push((directive.module_id, call_id));
526                 return false;
527             }
528
529             let resolved_res = self.def_map.resolve_path_fp_with_macro(
530                 self.db,
531                 ResolveMode::Other,
532                 directive.module_id,
533                 &directive.path,
534                 BuiltinShadowMode::Module,
535             );
536
537             if let Some(def) = resolved_res.resolved_def.take_macros() {
538                 let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id));
539                 resolved.push((directive.module_id, call_id));
540                 res = ReachedFixedPoint::No;
541                 return false;
542             }
543
544             true
545         });
546         attribute_macros.retain(|(module_id, ast_id, path)| {
547             let resolved_res = self.resolve_attribute_macro(path);
548
549             if let Some(def) = resolved_res {
550                 let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id));
551                 resolved.push((*module_id, call_id));
552                 res = ReachedFixedPoint::No;
553                 return false;
554             }
555
556             true
557         });
558
559         self.unexpanded_macros = macros;
560         self.unexpanded_attribute_macros = attribute_macros;
561
562         for (module_id, macro_call_id) in resolved {
563             self.collect_macro_expansion(module_id, macro_call_id);
564         }
565
566         res
567     }
568
569     fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> {
570         // FIXME this is currently super hacky, just enough to support the
571         // built-in derives
572         if let Some(name) = path.as_ident() {
573             // FIXME this should actually be handled with the normal name
574             // resolution; the std lib defines built-in stubs for the derives,
575             // but these are new-style `macro`s, which we don't support yet
576             if let Some(def_id) = find_builtin_derive(name) {
577                 return Some(def_id);
578             }
579         }
580         None
581     }
582
583     fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) {
584         let file_id: HirFileId = macro_call_id.as_file();
585         let raw_items = self.db.raw_items(file_id);
586         let mod_dir = self.mod_dirs[&module_id].clone();
587         ModCollector {
588             def_collector: &mut *self,
589             file_id,
590             module_id,
591             raw_items: &raw_items,
592             mod_dir,
593         }
594         .collect(raw_items.items());
595     }
596
597     fn finish(self) -> CrateDefMap {
598         self.def_map
599     }
600 }
601
602 /// Walks a single module, populating defs, imports and macros
603 struct ModCollector<'a, D> {
604     def_collector: D,
605     module_id: LocalModuleId,
606     file_id: HirFileId,
607     raw_items: &'a raw::RawItems,
608     mod_dir: ModDir,
609 }
610
611 impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
612 where
613     DB: DefDatabase,
614 {
615     fn collect(&mut self, items: &[raw::RawItem]) {
616         // Note: don't assert that inserted value is fresh: it's simply not true
617         // for macros.
618         self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
619
620         // Prelude module is always considered to be `#[macro_use]`.
621         if let Some(prelude_module) = self.def_collector.def_map.prelude {
622             if prelude_module.krate != self.def_collector.def_map.krate {
623                 tested_by!(prelude_is_macro_use);
624                 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
625             }
626         }
627
628         // This should be processed eagerly instead of deferred to resolving.
629         // `#[macro_use] extern crate` is hoisted to imports macros before collecting
630         // any other items.
631         for item in items {
632             if self.is_cfg_enabled(&item.attrs) {
633                 if let raw::RawItemKind::Import(import_id) = item.kind {
634                     let import = self.raw_items[import_id].clone();
635                     if import.is_extern_crate && import.is_macro_use {
636                         self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
637                     }
638                 }
639             }
640         }
641
642         for item in items {
643             if self.is_cfg_enabled(&item.attrs) {
644                 match item.kind {
645                     raw::RawItemKind::Module(m) => {
646                         self.collect_module(&self.raw_items[m], &item.attrs)
647                     }
648                     raw::RawItemKind::Import(import_id) => {
649                         self.def_collector.unresolved_imports.push(ImportDirective {
650                             module_id: self.module_id,
651                             import_id,
652                             import: self.raw_items[import_id].clone(),
653                             status: PartialResolvedImport::Unresolved,
654                         })
655                     }
656                     raw::RawItemKind::Def(def) => {
657                         self.define_def(&self.raw_items[def], &item.attrs)
658                     }
659                     raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
660                     raw::RawItemKind::Impl(imp) => {
661                         let module = ModuleId {
662                             krate: self.def_collector.def_map.krate,
663                             local_id: self.module_id,
664                         };
665                         let container = ContainerId::ModuleId(module);
666                         let ast_id = self.raw_items[imp].ast_id;
667                         let impl_id =
668                             ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
669                                 .intern(self.def_collector.db);
670                         self.def_collector.def_map.modules[self.module_id].scope.impls.push(impl_id)
671                     }
672                 }
673             }
674         }
675     }
676
677     fn collect_module(&mut self, module: &raw::ModuleData, attrs: &Attrs) {
678         let path_attr = attrs.by_key("path").string_value();
679         let is_macro_use = attrs.by_key("macro_use").exists();
680         match module {
681             // inline module, just recurse
682             raw::ModuleData::Definition { name, items, ast_id } => {
683                 let module_id =
684                     self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None);
685
686                 ModCollector {
687                     def_collector: &mut *self.def_collector,
688                     module_id,
689                     file_id: self.file_id,
690                     raw_items: self.raw_items,
691                     mod_dir: self.mod_dir.descend_into_definition(name, path_attr),
692                 }
693                 .collect(&*items);
694                 if is_macro_use {
695                     self.import_all_legacy_macros(module_id);
696                 }
697             }
698             // out of line module, resolve, parse and recurse
699             raw::ModuleData::Declaration { name, ast_id } => {
700                 let ast_id = AstId::new(self.file_id, *ast_id);
701                 match self.mod_dir.resolve_declaration(
702                     self.def_collector.db,
703                     self.file_id,
704                     name,
705                     path_attr,
706                 ) {
707                     Ok((file_id, mod_dir)) => {
708                         let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
709                         let raw_items = self.def_collector.db.raw_items(file_id.into());
710                         ModCollector {
711                             def_collector: &mut *self.def_collector,
712                             module_id,
713                             file_id: file_id.into(),
714                             raw_items: &raw_items,
715                             mod_dir,
716                         }
717                         .collect(raw_items.items());
718                         if is_macro_use {
719                             self.import_all_legacy_macros(module_id);
720                         }
721                     }
722                     Err(candidate) => self.def_collector.def_map.diagnostics.push(
723                         DefDiagnostic::UnresolvedModule {
724                             module: self.module_id,
725                             declaration: ast_id,
726                             candidate,
727                         },
728                     ),
729                 };
730             }
731         }
732     }
733
734     fn push_child_module(
735         &mut self,
736         name: Name,
737         declaration: AstId<ast::Module>,
738         definition: Option<FileId>,
739     ) -> LocalModuleId {
740         let modules = &mut self.def_collector.def_map.modules;
741         let res = modules.alloc(ModuleData::default());
742         modules[res].parent = Some(self.module_id);
743         modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
744         modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone();
745         modules[self.module_id].children.insert(name.clone(), res);
746         let resolution = Resolution {
747             def: PerNs::types(
748                 ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(),
749             ),
750             import: None,
751         };
752         self.def_collector.update(self.module_id, None, &[(name, resolution)]);
753         res
754     }
755
756     fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) {
757         let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
758         // FIXME: check attrs to see if this is an attribute macro invocation;
759         // in which case we don't add the invocation, just a single attribute
760         // macro invocation
761
762         self.collect_derives(attrs, def);
763
764         let name = def.name.clone();
765         let container = ContainerId::ModuleId(module);
766         let def: PerNs = match def.kind {
767             raw::DefKind::Function(ast_id) => {
768                 let def = FunctionLoc {
769                     container: container.into(),
770                     ast_id: AstId::new(self.file_id, ast_id),
771                 }
772                 .intern(self.def_collector.db);
773
774                 PerNs::values(def.into())
775             }
776             raw::DefKind::Struct(ast_id) => {
777                 let def = StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
778                     .intern(self.def_collector.db);
779                 PerNs::both(def.into(), def.into())
780             }
781             raw::DefKind::Union(ast_id) => {
782                 let def = UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
783                     .intern(self.def_collector.db);
784                 PerNs::both(def.into(), def.into())
785             }
786             raw::DefKind::Enum(ast_id) => {
787                 let def = EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
788                     .intern(self.def_collector.db);
789                 PerNs::types(def.into())
790             }
791             raw::DefKind::Const(ast_id) => {
792                 let def = ConstLoc {
793                     container: container.into(),
794                     ast_id: AstId::new(self.file_id, ast_id),
795                 }
796                 .intern(self.def_collector.db);
797
798                 PerNs::values(def.into())
799             }
800             raw::DefKind::Static(ast_id) => {
801                 let def = StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
802                     .intern(self.def_collector.db);
803
804                 PerNs::values(def.into())
805             }
806             raw::DefKind::Trait(ast_id) => {
807                 let def = TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
808                     .intern(self.def_collector.db);
809
810                 PerNs::types(def.into())
811             }
812             raw::DefKind::TypeAlias(ast_id) => {
813                 let def = TypeAliasLoc {
814                     container: container.into(),
815                     ast_id: AstId::new(self.file_id, ast_id),
816                 }
817                 .intern(self.def_collector.db);
818
819                 PerNs::types(def.into())
820             }
821         };
822         let resolution = Resolution { def, import: None };
823         self.def_collector.update(self.module_id, None, &[(name, resolution)])
824     }
825
826     fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
827         for derive_subtree in attrs.by_key("derive").tt_values() {
828             // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
829             for tt in &derive_subtree.token_trees {
830                 let ident = match &tt {
831                     tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
832                     tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
833                     _ => continue, // anything else would be an error (which we currently ignore)
834                 };
835                 let path = ModPath::from_tt_ident(ident);
836
837                 let ast_id = AstId::new(self.file_id, def.kind.ast_id());
838                 self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path));
839             }
840         }
841     }
842
843     fn collect_macro(&mut self, mac: &raw::MacroData) {
844         let ast_id = AstId::new(self.file_id, mac.ast_id);
845
846         // Case 0: builtin macros
847         if mac.builtin {
848             if let Some(name) = &mac.name {
849                 let krate = self.def_collector.def_map.krate;
850                 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
851                     self.def_collector.define_macro(
852                         self.module_id,
853                         name.clone(),
854                         macro_id,
855                         mac.export,
856                     );
857                     return;
858                 }
859             }
860         }
861
862         // Case 1: macro rules, define a macro in crate-global mutable scope
863         if is_macro_rules(&mac.path) {
864             if let Some(name) = &mac.name {
865                 let macro_id = MacroDefId {
866                     ast_id: Some(ast_id),
867                     krate: Some(self.def_collector.def_map.krate),
868                     kind: MacroDefKind::Declarative,
869                 };
870                 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
871             }
872             return;
873         }
874
875         // Case 2: try to resolve in legacy scope and expand macro_rules
876         if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
877             self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
878         }) {
879             let macro_call_id =
880                 macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id));
881
882             self.def_collector.unexpanded_macros.push(MacroDirective {
883                 module_id: self.module_id,
884                 path: mac.path.clone(),
885                 ast_id,
886                 legacy: Some(macro_call_id),
887             });
888
889             return;
890         }
891
892         // Case 3: resolve in module scope, expand during name resolution.
893         // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only.
894         let mut path = mac.path.clone();
895         if path.is_ident() {
896             path.kind = PathKind::Super(0);
897         }
898
899         self.def_collector.unexpanded_macros.push(MacroDirective {
900             module_id: self.module_id,
901             path,
902             ast_id,
903             legacy: None,
904         });
905     }
906
907     fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
908         let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
909         for (name, macro_) in macros {
910             self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
911         }
912     }
913
914     fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
915         // FIXME: handle cfg_attr :-)
916         attrs
917             .by_key("cfg")
918             .tt_values()
919             .all(|tt| self.def_collector.cfg_options.is_cfg_enabled(tt) != Some(false))
920     }
921 }
922
923 fn is_macro_rules(path: &ModPath) -> bool {
924     path.as_ident() == Some(&name![macro_rules])
925 }
926
927 #[cfg(test)]
928 mod tests {
929     use crate::{db::DefDatabase, test_db::TestDB};
930     use ra_arena::Arena;
931     use ra_db::{fixture::WithFixture, SourceDatabase};
932
933     use super::*;
934
935     fn do_collect_defs(db: &impl DefDatabase, def_map: CrateDefMap) -> CrateDefMap {
936         let mut collector = DefCollector {
937             db,
938             def_map,
939             glob_imports: FxHashMap::default(),
940             unresolved_imports: Vec::new(),
941             resolved_imports: Vec::new(),
942             unexpanded_macros: Vec::new(),
943             unexpanded_attribute_macros: Vec::new(),
944             mod_dirs: FxHashMap::default(),
945             cfg_options: &CfgOptions::default(),
946         };
947         collector.collect();
948         collector.def_map
949     }
950
951     fn do_resolve(code: &str) -> CrateDefMap {
952         let (db, _file_id) = TestDB::with_single_file(&code);
953         let krate = db.test_crate();
954
955         let def_map = {
956             let edition = db.crate_graph().edition(krate);
957             let mut modules: Arena<LocalModuleId, ModuleData> = Arena::default();
958             let root = modules.alloc(ModuleData::default());
959             CrateDefMap {
960                 krate,
961                 edition,
962                 extern_prelude: FxHashMap::default(),
963                 prelude: None,
964                 root,
965                 modules,
966                 diagnostics: Vec::new(),
967             }
968         };
969         do_collect_defs(&db, def_map)
970     }
971
972     #[test]
973     fn test_macro_expand_will_stop() {
974         do_resolve(
975             r#"
976         macro_rules! foo {
977             ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }
978         }
979 foo!(KABOOM);
980         "#,
981         );
982     }
983 }