diff options
Diffstat (limited to 'crates/hir_def/src/nameres/collector.rs')
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 136 |
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 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use 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)] |
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, |
@@ -207,8 +215,8 @@ struct MacroDirective { | |||
207 | 215 | ||
208 | #[derive(Clone, Debug, Eq, PartialEq)] | 216 | #[derive(Clone, Debug, Eq, PartialEq)] |
209 | enum MacroDirectiveKind { | 217 | enum 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 | ||
214 | struct DefData<'a> { | 222 | struct 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 | ||