diff options
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 56 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/diagnostics.rs | 20 |
2 files changed, 57 insertions, 19 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index d58135ec9..4ddc791ce 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -23,6 +23,7 @@ use crate::{ | |||
23 | attr::Attrs, | 23 | attr::Attrs, |
24 | db::DefDatabase, | 24 | db::DefDatabase, |
25 | derive_macro_as_call_id, | 25 | derive_macro_as_call_id, |
26 | intern::Interned, | ||
26 | item_scope::{ImportType, PerNsGlobImports}, | 27 | item_scope::{ImportType, PerNsGlobImports}, |
27 | item_tree::{ | 28 | item_tree::{ |
28 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, | 29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, |
@@ -54,20 +55,22 @@ pub(super) fn collect_defs( | |||
54 | ) -> DefMap { | 55 | ) -> DefMap { |
55 | let crate_graph = db.crate_graph(); | 56 | let crate_graph = db.crate_graph(); |
56 | 57 | ||
57 | // populate external prelude | 58 | if block.is_none() { |
58 | for dep in &crate_graph[def_map.krate].dependencies { | 59 | // populate external prelude |
59 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); | 60 | for dep in &crate_graph[def_map.krate].dependencies { |
60 | let dep_def_map = db.crate_def_map(dep.crate_id); | 61 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); |
61 | def_map | 62 | let dep_def_map = db.crate_def_map(dep.crate_id); |
62 | .extern_prelude | 63 | def_map |
63 | .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); | 64 | .extern_prelude |
64 | 65 | .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); | |
65 | // look for the prelude | 66 | |
66 | // If the dependency defines a prelude, we overwrite an already defined | 67 | // look for the prelude |
67 | // prelude. This is necessary to import the "std" prelude if a crate | 68 | // If the dependency defines a prelude, we overwrite an already defined |
68 | // depends on both "core" and "std". | 69 | // prelude. This is necessary to import the "std" prelude if a crate |
69 | if dep_def_map.prelude.is_some() { | 70 | // depends on both "core" and "std". |
70 | def_map.prelude = dep_def_map.prelude; | 71 | if dep_def_map.prelude.is_some() { |
72 | def_map.prelude = dep_def_map.prelude; | ||
73 | } | ||
71 | } | 74 | } |
72 | } | 75 | } |
73 | 76 | ||
@@ -106,7 +109,9 @@ pub(super) fn collect_defs( | |||
106 | } | 109 | } |
107 | } | 110 | } |
108 | collector.collect(); | 111 | collector.collect(); |
109 | collector.finish() | 112 | let mut def_map = collector.finish(); |
113 | def_map.shrink_to_fit(); | ||
114 | def_map | ||
110 | } | 115 | } |
111 | 116 | ||
112 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | 117 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
@@ -137,7 +142,7 @@ enum ImportSource { | |||
137 | 142 | ||
138 | #[derive(Clone, Debug, Eq, PartialEq)] | 143 | #[derive(Clone, Debug, Eq, PartialEq)] |
139 | struct Import { | 144 | struct Import { |
140 | path: ModPath, | 145 | path: Interned<ModPath>, |
141 | alias: Option<ImportAlias>, | 146 | alias: Option<ImportAlias>, |
142 | visibility: RawVisibility, | 147 | visibility: RawVisibility, |
143 | is_glob: bool, | 148 | is_glob: bool, |
@@ -179,7 +184,10 @@ impl Import { | |||
179 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); | 184 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); |
180 | let visibility = &tree[it.visibility]; | 185 | let visibility = &tree[it.visibility]; |
181 | Self { | 186 | Self { |
182 | path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), | 187 | path: Interned::new(ModPath::from_segments( |
188 | PathKind::Plain, | ||
189 | iter::once(it.name.clone()), | ||
190 | )), | ||
183 | alias: it.alias.clone(), | 191 | alias: it.alias.clone(), |
184 | visibility: visibility.clone(), | 192 | visibility: visibility.clone(), |
185 | is_glob: false, | 193 | is_glob: false, |
@@ -1400,8 +1408,18 @@ impl ModCollector<'_, '_> { | |||
1400 | 1408 | ||
1401 | // Case 1: builtin macros | 1409 | // Case 1: builtin macros |
1402 | if attrs.by_key("rustc_builtin_macro").exists() { | 1410 | if attrs.by_key("rustc_builtin_macro").exists() { |
1411 | // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name. | ||
1412 | let name; | ||
1413 | let name = match attrs.by_key("rustc_builtin_macro").string_value() { | ||
1414 | Some(it) => { | ||
1415 | // FIXME: a hacky way to create a Name from string. | ||
1416 | name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name(); | ||
1417 | &name | ||
1418 | } | ||
1419 | None => &mac.name, | ||
1420 | }; | ||
1403 | let krate = self.def_collector.def_map.krate; | 1421 | let krate = self.def_collector.def_map.krate; |
1404 | if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { | 1422 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) { |
1405 | self.def_collector.define_macro_rules( | 1423 | self.def_collector.define_macro_rules( |
1406 | self.module_id, | 1424 | self.module_id, |
1407 | mac.name.clone(), | 1425 | mac.name.clone(), |
@@ -1464,7 +1482,7 @@ impl ModCollector<'_, '_> { | |||
1464 | } | 1482 | } |
1465 | 1483 | ||
1466 | fn collect_macro_call(&mut self, mac: &MacroCall) { | 1484 | fn collect_macro_call(&mut self, mac: &MacroCall) { |
1467 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); | 1485 | let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, (*mac.path).clone()); |
1468 | 1486 | ||
1469 | // Case 1: try to resolve in legacy scope and expand macro_rules | 1487 | // Case 1: try to resolve in legacy scope and expand macro_rules |
1470 | let mut error = None; | 1488 | let mut error = None; |
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs index a89061c2e..fefdadb22 100644 --- a/crates/hir_def/src/nameres/tests/diagnostics.rs +++ b/crates/hir_def/src/nameres/tests/diagnostics.rs | |||
@@ -7,6 +7,11 @@ fn check_diagnostics(ra_fixture: &str) { | |||
7 | db.check_diagnostics(); | 7 | db.check_diagnostics(); |
8 | } | 8 | } |
9 | 9 | ||
10 | fn check_no_diagnostics(ra_fixture: &str) { | ||
11 | let db: TestDB = TestDB::with_files(ra_fixture); | ||
12 | db.check_no_diagnostics(); | ||
13 | } | ||
14 | |||
10 | #[test] | 15 | #[test] |
11 | fn unresolved_import() { | 16 | fn unresolved_import() { |
12 | check_diagnostics( | 17 | check_diagnostics( |
@@ -202,6 +207,21 @@ fn builtin_macro_fails_expansion() { | |||
202 | } | 207 | } |
203 | 208 | ||
204 | #[test] | 209 | #[test] |
210 | fn include_macro_should_allow_empty_content() { | ||
211 | check_no_diagnostics( | ||
212 | r#" | ||
213 | //- /lib.rs | ||
214 | #[rustc_builtin_macro] | ||
215 | macro_rules! include { () => {} } | ||
216 | |||
217 | include!("bar.rs"); | ||
218 | //- /bar.rs | ||
219 | // empty | ||
220 | "#, | ||
221 | ); | ||
222 | } | ||
223 | |||
224 | #[test] | ||
205 | fn good_out_dir_diagnostic() { | 225 | fn good_out_dir_diagnostic() { |
206 | check_diagnostics( | 226 | check_diagnostics( |
207 | r#" | 227 | r#" |