From c31c3246a8c87a3639623c30b692a57e728bb046 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 15 Dec 2020 18:43:19 +0100 Subject: Basic support for decl macros 2.0 --- crates/hir_def/src/body/lower.rs | 5 ++++- crates/hir_def/src/item_tree.rs | 20 ++++++++++++++++++-- crates/hir_def/src/item_tree/lower.rs | 16 +++++++++++++++- crates/hir_def/src/nameres/collector.rs | 29 ++++++++++++++++++++++++++++- 4 files changed, 65 insertions(+), 5 deletions(-) (limited to 'crates/hir_def/src') 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<'_> { | ast::Item::Module(_) | ast::Item::MacroCall(_) => return None, ast::Item::MacroRules(def) => { - return Some(Either::Right(def)); + return Some(Either::Right(ast::Macro::from(def))); + } + ast::Item::MacroDef(def) => { + return Some(Either::Right(ast::Macro::from(def))); } }; 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 { mods, macro_calls, macro_rules, + macro_defs, exprs, vis, generics, @@ -164,6 +165,7 @@ impl ItemTree { mods.shrink_to_fit(); macro_calls.shrink_to_fit(); macro_rules.shrink_to_fit(); + macro_defs.shrink_to_fit(); exprs.shrink_to_fit(); vis.arena.shrink_to_fit(); @@ -283,6 +285,7 @@ struct ItemTreeData { mods: Arena, macro_calls: Arena, macro_rules: Arena, + macro_defs: Arena, exprs: Arena, vis: ItemVisibilities, @@ -431,6 +434,7 @@ mod_items! { Mod in mods -> ast::Module, MacroCall in macro_calls -> ast::MacroCall, MacroRules in macro_rules -> ast::MacroRules, + MacroDef in macro_defs -> ast::MacroDef, } macro_rules! impl_index { @@ -640,7 +644,7 @@ pub struct MacroCall { #[derive(Debug, Clone, Eq, PartialEq)] pub struct MacroRules { - /// For `macro_rules!` declarations, this is the name of the declared macro. + /// The name of the declared macro. pub name: Name, /// Has `#[macro_export]`. pub is_export: bool, @@ -651,6 +655,16 @@ pub struct MacroRules { pub ast_id: FileAstId, } +/// "Macros 2.0" macro definition. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct MacroDef { + pub name: Name, + pub visibility: RawVisibilityId, + /// Has `#[rustc_builtin_macro]`. + pub is_builtin: bool, + pub ast_id: FileAstId, +} + // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array // lengths, but we don't do much with them yet. #[derive(Debug, Clone, Eq, PartialEq)] @@ -680,7 +694,8 @@ impl ModItem { | ModItem::Trait(_) | ModItem::Impl(_) | ModItem::Mod(_) - | ModItem::MacroRules(_) => None, + | ModItem::MacroRules(_) + | ModItem::MacroDef(_) => None, ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)), ModItem::Const(konst) => Some(AssocItem::Const(*konst)), ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)), @@ -708,6 +723,7 @@ impl ModItem { ModItem::Mod(it) => tree[it.index].ast_id().upcast(), ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(), ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(), + ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(), } } } 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 { | ast::Item::ExternCrate(_) | ast::Item::Use(_) | ast::Item::MacroCall(_) - | ast::Item::MacroRules(_) => {} + | ast::Item::MacroRules(_) + | ast::Item::MacroDef(_) => {} }; let attrs = Attrs::new(item, &self.hygiene); @@ -122,6 +123,7 @@ impl Ctx { ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into), ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into), ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into), + ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into), ast::Item::ExternBlock(ast) => { Some(ModItems(self.lower_extern_block(ast).into_iter().collect::>())) } @@ -561,6 +563,18 @@ impl Ctx { Some(id(self.data().macro_rules.alloc(res))) } + fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option> { + let name = m.name().map(|it| it.as_name())?; + let attrs = Attrs::new(m, &self.hygiene); + + let ast_id = self.source_ast_id_map.ast_id(m); + let visibility = self.lower_visibility(m); + + let is_builtin = attrs.by_key("rustc_builtin_macro").exists(); + let res = MacroDef { name, is_builtin, ast_id, visibility }; + Some(id(self.data().macro_defs.alloc(res))) + } + fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec { block.extern_item_list().map_or(Vec::new(), |list| { 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<'_, '_> { } ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), ModItem::MacroRules(mac) => self.collect_macro_rules(&self.item_tree[mac]), + ModItem::MacroDef(id) => { + let mac = &self.item_tree[id]; + let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); + + // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it + // to define builtin macros, so we support at least that part. + if mac.is_builtin { + let krate = self.def_collector.def_map.krate; + if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { + let vis = self + .def_collector + .def_map + .resolve_visibility( + self.def_collector.db, + self.module_id, + &self.item_tree[mac.visibility], + ) + .unwrap_or(Visibility::Public); + self.def_collector.update( + self.module_id, + &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))], + vis, + ImportType::Named, + ); + } + } + } ModItem::Impl(imp) => { let module = ModuleId { krate: self.def_collector.def_map.krate, @@ -1280,7 +1307,7 @@ impl ModCollector<'_, '_> { } fn collect_macro_rules(&mut self, mac: &MacroRules) { - let ast_id = InFile::new(self.file_id, mac.ast_id); + let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); // Case 1: builtin macros if mac.is_builtin { -- cgit v1.2.3