aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-12-15 17:43:19 +0000
committerJonas Schievink <[email protected]>2020-12-15 17:43:34 +0000
commitc31c3246a8c87a3639623c30b692a57e728bb046 (patch)
treee66cdc459e249767c69c1b29b13e85fe30bdc935 /crates/hir_def
parentbd4c352831662762ee7a66da77ec9adf623b0a0a (diff)
Basic support for decl macros 2.0
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/body/lower.rs5
-rw-r--r--crates/hir_def/src/item_tree.rs20
-rw-r--r--crates/hir_def/src/item_tree/lower.rs16
-rw-r--r--crates/hir_def/src/nameres/collector.rs29
4 files changed, 65 insertions, 5 deletions
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index bdba4c33e..e4bf5603c 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -772,7 +772,10 @@ impl ExprCollector<'_> {
772 | ast::Item::Module(_) 772 | ast::Item::Module(_)
773 | ast::Item::MacroCall(_) => return None, 773 | ast::Item::MacroCall(_) => return None,
774 ast::Item::MacroRules(def) => { 774 ast::Item::MacroRules(def) => {
775 return Some(Either::Right(def)); 775 return Some(Either::Right(ast::Macro::from(def)));
776 }
777 ast::Item::MacroDef(def) => {
778 return Some(Either::Right(ast::Macro::from(def)));
776 } 779 }
777 }; 780 };
778 781
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 1c9babf37..8cd0b18cc 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -143,6 +143,7 @@ impl ItemTree {
143 mods, 143 mods,
144 macro_calls, 144 macro_calls,
145 macro_rules, 145 macro_rules,
146 macro_defs,
146 exprs, 147 exprs,
147 vis, 148 vis,
148 generics, 149 generics,
@@ -164,6 +165,7 @@ impl ItemTree {
164 mods.shrink_to_fit(); 165 mods.shrink_to_fit();
165 macro_calls.shrink_to_fit(); 166 macro_calls.shrink_to_fit();
166 macro_rules.shrink_to_fit(); 167 macro_rules.shrink_to_fit();
168 macro_defs.shrink_to_fit();
167 exprs.shrink_to_fit(); 169 exprs.shrink_to_fit();
168 170
169 vis.arena.shrink_to_fit(); 171 vis.arena.shrink_to_fit();
@@ -283,6 +285,7 @@ struct ItemTreeData {
283 mods: Arena<Mod>, 285 mods: Arena<Mod>,
284 macro_calls: Arena<MacroCall>, 286 macro_calls: Arena<MacroCall>,
285 macro_rules: Arena<MacroRules>, 287 macro_rules: Arena<MacroRules>,
288 macro_defs: Arena<MacroDef>,
286 exprs: Arena<Expr>, 289 exprs: Arena<Expr>,
287 290
288 vis: ItemVisibilities, 291 vis: ItemVisibilities,
@@ -431,6 +434,7 @@ mod_items! {
431 Mod in mods -> ast::Module, 434 Mod in mods -> ast::Module,
432 MacroCall in macro_calls -> ast::MacroCall, 435 MacroCall in macro_calls -> ast::MacroCall,
433 MacroRules in macro_rules -> ast::MacroRules, 436 MacroRules in macro_rules -> ast::MacroRules,
437 MacroDef in macro_defs -> ast::MacroDef,
434} 438}
435 439
436macro_rules! impl_index { 440macro_rules! impl_index {
@@ -640,7 +644,7 @@ pub struct MacroCall {
640 644
641#[derive(Debug, Clone, Eq, PartialEq)] 645#[derive(Debug, Clone, Eq, PartialEq)]
642pub struct MacroRules { 646pub struct MacroRules {
643 /// For `macro_rules!` declarations, this is the name of the declared macro. 647 /// The name of the declared macro.
644 pub name: Name, 648 pub name: Name,
645 /// Has `#[macro_export]`. 649 /// Has `#[macro_export]`.
646 pub is_export: bool, 650 pub is_export: bool,
@@ -651,6 +655,16 @@ pub struct MacroRules {
651 pub ast_id: FileAstId<ast::MacroRules>, 655 pub ast_id: FileAstId<ast::MacroRules>,
652} 656}
653 657
658/// "Macros 2.0" macro definition.
659#[derive(Debug, Clone, Eq, PartialEq)]
660pub struct MacroDef {
661 pub name: Name,
662 pub visibility: RawVisibilityId,
663 /// Has `#[rustc_builtin_macro]`.
664 pub is_builtin: bool,
665 pub ast_id: FileAstId<ast::MacroDef>,
666}
667
654// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array 668// NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
655// lengths, but we don't do much with them yet. 669// lengths, but we don't do much with them yet.
656#[derive(Debug, Clone, Eq, PartialEq)] 670#[derive(Debug, Clone, Eq, PartialEq)]
@@ -680,7 +694,8 @@ impl ModItem {
680 | ModItem::Trait(_) 694 | ModItem::Trait(_)
681 | ModItem::Impl(_) 695 | ModItem::Impl(_)
682 | ModItem::Mod(_) 696 | ModItem::Mod(_)
683 | ModItem::MacroRules(_) => None, 697 | ModItem::MacroRules(_)
698 | ModItem::MacroDef(_) => None,
684 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), 699 ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
685 ModItem::Const(konst) => Some(AssocItem::Const(*konst)), 700 ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
686 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), 701 ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
@@ -708,6 +723,7 @@ impl ModItem {
708 ModItem::Mod(it) => tree[it.index].ast_id().upcast(), 723 ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
709 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), 724 ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
710 ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), 725 ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
726 ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(),
711 } 727 }
712 } 728 }
713} 729}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index b39d7fb7a..1dc06a211 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -101,7 +101,8 @@ impl Ctx {
101 | ast::Item::ExternCrate(_) 101 | ast::Item::ExternCrate(_)
102 | ast::Item::Use(_) 102 | ast::Item::Use(_)
103 | ast::Item::MacroCall(_) 103 | ast::Item::MacroCall(_)
104 | ast::Item::MacroRules(_) => {} 104 | ast::Item::MacroRules(_)
105 | ast::Item::MacroDef(_) => {}
105 }; 106 };
106 107
107 let attrs = Attrs::new(item, &self.hygiene); 108 let attrs = Attrs::new(item, &self.hygiene);
@@ -122,6 +123,7 @@ impl Ctx {
122 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), 123 ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into),
123 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), 124 ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
124 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), 125 ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
126 ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into),
125 ast::Item::ExternBlock(ast) => { 127 ast::Item::ExternBlock(ast) => {
126 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>())) 128 Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
127 } 129 }
@@ -561,6 +563,18 @@ impl Ctx {
561 Some(id(self.data().macro_rules.alloc(res))) 563 Some(id(self.data().macro_rules.alloc(res)))
562 } 564 }
563 565
566 fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> {
567 let name = m.name().map(|it| it.as_name())?;
568 let attrs = Attrs::new(m, &self.hygiene);
569
570 let ast_id = self.source_ast_id_map.ast_id(m);
571 let visibility = self.lower_visibility(m);
572
573 let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
574 let res = MacroDef { name, is_builtin, ast_id, visibility };
575 Some(id(self.data().macro_defs.alloc(res)))
576 }
577
564 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> { 578 fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
565 block.extern_item_list().map_or(Vec::new(), |list| { 579 block.extern_item_list().map_or(Vec::new(), |list| {
566 list.extern_items() 580 list.extern_items()
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 85cc342c4..c2f741060 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -976,6 +976,33 @@ impl ModCollector<'_, '_> {
976 } 976 }
977 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), 977 ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
978 ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), 978 ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]),
979 ModItem::MacroDef(id) => {
980 let mac = &self.item_tree[id];
981 let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
982
983 // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it
984 // to define builtin macros, so we support at least that part.
985 if mac.is_builtin {
986 let krate = self.def_collector.def_map.krate;
987 if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) {
988 let vis = self
989 .def_collector
990 .def_map
991 .resolve_visibility(
992 self.def_collector.db,
993 self.module_id,
994 &self.item_tree[mac.visibility],
995 )
996 .unwrap_or(Visibility::Public);
997 self.def_collector.update(
998 self.module_id,
999 &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))],
1000 vis,
1001 ImportType::Named,
1002 );
1003 }
1004 }
1005 }
979 ModItem::Impl(imp) => { 1006 ModItem::Impl(imp) => {
980 let module = ModuleId { 1007 let module = ModuleId {
981 krate: self.def_collector.def_map.krate, 1008 krate: self.def_collector.def_map.krate,
@@ -1280,7 +1307,7 @@ impl ModCollector<'_, '_> {
1280 } 1307 }
1281 1308
1282 fn collect_macro_rules(&mut self, mac: &MacroRules) { 1309 fn collect_macro_rules(&mut self, mac: &MacroRules) {
1283 let ast_id = InFile::new(self.file_id, mac.ast_id); 1310 let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
1284 1311
1285 // Case 1: builtin macros 1312 // Case 1: builtin macros
1286 if mac.is_builtin { 1313 if mac.is_builtin {