aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres/collector.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r--crates/hir_def/src/nameres/collector.rs136
1 files changed, 81 insertions, 55 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index d58135ec9..05ceb1efb 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,7 +13,7 @@ use hir_expand::{
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -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,
@@ -207,8 +215,8 @@ struct MacroDirective {
207 215
208#[derive(Clone, Debug, Eq, PartialEq)] 216#[derive(Clone, Debug, Eq, PartialEq)]
209enum MacroDirectiveKind { 217enum MacroDirectiveKind {
210 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, legacy: Option<MacroCallId> }, 218 FnLike { ast_id: AstIdWithPath<ast::MacroCall> },
211 Derive { ast_id: AstIdWithPath<ast::Item> }, 219 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
212} 220}
213 221
214struct DefData<'a> { 222struct DefData<'a> {
@@ -470,7 +478,7 @@ impl DefCollector<'_> {
470 self.def_map.edition, 478 self.def_map.edition,
471 ); 479 );
472 480
473 let res = self.def_map.resolve_name_in_extern_prelude(&extern_crate.name); 481 let res = self.def_map.resolve_name_in_extern_prelude(self.db, &extern_crate.name);
474 482
475 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { 483 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
476 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); 484 cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
@@ -526,6 +534,7 @@ impl DefCollector<'_> {
526 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); 534 log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
527 if import.is_extern_crate { 535 if import.is_extern_crate {
528 let res = self.def_map.resolve_name_in_extern_prelude( 536 let res = self.def_map.resolve_name_in_extern_prelude(
537 self.db,
529 &import 538 &import
530 .path 539 .path
531 .as_ident() 540 .as_ident()
@@ -798,13 +807,7 @@ impl DefCollector<'_> {
798 let mut res = ReachedFixedPoint::Yes; 807 let mut res = ReachedFixedPoint::Yes;
799 macros.retain(|directive| { 808 macros.retain(|directive| {
800 match &directive.kind { 809 match &directive.kind {
801 MacroDirectiveKind::FnLike { ast_id, legacy } => { 810 MacroDirectiveKind::FnLike { ast_id } => {
802 if let Some(call_id) = legacy {
803 res = ReachedFixedPoint::No;
804 resolved.push((directive.module_id, *call_id, directive.depth));
805 return false;
806 }
807
808 match macro_call_as_call_id( 811 match macro_call_as_call_id(
809 ast_id, 812 ast_id,
810 self.db, 813 self.db,
@@ -826,19 +829,23 @@ impl DefCollector<'_> {
826 res = ReachedFixedPoint::No; 829 res = ReachedFixedPoint::No;
827 return false; 830 return false;
828 } 831 }
829 Err(UnresolvedMacro) | Ok(Err(_)) => {} 832 Err(UnresolvedMacro { .. }) | Ok(Err(_)) => {}
830 } 833 }
831 } 834 }
832 MacroDirectiveKind::Derive { ast_id } => { 835 MacroDirectiveKind::Derive { ast_id, derive_attr } => {
833 match derive_macro_as_call_id(ast_id, self.db, self.def_map.krate, |path| { 836 match derive_macro_as_call_id(
834 self.resolve_derive_macro(directive.module_id, &path) 837 ast_id,
835 }) { 838 *derive_attr,
839 self.db,
840 self.def_map.krate,
841 |path| self.resolve_derive_macro(directive.module_id, &path),
842 ) {
836 Ok(call_id) => { 843 Ok(call_id) => {
837 resolved.push((directive.module_id, call_id, 0)); 844 resolved.push((directive.module_id, call_id, directive.depth));
838 res = ReachedFixedPoint::No; 845 res = ReachedFixedPoint::No;
839 return false; 846 return false;
840 } 847 }
841 Err(UnresolvedMacro) => (), 848 Err(UnresolvedMacro { .. }) => (),
842 } 849 }
843 } 850 }
844 } 851 }
@@ -936,10 +943,11 @@ impl DefCollector<'_> {
936 &mut |_| (), 943 &mut |_| (),
937 ) { 944 ) {
938 Ok(_) => (), 945 Ok(_) => (),
939 Err(UnresolvedMacro) => { 946 Err(UnresolvedMacro { path }) => {
940 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call( 947 self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
941 directive.module_id, 948 directive.module_id,
942 ast_id.ast_id, 949 ast_id.ast_id,
950 path,
943 )); 951 ));
944 } 952 }
945 }, 953 },
@@ -1161,19 +1169,27 @@ impl ModCollector<'_, '_> {
1161 } 1169 }
1162 ModItem::Const(id) => { 1170 ModItem::Const(id) => {
1163 let it = &self.item_tree[id]; 1171 let it = &self.item_tree[id];
1164 1172 let const_id = ConstLoc {
1165 if let Some(name) = &it.name { 1173 container: module.into(),
1166 def = Some(DefData { 1174 id: ItemTreeId::new(self.file_id, id),
1167 id: ConstLoc { 1175 }
1168 container: module.into(), 1176 .intern(self.def_collector.db);
1169 id: ItemTreeId::new(self.file_id, id), 1177
1170 } 1178 match &it.name {
1171 .intern(self.def_collector.db) 1179 Some(name) => {
1172 .into(), 1180 def = Some(DefData {
1173 name, 1181 id: const_id.into(),
1174 visibility: &self.item_tree[it.visibility], 1182 name,
1175 has_constructor: false, 1183 visibility: &self.item_tree[it.visibility],
1176 }); 1184 has_constructor: false,
1185 });
1186 }
1187 None => {
1188 // const _: T = ...;
1189 self.def_collector.def_map.modules[self.module_id]
1190 .scope
1191 .define_unnamed_const(const_id);
1192 }
1177 } 1193 }
1178 } 1194 }
1179 ModItem::Static(id) => { 1195 ModItem::Static(id) => {
@@ -1358,7 +1374,7 @@ impl ModCollector<'_, '_> {
1358 self.def_collector.unexpanded_macros.push(MacroDirective { 1374 self.def_collector.unexpanded_macros.push(MacroDirective {
1359 module_id: self.module_id, 1375 module_id: self.module_id,
1360 depth: self.macro_depth + 1, 1376 depth: self.macro_depth + 1,
1361 kind: MacroDirectiveKind::Derive { ast_id }, 1377 kind: MacroDirectiveKind::Derive { ast_id, derive_attr: derive.id },
1362 }); 1378 });
1363 } 1379 }
1364 } 1380 }
@@ -1400,8 +1416,18 @@ impl ModCollector<'_, '_> {
1400 1416
1401 // Case 1: builtin macros 1417 // Case 1: builtin macros
1402 if attrs.by_key("rustc_builtin_macro").exists() { 1418 if attrs.by_key("rustc_builtin_macro").exists() {
1419 // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
1420 let name;
1421 let name = match attrs.by_key("rustc_builtin_macro").string_value() {
1422 Some(it) => {
1423 // FIXME: a hacky way to create a Name from string.
1424 name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
1425 &name
1426 }
1427 None => &mac.name,
1428 };
1403 let krate = self.def_collector.def_map.krate; 1429 let krate = self.def_collector.def_map.krate;
1404 if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { 1430 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
1405 self.def_collector.define_macro_rules( 1431 self.def_collector.define_macro_rules(
1406 self.module_id, 1432 self.module_id,
1407 mac.name.clone(), 1433 mac.name.clone(),
@@ -1464,7 +1490,7 @@ impl ModCollector<'_, '_> {
1464 } 1490 }
1465 1491
1466 fn collect_macro_call(&mut self, mac: &MacroCall) { 1492 fn collect_macro_call(&mut self, mac: &MacroCall) {
1467 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1493 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, (*mac.path).clone());
1468 1494
1469 // Case 1: try to resolve in legacy scope and expand macro_rules 1495 // Case 1: try to resolve in legacy scope and expand macro_rules
1470 let mut error = None; 1496 let mut error = None;
@@ -1500,12 +1526,12 @@ impl ModCollector<'_, '_> {
1500 // Built-in macro failed eager expansion. 1526 // Built-in macro failed eager expansion.
1501 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( 1527 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1502 self.module_id, 1528 self.module_id,
1503 MacroCallKind::FnLike(ast_id.ast_id), 1529 MacroCallKind::FnLike { ast_id: ast_id.ast_id },
1504 error.unwrap().to_string(), 1530 error.unwrap().to_string(),
1505 )); 1531 ));
1506 return; 1532 return;
1507 } 1533 }
1508 Err(UnresolvedMacro) => (), 1534 Err(UnresolvedMacro { .. }) => (),
1509 } 1535 }
1510 1536
1511 // Case 2: resolve in module scope, expand during name resolution. 1537 // Case 2: resolve in module scope, expand during name resolution.
@@ -1517,7 +1543,7 @@ impl ModCollector<'_, '_> {
1517 self.def_collector.unexpanded_macros.push(MacroDirective { 1543 self.def_collector.unexpanded_macros.push(MacroDirective {
1518 module_id: self.module_id, 1544 module_id: self.module_id,
1519 depth: self.macro_depth + 1, 1545 depth: self.macro_depth + 1,
1520 kind: MacroDirectiveKind::FnLike { ast_id, legacy: None }, 1546 kind: MacroDirectiveKind::FnLike { ast_id },
1521 }); 1547 });
1522 } 1548 }
1523 1549