diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-09 22:09:23 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-09 22:09:23 +0100 |
commit | c3d96f64ef1b2a5ded9cf5950f8e0f5798de4e1b (patch) | |
tree | a0d6c8121ca6845a48acbb3e9a895a07bfc584ce /crates/ra_hir/src/nameres/tests.rs | |
parent | 5fbdf57c4fe7ee99ba94549766a2644431f61b26 (diff) | |
parent | 5f48ef39024f62c135197e764741354611e02b6f (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.rs | 46 |
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 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | mock::{CrateGraphFixture, MockDatabase}, | 14 | mock::{CrateGraphFixture, MockDatabase}, |
15 | nameres::Resolution, | 15 | Crate, |
16 | Crate, Either, | ||
17 | }; | 16 | }; |
18 | 17 | ||
19 | use super::*; | 18 | use 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 | ||
71 | fn def_map(fixtute: &str) -> String { | 73 | fn def_map(fixtute: &str) -> String { |