Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/nameres/collector.rs')
-rw-r--r--crates/hir-def/src/nameres/collector.rs39
1 files changed, 31 insertions, 8 deletions
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 756a8f5049..ba93b2c70e 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -14,6 +14,7 @@ use hir_expand::{
builtin_attr_macro::find_builtin_attr,
builtin_derive_macro::find_builtin_derive,
builtin_fn_macro::find_builtin_macro,
+ hygiene::Hygiene,
name::{name, AsName, Name},
proc_macro::ProcMacroExpander,
ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallLoc,
@@ -122,6 +123,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
from_glob_import: Default::default(),
skip_attrs: Default::default(),
is_proc_macro,
+ hygienes: FxHashMap::default(),
};
if tree_id.is_block() {
collector.seed_with_inner(tree_id);
@@ -269,6 +271,12 @@ struct DefCollector<'a> {
/// This also stores the attributes to skip when we resolve derive helpers and non-macro
/// non-builtin attributes in general.
skip_attrs: FxHashMap<InFile<ModItem>, AttrId>,
+ /// `Hygiene` cache, because `Hygiene` construction is expensive.
+ ///
+ /// Almost all paths should have been lowered to `ModPath` during `ItemTree` construction.
+ /// However, `DefCollector` still needs to lower paths in attributes, in particular those in
+ /// derive meta item list.
+ hygienes: FxHashMap<HirFileId, Hygiene>,
}
impl DefCollector<'_> {
@@ -312,13 +320,15 @@ impl DefCollector<'_> {
}
if *attr_name == hir_expand::name![feature] {
- let features =
- attr.parse_path_comma_token_tree().into_iter().flatten().filter_map(
- |feat| match feat.segments() {
- [name] => Some(name.to_smol_str()),
- _ => None,
- },
- );
+ let hygiene = &Hygiene::new_unhygienic();
+ let features = attr
+ .parse_path_comma_token_tree(self.db.upcast(), hygiene)
+ .into_iter()
+ .flatten()
+ .filter_map(|feat| match feat.segments() {
+ [name] => Some(name.to_smol_str()),
+ _ => None,
+ });
self.def_map.unstable_features.extend(features);
}
@@ -1224,7 +1234,19 @@ impl DefCollector<'_> {
};
let ast_id = ast_id.with_value(ast_adt_id);
- match attr.parse_path_comma_token_tree() {
+ let extend_unhygenic;
+ let hygiene = if file_id.is_macro() {
+ self.hygienes
+ .entry(file_id)
+ .or_insert_with(|| Hygiene::new(self.db.upcast(), file_id))
+ } else {
+ // Avoid heap allocation (`Hygiene` embraces `Arc`) and hash map entry
+ // when we're in an oridinary (non-macro) file.
+ extend_unhygenic = Hygiene::new_unhygienic();
+ &extend_unhygenic
+ };
+
+ match attr.parse_path_comma_token_tree(self.db.upcast(), hygiene) {
Some(derive_macros) => {
let mut len = 0;
for (idx, path) in derive_macros.enumerate() {
@@ -2212,6 +2234,7 @@ mod tests {
from_glob_import: Default::default(),
skip_attrs: Default::default(),
is_proc_macro: false,
+ hygienes: FxHashMap::default(),
};
collector.seed_with_top_level();
collector.collect();