about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-06-01 18:58:59 +0000
committerbors <bors@rust-lang.org>2024-06-01 18:58:59 +0000
commit60d2f73fd163b6a9af61bd3b9bebe0bd77dfa40f (patch)
treef11c0ad248746c943426f6b9b1c79ab969c8abbf
parentc1ea2b562e622aeddf5c0fd3dc7b340b532a4fea (diff)
parent8ab8bb0603dfab5c2c65e5a5ed2b1a2baac23004 (diff)
downloadrust-60d2f73fd163b6a9af61bd3b9bebe0bd77dfa40f.tar.gz
rust-60d2f73fd163b6a9af61bd3b9bebe0bd77dfa40f.zip
Auto merge of #17326 - Veykril:fix-attr-derive-container, r=Veykril
fix: Fix container search failing for tokens originating within derive attributes
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/files.rs22
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs28
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs20
5 files changed, 48 insertions, 40 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index 2e5fa6131a7..12421bbe702 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -298,7 +298,7 @@ pub fn expand_speculative(
             // prefer tokens of the same kind and text
             // Note the inversion of the score here, as we want to prefer the first token in case
             // of all tokens having the same score
-            (t.kind() != token_to_map.kind()) as u8 + (t.text() != token_to_map.text()) as u8
+            (t.kind() != token_to_map.kind()) as u8 + 2 * ((t.text() != token_to_map.text()) as u8)
         })?;
     Some((node.syntax_node(), token))
 }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
index 04a4851ddb7..1ba85c5c7ea 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
@@ -153,24 +153,20 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
 // region:specific impls
 
 impl InFile<&SyntaxNode> {
-    /// Skips the attributed item that caused the macro invocation we are climbing up
-    pub fn ancestors_with_macros_skip_attr_item(
+    /// Traverse up macro calls and skips the macro invocation node
+    pub fn ancestors_with_macros(
         self,
         db: &dyn db::ExpandDatabase,
     ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
         let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() {
             Some(parent) => Some(node.with_value(parent)),
-            None => {
-                let macro_file_id = node.file_id.macro_file()?;
-                let parent_node = macro_file_id.call_node(db);
-                if macro_file_id.is_attr_macro(db) {
-                    // macro call was an attributed item, skip it
-                    // FIXME: does this fail if this is a direct expansion of another macro?
-                    parent_node.map(|node| node.parent()).transpose()
-                } else {
-                    Some(parent_node)
-                }
-            }
+            None => db
+                .lookup_intern_macro_call(node.file_id.macro_file()?.macro_call_id)
+                .to_node_item(db)
+                .syntax()
+                .cloned()
+                .map(|node| node.parent())
+                .transpose(),
         };
         iter::successors(succ(&self.cloned()), succ)
     }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index 4ab989bec2f..83e92565f4d 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -33,8 +33,8 @@ use std::{fmt, hash::Hash};
 use base_db::{salsa::impl_intern_value_trivial, CrateId, FileId};
 use either::Either;
 use span::{
-    Edition, ErasedFileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor, SyntaxContextData,
-    SyntaxContextId,
+    Edition, ErasedFileAstId, FileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor,
+    SyntaxContextData, SyntaxContextId,
 };
 use syntax::{
     ast::{self, AstNode},
@@ -546,6 +546,18 @@ impl MacroCallLoc {
         }
     }
 
+    pub fn to_node_item(&self, db: &dyn ExpandDatabase) -> InFile<ast::Item> {
+        match self.kind {
+            MacroCallKind::FnLike { ast_id, .. } => {
+                InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db))
+            }
+            MacroCallKind::Derive { ast_id, .. } => {
+                InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db))
+            }
+            MacroCallKind::Attr { ast_id, .. } => InFile::new(ast_id.file_id, ast_id.to_node(db)),
+        }
+    }
+
     fn expand_to(&self) -> ExpandTo {
         match self.kind {
             MacroCallKind::FnLike { expand_to, .. } => expand_to,
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 6c70cc4baf0..53242611f81 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -862,10 +862,9 @@ impl<'db> SemanticsImpl<'db> {
                         // attribute we failed expansion for earlier, this might be a derive invocation
                         // or derive helper attribute
                         let attr = meta.parent_attr()?;
-
                         let adt = if let Some(adt) = attr.syntax().parent().and_then(ast::Adt::cast)
                         {
-                            // this might be a derive, or a derive helper on an ADT
+                            // this might be a derive on an ADT
                             let derive_call = self.with_ctx(|ctx| {
                                 // so try downmapping the token into the pseudo derive expansion
                                 // see [hir_expand::builtin_attr_macro] for how the pseudo derive expansion works
@@ -882,7 +881,7 @@ impl<'db> SemanticsImpl<'db> {
                                     let file_id = call_id.as_macro_file();
                                     let text_range = attr.syntax().text_range();
                                     // remove any other token in this macro input, all their mappings are the
-                                    // same as this one
+                                    // same as this
                                     tokens.retain(|t| !text_range.contains_range(t.text_range()));
                                     return process_expansion_for_token(&mut stack, file_id);
                                 }
@@ -890,21 +889,14 @@ impl<'db> SemanticsImpl<'db> {
                             }
                         } else {
                             // Otherwise this could be a derive helper on a variant or field
-                            if let Some(field) =
-                                attr.syntax().parent().and_then(ast::RecordField::cast)
-                            {
-                                field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
-                            } else if let Some(field) =
-                                attr.syntax().parent().and_then(ast::TupleField::cast)
-                            {
-                                field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
-                            } else if let Some(variant) =
-                                attr.syntax().parent().and_then(ast::Variant::cast)
-                            {
-                                variant.syntax().ancestors().nth(2).and_then(ast::Adt::cast)
-                            } else {
-                                None
-                            }
+                            attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| {
+                                match it {
+                                    ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
+                                    ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
+                                    ast::Item::Union(it) => Some(ast::Adt::Union(it)),
+                                    _ => None,
+                                }
+                            })
                         }?;
                         if !self.with_ctx(|ctx| ctx.has_derives(InFile::new(file_id, &adt))) {
                             return None;
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index d2bd8b0e799..77e7cdb58ab 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -139,7 +139,7 @@ impl SourceToDefCtx<'_, '_> {
         let _p = tracing::span!(tracing::Level::INFO, "module_to_def").entered();
         let parent_declaration = src
             .syntax()
-            .ancestors_with_macros_skip_attr_item(self.db.upcast())
+            .ancestors_with_macros(self.db.upcast())
             .find_map(|it| it.map(Either::<ast::Module, ast::BlockExpr>::cast).transpose())
             .map(|it| it.transpose());
 
@@ -366,7 +366,7 @@ impl SourceToDefCtx<'_, '_> {
     }
 
     pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
-        for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()) {
+        for container in src.ancestors_with_macros(self.db.upcast()) {
             if let Some(res) = self.container_to_def(container) {
                 return Some(res);
             }
@@ -420,7 +420,7 @@ impl SourceToDefCtx<'_, '_> {
     }
 
     fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
-        let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast());
+        let ancestors = src.ancestors_with_macros(self.db.upcast());
         for InFile { file_id, value } in ancestors {
             let item = match ast::Item::cast(value) {
                 Some(it) => it,
@@ -429,6 +429,7 @@ impl SourceToDefCtx<'_, '_> {
             let res: GenericDefId = match item {
                 ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(),
                 ast::Item::Struct(it) => self.struct_to_def(InFile::new(file_id, it))?.into(),
+                ast::Item::Union(it) => self.union_to_def(InFile::new(file_id, it))?.into(),
                 ast::Item::Enum(it) => self.enum_to_def(InFile::new(file_id, it))?.into(),
                 ast::Item::Trait(it) => self.trait_to_def(InFile::new(file_id, it))?.into(),
                 ast::Item::TraitAlias(it) => {
@@ -446,11 +447,18 @@ impl SourceToDefCtx<'_, '_> {
     }
 
     fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
-        let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast());
+        let ancestors = src.ancestors_with_macros(self.db.upcast());
         for InFile { file_id, value } in ancestors {
-            let item = match ast::Item::cast(value) {
+            let item = match ast::Item::cast(value.clone()) {
                 Some(it) => it,
-                None => continue,
+                None => {
+                    if let Some(variant) = ast::Variant::cast(value.clone()) {
+                        return self
+                            .enum_variant_to_def(InFile::new(file_id, variant))
+                            .map(Into::into);
+                    }
+                    continue;
+                }
             };
             let res: DefWithBodyId = match item {
                 ast::Item::Const(it) => self.const_to_def(InFile::new(file_id, it))?.into(),