aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres/tests.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-09-09 22:09:23 +0100
committerGitHub <[email protected]>2019-09-09 22:09:23 +0100
commitc3d96f64ef1b2a5ded9cf5950f8e0f5798de4e1b (patch)
treea0d6c8121ca6845a48acbb3e9a895a07bfc584ce /crates/ra_hir/src/nameres/tests.rs
parent5fbdf57c4fe7ee99ba94549766a2644431f61b26 (diff)
parent5f48ef39024f62c135197e764741354611e02b6f (diff)
Merge #1795
1795: Make macro scope a real name scope and fix some details r=matklad a=uHOOCCOOHu This PR make macro's module scope a real name scope in `PerNs`, instead of handling `Either<PerNs, MacroDef>` everywhere. In `rustc`, the macro scope behave exactly the same as type and value scope. It is valid that macros, types and values having exact the same name, and a `use` statement will import all of them. This happened to module `alloc::vec` and macro `alloc::vec!`. So `Either` is not suitable here. There is a trap that not only does `#[macro_use]` import all `#[macro_export] macro_rules`, but also imports all macros `use`d in the crate root. In other words, it just _imports all macros in the module scope of crate root_. (Visibility of `use` doesn't matter.) And it also happened to `libstd` which has `use alloc_crate::vec;` in crate root to re-export `alloc::vec`, which it both a module and a macro. The current implementation of `#[macro_use] extern crate` doesn't work here, so that is why only macros directly from `libstd` like `dbg!` work, while `vec!` from `liballoc` doesn't. This PR fixes this. Another point is that, after some tests, I figure out that _`macro_rules` does NOT define macro in current module scope at all_. It defines itself in legacy textual scope. And if `#[macro_export]` is given, it also is defined ONLY in module scope of crate root. (Then being `macro_use`d, as mentioned above) (Well, the nightly [Declarative Macro 2.0](https://github.com/rust-lang/rust/issues/39412) simply always define in current module scope only, just like normal items do. But it is not yet supported by us) After this PR, in my test, all non-builtin macros are resolved now. (Hover text for documentation is available) So it fixes #1688 . Since compiler builtin macros are marked as `#[rustc_doc_only_macro]` instead of `#[macro_export]`, we can simply tweak the condition to let it resolved, but it may cause expansion error. Some critical notes are also given in doc-comments. <img width="447" alt="Screenshot_20190909_223859" src="https://user-images.githubusercontent.com/14816024/64540366-ac1ef600-d352-11e9-804f-566ba7559206.png"> Co-authored-by: uHOOCCOOHu <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/nameres/tests.rs')
-rw-r--r--crates/ra_hir/src/nameres/tests.rs46
1 files changed, 24 insertions, 22 deletions
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 {