about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2020-12-16 23:42:03 +0100
committerJonas Schievink <jonasschievink@gmail.com>2020-12-16 23:42:03 +0100
commit28b5334580e5814d102b006e310ca0d1f03cdd72 (patch)
treeda9ac7abc2f426dbe2783aa7a2a29e57d17cddf8
parent067067a6c11bb5afda98f5af14bfdec4744e7812 (diff)
downloadrust-28b5334580e5814d102b006e310ca0d1f03cdd72.tar.gz
rust-28b5334580e5814d102b006e310ca0d1f03cdd72.zip
Avoid querying attributes in item tree lowering
ItemTree is per-file, so there is no unique crate associated with it.
This means that it cannot know the active CfgOptions and thus couldn't
handle `cfg_attr`.

Prepare it for `cfg_attr`s by avoiding accessing attributes.
-rw-r--r--crates/hir_def/src/item_tree.rs8
-rw-r--r--crates/hir_def/src/item_tree/lower.rs24
-rw-r--r--crates/hir_def/src/nameres/collector.rs34
3 files changed, 28 insertions, 38 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 8cd0b18ccda..b8e09e3af31 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -646,12 +646,6 @@ pub struct MacroCall {
 pub struct MacroRules {
     /// The name of the declared macro.
     pub name: Name,
-    /// Has `#[macro_export]`.
-    pub is_export: bool,
-    /// Has `#[macro_export(local_inner_macros)]`.
-    pub is_local_inner: bool,
-    /// Has `#[rustc_builtin_macro]`.
-    pub is_builtin: bool,
     pub ast_id: FileAstId<ast::MacroRules>,
 }
 
@@ -660,8 +654,6 @@ pub struct MacroRules {
 pub struct MacroDef {
     pub name: Name,
     pub visibility: RawVisibilityId,
-    /// Has `#[rustc_builtin_macro]`.
-    pub is_builtin: bool,
     pub ast_id: FileAstId<ast::MacroDef>,
 }
 
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index dd3409762e3..7de385ee83e 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -539,39 +539,19 @@ impl Ctx {
 
     fn lower_macro_rules(&mut self, m: &ast::MacroRules) -> Option<FileItemTreeId<MacroRules>> {
         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);
 
-        // FIXME: cfg_attr
-        let export_attr = attrs.by_key("macro_export");
-
-        let is_export = export_attr.exists();
-        let is_local_inner = if is_export {
-            export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
-                tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
-                    ident.text.contains("local_inner_macros")
-                }
-                _ => false,
-            })
-        } else {
-            false
-        };
-
-        let is_builtin = attrs.by_key("rustc_builtin_macro").exists();
-        let res = MacroRules { name, is_export, is_builtin, is_local_inner, ast_id };
+        let res = MacroRules { name, ast_id };
         Some(id(self.data().macro_rules.alloc(res)))
     }
 
     fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroDef>> {
         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 };
+        let res = MacroDef { name, ast_id, visibility };
         Some(id(self.data().macro_defs.alloc(res)))
     }
 
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 785895277fa..1936348fb43 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -26,7 +26,8 @@ use crate::{
     db::DefDatabase,
     item_scope::{ImportType, PerNsGlobImports},
     item_tree::{
-        self, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, StructDefKind,
+        self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind,
+        StructDefKind,
     },
     nameres::{
         diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
@@ -967,14 +968,15 @@ 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::MacroRules(id) => self.collect_macro_rules(id),
                 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 attrs = self.item_tree.attrs(ModItem::from(id).into());
+                    if attrs.by_key("rustc_builtin_macro").exists() {
                         let krate = self.def_collector.def_map.krate;
                         let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
                             .or_else(|| find_builtin_derive(&mac.name, krate, ast_id));
@@ -1300,18 +1302,34 @@ impl ModCollector<'_, '_> {
         self.def_collector.resolve_proc_macro(&macro_name);
     }
 
-    fn collect_macro_rules(&mut self, mac: &MacroRules) {
+    fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
+        let mac = &self.item_tree[id];
+        let attrs = self.item_tree.attrs(ModItem::from(id).into());
         let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
 
+        let export_attr = attrs.by_key("macro_export");
+
+        let is_export = export_attr.exists();
+        let is_local_inner = if is_export {
+            export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
+                tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
+                    ident.text.contains("local_inner_macros")
+                }
+                _ => false,
+            })
+        } else {
+            false
+        };
+
         // Case 1: builtin macros
-        if mac.is_builtin {
+        if attrs.by_key("rustc_builtin_macro").exists() {
             let krate = self.def_collector.def_map.krate;
             if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) {
                 self.def_collector.define_macro(
                     self.module_id,
                     mac.name.clone(),
                     macro_id,
-                    mac.is_export,
+                    is_export,
                 );
                 return;
             }
@@ -1322,9 +1340,9 @@ impl ModCollector<'_, '_> {
             ast_id: Some(ast_id),
             krate: self.def_collector.def_map.krate,
             kind: MacroDefKind::Declarative,
-            local_inner: mac.is_local_inner,
+            local_inner: is_local_inner,
         };
-        self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, mac.is_export);
+        self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export);
     }
 
     fn collect_macro_call(&mut self, mac: &MacroCall) {