Skip to content

Commit 83a2725

Browse files
Merge #6942
6942: Minor `#[derive]` resolution cleanup r=jonas-schievink a=jonas-schievink bors r+ Co-authored-by: Jonas Schievink <[email protected]>
2 parents c7b7c37 + aa00d1a commit 83a2725

File tree

6 files changed

+66
-33
lines changed

6 files changed

+66
-33
lines changed

crates/hir_def/src/attr.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{ops, sync::Arc};
55
use base_db::CrateId;
66
use cfg::{CfgExpr, CfgOptions};
77
use either::Either;
8-
use hir_expand::{hygiene::Hygiene, AstId, InFile};
8+
use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
99
use itertools::Itertools;
1010
use mbe::ast_to_token_tree;
1111
use syntax::{
@@ -19,7 +19,7 @@ use crate::{
1919
db::DefDatabase,
2020
item_tree::{ItemTreeId, ItemTreeNode},
2121
nameres::ModuleSource,
22-
path::ModPath,
22+
path::{ModPath, PathKind},
2323
src::HasChildSource,
2424
AdtId, AttrDefId, Lookup,
2525
};
@@ -357,6 +357,46 @@ impl Attr {
357357
};
358358
Some(Attr { path, input })
359359
}
360+
361+
/// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
362+
/// to derive macros.
363+
///
364+
/// Returns `None` when the attribute is not a well-formed `#[derive]` attribute.
365+
pub(crate) fn parse_derive(&self) -> Option<impl Iterator<Item = ModPath>> {
366+
if self.path.as_ident() != Some(&hir_expand::name![derive]) {
367+
return None;
368+
}
369+
370+
match &self.input {
371+
Some(AttrInput::TokenTree(args)) => {
372+
let mut counter = 0;
373+
let paths = args
374+
.token_trees
375+
.iter()
376+
.group_by(move |tt| {
377+
match tt {
378+
tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
379+
counter += 1;
380+
}
381+
_ => {}
382+
}
383+
counter
384+
})
385+
.into_iter()
386+
.map(|(_, tts)| {
387+
let segments = tts.filter_map(|tt| match tt {
388+
tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
389+
_ => None,
390+
});
391+
ModPath::from_segments(PathKind::Plain, segments)
392+
})
393+
.collect::<Vec<_>>();
394+
395+
Some(paths.into_iter())
396+
}
397+
_ => None,
398+
}
399+
}
360400
}
361401

362402
#[derive(Debug, Clone, Copy)]
@@ -384,7 +424,7 @@ impl<'a> AttrQuery<'a> {
384424
self.attrs().next().is_some()
385425
}
386426

387-
fn attrs(self) -> impl Iterator<Item = &'a Attr> {
427+
pub(crate) fn attrs(self) -> impl Iterator<Item = &'a Attr> {
388428
let key = self.key;
389429
self.attrs
390430
.iter()

crates/hir_def/src/nameres/collector.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,20 +1289,20 @@ impl ModCollector<'_, '_> {
12891289
}
12901290

12911291
fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) {
1292-
for derive_subtree in attrs.by_key("derive").tt_values() {
1293-
// for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
1294-
for tt in &derive_subtree.token_trees {
1295-
let ident = match &tt {
1296-
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
1297-
tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
1298-
_ => continue, // anything else would be an error (which we currently ignore)
1299-
};
1300-
let path = ModPath::from_tt_ident(ident);
1301-
1302-
let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
1303-
self.def_collector
1304-
.unexpanded_attribute_macros
1305-
.push(DeriveDirective { module_id: self.module_id, ast_id });
1292+
for derive in attrs.by_key("derive").attrs() {
1293+
match derive.parse_derive() {
1294+
Some(derive_macros) => {
1295+
for path in derive_macros {
1296+
let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
1297+
self.def_collector
1298+
.unexpanded_attribute_macros
1299+
.push(DeriveDirective { module_id: self.module_id, ast_id });
1300+
}
1301+
}
1302+
None => {
1303+
// FIXME: diagnose
1304+
log::debug!("malformed derive: {:?}", derive);
1305+
}
13061306
}
13071307
}
13081308
}

crates/hir_def/src/nameres/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use test_utils::mark;
1313

1414
use crate::{db::DefDatabase, nameres::*, test_db::TestDB};
1515

16-
fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> {
17-
let db = TestDB::with_files(fixture);
16+
fn compute_crate_def_map(ra_fixture: &str) -> Arc<CrateDefMap> {
17+
let db = TestDB::with_files(ra_fixture);
1818
let krate = db.crate_graph().iter().next().unwrap();
1919
db.crate_def_map(krate)
2020
}

crates/hir_def/src/nameres/tests/macros.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,11 +632,11 @@ pub struct bar;
632632
#[test]
633633
fn expand_derive() {
634634
let map = compute_crate_def_map(
635-
"
635+
r#"
636636
//- /main.rs crate:main deps:core
637-
use core::*;
637+
use core::Copy;
638638
639-
#[derive(Copy, Clone)]
639+
#[derive(Copy, core::Clone)]
640640
struct Foo;
641641
642642
//- /core.rs crate:core
@@ -645,7 +645,7 @@ fn expand_derive() {
645645
646646
#[rustc_builtin_macro]
647647
pub macro Clone {}
648-
",
648+
"#,
649649
);
650650
assert_eq!(map.modules[map.root].scope.impls().len(), 2);
651651
}

crates/hir_def/src/path.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,8 @@ use std::{
99

1010
use crate::{body::LowerCtx, type_ref::LifetimeRef};
1111
use base_db::CrateId;
12-
use hir_expand::{
13-
hygiene::Hygiene,
14-
name::{AsName, Name},
15-
};
16-
use syntax::ast::{self};
12+
use hir_expand::{hygiene::Hygiene, name::Name};
13+
use syntax::ast;
1714

1815
use crate::{
1916
type_ref::{TypeBound, TypeRef},
@@ -56,11 +53,6 @@ impl ModPath {
5653
ModPath { kind, segments }
5754
}
5855

59-
/// Converts an `tt::Ident` into a single-identifier `Path`.
60-
pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
61-
ident.as_name().into()
62-
}
63-
6456
/// Calls `cb` with all paths, represented by this use item.
6557
pub(crate) fn expand_use_item(
6658
item_src: InFile<ast::Use>,

crates/hir_expand/src/name.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ pub mod known {
152152
str,
153153
// Special names
154154
macro_rules,
155+
derive,
155156
doc,
156157
cfg_attr,
157158
// Components of known path (value or mod name)

0 commit comments

Comments
 (0)