about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWyatt Herkamp <wherkamp@gmail.com>2024-03-18 07:10:02 -0400
committerWyatt Herkamp <wherkamp@gmail.com>2024-03-21 08:07:54 -0400
commit2c2bbe07fdc08b52dfb4e9cb47ac66ecd4276027 (patch)
tree92a83bdce52e9617e35de29eddb583821caff98a
parent4bd2f948bb9c95fae834111f1e68baa99640e527 (diff)
downloadrust-2c2bbe07fdc08b52dfb4e9cb47ac66ecd4276027.tar.gz
rust-2c2bbe07fdc08b52dfb4e9cb47ac66ecd4276027.zip
Treat Derive Macro specially.
-rw-r--r--crates/hir-def/src/nameres/attr_resolution.rs17
-rw-r--r--crates/hir-def/src/nameres/collector.rs18
-rw-r--r--crates/hir-expand/src/cfg_process.rs2
-rw-r--r--crates/hir-expand/src/db.rs35
-rw-r--r--crates/hir-expand/src/lib.rs29
-rw-r--r--crates/hir/src/lib.rs26
6 files changed, 87 insertions, 40 deletions
diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs
index eb7f4c05ae2..e2d83c8e3bf 100644
--- a/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/crates/hir-def/src/nameres/attr_resolution.rs
@@ -3,7 +3,7 @@
 use base_db::CrateId;
 use hir_expand::{
     attrs::{Attr, AttrId, AttrInput},
-    MacroCallId, MacroCallKind, MacroDefId,
+    AstId, MacroCallId, MacroCallKind, MacroDefId,
 };
 use span::SyntaxContextId;
 use syntax::{ast, SmolStr};
@@ -98,7 +98,20 @@ impl DefMap {
         false
     }
 }
-
+pub(super) fn derive_attr_macro_as_call_id(
+    db: &dyn DefDatabase,
+    item_attr: &AstId<ast::Adt>,
+    macro_attr: &Attr,
+    krate: CrateId,
+    def: MacroDefId,
+) -> MacroCallId {
+    def.make_call(
+        db.upcast(),
+        krate,
+        MacroCallKind::DeriveAttr { ast_id: *item_attr, invoc_attr_index: macro_attr.id },
+        macro_attr.ctxt,
+    )
+}
 pub(super) fn attr_macro_as_call_id(
     db: &dyn DefDatabase,
     item_attr: &AstIdWithPath<ast::Item>,
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 481e8a4cb43..27ad3ad1f4c 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -14,6 +14,7 @@ use crate::item_tree::Mod;
 use crate::item_tree::ModKind;
 use crate::macro_call_as_call_id_with_eager;
 
+use crate::nameres::attr_resolution::derive_attr_macro_as_call_id;
 use crate::nameres::mod_resolution::ModDir;
 
 use crate::item_tree::ItemTree;
@@ -1258,9 +1259,7 @@ impl DefCollector<'_> {
                         Some(def) if def.is_attribute() => def,
                         _ => return Resolved::No,
                     };
-                    // We will treat derive macros as an attribute as a reference for the input to derives
-                    let call_id =
-                        attr_macro_as_call_id(self.db, file_ast_id, attr, self.def_map.krate, def);
+
                     if let MacroDefId {
                         kind:
                             MacroDefKind::BuiltInAttr(
@@ -1289,8 +1288,16 @@ impl DefCollector<'_> {
                                 return recollect_without(self);
                             }
                         };
-                        let ast_id = ast_id.with_value(ast_adt_id);
 
+                        let ast_id = ast_id.with_value(ast_adt_id);
+                        // the call_id for the actual derive macro. This is used so all the derive proc macros can share a token tree
+                        let call_id = derive_attr_macro_as_call_id(
+                            self.db,
+                            &ast_id,
+                            attr,
+                            self.def_map.krate,
+                            def,
+                        );
                         match attr.parse_path_comma_token_tree(self.db.upcast()) {
                             Some(derive_macros) => {
                                 let mut len = 0;
@@ -1338,7 +1345,8 @@ impl DefCollector<'_> {
 
                         return recollect_without(self);
                     }
-
+                    let call_id =
+                        attr_macro_as_call_id(self.db, file_ast_id, attr, self.def_map.krate, def);
                     // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
                     // due to duplicating functions into macro expansions
                     if matches!(
diff --git a/crates/hir-expand/src/cfg_process.rs b/crates/hir-expand/src/cfg_process.rs
index 68de05fafe2..7e9ff5c85b5 100644
--- a/crates/hir-expand/src/cfg_process.rs
+++ b/crates/hir-expand/src/cfg_process.rs
@@ -180,7 +180,7 @@ pub(crate) fn process_cfg_attrs(
     db: &dyn ExpandDatabase,
 ) -> Option<FxHashSet<SyntaxElement>> {
     // FIXME: #[cfg_eval] is not implemented. But it is not stable yet
-    if !matches!(loc.kind, MacroCallKind::Derive { .. }) {
+    if !matches!(loc.kind, MacroCallKind::Derive { .. } | MacroCallKind::DeriveAttr { .. }) {
         return None;
     }
     let mut remove = FxHashSet::default();
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index 004c4473011..277c268086b 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -7,7 +7,6 @@ use mbe::syntax_node_to_token_tree;
 use rustc_hash::FxHashSet;
 use span::{AstIdMap, Span, SyntaxContextData, SyntaxContextId};
 use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T};
-use tracing::debug;
 use triomphe::Arc;
 
 use crate::{
@@ -158,7 +157,8 @@ pub fn expand_speculative(
             SyntaxFixupUndoInfo::NONE,
         ),
         MacroCallKind::Derive { derive_attr_index: index, .. }
-        | MacroCallKind::Attr { invoc_attr_index: index, .. } => {
+        | MacroCallKind::Attr { invoc_attr_index: index, .. }
+        | MacroCallKind::DeriveAttr { invoc_attr_index: index, .. } => {
             let censor = if let MacroCallKind::Derive { .. } = loc.kind {
                 censor_derive_input(index, &ast::Adt::cast(speculative_args.clone())?)
             } else {
@@ -347,31 +347,18 @@ type MacroArgResult = (Arc<tt::Subtree>, SyntaxFixupUndoInfo, Span);
 /// Other wise return the [macro_arg] for the macro_call_id.
 ///
 /// This is not connected to the database so it does not cached the result. However, the inner [macro_arg] query is
-///
-/// FIXME: Pick a better name
-fn smart_macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
-    let loc = db.lookup_intern_macro_call(id);
+fn macro_arg_considering_derives(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
+    let macro_call_kind = db.lookup_intern_macro_call(id).kind;
     // FIXME: We called lookup_intern_macro_call twice.
-    match loc.kind {
+    match macro_call_kind {
         // Get the macro arg for the derive macro
-        MacroCallKind::Derive { derive_macro_id, .. } => {
-            debug!(
-                ?loc,
-                "{id:?} is a derive macro. Using the derive macro, id: {derive_macro_id:?}, attribute as the macro arg."
-            );
-            db.macro_arg(derive_macro_id)
-        }
+        MacroCallKind::Derive { derive_macro_id, .. } => db.macro_arg(derive_macro_id),
         // Normal macro arg
         _ => db.macro_arg(id),
     }
 }
 
-fn macro_arg(
-    db: &dyn ExpandDatabase,
-    id: MacroCallId,
-    // FIXME: consider the following by putting fixup info into eager call info args
-    // ) -> ValueResult<Arc<(tt::Subtree, SyntaxFixupUndoInfo)>, Arc<Box<[SyntaxError]>>> {
-) -> MacroArgResult {
+fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
     let loc = db.lookup_intern_macro_call(id);
 
     if let MacroCallLoc {
@@ -441,7 +428,9 @@ fn macro_arg(
             }
             return (Arc::new(tt), SyntaxFixupUndoInfo::NONE, span);
         }
-        MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
+        // MacroCallKind::Derive should not be here. As we are getting the argument for the derive macro
+        MacroCallKind::Derive { ast_id, derive_attr_index, .. }
+        | MacroCallKind::DeriveAttr { ast_id, invoc_attr_index: derive_attr_index } => {
             let node = ast_id.to_ptr(db).to_node(&root);
             let censor_derive_input = censor_derive_input(derive_attr_index, &node);
             let item_node = node.into();
@@ -553,7 +542,7 @@ fn macro_expand(
     let (ExpandResult { value: tt, err }, span) = match loc.def.kind {
         MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc),
         _ => {
-            let (macro_arg, undo_info, span) = smart_macro_arg(db, macro_call_id);
+            let (macro_arg, undo_info, span) = macro_arg_considering_derives(db, macro_call_id);
 
             let arg = &*macro_arg;
             let res =
@@ -630,7 +619,7 @@ fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
 
 fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
     let loc = db.lookup_intern_macro_call(id);
-    let (macro_arg, undo_info, span) = smart_macro_arg(db, id);
+    let (macro_arg, undo_info, span) = macro_arg_considering_derives(db, id);
 
     let (expander, ast) = match loc.def.kind {
         MacroDefKind::ProcMacro(expander, _, ast) => (expander, ast),
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index e7a313c68cd..870c3dc0aac 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -228,6 +228,10 @@ pub enum MacroCallKind {
         /// We will resolve the same token tree for all derive macros in the same derive attribute.
         derive_macro_id: MacroCallId,
     },
+    DeriveAttr {
+        ast_id: AstId<ast::Adt>,
+        invoc_attr_index: AttrId,
+    },
     Attr {
         ast_id: AstId<ast::Item>,
         // FIXME: This shouldn't be here, we can derive this from `invoc_attr_index`
@@ -515,7 +519,8 @@ impl MacroCallLoc {
             MacroCallKind::FnLike { ast_id, .. } => {
                 ast_id.with_value(ast_id.to_node(db).syntax().clone())
             }
-            MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
+            MacroCallKind::Derive { ast_id, derive_attr_index, .. }
+            | MacroCallKind::DeriveAttr { ast_id, invoc_attr_index: derive_attr_index } => {
                 // FIXME: handle `cfg_attr`
                 ast_id.with_value(ast_id.to_node(db)).map(|it| {
                     collect_attrs(&it)
@@ -549,7 +554,7 @@ impl MacroCallLoc {
     fn expand_to(&self) -> ExpandTo {
         match self.kind {
             MacroCallKind::FnLike { expand_to, .. } => expand_to,
-            MacroCallKind::Derive { .. } => ExpandTo::Items,
+            MacroCallKind::Derive { .. } | MacroCallKind::DeriveAttr { .. } => ExpandTo::Items,
             MacroCallKind::Attr { .. } if self.def.is_attribute_derive() => ExpandTo::Items,
             MacroCallKind::Attr { .. } => {
                 // FIXME(stmt_expr_attributes)
@@ -583,6 +588,7 @@ impl MacroCallKind {
             MacroCallKind::FnLike { .. } => "macro call",
             MacroCallKind::Derive { .. } => "derive macro",
             MacroCallKind::Attr { .. } => "attribute macro",
+            MacroCallKind::DeriveAttr { .. } => "derive attribute",
         }
     }
 
@@ -591,6 +597,7 @@ impl MacroCallKind {
         match *self {
             MacroCallKind::FnLike { ast_id: InFile { file_id, .. }, .. }
             | MacroCallKind::Derive { ast_id: InFile { file_id, .. }, .. }
+            | MacroCallKind::DeriveAttr { ast_id: InFile { file_id, .. }, .. }
             | MacroCallKind::Attr { ast_id: InFile { file_id, .. }, .. } => file_id,
         }
     }
@@ -598,7 +605,8 @@ impl MacroCallKind {
     pub fn erased_ast_id(&self) -> ErasedFileAstId {
         match *self {
             MacroCallKind::FnLike { ast_id: InFile { value, .. }, .. } => value.erase(),
-            MacroCallKind::Derive { ast_id: InFile { value, .. }, .. } => value.erase(),
+            MacroCallKind::Derive { ast_id: InFile { value, .. }, .. }
+            | MacroCallKind::DeriveAttr { ast_id: InFile { value, .. }, .. } => value.erase(),
             MacroCallKind::Attr { ast_id: InFile { value, .. }, .. } => value.erase(),
         }
     }
@@ -619,7 +627,9 @@ impl MacroCallKind {
 
         let range = match kind {
             MacroCallKind::FnLike { ast_id, .. } => ast_id.to_ptr(db).text_range(),
-            MacroCallKind::Derive { ast_id, .. } => ast_id.to_ptr(db).text_range(),
+            MacroCallKind::Derive { ast_id, .. } | MacroCallKind::DeriveAttr { ast_id, .. } => {
+                ast_id.to_ptr(db).text_range()
+            }
             MacroCallKind::Attr { ast_id, .. } => ast_id.to_ptr(db).text_range(),
         };
 
@@ -665,6 +675,15 @@ impl MacroCallKind {
                     .syntax()
                     .text_range()
             }
+            MacroCallKind::DeriveAttr { ast_id, invoc_attr_index } => {
+                collect_attrs(&ast_id.to_node(db))
+                    .nth(invoc_attr_index.ast_index())
+                    .expect("missing attribute")
+                    .1
+                    .expect_left("attribute macro is a doc comment?")
+                    .syntax()
+                    .text_range()
+            }
         };
 
         FileRange { range, file_id }
@@ -675,7 +694,7 @@ impl MacroCallKind {
             MacroCallKind::FnLike { ast_id, .. } => {
                 ast_id.to_in_file_node(db).map(|it| Some(it.token_tree()?.syntax().clone()))
             }
-            MacroCallKind::Derive { ast_id, .. } => {
+            MacroCallKind::Derive { ast_id, .. } | MacroCallKind::DeriveAttr { ast_id, .. } => {
                 ast_id.to_in_file_node(db).syntax().cloned().map(Some)
             }
             MacroCallKind::Attr { ast_id, .. } => {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 2585d8e6f4e..acd53e19e8b 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -972,8 +972,7 @@ fn precise_macro_call_location(
                 MacroKind::ProcMacro,
             )
         }
-        // TODO: derive_macro_id
-        MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, derive_macro_id } => {
+        MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
             let node = ast_id.to_node(db.upcast());
             // Compute the precise location of the macro name's token in the derive
             // list.
@@ -1023,6 +1022,26 @@ fn precise_macro_call_location(
                 MacroKind::Attr,
             )
         }
+        MacroCallKind::DeriveAttr { ast_id, invoc_attr_index } => {
+            let node = ast_id.to_node(db.upcast());
+            let attr = collect_attrs(&node)
+                .nth(invoc_attr_index.ast_index())
+                .and_then(|x| Either::left(x.1))
+                .unwrap_or_else(|| {
+                    panic!("cannot find attribute #{}", invoc_attr_index.ast_index())
+                });
+
+            (
+                ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
+                Some(attr.syntax().text_range()),
+                attr.path()
+                    .and_then(|path| path.segment())
+                    .and_then(|seg| seg.name_ref())
+                    .as_ref()
+                    .map(ToString::to_string),
+                MacroKind::Attr,
+            )
+        }
     }
 }
 
@@ -3710,8 +3729,7 @@ impl Impl {
         let macro_file = src.file_id.macro_file()?;
         let loc = macro_file.macro_call_id.lookup(db.upcast());
         let (derive_attr, derive_index) = match loc.kind {
-            // TODO: derive_macro_id
-            MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, derive_macro_id } => {
+            MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
                 let module_id = self.id.lookup(db.upcast()).container;
                 (
                     db.crate_def_map(module_id.krate())[module_id.local_id]