aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres')
-rw-r--r--crates/hir_def/src/nameres/collector.rs56
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs20
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)]
139struct Import { 144struct 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
10fn 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]
11fn unresolved_import() { 16fn 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]
210fn 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]
205fn good_out_dir_diagnostic() { 225fn good_out_dir_diagnostic() {
206 check_diagnostics( 226 check_diagnostics(
207 r#" 227 r#"