fix: Record macro calls in signatures in ChildBySource impls

This commit is contained in:
Lukas Wirth 2025-06-05 15:04:50 +02:00
parent 634596e2d7
commit bb5e6deff5
4 changed files with 77 additions and 19 deletions

View file

@ -1948,18 +1948,12 @@ impl<'db> SemanticsImpl<'db> {
ChildContainer::TraitId(it) => { ChildContainer::TraitId(it) => {
return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
} }
ChildContainer::TraitAliasId(it) => {
return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
}
ChildContainer::ImplId(it) => { ChildContainer::ImplId(it) => {
return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
} }
ChildContainer::EnumId(it) => { ChildContainer::EnumId(it) => {
return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
} }
ChildContainer::TypeAliasId(it) => {
return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
}
ChildContainer::GenericDefId(it) => { ChildContainer::GenericDefId(it) => {
return Some(SourceAnalyzer::new_generic_def(self.db, it, node, offset)); return Some(SourceAnalyzer::new_generic_def(self.db, it, node, offset));
} }

View file

@ -17,6 +17,7 @@ use hir_def::{
DynMap, DynMap,
keys::{self, Key}, keys::{self, Key},
}, },
hir::generics::GenericParams,
item_scope::ItemScope, item_scope::ItemScope,
item_tree::ItemTreeNode, item_tree::ItemTreeNode,
nameres::DefMap, nameres::DefMap,
@ -49,6 +50,12 @@ impl ChildBySource for TraitId {
data.items.iter().for_each(|&(_, item)| { data.items.iter().for_each(|&(_, item)| {
add_assoc_item(db, res, file_id, item); add_assoc_item(db, res, file_id, item);
}); });
let (_, source_map) = db.trait_signature_with_source_map(*self);
source_map.expansions().filter(|(ast, _)| ast.file_id == file_id).for_each(
|(ast, &exp_id)| {
res[keys::MACRO_CALL].insert(ast.value, exp_id);
},
);
} }
} }
@ -68,6 +75,12 @@ impl ChildBySource for ImplId {
data.items.iter().for_each(|&(_, item)| { data.items.iter().for_each(|&(_, item)| {
add_assoc_item(db, res, file_id, item); add_assoc_item(db, res, file_id, item);
}); });
let (_, source_map) = db.impl_signature_with_source_map(*self);
source_map.expansions().filter(|(ast, _)| ast.file_id == file_id).for_each(
|(ast, &exp_id)| {
res[keys::MACRO_CALL].insert(ast.value, exp_id);
},
);
} }
} }
@ -195,6 +208,12 @@ impl ChildBySource for EnumId {
res[keys::ENUM_VARIANT] res[keys::ENUM_VARIANT]
.insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant); .insert(ast_id_map.get(tree[variant.lookup(db).id.value].ast_id), variant);
}); });
let (_, source_map) = db.enum_signature_with_source_map(*self);
source_map.expansions().filter(|(ast, _)| ast.file_id == file_id).for_each(
|(ast, &exp_id)| {
res[keys::MACRO_CALL].insert(ast.value, exp_id);
},
);
} }
} }
@ -225,7 +244,8 @@ impl ChildBySource for GenericDefId {
return; return;
} }
let generic_params = db.generic_params(*self); let (generic_params, _, source_map) =
GenericParams::generic_params_and_store_and_source_map(db, *self);
let mut toc_idx_iter = generic_params.iter_type_or_consts().map(|(idx, _)| idx); let mut toc_idx_iter = generic_params.iter_type_or_consts().map(|(idx, _)| idx);
let lts_idx_iter = generic_params.iter_lt().map(|(idx, _)| idx); let lts_idx_iter = generic_params.iter_lt().map(|(idx, _)| idx);
@ -253,6 +273,12 @@ impl ChildBySource for GenericDefId {
res[keys::LIFETIME_PARAM].insert(AstPtr::new(&ast_param), id); res[keys::LIFETIME_PARAM].insert(AstPtr::new(&ast_param), id);
} }
} }
source_map.expansions().filter(|(ast, _)| ast.file_id == file_id).for_each(
|(ast, &exp_id)| {
res[keys::MACRO_CALL].insert(ast.value, exp_id);
},
);
} }
} }

View file

@ -631,14 +631,14 @@ impl SourceToDefCtx<'_, '_> {
match &item { match &item {
ast::Item::Module(it) => self.module_to_def(container.with_value(it))?.into(), ast::Item::Module(it) => self.module_to_def(container.with_value(it))?.into(),
ast::Item::Trait(it) => self.trait_to_def(container.with_value(it))?.into(), ast::Item::Trait(it) => self.trait_to_def(container.with_value(it))?.into(),
ast::Item::TraitAlias(it) => {
self.trait_alias_to_def(container.with_value(it))?.into()
}
ast::Item::Impl(it) => self.impl_to_def(container.with_value(it))?.into(), ast::Item::Impl(it) => self.impl_to_def(container.with_value(it))?.into(),
ast::Item::Enum(it) => self.enum_to_def(container.with_value(it))?.into(), ast::Item::Enum(it) => self.enum_to_def(container.with_value(it))?.into(),
ast::Item::TypeAlias(it) => { ast::Item::TypeAlias(it) => ChildContainer::GenericDefId(
self.type_alias_to_def(container.with_value(it))?.into() self.type_alias_to_def(container.with_value(it))?.into(),
} ),
ast::Item::TraitAlias(it) => ChildContainer::GenericDefId(
self.trait_alias_to_def(container.with_value(it))?.into(),
),
ast::Item::Struct(it) => { ast::Item::Struct(it) => {
let def = self.struct_to_def(container.with_value(it))?; let def = self.struct_to_def(container.with_value(it))?;
let is_in_body = it.field_list().is_some_and(|it| { let is_in_body = it.field_list().is_some_and(|it| {
@ -738,11 +738,9 @@ pub(crate) enum ChildContainer {
DefWithBodyId(DefWithBodyId), DefWithBodyId(DefWithBodyId),
ModuleId(ModuleId), ModuleId(ModuleId),
TraitId(TraitId), TraitId(TraitId),
TraitAliasId(TraitAliasId),
ImplId(ImplId), ImplId(ImplId),
EnumId(EnumId), EnumId(EnumId),
VariantId(VariantId), VariantId(VariantId),
TypeAliasId(TypeAliasId),
/// XXX: this might be the same def as, for example an `EnumId`. However, /// XXX: this might be the same def as, for example an `EnumId`. However,
/// here the children are generic parameters, and not, eg enum variants. /// here the children are generic parameters, and not, eg enum variants.
GenericDefId(GenericDefId), GenericDefId(GenericDefId),
@ -751,11 +749,9 @@ impl_from! {
DefWithBodyId, DefWithBodyId,
ModuleId, ModuleId,
TraitId, TraitId,
TraitAliasId,
ImplId, ImplId,
EnumId, EnumId,
VariantId, VariantId,
TypeAliasId,
GenericDefId GenericDefId
for ChildContainer for ChildContainer
} }
@ -767,11 +763,9 @@ impl ChildContainer {
ChildContainer::DefWithBodyId(it) => it.child_by_source(db, file_id), ChildContainer::DefWithBodyId(it) => it.child_by_source(db, file_id),
ChildContainer::ModuleId(it) => it.child_by_source(db, file_id), ChildContainer::ModuleId(it) => it.child_by_source(db, file_id),
ChildContainer::TraitId(it) => it.child_by_source(db, file_id), ChildContainer::TraitId(it) => it.child_by_source(db, file_id),
ChildContainer::TraitAliasId(_) => DynMap::default(),
ChildContainer::ImplId(it) => it.child_by_source(db, file_id), ChildContainer::ImplId(it) => it.child_by_source(db, file_id),
ChildContainer::EnumId(it) => it.child_by_source(db, file_id), ChildContainer::EnumId(it) => it.child_by_source(db, file_id),
ChildContainer::VariantId(it) => it.child_by_source(db, file_id), ChildContainer::VariantId(it) => it.child_by_source(db, file_id),
ChildContainer::TypeAliasId(_) => DynMap::default(),
ChildContainer::GenericDefId(it) => it.child_by_source(db, file_id), ChildContainer::GenericDefId(it) => it.child_by_source(db, file_id),
} }
} }

View file

@ -800,4 +800,48 @@ foo();
foo();"#]], foo();"#]],
); );
} }
#[test]
fn works_in_sig() {
check(
r#"
macro_rules! foo {
() => { u32 };
}
fn foo() -> foo$0!() {
42
}
"#,
expect![[r#"
foo!
u32"#]],
);
check(
r#"
macro_rules! foo {
() => { u32 };
}
fn foo(_: foo$0!() ) {}
"#,
expect![[r#"
foo!
u32"#]],
);
}
#[test]
fn works_in_generics() {
check(
r#"
trait Trait {}
macro_rules! foo {
() => { Trait };
}
impl<const C: foo$0!()> Trait for () {}
"#,
expect![[r#"
foo!
Trait"#]],
);
}
} }