Skip to content

Commit 85e7654

Browse files
committed
Cache Hygiene in DefCollector
1 parent cf72b62 commit 85e7654

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

crates/hir-def/src/nameres/collector.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
123123
from_glob_import: Default::default(),
124124
skip_attrs: Default::default(),
125125
is_proc_macro,
126+
hygienes: FxHashMap::default(),
126127
};
127128
if tree_id.is_block() {
128129
collector.seed_with_inner(tree_id);
@@ -270,6 +271,12 @@ struct DefCollector<'a> {
270271
/// This also stores the attributes to skip when we resolve derive helpers and non-macro
271272
/// non-builtin attributes in general.
272273
skip_attrs: FxHashMap<InFile<ModItem>, AttrId>,
274+
/// `Hygiene` cache, because `Hygiene` construction is expensive.
275+
///
276+
/// Almost all paths should have been lowered to `ModPath` during `ItemTree` construction.
277+
/// However, `DefCollector` still needs to lower paths in attributes, in particular those in
278+
/// derive meta item list.
279+
hygienes: FxHashMap<HirFileId, Hygiene>,
273280
}
274281

275282
impl DefCollector<'_> {
@@ -313,8 +320,9 @@ impl DefCollector<'_> {
313320
}
314321

315322
if *attr_name == hir_expand::name![feature] {
323+
let hygiene = &Hygiene::new_unhygienic();
316324
let features = attr
317-
.parse_path_comma_token_tree(self.db.upcast(), Hygiene::new_unhygienic())
325+
.parse_path_comma_token_tree(self.db.upcast(), hygiene)
318326
.into_iter()
319327
.flatten()
320328
.filter_map(|feat| match feat.segments() {
@@ -1225,7 +1233,18 @@ impl DefCollector<'_> {
12251233
}
12261234
};
12271235
let ast_id = ast_id.with_value(ast_adt_id);
1228-
let hygiene = Hygiene::new(self.db.upcast(), file_id);
1236+
1237+
let extend_unhygenic;
1238+
let hygiene = if file_id.is_macro() {
1239+
self.hygienes
1240+
.entry(file_id)
1241+
.or_insert_with(|| Hygiene::new(self.db.upcast(), file_id))
1242+
} else {
1243+
// Avoid heap allocation (`Hygiene` embraces `Arc`) and hash map entry
1244+
// when we're in an oridinary (non-macro) file.
1245+
extend_unhygenic = Hygiene::new_unhygienic();
1246+
&extend_unhygenic
1247+
};
12291248

12301249
match attr.parse_path_comma_token_tree(self.db.upcast(), hygiene) {
12311250
Some(derive_macros) => {
@@ -2215,6 +2234,7 @@ mod tests {
22152234
from_glob_import: Default::default(),
22162235
skip_attrs: Default::default(),
22172236
is_proc_macro: false,
2237+
hygienes: FxHashMap::default(),
22182238
};
22192239
collector.seed_with_top_level();
22202240
collector.collect();

crates/hir-expand/src/attrs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ impl Attr {
269269
pub fn parse_path_comma_token_tree<'a>(
270270
&'a self,
271271
db: &'a dyn ExpandDatabase,
272-
hygiene: Hygiene,
272+
hygiene: &'a Hygiene,
273273
) -> Option<impl Iterator<Item = ModPath> + 'a> {
274274
let args = self.token_tree_value()?;
275275

@@ -297,7 +297,7 @@ impl Attr {
297297
return None;
298298
}
299299
let path = meta.path()?;
300-
ModPath::from_src(db, path, &hygiene)
300+
ModPath::from_src(db, path, hygiene)
301301
});
302302

303303
Some(paths)

0 commit comments

Comments
 (0)