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.rs118
1 files changed, 55 insertions, 63 deletions
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index d0fefb5af..28b73c3a1 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -18,12 +18,11 @@ use hir_expand::{
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
20use syntax::ast; 20use syntax::ast;
21use tt::{Leaf, TokenTree};
22 21
23use crate::{ 22use crate::{
24 attr::Attrs, 23 attr::Attrs,
25 db::DefDatabase, 24 db::DefDatabase,
26 item_attr_as_call_id, 25 derive_macro_as_call_id,
27 item_scope::{ImportType, PerNsGlobImports}, 26 item_scope::{ImportType, PerNsGlobImports},
28 item_tree::{ 27 item_tree::{
29 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, 28 self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind,
@@ -42,6 +41,8 @@ use crate::{
42 UnresolvedMacro, 41 UnresolvedMacro,
43}; 42};
44 43
44use super::proc_macro::ProcMacroDef;
45
45const GLOB_RECURSION_LIMIT: usize = 100; 46const GLOB_RECURSION_LIMIT: usize = 100;
46const EXPANSION_DEPTH_LIMIT: usize = 128; 47const EXPANSION_DEPTH_LIMIT: usize = 128;
47const FIXED_POINT_LIMIT: usize = 8192; 48const FIXED_POINT_LIMIT: usize = 8192;
@@ -353,24 +354,23 @@ impl DefCollector<'_> {
353 /// use a dummy expander that always errors. This comes with the drawback of macros potentially 354 /// use a dummy expander that always errors. This comes with the drawback of macros potentially
354 /// going out of sync with what the build system sees (since we resolve using VFS state, but 355 /// going out of sync with what the build system sees (since we resolve using VFS state, but
355 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that. 356 /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
356 fn resolve_proc_macro(&mut self, name: &Name) { 357 fn export_proc_macro(&mut self, def: ProcMacroDef, ast_id: AstId<ast::Fn>) {
357 self.exports_proc_macros = true; 358 self.exports_proc_macros = true;
358 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) { 359 let macro_def = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
359 Some((_, expander)) => MacroDefId { 360 Some((_, expander)) => MacroDefId {
360 ast_id: None,
361 krate: self.def_map.krate, 361 krate: self.def_map.krate,
362 kind: MacroDefKind::ProcMacro(*expander), 362 kind: MacroDefKind::ProcMacro(*expander, ast_id),
363 local_inner: false, 363 local_inner: false,
364 }, 364 },
365 None => MacroDefId { 365 None => MacroDefId {
366 ast_id: None,
367 krate: self.def_map.krate, 366 krate: self.def_map.krate,
368 kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate)), 367 kind: MacroDefKind::ProcMacro(ProcMacroExpander::dummy(self.def_map.krate), ast_id),
369 local_inner: false, 368 local_inner: false,
370 }, 369 },
371 }; 370 };
372 371
373 self.define_proc_macro(name.clone(), macro_def); 372 self.define_proc_macro(def.name.clone(), macro_def);
373 self.def_map.exported_proc_macros.insert(macro_def, def);
374 } 374 }
375 375
376 /// Define a macro with `macro_rules`. 376 /// Define a macro with `macro_rules`.
@@ -820,8 +820,8 @@ impl DefCollector<'_> {
820 true 820 true
821 }); 821 });
822 attribute_macros.retain(|directive| { 822 attribute_macros.retain(|directive| {
823 match item_attr_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| { 823 match derive_macro_as_call_id(&directive.ast_id, self.db, self.def_map.krate, |path| {
824 self.resolve_attribute_macro(&directive, &path) 824 self.resolve_derive_macro(&directive, &path)
825 }) { 825 }) {
826 Ok(call_id) => { 826 Ok(call_id) => {
827 resolved.push((directive.module_id, call_id, 0)); 827 resolved.push((directive.module_id, call_id, 0));
@@ -844,7 +844,7 @@ impl DefCollector<'_> {
844 res 844 res
845 } 845 }
846 846
847 fn resolve_attribute_macro( 847 fn resolve_derive_macro(
848 &self, 848 &self,
849 directive: &DeriveDirective, 849 directive: &DeriveDirective,
850 path: &ModPath, 850 path: &ModPath,
@@ -1118,7 +1118,8 @@ impl ModCollector<'_, '_> {
1118 ModItem::Function(id) => { 1118 ModItem::Function(id) => {
1119 let func = &self.item_tree[id]; 1119 let func = &self.item_tree[id];
1120 1120
1121 self.collect_proc_macro_def(&func.name, &attrs); 1121 let ast_id = InFile::new(self.file_id, func.ast_id);
1122 self.collect_proc_macro_def(&func.name, ast_id, &attrs);
1122 1123
1123 def = Some(DefData { 1124 def = Some(DefData {
1124 id: FunctionLoc { 1125 id: FunctionLoc {
@@ -1293,29 +1294,37 @@ impl ModCollector<'_, '_> {
1293 let db = self.def_collector.db; 1294 let db = self.def_collector.db;
1294 match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) { 1295 match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) {
1295 Ok((file_id, is_mod_rs, mod_dir)) => { 1296 Ok((file_id, is_mod_rs, mod_dir)) => {
1296 let module_id = self.push_child_module(
1297 module.name.clone(),
1298 ast_id,
1299 Some((file_id, is_mod_rs)),
1300 &self.item_tree[module.visibility],
1301 );
1302 let item_tree = db.file_item_tree(file_id.into()); 1297 let item_tree = db.file_item_tree(file_id.into());
1303 ModCollector { 1298 if item_tree
1304 def_collector: &mut *self.def_collector, 1299 .top_level_attrs(db, self.def_collector.def_map.krate)
1305 macro_depth: self.macro_depth, 1300 .cfg()
1306 module_id, 1301 .map_or(true, |cfg| {
1307 file_id: file_id.into(), 1302 self.def_collector.cfg_options.check(&cfg) != Some(false)
1308 item_tree: &item_tree, 1303 })
1309 mod_dir,
1310 }
1311 .collect(item_tree.top_level_items());
1312 if is_macro_use
1313 || item_tree
1314 .top_level_attrs(db, self.def_collector.def_map.krate)
1315 .by_key("macro_use")
1316 .exists()
1317 { 1304 {
1318 self.import_all_legacy_macros(module_id); 1305 let module_id = self.push_child_module(
1306 module.name.clone(),
1307 ast_id,
1308 Some((file_id, is_mod_rs)),
1309 &self.item_tree[module.visibility],
1310 );
1311 ModCollector {
1312 def_collector: &mut *self.def_collector,
1313 macro_depth: self.macro_depth,
1314 module_id,
1315 file_id: file_id.into(),
1316 item_tree: &item_tree,
1317 mod_dir,
1318 }
1319 .collect(item_tree.top_level_items());
1320 if is_macro_use
1321 || item_tree
1322 .top_level_attrs(db, self.def_collector.def_map.krate)
1323 .by_key("macro_use")
1324 .exists()
1325 {
1326 self.import_all_legacy_macros(module_id);
1327 }
1319 } 1328 }
1320 } 1329 }
1321 Err(candidate) => { 1330 Err(candidate) => {
@@ -1385,28 +1394,11 @@ impl ModCollector<'_, '_> {
1385 } 1394 }
1386 1395
1387 /// If `attrs` registers a procedural macro, collects its definition. 1396 /// If `attrs` registers a procedural macro, collects its definition.
1388 fn collect_proc_macro_def(&mut self, func_name: &Name, attrs: &Attrs) { 1397 fn collect_proc_macro_def(&mut self, func_name: &Name, ast_id: AstId<ast::Fn>, attrs: &Attrs) {
1389 // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere 1398 // FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere
1390 // FIXME: distinguish the type of macro 1399 if let Some(proc_macro) = attrs.parse_proc_macro_decl(func_name) {
1391 let macro_name = if attrs.by_key("proc_macro").exists() 1400 self.def_collector.export_proc_macro(proc_macro, ast_id);
1392 || attrs.by_key("proc_macro_attribute").exists() 1401 }
1393 {
1394 func_name.clone()
1395 } else {
1396 let derive = attrs.by_key("proc_macro_derive");
1397 if let Some(arg) = derive.tt_values().next() {
1398 if let [TokenTree::Leaf(Leaf::Ident(trait_name)), ..] = &*arg.token_trees {
1399 trait_name.as_name()
1400 } else {
1401 log::trace!("malformed `#[proc_macro_derive]`: {}", arg);
1402 return;
1403 }
1404 } else {
1405 return;
1406 }
1407 };
1408
1409 self.def_collector.resolve_proc_macro(&macro_name);
1410 } 1402 }
1411 1403
1412 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) { 1404 fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
@@ -1445,9 +1437,8 @@ impl ModCollector<'_, '_> {
1445 1437
1446 // Case 2: normal `macro_rules!` macro 1438 // Case 2: normal `macro_rules!` macro
1447 let macro_id = MacroDefId { 1439 let macro_id = MacroDefId {
1448 ast_id: Some(ast_id),
1449 krate: self.def_collector.def_map.krate, 1440 krate: self.def_collector.def_map.krate,
1450 kind: MacroDefKind::Declarative, 1441 kind: MacroDefKind::Declarative(ast_id),
1451 local_inner: is_local_inner, 1442 local_inner: is_local_inner,
1452 }; 1443 };
1453 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export); 1444 self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export);
@@ -1476,12 +1467,13 @@ impl ModCollector<'_, '_> {
1476 }, 1467 },
1477 ) { 1468 ) {
1478 Ok(Ok(macro_call_id)) => { 1469 Ok(Ok(macro_call_id)) => {
1479 self.def_collector.unexpanded_macros.push(MacroDirective { 1470 // Legacy macros need to be expanded immediately, so that any macros they produce
1480 module_id: self.module_id, 1471 // are in scope.
1481 ast_id, 1472 self.def_collector.collect_macro_expansion(
1482 legacy: Some(macro_call_id), 1473 self.module_id,
1483 depth: self.macro_depth + 1, 1474 macro_call_id,
1484 }); 1475 self.macro_depth + 1,
1476 );
1485 1477
1486 return; 1478 return;
1487 } 1479 }