Skip to content

Commit 60d2f73

Browse files
committed
Auto merge of #17326 - Veykril:fix-attr-derive-container, r=Veykril
fix: Fix container search failing for tokens originating within derive attributes
2 parents c1ea2b5 + 8ab8bb0 commit 60d2f73

File tree

5 files changed

+48
-40
lines changed

5 files changed

+48
-40
lines changed

src/tools/rust-analyzer/crates/hir-expand/src/db.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ pub fn expand_speculative(
298298
// prefer tokens of the same kind and text
299299
// Note the inversion of the score here, as we want to prefer the first token in case
300300
// of all tokens having the same score
301-
(t.kind() != token_to_map.kind()) as u8 + (t.text() != token_to_map.text()) as u8
301+
(t.kind() != token_to_map.kind()) as u8 + 2 * ((t.text() != token_to_map.text()) as u8)
302302
})?;
303303
Some((node.syntax_node(), token))
304304
}

src/tools/rust-analyzer/crates/hir-expand/src/files.rs

+9-13
Original file line numberDiff line numberDiff line change
@@ -153,24 +153,20 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
153153
// region:specific impls
154154

155155
impl InFile<&SyntaxNode> {
156-
/// Skips the attributed item that caused the macro invocation we are climbing up
157-
pub fn ancestors_with_macros_skip_attr_item(
156+
/// Traverse up macro calls and skips the macro invocation node
157+
pub fn ancestors_with_macros(
158158
self,
159159
db: &dyn db::ExpandDatabase,
160160
) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
161161
let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() {
162162
Some(parent) => Some(node.with_value(parent)),
163-
None => {
164-
let macro_file_id = node.file_id.macro_file()?;
165-
let parent_node = macro_file_id.call_node(db);
166-
if macro_file_id.is_attr_macro(db) {
167-
// macro call was an attributed item, skip it
168-
// FIXME: does this fail if this is a direct expansion of another macro?
169-
parent_node.map(|node| node.parent()).transpose()
170-
} else {
171-
Some(parent_node)
172-
}
173-
}
163+
None => db
164+
.lookup_intern_macro_call(node.file_id.macro_file()?.macro_call_id)
165+
.to_node_item(db)
166+
.syntax()
167+
.cloned()
168+
.map(|node| node.parent())
169+
.transpose(),
174170
};
175171
iter::successors(succ(&self.cloned()), succ)
176172
}

src/tools/rust-analyzer/crates/hir-expand/src/lib.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ use std::{fmt, hash::Hash};
3333
use base_db::{salsa::impl_intern_value_trivial, CrateId, FileId};
3434
use either::Either;
3535
use span::{
36-
Edition, ErasedFileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor, SyntaxContextData,
37-
SyntaxContextId,
36+
Edition, ErasedFileAstId, FileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor,
37+
SyntaxContextData, SyntaxContextId,
3838
};
3939
use syntax::{
4040
ast::{self, AstNode},
@@ -546,6 +546,18 @@ impl MacroCallLoc {
546546
}
547547
}
548548

549+
pub fn to_node_item(&self, db: &dyn ExpandDatabase) -> InFile<ast::Item> {
550+
match self.kind {
551+
MacroCallKind::FnLike { ast_id, .. } => {
552+
InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db))
553+
}
554+
MacroCallKind::Derive { ast_id, .. } => {
555+
InFile::new(ast_id.file_id, ast_id.map(FileAstId::upcast).to_node(db))
556+
}
557+
MacroCallKind::Attr { ast_id, .. } => InFile::new(ast_id.file_id, ast_id.to_node(db)),
558+
}
559+
}
560+
549561
fn expand_to(&self) -> ExpandTo {
550562
match self.kind {
551563
MacroCallKind::FnLike { expand_to, .. } => expand_to,

src/tools/rust-analyzer/crates/hir/src/semantics.rs

+10-18
Original file line numberDiff line numberDiff line change
@@ -862,10 +862,9 @@ impl<'db> SemanticsImpl<'db> {
862862
// attribute we failed expansion for earlier, this might be a derive invocation
863863
// or derive helper attribute
864864
let attr = meta.parent_attr()?;
865-
866865
let adt = if let Some(adt) = attr.syntax().parent().and_then(ast::Adt::cast)
867866
{
868-
// this might be a derive, or a derive helper on an ADT
867+
// this might be a derive on an ADT
869868
let derive_call = self.with_ctx(|ctx| {
870869
// so try downmapping the token into the pseudo derive expansion
871870
// see [hir_expand::builtin_attr_macro] for how the pseudo derive expansion works
@@ -882,29 +881,22 @@ impl<'db> SemanticsImpl<'db> {
882881
let file_id = call_id.as_macro_file();
883882
let text_range = attr.syntax().text_range();
884883
// remove any other token in this macro input, all their mappings are the
885-
// same as this one
884+
// same as this
886885
tokens.retain(|t| !text_range.contains_range(t.text_range()));
887886
return process_expansion_for_token(&mut stack, file_id);
888887
}
889888
None => Some(adt),
890889
}
891890
} else {
892891
// Otherwise this could be a derive helper on a variant or field
893-
if let Some(field) =
894-
attr.syntax().parent().and_then(ast::RecordField::cast)
895-
{
896-
field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
897-
} else if let Some(field) =
898-
attr.syntax().parent().and_then(ast::TupleField::cast)
899-
{
900-
field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
901-
} else if let Some(variant) =
902-
attr.syntax().parent().and_then(ast::Variant::cast)
903-
{
904-
variant.syntax().ancestors().nth(2).and_then(ast::Adt::cast)
905-
} else {
906-
None
907-
}
892+
attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| {
893+
match it {
894+
ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
895+
ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
896+
ast::Item::Union(it) => Some(ast::Adt::Union(it)),
897+
_ => None,
898+
}
899+
})
908900
}?;
909901
if !self.with_ctx(|ctx| ctx.has_derives(InFile::new(file_id, &adt))) {
910902
return None;

src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl SourceToDefCtx<'_, '_> {
139139
let _p = tracing::span!(tracing::Level::INFO, "module_to_def").entered();
140140
let parent_declaration = src
141141
.syntax()
142-
.ancestors_with_macros_skip_attr_item(self.db.upcast())
142+
.ancestors_with_macros(self.db.upcast())
143143
.find_map(|it| it.map(Either::<ast::Module, ast::BlockExpr>::cast).transpose())
144144
.map(|it| it.transpose());
145145

@@ -366,7 +366,7 @@ impl SourceToDefCtx<'_, '_> {
366366
}
367367

368368
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
369-
for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()) {
369+
for container in src.ancestors_with_macros(self.db.upcast()) {
370370
if let Some(res) = self.container_to_def(container) {
371371
return Some(res);
372372
}
@@ -420,7 +420,7 @@ impl SourceToDefCtx<'_, '_> {
420420
}
421421

422422
fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
423-
let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast());
423+
let ancestors = src.ancestors_with_macros(self.db.upcast());
424424
for InFile { file_id, value } in ancestors {
425425
let item = match ast::Item::cast(value) {
426426
Some(it) => it,
@@ -429,6 +429,7 @@ impl SourceToDefCtx<'_, '_> {
429429
let res: GenericDefId = match item {
430430
ast::Item::Fn(it) => self.fn_to_def(InFile::new(file_id, it))?.into(),
431431
ast::Item::Struct(it) => self.struct_to_def(InFile::new(file_id, it))?.into(),
432+
ast::Item::Union(it) => self.union_to_def(InFile::new(file_id, it))?.into(),
432433
ast::Item::Enum(it) => self.enum_to_def(InFile::new(file_id, it))?.into(),
433434
ast::Item::Trait(it) => self.trait_to_def(InFile::new(file_id, it))?.into(),
434435
ast::Item::TraitAlias(it) => {
@@ -446,11 +447,18 @@ impl SourceToDefCtx<'_, '_> {
446447
}
447448

448449
fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
449-
let ancestors = src.ancestors_with_macros_skip_attr_item(self.db.upcast());
450+
let ancestors = src.ancestors_with_macros(self.db.upcast());
450451
for InFile { file_id, value } in ancestors {
451-
let item = match ast::Item::cast(value) {
452+
let item = match ast::Item::cast(value.clone()) {
452453
Some(it) => it,
453-
None => continue,
454+
None => {
455+
if let Some(variant) = ast::Variant::cast(value.clone()) {
456+
return self
457+
.enum_variant_to_def(InFile::new(file_id, variant))
458+
.map(Into::into);
459+
}
460+
continue;
461+
}
454462
};
455463
let res: DefWithBodyId = match item {
456464
ast::Item::Const(it) => self.const_to_def(InFile::new(file_id, it))?.into(),

0 commit comments

Comments
 (0)