aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/nameres.rs158
-rw-r--r--crates/ra_hir/src/nameres/collector.rs178
-rw-r--r--crates/ra_hir/src/nameres/per_ns.rs59
-rw-r--r--crates/ra_hir/src/nameres/tests.rs46
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs119
-rw-r--r--crates/ra_hir/src/resolve.rs14
-rw-r--r--crates/ra_hir/src/ty/tests.rs58
7 files changed, 393 insertions, 239 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index 74546e5e2..7488d75a5 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -67,7 +67,6 @@ use test_utils::tested_by;
67use crate::{ 67use crate::{
68 db::{AstDatabase, DefDatabase}, 68 db::{AstDatabase, DefDatabase},
69 diagnostics::DiagnosticSink, 69 diagnostics::DiagnosticSink,
70 either::Either,
71 ids::MacroDefId, 70 ids::MacroDefId,
72 nameres::diagnostics::DefDiagnostic, 71 nameres::diagnostics::DefDiagnostic,
73 AstId, BuiltinType, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, Trait, 72 AstId, BuiltinType, Crate, HirFileId, MacroDef, Module, ModuleDef, Name, Path, PathKind, Trait,
@@ -105,8 +104,6 @@ pub struct CrateDefMap {
105 /// However, do we want to put it as a global variable? 104 /// However, do we want to put it as a global variable?
106 poison_macros: FxHashSet<MacroDefId>, 105 poison_macros: FxHashSet<MacroDefId>,
107 106
108 exported_macros: FxHashMap<Name, MacroDefId>,
109
110 diagnostics: Vec<DefDiagnostic>, 107 diagnostics: Vec<DefDiagnostic>,
111} 108}
112 109
@@ -138,12 +135,6 @@ pub(crate) struct ModuleData {
138#[derive(Debug, Default, PartialEq, Eq, Clone)] 135#[derive(Debug, Default, PartialEq, Eq, Clone)]
139pub struct ModuleScope { 136pub struct ModuleScope {
140 items: FxHashMap<Name, Resolution>, 137 items: FxHashMap<Name, Resolution>,
141 /// Macros in current module scoped
142 ///
143 /// This scope works exactly the same way that item scoping does.
144 /// Macro invocation with quantified path will search in it.
145 /// See details below.
146 macros: FxHashMap<Name, MacroDef>,
147 /// Macros visable in current module in legacy textual scope 138 /// Macros visable in current module in legacy textual scope
148 /// 139 ///
149 /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. 140 /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
@@ -152,6 +143,10 @@ pub struct ModuleScope {
152 /// and only normal scoped `macros` will be searched in. 143 /// and only normal scoped `macros` will be searched in.
153 /// 144 ///
154 /// Note that this automatically inherit macros defined textually before the definition of module itself. 145 /// Note that this automatically inherit macros defined textually before the definition of module itself.
146 ///
147 /// Module scoped macros will be inserted into `items` instead of here.
148 // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
149 // be all resolved to the last one defined if shadowing happens.
155 legacy_macros: FxHashMap<Name, MacroDef>, 150 legacy_macros: FxHashMap<Name, MacroDef>,
156} 151}
157 152
@@ -164,35 +159,43 @@ static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
164 .collect() 159 .collect()
165}); 160});
166 161
162/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
163/// Other methods will only resolve values, types and module scoped macros only.
167impl ModuleScope { 164impl ModuleScope {
168 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a { 165 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
169 //FIXME: shadowing 166 //FIXME: shadowing
170 self.items.iter().chain(BUILTIN_SCOPE.iter()) 167 self.items.iter().chain(BUILTIN_SCOPE.iter())
171 } 168 }
169
170 /// Iterate over all module scoped macros
171 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDef)> + 'a {
172 self.items
173 .iter()
174 .filter_map(|(name, res)| res.def.get_macros().map(|macro_| (name, macro_)))
175 }
176
177 /// Iterate over all legacy textual scoped macros visable at the end of the module
178 pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDef)> + 'a {
179 self.legacy_macros.iter().map(|(name, def)| (name, *def))
180 }
181
182 /// Get a name from current module scope, legacy macros are not included
172 pub fn get(&self, name: &Name) -> Option<&Resolution> { 183 pub fn get(&self, name: &Name) -> Option<&Resolution> {
173 self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)) 184 self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name))
174 } 185 }
186
175 pub fn traits<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a { 187 pub fn traits<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a {
176 self.items.values().filter_map(|r| match r.def.take_types() { 188 self.items.values().filter_map(|r| match r.def.take_types() {
177 Some(ModuleDef::Trait(t)) => Some(t), 189 Some(ModuleDef::Trait(t)) => Some(t),
178 _ => None, 190 _ => None,
179 }) 191 })
180 } 192 }
181 /// It resolves in module scope. Textual scoped macros are ignored here. 193
182 fn get_item_or_macro(&self, name: &Name) -> Option<ItemOrMacro> {
183 match (self.get(name), self.macros.get(name)) {
184 (Some(item), _) if !item.def.is_none() => Some(Either::A(item.def)),
185 (_, Some(macro_)) => Some(Either::B(*macro_)),
186 _ => None,
187 }
188 }
189 fn get_legacy_macro(&self, name: &Name) -> Option<MacroDef> { 194 fn get_legacy_macro(&self, name: &Name) -> Option<MacroDef> {
190 self.legacy_macros.get(name).copied() 195 self.legacy_macros.get(name).copied()
191 } 196 }
192} 197}
193 198
194type ItemOrMacro = Either<PerNs<ModuleDef>, MacroDef>;
195
196#[derive(Debug, Clone, PartialEq, Eq, Default)] 199#[derive(Debug, Clone, PartialEq, Eq, Default)]
197pub struct Resolution { 200pub struct Resolution {
198 /// None for unresolved 201 /// None for unresolved
@@ -201,20 +204,26 @@ pub struct Resolution {
201 pub import: Option<ImportId>, 204 pub import: Option<ImportId>,
202} 205}
203 206
207impl Resolution {
208 pub(crate) fn from_macro(macro_: MacroDef) -> Self {
209 Resolution { def: PerNs::macros(macro_), import: None }
210 }
211}
212
204#[derive(Debug, Clone)] 213#[derive(Debug, Clone)]
205struct ResolvePathResult { 214struct ResolvePathResult {
206 resolved_def: ItemOrMacro, 215 resolved_def: PerNs<ModuleDef>,
207 segment_index: Option<usize>, 216 segment_index: Option<usize>,
208 reached_fixedpoint: ReachedFixedPoint, 217 reached_fixedpoint: ReachedFixedPoint,
209} 218}
210 219
211impl ResolvePathResult { 220impl ResolvePathResult {
212 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { 221 fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
213 ResolvePathResult::with(Either::A(PerNs::none()), reached_fixedpoint, None) 222 ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None)
214 } 223 }
215 224
216 fn with( 225 fn with(
217 resolved_def: ItemOrMacro, 226 resolved_def: PerNs<ModuleDef>,
218 reached_fixedpoint: ReachedFixedPoint, 227 reached_fixedpoint: ReachedFixedPoint,
219 segment_index: Option<usize>, 228 segment_index: Option<usize>,
220 ) -> ResolvePathResult { 229 ) -> ResolvePathResult {
@@ -234,21 +243,6 @@ enum ReachedFixedPoint {
234 No, 243 No,
235} 244}
236 245
237/// helper function for select item or macro to use
238fn or(left: ItemOrMacro, right: ItemOrMacro) -> ItemOrMacro {
239 match (left, right) {
240 (Either::A(s), Either::A(o)) => Either::A(s.or(o)),
241 (Either::B(s), _) => Either::B(s),
242 (Either::A(s), Either::B(o)) => {
243 if !s.is_none() {
244 Either::A(s)
245 } else {
246 Either::B(o)
247 }
248 }
249 }
250}
251
252impl CrateDefMap { 246impl CrateDefMap {
253 pub(crate) fn crate_def_map_query( 247 pub(crate) fn crate_def_map_query(
254 // Note that this doesn't have `+ AstDatabase`! 248 // Note that this doesn't have `+ AstDatabase`!
@@ -269,7 +263,6 @@ impl CrateDefMap {
269 root, 263 root,
270 modules, 264 modules,
271 poison_macros: FxHashSet::default(), 265 poison_macros: FxHashSet::default(),
272 exported_macros: FxHashMap::default(),
273 diagnostics: Vec::new(), 266 diagnostics: Vec::new(),
274 } 267 }
275 }; 268 };
@@ -328,16 +321,6 @@ impl CrateDefMap {
328 path: &Path, 321 path: &Path,
329 ) -> (PerNs<ModuleDef>, Option<usize>) { 322 ) -> (PerNs<ModuleDef>, Option<usize>) {
330 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); 323 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
331 (res.resolved_def.a().unwrap_or_else(PerNs::none), res.segment_index)
332 }
333
334 pub(crate) fn resolve_path_with_macro(
335 &self,
336 db: &impl DefDatabase,
337 original_module: CrateModuleId,
338 path: &Path,
339 ) -> (ItemOrMacro, Option<usize>) {
340 let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
341 (res.resolved_def, res.segment_index) 324 (res.resolved_def, res.segment_index)
342 } 325 }
343 326
@@ -351,13 +334,13 @@ impl CrateDefMap {
351 path: &Path, 334 path: &Path,
352 ) -> ResolvePathResult { 335 ) -> ResolvePathResult {
353 let mut segments = path.segments.iter().enumerate(); 336 let mut segments = path.segments.iter().enumerate();
354 let mut curr_per_ns: ItemOrMacro = match path.kind { 337 let mut curr_per_ns: PerNs<ModuleDef> = match path.kind {
355 PathKind::Crate => { 338 PathKind::Crate => {
356 Either::A(PerNs::types(Module { krate: self.krate, module_id: self.root }.into())) 339 PerNs::types(Module { krate: self.krate, module_id: self.root }.into())
340 }
341 PathKind::Self_ => {
342 PerNs::types(Module { krate: self.krate, module_id: original_module }.into())
357 } 343 }
358 PathKind::Self_ => Either::A(PerNs::types(
359 Module { krate: self.krate, module_id: original_module }.into(),
360 )),
361 // plain import or absolute path in 2015: crate-relative with 344 // plain import or absolute path in 2015: crate-relative with
362 // fallback to extern prelude (with the simplification in 345 // fallback to extern prelude (with the simplification in
363 // rust-lang/rust#57745) 346 // rust-lang/rust#57745)
@@ -379,11 +362,11 @@ impl CrateDefMap {
379 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), 362 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
380 }; 363 };
381 log::debug!("resolving {:?} in module", segment); 364 log::debug!("resolving {:?} in module", segment);
382 self.resolve_name_in_module_with_macro(db, original_module, &segment.name) 365 self.resolve_name_in_module(db, original_module, &segment.name)
383 } 366 }
384 PathKind::Super => { 367 PathKind::Super => {
385 if let Some(p) = self.modules[original_module].parent { 368 if let Some(p) = self.modules[original_module].parent {
386 Either::A(PerNs::types(Module { krate: self.krate, module_id: p }.into())) 369 PerNs::types(Module { krate: self.krate, module_id: p }.into())
387 } else { 370 } else {
388 log::debug!("super path in root module"); 371 log::debug!("super path in root module");
389 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 372 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
@@ -397,7 +380,7 @@ impl CrateDefMap {
397 }; 380 };
398 if let Some(def) = self.extern_prelude.get(&segment.name) { 381 if let Some(def) = self.extern_prelude.get(&segment.name) {
399 log::debug!("absolute path {:?} resolved to crate {:?}", path, def); 382 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
400 Either::A(PerNs::types(*def)) 383 PerNs::types(*def)
401 } else { 384 } else {
402 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude 385 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
403 } 386 }
@@ -405,7 +388,7 @@ impl CrateDefMap {
405 }; 388 };
406 389
407 for (i, segment) in segments { 390 for (i, segment) in segments {
408 let curr = match curr_per_ns.as_ref().a().and_then(|m| m.as_ref().take_types()) { 391 let curr = match curr_per_ns.as_ref().take_types() {
409 Some(r) => r, 392 Some(r) => r,
410 None => { 393 None => {
411 // we still have path segments left, but the path so far 394 // we still have path segments left, but the path so far
@@ -425,8 +408,7 @@ impl CrateDefMap {
425 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; 408 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
426 log::debug!("resolving {:?} in other crate", path); 409 log::debug!("resolving {:?} in other crate", path);
427 let defp_map = db.crate_def_map(module.krate); 410 let defp_map = db.crate_def_map(module.krate);
428 let (def, s) = 411 let (def, s) = defp_map.resolve_path(db, module.module_id, &path);
429 defp_map.resolve_path_with_macro(db, module.module_id, &path);
430 return ResolvePathResult::with( 412 return ResolvePathResult::with(
431 def, 413 def,
432 ReachedFixedPoint::Yes, 414 ReachedFixedPoint::Yes,
@@ -434,8 +416,9 @@ impl CrateDefMap {
434 ); 416 );
435 } 417 }
436 418
437 match self[module.module_id].scope.get_item_or_macro(&segment.name) { 419 // Since it is a quantified path here, it should not contains legacy macros
438 Some(res) => res, 420 match self[module.module_id].scope.get(&segment.name) {
421 Some(res) => res.def,
439 _ => { 422 _ => {
440 log::debug!("path segment {:?} not found", segment.name); 423 log::debug!("path segment {:?} not found", segment.name);
441 return ResolvePathResult::empty(ReachedFixedPoint::No); 424 return ResolvePathResult::empty(ReachedFixedPoint::No);
@@ -446,10 +429,10 @@ impl CrateDefMap {
446 // enum variant 429 // enum variant
447 tested_by!(can_import_enum_variant); 430 tested_by!(can_import_enum_variant);
448 match e.variant(db, &segment.name) { 431 match e.variant(db, &segment.name) {
449 Some(variant) => Either::A(PerNs::both(variant.into(), variant.into())), 432 Some(variant) => PerNs::both(variant.into(), variant.into()),
450 None => { 433 None => {
451 return ResolvePathResult::with( 434 return ResolvePathResult::with(
452 Either::A(PerNs::types((*e).into())), 435 PerNs::types((*e).into()),
453 ReachedFixedPoint::Yes, 436 ReachedFixedPoint::Yes,
454 Some(i), 437 Some(i),
455 ); 438 );
@@ -466,7 +449,7 @@ impl CrateDefMap {
466 ); 449 );
467 450
468 return ResolvePathResult::with( 451 return ResolvePathResult::with(
469 Either::A(PerNs::types(*s)), 452 PerNs::types(*s),
470 ReachedFixedPoint::Yes, 453 ReachedFixedPoint::Yes,
471 Some(i), 454 Some(i),
472 ); 455 );
@@ -476,14 +459,12 @@ impl CrateDefMap {
476 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) 459 ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
477 } 460 }
478 461
479 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> ItemOrMacro { 462 fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
480 let from_crate_root = self[self.root] 463 let from_crate_root =
481 .scope 464 self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def);
482 .get_item_or_macro(name)
483 .unwrap_or_else(|| Either::A(PerNs::none()));
484 let from_extern_prelude = self.resolve_name_in_extern_prelude(name); 465 let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
485 466
486 or(from_crate_root, Either::A(from_extern_prelude)) 467 from_crate_root.or(from_extern_prelude)
487 } 468 }
488 469
489 pub(crate) fn resolve_name_in_module( 470 pub(crate) fn resolve_name_in_module(
@@ -492,47 +473,38 @@ impl CrateDefMap {
492 module: CrateModuleId, 473 module: CrateModuleId,
493 name: &Name, 474 name: &Name,
494 ) -> PerNs<ModuleDef> { 475 ) -> PerNs<ModuleDef> {
495 self.resolve_name_in_module_with_macro(db, module, name).a().unwrap_or_else(PerNs::none)
496 }
497
498 fn resolve_name_in_module_with_macro(
499 &self,
500 db: &impl DefDatabase,
501 module: CrateModuleId,
502 name: &Name,
503 ) -> ItemOrMacro {
504 // Resolve in: 476 // Resolve in:
505 // - legacy scope 477 // - legacy scope of macro
506 // - current module / scope 478 // - current module / scope
507 // - extern prelude 479 // - extern prelude
508 // - std prelude 480 // - std prelude
509 let from_legacy_macro = self[module] 481 let from_legacy_macro =
510 .scope 482 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
511 .get_legacy_macro(name) 483 let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def);
512 .map_or_else(|| Either::A(PerNs::none()), Either::B);
513 let from_scope =
514 self[module].scope.get_item_or_macro(name).unwrap_or_else(|| Either::A(PerNs::none()));
515 let from_extern_prelude = 484 let from_extern_prelude =
516 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); 485 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
517 let from_prelude = self.resolve_in_prelude(db, name); 486 let from_prelude = self.resolve_in_prelude(db, name);
518 487
519 or(from_legacy_macro, or(from_scope, or(Either::A(from_extern_prelude), from_prelude))) 488 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
520 } 489 }
521 490
522 fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { 491 fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> {
523 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) 492 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
524 } 493 }
525 494
526 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> ItemOrMacro { 495 fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs<ModuleDef> {
527 if let Some(prelude) = self.prelude { 496 if let Some(prelude) = self.prelude {
528 let resolution = if prelude.krate == self.krate { 497 let keep;
529 self[prelude.module_id].scope.get_item_or_macro(name) 498 let def_map = if prelude.krate == self.krate {
499 self
530 } else { 500 } else {
531 db.crate_def_map(prelude.krate)[prelude.module_id].scope.get_item_or_macro(name) 501 // Extend lifetime
502 keep = db.crate_def_map(prelude.krate);
503 &keep
532 }; 504 };
533 resolution.unwrap_or_else(|| Either::A(PerNs::none())) 505 def_map[prelude.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
534 } else { 506 } else {
535 Either::A(PerNs::none()) 507 PerNs::none()
536 } 508 }
537 } 509 }
538} 510}
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 09cda7656..03fbbd33f 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -5,14 +5,13 @@ use test_utils::tested_by;
5 5
6use crate::{ 6use crate::{
7 db::DefDatabase, 7 db::DefDatabase,
8 either::Either,
9 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind}, 8 ids::{AstItemDef, LocationCtx, MacroCallId, MacroCallLoc, MacroDefId, MacroFileKind},
10 name::MACRO_RULES, 9 name::MACRO_RULES,
11 nameres::{ 10 nameres::{
12 diagnostics::DefDiagnostic, 11 diagnostics::DefDiagnostic,
13 mod_resolution::{resolve_submodule, ParentModule}, 12 mod_resolution::{resolve_submodule, ParentModule},
14 raw, CrateDefMap, CrateModuleId, ItemOrMacro, ModuleData, ModuleDef, PerNs, 13 raw, Crate, CrateDefMap, CrateModuleId, ModuleData, ModuleDef, PerNs, ReachedFixedPoint,
15 ReachedFixedPoint, Resolution, ResolveMode, 14 Resolution, ResolveMode,
16 }, 15 },
17 AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static, 16 AstId, Const, Enum, Function, HirFileId, MacroDef, Module, Name, Path, PathKind, Static,
18 Struct, Trait, TypeAlias, Union, 17 Struct, Trait, TypeAlias, Union,
@@ -123,30 +122,51 @@ where
123 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); 122 let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new());
124 // show unresolved imports in completion, etc 123 // show unresolved imports in completion, etc
125 for (module_id, import, import_data) in unresolved_imports { 124 for (module_id, import, import_data) in unresolved_imports {
126 self.record_resolved_import(module_id, Either::A(PerNs::none()), import, &import_data) 125 self.record_resolved_import(module_id, PerNs::none(), import, &import_data)
127 } 126 }
128 } 127 }
129 128
129 /// Define a macro with `macro_rules`.
130 ///
131 /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
132 /// then it is also defined in the root module scope.
133 /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
134 ///
135 /// It is surprising that the macro will never be in the current module scope.
136 /// These code fails with "unresolved import/macro",
137 /// ```rust,compile_fail
138 /// mod m { macro_rules! foo { () => {} } }
139 /// use m::foo as bar;
140 /// ```
141 ///
142 /// ```rust,compile_fail
143 /// macro_rules! foo { () => {} }
144 /// self::foo!();
145 /// crate::foo!();
146 /// ```
147 ///
148 /// Well, this code compiles, bacause the plain path `foo` in `use` is searched
149 /// in the legacy textual scope only.
150 /// ```rust
151 /// macro_rules! foo { () => {} }
152 /// use foo as bar;
153 /// ```
130 fn define_macro( 154 fn define_macro(
131 &mut self, 155 &mut self,
132 module_id: CrateModuleId, 156 module_id: CrateModuleId,
133 name: Name, 157 name: Name,
134 macro_id: MacroDefId, 158 macro_: MacroDef,
135 export: bool, 159 export: bool,
136 ) { 160 ) {
137 let def = Either::B(MacroDef { id: macro_id }); 161 // Textual scoping
162 self.define_legacy_macro(module_id, name.clone(), macro_);
138 163
164 // Module scoping
139 // In Rust, `#[macro_export]` macros are unconditionally visible at the 165 // In Rust, `#[macro_export]` macros are unconditionally visible at the
140 // crate root, even if the parent modules is **not** visible. 166 // crate root, even if the parent modules is **not** visible.
141 if export { 167 if export {
142 self.update(self.def_map.root, None, &[(name.clone(), def.clone())]); 168 self.update(self.def_map.root, None, &[(name.clone(), Resolution::from_macro(macro_))]);
143
144 // Exported macros are collected in crate level ready for
145 // glob import with `#[macro_use]`.
146 self.def_map.exported_macros.insert(name.clone(), macro_id);
147 } 169 }
148 self.update(module_id, None, &[(name.clone(), def)]);
149 self.define_legacy_macro(module_id, name.clone(), macro_id);
150 } 170 }
151 171
152 /// Define a legacy textual scoped macro in module 172 /// Define a legacy textual scoped macro in module
@@ -156,14 +176,12 @@ where
156 /// the definition of current module. 176 /// the definition of current module.
157 /// And also, `macro_use` on a module will import all legacy macros visable inside to 177 /// And also, `macro_use` on a module will import all legacy macros visable inside to
158 /// current legacy scope, with possible shadowing. 178 /// current legacy scope, with possible shadowing.
159 fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_id: MacroDefId) { 179 fn define_legacy_macro(&mut self, module_id: CrateModuleId, name: Name, macro_: MacroDef) {
160 // Always shadowing 180 // Always shadowing
161 self.def_map.modules[module_id].scope.legacy_macros.insert(name, MacroDef { id: macro_id }); 181 self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_);
162 } 182 }
163 183
164 /// Import macros from `#[macro_use] extern crate`. 184 /// Import macros from `#[macro_use] extern crate`.
165 ///
166 /// They are non-scoped, and will only be inserted into mutable `global_macro_scope`.
167 fn import_macros_from_extern_crate( 185 fn import_macros_from_extern_crate(
168 &mut self, 186 &mut self,
169 current_module_id: CrateModuleId, 187 current_module_id: CrateModuleId,
@@ -184,14 +202,20 @@ where
184 202
185 if let Some(ModuleDef::Module(m)) = res.take_types() { 203 if let Some(ModuleDef::Module(m)) = res.take_types() {
186 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use); 204 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use);
187 self.import_all_macros_exported(current_module_id, m); 205 self.import_all_macros_exported(current_module_id, m.krate);
188 } 206 }
189 } 207 }
190 208
191 fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, module: Module) { 209 /// Import all exported macros from another crate
192 let item_map = self.db.crate_def_map(module.krate); 210 ///
193 for (name, &macro_id) in &item_map.exported_macros { 211 /// Exported macros are just all macros in the root module scope.
194 self.define_legacy_macro(current_module_id, name.clone(), macro_id); 212 /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
213 /// created by `use` in the root module, ignoring the visibility of `use`.
214 fn import_all_macros_exported(&mut self, current_module_id: CrateModuleId, krate: Crate) {
215 let def_map = self.db.crate_def_map(krate);
216 for (name, def) in def_map[def_map.root].scope.macros() {
217 // `macro_use` only bring things into legacy scope.
218 self.define_legacy_macro(current_module_id, name.clone(), def);
195 } 219 }
196 } 220 }
197 221
@@ -219,7 +243,7 @@ where
219 &self, 243 &self,
220 module_id: CrateModuleId, 244 module_id: CrateModuleId,
221 import: &raw::ImportData, 245 import: &raw::ImportData,
222 ) -> (ItemOrMacro, ReachedFixedPoint) { 246 ) -> (PerNs<ModuleDef>, ReachedFixedPoint) {
223 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 247 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
224 if import.is_extern_crate { 248 if import.is_extern_crate {
225 let res = self.def_map.resolve_name_in_extern_prelude( 249 let res = self.def_map.resolve_name_in_extern_prelude(
@@ -228,7 +252,7 @@ where
228 .as_ident() 252 .as_ident()
229 .expect("extern crate should have been desugared to one-element path"), 253 .expect("extern crate should have been desugared to one-element path"),
230 ); 254 );
231 (Either::A(res), ReachedFixedPoint::Yes) 255 (res, ReachedFixedPoint::Yes)
232 } else { 256 } else {
233 let res = self.def_map.resolve_path_fp_with_macro( 257 let res = self.def_map.resolve_path_fp_with_macro(
234 self.db, 258 self.db,
@@ -244,13 +268,13 @@ where
244 fn record_resolved_import( 268 fn record_resolved_import(
245 &mut self, 269 &mut self,
246 module_id: CrateModuleId, 270 module_id: CrateModuleId,
247 def: ItemOrMacro, 271 def: PerNs<ModuleDef>,
248 import_id: raw::ImportId, 272 import_id: raw::ImportId,
249 import: &raw::ImportData, 273 import: &raw::ImportData,
250 ) { 274 ) {
251 if import.is_glob { 275 if import.is_glob {
252 log::debug!("glob import: {:?}", import); 276 log::debug!("glob import: {:?}", import);
253 match def.a().and_then(|item| item.take_types()) { 277 match def.take_types() {
254 Some(ModuleDef::Module(m)) => { 278 Some(ModuleDef::Module(m)) => {
255 if import.is_prelude { 279 if import.is_prelude {
256 tested_by!(std_prelude); 280 tested_by!(std_prelude);
@@ -260,30 +284,29 @@ where
260 // glob import from other crate => we can just import everything once 284 // glob import from other crate => we can just import everything once
261 let item_map = self.db.crate_def_map(m.krate); 285 let item_map = self.db.crate_def_map(m.krate);
262 let scope = &item_map[m.module_id].scope; 286 let scope = &item_map[m.module_id].scope;
287
288 // Module scoped macros is included
263 let items = scope 289 let items = scope
264 .items 290 .items
265 .iter() 291 .iter()
266 .map(|(name, res)| (name.clone(), Either::A(res.clone()))); 292 .map(|(name, res)| (name.clone(), res.clone()))
267 let macros = 293 .collect::<Vec<_>>();
268 scope.macros.iter().map(|(name, res)| (name.clone(), Either::B(*res)));
269 294
270 let all = items.chain(macros).collect::<Vec<_>>(); 295 self.update(module_id, Some(import_id), &items);
271 self.update(module_id, Some(import_id), &all);
272 } else { 296 } else {
273 // glob import from same crate => we do an initial 297 // glob import from same crate => we do an initial
274 // import, and then need to propagate any further 298 // import, and then need to propagate any further
275 // additions 299 // additions
276 let scope = &self.def_map[m.module_id].scope; 300 let scope = &self.def_map[m.module_id].scope;
301
302 // Module scoped macros is included
277 let items = scope 303 let items = scope
278 .items 304 .items
279 .iter() 305 .iter()
280 .map(|(name, res)| (name.clone(), Either::A(res.clone()))); 306 .map(|(name, res)| (name.clone(), res.clone()))
281 let macros = 307 .collect::<Vec<_>>();
282 scope.macros.iter().map(|(name, res)| (name.clone(), Either::B(*res)));
283 308
284 let all = items.chain(macros).collect::<Vec<_>>(); 309 self.update(module_id, Some(import_id), &items);
285
286 self.update(module_id, Some(import_id), &all);
287 // record the glob import in case we add further items 310 // record the glob import in case we add further items
288 self.glob_imports 311 self.glob_imports
289 .entry(m.module_id) 312 .entry(m.module_id)
@@ -303,7 +326,7 @@ where
303 import: Some(import_id), 326 import: Some(import_id),
304 }; 327 };
305 let name = variant.name(self.db)?; 328 let name = variant.name(self.db)?;
306 Some((name, Either::A(res))) 329 Some((name, res))
307 }) 330 })
308 .collect::<Vec<_>>(); 331 .collect::<Vec<_>>();
309 self.update(module_id, Some(import_id), &resolutions); 332 self.update(module_id, Some(import_id), &resolutions);
@@ -323,18 +346,12 @@ where
323 346
324 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 347 // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
325 if import.is_extern_crate && module_id == self.def_map.root { 348 if import.is_extern_crate && module_id == self.def_map.root {
326 if let Some(def) = def.a().and_then(|item| item.take_types()) { 349 if let Some(def) = def.take_types() {
327 self.def_map.extern_prelude.insert(name.clone(), def); 350 self.def_map.extern_prelude.insert(name.clone(), def);
328 } 351 }
329 } 352 }
330 353
331 let resolution = match def { 354 let resolution = Resolution { def, import: Some(import_id) };
332 Either::A(item) => {
333 Either::A(Resolution { def: item, import: Some(import_id) })
334 }
335 Either::B(macro_) => Either::B(macro_),
336 };
337
338 self.update(module_id, Some(import_id), &[(name, resolution)]); 355 self.update(module_id, Some(import_id), &[(name, resolution)]);
339 } 356 }
340 None => tested_by!(bogus_paths), 357 None => tested_by!(bogus_paths),
@@ -346,7 +363,7 @@ where
346 &mut self, 363 &mut self,
347 module_id: CrateModuleId, 364 module_id: CrateModuleId,
348 import: Option<raw::ImportId>, 365 import: Option<raw::ImportId>,
349 resolutions: &[(Name, Either<Resolution, MacroDef>)], 366 resolutions: &[(Name, Resolution)],
350 ) { 367 ) {
351 self.update_recursive(module_id, import, resolutions, 0) 368 self.update_recursive(module_id, import, resolutions, 0)
352 } 369 }
@@ -355,7 +372,7 @@ where
355 &mut self, 372 &mut self,
356 module_id: CrateModuleId, 373 module_id: CrateModuleId,
357 import: Option<raw::ImportId>, 374 import: Option<raw::ImportId>,
358 resolutions: &[(Name, Either<Resolution, MacroDef>)], 375 resolutions: &[(Name, Resolution)],
359 depth: usize, 376 depth: usize,
360 ) { 377 ) {
361 if depth > 100 { 378 if depth > 100 {
@@ -365,35 +382,30 @@ where
365 let module_items = &mut self.def_map.modules[module_id].scope; 382 let module_items = &mut self.def_map.modules[module_id].scope;
366 let mut changed = false; 383 let mut changed = false;
367 for (name, res) in resolutions { 384 for (name, res) in resolutions {
368 match res { 385 let existing = module_items.items.entry(name.clone()).or_default();
369 // item
370 Either::A(res) => {
371 let existing = module_items.items.entry(name.clone()).or_default();
372
373 if existing.def.types.is_none() && res.def.types.is_some() {
374 existing.def.types = res.def.types;
375 existing.import = import.or(res.import);
376 changed = true;
377 }
378 if existing.def.values.is_none() && res.def.values.is_some() {
379 existing.def.values = res.def.values;
380 existing.import = import.or(res.import);
381 changed = true;
382 }
383 386
384 if existing.def.is_none() 387 if existing.def.types.is_none() && res.def.types.is_some() {
385 && res.def.is_none() 388 existing.def.types = res.def.types;
386 && existing.import.is_none() 389 existing.import = import.or(res.import);
387 && res.import.is_some() 390 changed = true;
388 { 391 }
389 existing.import = res.import; 392 if existing.def.values.is_none() && res.def.values.is_some() {
390 } 393 existing.def.values = res.def.values;
391 } 394 existing.import = import.or(res.import);
392 // macro 395 changed = true;
393 Either::B(res) => { 396 }
394 // Always shadowing 397 if existing.def.macros.is_none() && res.def.macros.is_some() {
395 module_items.macros.insert(name.clone(), *res); 398 existing.def.macros = res.def.macros;
396 } 399 existing.import = import.or(res.import);
400 changed = true;
401 }
402
403 if existing.def.is_none()
404 && res.def.is_none()
405 && existing.import.is_none()
406 && res.import.is_some()
407 {
408 existing.import = res.import;
397 } 409 }
398 } 410 }
399 411
@@ -425,7 +437,7 @@ where
425 path, 437 path,
426 ); 438 );
427 439
428 if let Some(def) = resolved_res.resolved_def.b() { 440 if let Some(def) = resolved_res.resolved_def.get_macros() {
429 let call_id = MacroCallLoc { def: def.id, ast_id: *ast_id }.id(self.db); 441 let call_id = MacroCallLoc { def: def.id, ast_id: *ast_id }.id(self.db);
430 resolved.push((*module_id, call_id, def.id)); 442 resolved.push((*module_id, call_id, def.id));
431 res = ReachedFixedPoint::No; 443 res = ReachedFixedPoint::No;
@@ -528,7 +540,7 @@ where
528 if let Some(prelude_module) = self.def_collector.def_map.prelude { 540 if let Some(prelude_module) = self.def_collector.def_map.prelude {
529 if prelude_module.krate != self.def_collector.def_map.krate { 541 if prelude_module.krate != self.def_collector.def_map.krate {
530 tested_by!(prelude_is_macro_use); 542 tested_by!(prelude_is_macro_use);
531 self.def_collector.import_all_macros_exported(self.module_id, prelude_module); 543 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
532 } 544 }
533 } 545 }
534 546
@@ -636,7 +648,7 @@ where
636 ), 648 ),
637 import: None, 649 import: None,
638 }; 650 };
639 self.def_collector.update(self.module_id, None, &[(name, Either::A(resolution))]); 651 self.def_collector.update(self.module_id, None, &[(name, resolution)]);
640 res 652 res
641 } 653 }
642 654
@@ -667,7 +679,7 @@ where
667 raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)), 679 raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)),
668 }; 680 };
669 let resolution = Resolution { def, import: None }; 681 let resolution = Resolution { def, import: None };
670 self.def_collector.update(self.module_id, None, &[(name, Either::A(resolution))]) 682 self.def_collector.update(self.module_id, None, &[(name, resolution)])
671 } 683 }
672 684
673 fn collect_macro(&mut self, mac: &raw::MacroData) { 685 fn collect_macro(&mut self, mac: &raw::MacroData) {
@@ -675,7 +687,8 @@ where
675 if is_macro_rules(&mac.path) { 687 if is_macro_rules(&mac.path) {
676 if let Some(name) = &mac.name { 688 if let Some(name) = &mac.name {
677 let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id)); 689 let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id));
678 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export) 690 let macro_ = MacroDef { id: macro_id };
691 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export);
679 } 692 }
680 return; 693 return;
681 } 694 }
@@ -706,7 +719,7 @@ where
706 fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) { 719 fn import_all_legacy_macros(&mut self, module_id: CrateModuleId) {
707 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); 720 let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone();
708 for (name, macro_) in macros { 721 for (name, macro_) in macros {
709 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_.id); 722 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
710 } 723 }
711 } 724 }
712} 725}
@@ -758,7 +771,6 @@ mod tests {
758 root, 771 root,
759 modules, 772 modules,
760 poison_macros: FxHashSet::default(), 773 poison_macros: FxHashSet::default(),
761 exported_macros: FxHashMap::default(),
762 diagnostics: Vec::new(), 774 diagnostics: Vec::new(),
763 } 775 }
764 }; 776 };
diff --git a/crates/ra_hir/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs
index c40a3ff9d..d07cc08f4 100644
--- a/crates/ra_hir/src/nameres/per_ns.rs
+++ b/crates/ra_hir/src/nameres/per_ns.rs
@@ -1,78 +1,87 @@
1use crate::MacroDef;
2
1#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 3#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub enum Namespace { 4pub enum Namespace {
3 Types, 5 Types,
4 Values, 6 Values,
7 // Note that only type inference uses this enum, and it doesn't care about macros.
8 // Macro,
5} 9}
6 10
7#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 11#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8pub struct PerNs<T> { 12pub struct PerNs<T> {
9 pub types: Option<T>, 13 pub types: Option<T>,
10 pub values: Option<T>, 14 pub values: Option<T>,
15 /// Since macros has different type, many methods simply ignore it.
16 /// We can only use special method like `get_macros` to access it.
17 pub macros: Option<MacroDef>,
11} 18}
12 19
13impl<T> Default for PerNs<T> { 20impl<T> Default for PerNs<T> {
14 fn default() -> Self { 21 fn default() -> Self {
15 PerNs { types: None, values: None } 22 PerNs { types: None, values: None, macros: None }
16 } 23 }
17} 24}
18 25
19impl<T> PerNs<T> { 26impl<T> PerNs<T> {
20 pub fn none() -> PerNs<T> { 27 pub fn none() -> PerNs<T> {
21 PerNs { types: None, values: None } 28 PerNs { types: None, values: None, macros: None }
22 } 29 }
23 30
24 pub fn values(t: T) -> PerNs<T> { 31 pub fn values(t: T) -> PerNs<T> {
25 PerNs { types: None, values: Some(t) } 32 PerNs { types: None, values: Some(t), macros: None }
26 } 33 }
27 34
28 pub fn types(t: T) -> PerNs<T> { 35 pub fn types(t: T) -> PerNs<T> {
29 PerNs { types: Some(t), values: None } 36 PerNs { types: Some(t), values: None, macros: None }
30 } 37 }
31 38
32 pub fn both(types: T, values: T) -> PerNs<T> { 39 pub fn both(types: T, values: T) -> PerNs<T> {
33 PerNs { types: Some(types), values: Some(values) } 40 PerNs { types: Some(types), values: Some(values), macros: None }
34 } 41 }
35 42
36 pub fn is_none(&self) -> bool { 43 pub fn macros(macro_: MacroDef) -> PerNs<T> {
37 self.types.is_none() && self.values.is_none() 44 PerNs { types: None, values: None, macros: Some(macro_) }
38 } 45 }
39 46
40 pub fn is_both(&self) -> bool { 47 pub fn is_none(&self) -> bool {
41 self.types.is_some() && self.values.is_some() 48 self.types.is_none() && self.values.is_none() && self.macros.is_none()
42 } 49 }
43 50
44 pub fn take(self, namespace: Namespace) -> Option<T> { 51 pub fn is_all(&self) -> bool {
45 match namespace { 52 self.types.is_some() && self.values.is_some() && self.macros.is_some()
46 Namespace::Types => self.types,
47 Namespace::Values => self.values,
48 }
49 } 53 }
50 54
51 pub fn take_types(self) -> Option<T> { 55 pub fn take_types(self) -> Option<T> {
52 self.take(Namespace::Types) 56 self.types
53 } 57 }
54 58
55 pub fn take_values(self) -> Option<T> { 59 pub fn take_values(self) -> Option<T> {
56 self.take(Namespace::Values) 60 self.values
57 } 61 }
58 62
59 pub fn get(&self, namespace: Namespace) -> Option<&T> { 63 pub fn get_macros(&self) -> Option<MacroDef> {
60 self.as_ref().take(namespace) 64 self.macros
61 } 65 }
62 66
63 pub fn as_ref(&self) -> PerNs<&T> { 67 pub fn only_macros(&self) -> PerNs<T> {
64 PerNs { types: self.types.as_ref(), values: self.values.as_ref() } 68 PerNs { types: None, values: None, macros: self.macros }
65 } 69 }
66 70
67 pub fn or(self, other: PerNs<T>) -> PerNs<T> { 71 pub fn as_ref(&self) -> PerNs<&T> {
68 PerNs { types: self.types.or(other.types), values: self.values.or(other.values) } 72 PerNs { types: self.types.as_ref(), values: self.values.as_ref(), macros: self.macros }
69 } 73 }
70 74
71 pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { 75 pub fn or(self, other: PerNs<T>) -> PerNs<T> {
72 PerNs { types: self.types.and_then(&f), values: self.values.and_then(&f) } 76 PerNs {
77 types: self.types.or(other.types),
78 values: self.values.or(other.values),
79 macros: self.macros.or(other.macros),
80 }
73 } 81 }
74 82
83 /// Map types and values. Leave macros unchanged.
75 pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> { 84 pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> {
76 PerNs { types: self.types.map(&f), values: self.values.map(&f) } 85 PerNs { types: self.types.map(&f), values: self.values.map(&f), macros: self.macros }
77 } 86 }
78} 87}
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 4ff897ca5..bc4b47b70 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -12,8 +12,7 @@ use test_utils::covers;
12 12
13use crate::{ 13use crate::{
14 mock::{CrateGraphFixture, MockDatabase}, 14 mock::{CrateGraphFixture, MockDatabase},
15 nameres::Resolution, 15 Crate,
16 Crate, Either,
17}; 16};
18 17
19use super::*; 18use super::*;
@@ -37,35 +36,38 @@ fn render_crate_def_map(map: &CrateDefMap) -> String {
37 *buf += path; 36 *buf += path;
38 *buf += "\n"; 37 *buf += "\n";
39 38
40 let items = map.modules[module].scope.items.iter().map(|(name, it)| (name, Either::A(it))); 39 let mut entries = map.modules[module]
41 let macros = map.modules[module].scope.macros.iter().map(|(name, m)| (name, Either::B(m))); 40 .scope
42 let mut entries = items.chain(macros).collect::<Vec<_>>(); 41 .items
43 42 .iter()
43 .map(|(name, res)| (name, res.def))
44 .collect::<Vec<_>>();
44 entries.sort_by_key(|(name, _)| *name); 45 entries.sort_by_key(|(name, _)| *name);
46
45 for (name, res) in entries { 47 for (name, res) in entries {
46 match res { 48 *buf += &format!("{}:", name);
47 Either::A(it) => { 49
48 *buf += &format!("{}: {}\n", name, dump_resolution(it)); 50 if res.types.is_some() {
49 } 51 *buf += " t";
50 Either::B(_) => { 52 }
51 *buf += &format!("{}: m\n", name); 53 if res.values.is_some() {
52 } 54 *buf += " v";
55 }
56 if res.macros.is_some() {
57 *buf += " m";
58 }
59 if res.is_none() {
60 *buf += " _";
53 } 61 }
62
63 *buf += "\n";
54 } 64 }
65
55 for (name, child) in map.modules[module].children.iter() { 66 for (name, child) in map.modules[module].children.iter() {
56 let path = path.to_string() + &format!("::{}", name); 67 let path = path.to_string() + &format!("::{}", name);
57 go(buf, map, &path, *child); 68 go(buf, map, &path, *child);
58 } 69 }
59 } 70 }
60
61 fn dump_resolution(resolution: &Resolution) -> &'static str {
62 match (resolution.def.types.is_some(), resolution.def.values.is_some()) {
63 (true, true) => "t v",
64 (true, false) => "t",
65 (false, true) => "v",
66 (false, false) => "_",
67 }
68 }
69} 71}
70 72
71fn def_map(fixtute: &str) -> String { 73fn def_map(fixtute: &str) -> String {
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
index ebc4d6890..20ee63c67 100644
--- a/crates/ra_hir/src/nameres/tests/macros.rs
+++ b/crates/ra_hir/src/nameres/tests/macros.rs
@@ -21,7 +21,6 @@ fn macro_rules_are_globally_visible() {
21 ⋮crate 21 ⋮crate
22 ⋮Foo: t v 22 ⋮Foo: t v
23 ⋮nested: t 23 ⋮nested: t
24 ⋮structs: m
25 24
26 ⋮crate::nested 25 ⋮crate::nested
27 ⋮Bar: t v 26 ⋮Bar: t v
@@ -47,7 +46,6 @@ fn macro_rules_can_define_modules() {
47 ); 46 );
48 assert_snapshot!(map, @r###" 47 assert_snapshot!(map, @r###"
49 ⋮crate 48 ⋮crate
50 ⋮m: m
51 ⋮n1: t 49 ⋮n1: t
52 50
53 ⋮crate::n1 51 ⋮crate::n1
@@ -133,7 +131,6 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
133 ⋮crate 131 ⋮crate
134 ⋮Foo: t v 132 ⋮Foo: t v
135 ⋮bar: m 133 ⋮bar: m
136 ⋮baz: m
137 ⋮foo: m 134 ⋮foo: m
138 "###); 135 "###);
139} 136}
@@ -271,7 +268,6 @@ fn prelude_cycle() {
271 ⋮prelude: t 268 ⋮prelude: t
272 269
273 ⋮crate::prelude 270 ⋮crate::prelude
274 ⋮declare_mod: m
275 "###); 271 "###);
276} 272}
277 273
@@ -345,7 +341,6 @@ fn plain_macros_are_legacy_textual_scoped() {
345 ⋮Ok: t v 341 ⋮Ok: t v
346 ⋮OkAfter: t v 342 ⋮OkAfter: t v
347 ⋮OkShadowStop: t v 343 ⋮OkShadowStop: t v
348 ⋮foo: m
349 ⋮m1: t 344 ⋮m1: t
350 ⋮m2: t 345 ⋮m2: t
351 ⋮m3: t 346 ⋮m3: t
@@ -354,28 +349,132 @@ fn plain_macros_are_legacy_textual_scoped() {
354 ⋮ok_double_macro_use_shadow: v 349 ⋮ok_double_macro_use_shadow: v
355 350
356 ⋮crate::m7 351 ⋮crate::m7
357 ⋮baz: m
358 352
359 ⋮crate::m1 353 ⋮crate::m1
360 ⋮bar: m
361 354
362 ⋮crate::m5 355 ⋮crate::m5
363 ⋮m6: t 356 ⋮m6: t
364 357
365 ⋮crate::m5::m6 358 ⋮crate::m5::m6
366 ⋮foo: m
367 359
368 ⋮crate::m2 360 ⋮crate::m2
369 361
370 ⋮crate::m3 362 ⋮crate::m3
371 ⋮OkAfterInside: t v 363 ⋮OkAfterInside: t v
372 ⋮OkMacroUse: t v 364 ⋮OkMacroUse: t v
373 ⋮foo: m
374 ⋮m4: t 365 ⋮m4: t
375 ⋮ok_shadow: v 366 ⋮ok_shadow: v
376 367
377 ⋮crate::m3::m4 368 ⋮crate::m3::m4
378 ⋮bar: m
379 ⋮ok_shadow_deep: v 369 ⋮ok_shadow_deep: v
380 "###); 370 "###);
381} 371}
372
373#[test]
374fn type_value_macro_live_in_different_scopes() {
375 let map = def_map(
376 "
377 //- /main.rs
378 #[macro_export]
379 macro_rules! foo {
380 ($x:ident) => { type $x = (); }
381 }
382
383 foo!(foo);
384 use foo as bar;
385
386 use self::foo as baz;
387 fn baz() {}
388 ",
389 );
390 assert_snapshot!(map, @r###"
391 ⋮crate
392 ⋮bar: t m
393 ⋮baz: t v m
394 ⋮foo: t m
395 "###);
396}
397
398#[test]
399fn macro_use_can_be_aliased() {
400 let map = def_map_with_crate_graph(
401 "
402 //- /main.rs
403 #[macro_use]
404 extern crate foo;
405
406 foo!(Direct);
407 bar!(Alias);
408
409 //- /lib.rs
410 use crate::foo as bar;
411
412 mod m {
413 #[macro_export]
414 macro_rules! foo {
415 ($x:ident) => { struct $x; }
416 }
417 }
418 ",
419 crate_graph! {
420 "main": ("/main.rs", ["foo"]),
421 "foo": ("/lib.rs", []),
422 },
423 );
424 assert_snapshot!(map, @r###"
425 ⋮crate
426 ⋮Alias: t v
427 ⋮Direct: t v
428 ⋮foo: t
429 "###);
430}
431
432#[test]
433fn path_quantified_macros() {
434 let map = def_map(
435 "
436 //- /main.rs
437 macro_rules! foo {
438 ($x:ident) => { struct $x; }
439 }
440
441 crate::foo!(NotResolved);
442
443 crate::bar!(OkCrate);
444 bar!(OkPlain);
445 alias1!(NotHere);
446 m::alias1!(OkAliasPlain);
447 m::alias2!(OkAliasSuper);
448 m::alias3!(OkAliasCrate);
449 not_found!(NotFound);
450
451 mod m {
452 #[macro_export]
453 macro_rules! bar {
454 ($x:ident) => { struct $x; }
455 }
456
457 pub use bar as alias1;
458 pub use super::bar as alias2;
459 pub use crate::bar as alias3;
460 pub use self::bar as not_found;
461 }
462 ",
463 );
464 assert_snapshot!(map, @r###"
465 ⋮crate
466 ⋮OkAliasCrate: t v
467 ⋮OkAliasPlain: t v
468 ⋮OkAliasSuper: t v
469 ⋮OkCrate: t v
470 ⋮OkPlain: t v
471 ⋮bar: m
472 ⋮m: t
473
474 ⋮crate::m
475 ⋮alias1: m
476 ⋮alias2: m
477 ⋮alias3: m
478 ⋮not_found: _
479 "###);
480}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index ef75308f6..d9bdd0e22 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -6,7 +6,6 @@ use rustc_hash::{FxHashMap, FxHashSet};
6use crate::{ 6use crate::{
7 code_model::Crate, 7 code_model::Crate,
8 db::HirDatabase, 8 db::HirDatabase,
9 either::Either,
10 expr::{ 9 expr::{
11 scope::{ExprScopes, ScopeId}, 10 scope::{ExprScopes, ScopeId},
12 PatId, 11 PatId,
@@ -126,7 +125,7 @@ impl Resolver {
126 let mut resolution = PerNs::none(); 125 let mut resolution = PerNs::none();
127 for scope in self.scopes.iter().rev() { 126 for scope in self.scopes.iter().rev() {
128 resolution = resolution.or(scope.resolve_name(db, name)); 127 resolution = resolution.or(scope.resolve_name(db, name));
129 if resolution.is_both() { 128 if resolution.is_all() {
130 return resolution; 129 return resolution;
131 } 130 }
132 } 131 }
@@ -139,10 +138,7 @@ impl Resolver {
139 path: &Path, 138 path: &Path,
140 ) -> Option<MacroDef> { 139 ) -> Option<MacroDef> {
141 let (item_map, module) = self.module()?; 140 let (item_map, module) = self.module()?;
142 match item_map.resolve_path_with_macro(db, module, path) { 141 item_map.resolve_path(db, module, path).0.get_macros()
143 (Either::B(macro_def), None) => Some(macro_def),
144 _ => None,
145 }
146 } 142 }
147 143
148 /// Returns the resolved path segments 144 /// Returns the resolved path segments
@@ -191,6 +187,9 @@ impl Resolver {
191 if current.values.is_none() { 187 if current.values.is_none() {
192 current.values = res.values; 188 current.values = res.values;
193 } 189 }
190 if current.macros.is_none() {
191 current.macros = res.macros;
192 }
194 }); 193 });
195 } 194 }
196 names 195 names
@@ -313,6 +312,9 @@ impl Scope {
313 m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| { 312 m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| {
314 f(name.clone(), res.def.map(Resolution::Def)); 313 f(name.clone(), res.def.map(Resolution::Def));
315 }); 314 });
315 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
316 f(name.clone(), PerNs::macros(macro_));
317 });
316 m.crate_def_map.extern_prelude().iter().for_each(|(name, def)| { 318 m.crate_def_map.extern_prelude().iter().for_each(|(name, def)| {
317 f(name.clone(), PerNs::types(Resolution::Def(*def))); 319 f(name.clone(), PerNs::types(Resolution::Def(*def)));
318 }); 320 });
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 2c7d94bce..c60e72abf 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2838,6 +2838,64 @@ fn main() {
2838 ); 2838 );
2839} 2839}
2840 2840
2841#[test]
2842fn infer_path_quantified_macros_expanded() {
2843 assert_snapshot!(
2844 infer(r#"
2845#[macro_export]
2846macro_rules! foo {
2847 () => { 42i32 }
2848}
2849
2850mod m {
2851 pub use super::foo as bar;
2852}
2853
2854fn main() {
2855 let x = crate::foo!();
2856 let y = m::bar!();
2857}
2858"#),
2859 @r###"
2860 ![0; 5) '42i32': i32
2861 ![0; 5) '42i32': i32
2862 [111; 164) '{ ...!(); }': ()
2863 [121; 122) 'x': i32
2864 [148; 149) 'y': i32
2865 "###
2866 );
2867}
2868
2869#[test]
2870fn infer_type_value_macro_having_same_name() {
2871 assert_snapshot!(
2872 infer(r#"
2873#[macro_export]
2874macro_rules! foo {
2875 () => {
2876 mod foo {
2877 pub use super::foo;
2878 }
2879 };
2880 ($x:tt) => {
2881 $x
2882 };
2883}
2884
2885foo!();
2886
2887fn foo() {
2888 let foo = foo::foo!(42i32);
2889}
2890"#),
2891 @r###"
2892 ![0; 5) '42i32': i32
2893 [171; 206) '{ ...32); }': ()
2894 [181; 184) 'foo': i32
2895 "###
2896 );
2897}
2898
2841#[ignore] 2899#[ignore]
2842#[test] 2900#[test]
2843fn method_resolution_trait_before_autoref() { 2901fn method_resolution_trait_before_autoref() {