Skip to content

Commit fdd49b9

Browse files
bors[bot]Veykril
andauthored
Merge #10789
10789: internal: Check for derive attributes by item path, not `derive` identifier r=Veykril a=Veykril Prior we only checked if an attribute is the exact `derive` identifier and nothing else to collect derive attributes. That means when we encounter the following: ```rs #[::core::macros::builtin::derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ModPath { pub kind: PathKind, segments: Vec<Name>, } ``` We won't actually expand the derive attributes, but instead we just expand the `derive` attribute with our dummy identity expander. The changes here make it so we actually lookup the attribute path, check if it is the derive attribute and then collect the derives. Co-authored-by: Lukas Wirth <[email protected]>
2 parents 32f425d + f72512f commit fdd49b9

File tree

10 files changed

+188
-269
lines changed

10 files changed

+188
-269
lines changed

crates/hir_def/src/attr.rs

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use either::Either;
88
use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
99
use itertools::Itertools;
1010
use la_arena::ArenaMap;
11-
use mbe::{syntax_node_to_token_tree, DelimiterKind};
11+
use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
1212
use smallvec::{smallvec, SmallVec};
1313
use syntax::{
1414
ast::{self, AstNode, HasAttrs, IsString},
@@ -722,41 +722,35 @@ impl Attr {
722722
/// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
723723
/// to derive macros.
724724
///
725-
/// Returns `None` when the attribute is not a well-formed `#[derive]` attribute.
725+
/// Returns `None` when the attribute does not have a well-formed `#[derive]` attribute input.
726726
pub(crate) fn parse_derive(&self) -> Option<impl Iterator<Item = ModPath>> {
727-
if self.path.as_ident() != Some(&hir_expand::name![derive]) {
728-
return None;
729-
}
730-
731-
match self.input.as_deref() {
732-
Some(AttrInput::TokenTree(args, _)) => {
733-
let mut counter = 0;
734-
let paths = args
735-
.token_trees
736-
.iter()
737-
.group_by(move |tt| {
738-
match tt {
739-
tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
740-
counter += 1;
741-
}
742-
_ => {}
743-
}
744-
counter
745-
})
746-
.into_iter()
747-
.map(|(_, tts)| {
748-
let segments = tts.filter_map(|tt| match tt {
749-
tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
750-
_ => None,
751-
});
752-
ModPath::from_segments(PathKind::Plain, segments)
753-
})
754-
.collect::<Vec<_>>();
755-
756-
Some(paths.into_iter())
727+
if let Some(AttrInput::TokenTree(args, _)) = self.input.as_deref() {
728+
if args.delimiter_kind() != Some(DelimiterKind::Parenthesis) {
729+
return None;
757730
}
758-
_ => None,
731+
let mut counter = 0;
732+
let paths = args
733+
.token_trees
734+
.iter()
735+
.group_by(move |tt| {
736+
if let tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })) = tt {
737+
counter += 1;
738+
}
739+
counter
740+
})
741+
.into_iter()
742+
.map(|(_, tts)| {
743+
let segments = tts.filter_map(|tt| match tt {
744+
tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
745+
_ => None,
746+
});
747+
ModPath::from_segments(PathKind::Plain, segments)
748+
})
749+
.collect::<Vec<_>>();
750+
751+
return Some(paths.into_iter());
759752
}
753+
None
760754
}
761755

762756
pub fn string_value(&self) -> Option<&SmolStr> {

crates/hir_def/src/lib.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -776,13 +776,10 @@ fn attr_macro_as_call_id(
776776
macro_attr: &Attr,
777777
db: &dyn db::DefDatabase,
778778
krate: CrateId,
779-
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
779+
def: Option<MacroDefId>,
780780
) -> Result<MacroCallId, UnresolvedMacro> {
781781
let attr_path = &item_attr.path;
782-
783-
let def = resolver(attr_path.clone())
784-
.filter(MacroDefId::is_attribute)
785-
.ok_or_else(|| UnresolvedMacro { path: attr_path.clone() })?;
782+
let def = def.ok_or_else(|| UnresolvedMacro { path: attr_path.clone() })?;
786783
let last_segment =
787784
attr_path.segments().last().ok_or_else(|| UnresolvedMacro { path: attr_path.clone() })?;
788785
let mut arg = match macro_attr.input.as_deref() {

crates/hir_def/src/macro_expansion_tests/builtin_derive_macro.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,16 @@ fn test_copy_expand_in_core() {
2626
check(
2727
r#"
2828
#[rustc_builtin_macro]
29+
macro derive {}
30+
#[rustc_builtin_macro]
2931
macro Copy {}
3032
#[derive(Copy)]
3133
struct Foo;
3234
"#,
3335
expect![[r##"
3436
#[rustc_builtin_macro]
37+
macro derive {}
38+
#[rustc_builtin_macro]
3539
macro Copy {}
3640
#[derive(Copy)]
3741
struct Foo;

crates/hir_def/src/macro_expansion_tests/proc_macros.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ fn derive_censoring() {
3131
check(
3232
r#"
3333
//- proc_macros: derive_identity
34+
//- minicore:derive
3435
#[attr1]
3536
#[derive(Foo)]
3637
#[derive(proc_macros::DeriveIdentity)]

0 commit comments

Comments
 (0)