Skip to content

Commit 801a887

Browse files
committed
Record all import paths per item in ImportMap
1 parent 2339ba4 commit 801a887

File tree

1 file changed

+55
-94
lines changed

1 file changed

+55
-94
lines changed

crates/hir-def/src/import_map.rs

Lines changed: 55 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
//! A map of all publicly exported items in a crate.
22
3-
use std::{collections::hash_map::Entry, fmt, hash::BuildHasherDefault};
3+
use std::{fmt, hash::BuildHasherDefault};
44

55
use base_db::CrateId;
66
use fst::{self, raw::IndexedValue, Streamer};
77
use hir_expand::name::Name;
88
use indexmap::IndexMap;
99
use itertools::Itertools;
10-
use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
11-
use smallvec::{smallvec, SmallVec};
10+
use rustc_hash::{FxHashSet, FxHasher};
11+
use smallvec::SmallVec;
1212
use triomphe::Arc;
1313

1414
use crate::{
@@ -103,11 +103,13 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
103103

104104
// We look only into modules that are public(ly reexported), starting with the crate root.
105105
let root = def_map.module_id(DefMap::ROOT);
106-
let mut worklist = vec![(root, 0u32)];
107-
// Records items' minimum module depth.
108-
let mut depth_map = FxHashMap::default();
106+
let mut worklist = vec![root];
107+
let mut visited = FxHashSet::default();
109108

110-
while let Some((module, depth)) = worklist.pop() {
109+
while let Some(module) = worklist.pop() {
110+
if !visited.insert(module) {
111+
continue;
112+
}
111113
let ext_def_map;
112114
let mod_data = if module.krate == krate {
113115
&def_map[module.local_id]
@@ -126,6 +128,7 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
126128
}
127129
});
128130

131+
// FIXME: This loop might add the same entry up to 3 times per item! dedup
129132
for (name, per_ns) in visible_items {
130133
for (item, import) in per_ns.iter_items() {
131134
let attr_id = if let Some(import) = import {
@@ -139,11 +142,10 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
139142
ItemInNs::Macros(id) => Some(id.into()),
140143
}
141144
};
142-
let status @ (is_doc_hidden, is_unstable) =
143-
attr_id.map_or((false, false), |attr_id| {
144-
let attrs = db.attrs(attr_id);
145-
(attrs.has_doc_hidden(), attrs.is_unstable())
146-
});
145+
let (is_doc_hidden, is_unstable) = attr_id.map_or((false, false), |attr_id| {
146+
let attrs = db.attrs(attr_id);
147+
(attrs.has_doc_hidden(), attrs.is_unstable())
148+
});
147149

148150
let import_info = ImportInfo {
149151
name: name.clone(),
@@ -152,50 +154,6 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
152154
is_unstable,
153155
};
154156

155-
match depth_map.entry(item) {
156-
Entry::Vacant(entry) => _ = entry.insert((depth, status)),
157-
Entry::Occupied(mut entry) => {
158-
let &(occ_depth, (occ_is_doc_hidden, occ_is_unstable)) = entry.get();
159-
(depth, occ_depth);
160-
let overwrite = match (
161-
is_doc_hidden,
162-
occ_is_doc_hidden,
163-
is_unstable,
164-
occ_is_unstable,
165-
) {
166-
// no change of hiddeness or unstableness
167-
(true, true, true, true)
168-
| (true, true, false, false)
169-
| (false, false, true, true)
170-
| (false, false, false, false) => depth < occ_depth,
171-
172-
// either less hidden or less unstable, accept
173-
(true, true, false, true)
174-
| (false, true, true, true)
175-
| (false, true, false, true)
176-
| (false, true, false, false)
177-
| (false, false, false, true) => true,
178-
// more hidden or unstable, discard
179-
(true, true, true, false)
180-
| (true, false, true, true)
181-
| (true, false, true, false)
182-
| (true, false, false, false)
183-
| (false, false, true, false) => false,
184-
185-
// exchanges doc(hidden) for unstable (and vice-versa),
186-
(true, false, false, true) | (false, true, true, false) => {
187-
depth < occ_depth
188-
}
189-
};
190-
// FIXME: Remove the overwrite rules as we can now record exports and
191-
// aliases for the same item
192-
if !overwrite {
193-
continue;
194-
}
195-
entry.insert((depth, status));
196-
}
197-
}
198-
199157
if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
200158
collect_trait_assoc_items(
201159
db,
@@ -206,13 +164,14 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
206164
);
207165
}
208166

209-
map.insert(item, (smallvec![import_info], IsTraitAssocItem::No));
167+
map.entry(item)
168+
.or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::No))
169+
.0
170+
.push(import_info);
210171

211-
// If we've just added a module, descend into it. We might traverse modules
212-
// multiple times, but only if the module depth is smaller (else we `continue`
213-
// above).
172+
// If we've just added a module, descend into it.
214173
if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() {
215-
worklist.push((mod_id, depth + 1));
174+
worklist.push(mod_id);
216175
}
217176
}
218177
}
@@ -253,7 +212,11 @@ fn collect_trait_assoc_items(
253212
is_doc_hidden: attrs.has_doc_hidden(),
254213
is_unstable: attrs.is_unstable(),
255214
};
256-
map.insert(assoc_item, (smallvec![assoc_item_info], IsTraitAssocItem::Yes));
215+
216+
map.entry(assoc_item)
217+
.or_insert_with(|| (SmallVec::new(), IsTraitAssocItem::Yes))
218+
.0
219+
.push(assoc_item_info);
257220
}
258221
}
259222

@@ -284,7 +247,7 @@ impl fmt::Debug for ImportMap {
284247
}
285248

286249
/// A way to match import map contents against the search query.
287-
#[derive(Debug)]
250+
#[derive(Copy, Clone, Debug)]
288251
enum SearchMode {
289252
/// Import map entry should strictly match the query string.
290253
Exact,
@@ -426,7 +389,7 @@ pub fn search_dependencies(
426389
while let Some((_, indexed_values)) = stream.next() {
427390
for &IndexedValue { index, value } in indexed_values {
428391
let import_map = &import_maps[index];
429-
let [importable, importables @ ..] = &import_map.importables[value as usize..] else {
392+
let importables @ [importable, ..] = &import_map.importables[value as usize..] else {
430393
continue;
431394
};
432395

@@ -441,38 +404,32 @@ pub fn search_dependencies(
441404
else {
442405
continue;
443406
};
444-
res.insert(*importable);
445-
446-
if !importables.is_empty() {
447-
// FIXME: so many allocs...
448-
// Name shared by the importable items in this group.
449-
let common_importable_name =
450-
common_importable_data.name.to_smol_str().to_ascii_lowercase();
451-
// Add the items from this name group. Those are all subsequent items in
452-
// `importables` whose name match `common_importable_name`.
453-
let iter = importables
454-
.iter()
455-
.copied()
456-
.take_while(|item| {
407+
408+
// FIXME: so many allocs...
409+
// Name shared by the importable items in this group.
410+
let common_importable_name =
411+
common_importable_data.name.to_smol_str().to_ascii_lowercase();
412+
// Add the items from this name group. Those are all subsequent items in
413+
// `importables` whose name match `common_importable_name`.
414+
let iter = importables
415+
.iter()
416+
.copied()
417+
.take_while(|item| {
418+
let &(ref import_infos, assoc_mode) = &import_map.map[item];
419+
query.matches_assoc_mode(assoc_mode)
420+
&& import_infos.iter().any(|info| {
421+
info.name.to_smol_str().to_ascii_lowercase() == common_importable_name
422+
})
423+
})
424+
.filter(|item| {
425+
!query.case_sensitive || {
426+
// we've already checked the common importables name case-insensitively
457427
let &(ref import_infos, assoc_mode) = &import_map.map[item];
458428
query.matches_assoc_mode(assoc_mode)
459-
&& import_infos.iter().any(|info| {
460-
info.name.to_smol_str().to_ascii_lowercase()
461-
== common_importable_name
462-
})
463-
})
464-
.filter(|item| {
465-
!query.case_sensitive || {
466-
// we've already checked the common importables name case-insensitively
467-
let &(ref import_infos, assoc_mode) = &import_map.map[item];
468-
query.matches_assoc_mode(assoc_mode)
469-
&& import_infos
470-
.iter()
471-
.any(|info| query.import_matches(db, info, false))
472-
}
473-
});
474-
res.extend(iter);
475-
}
429+
&& import_infos.iter().any(|info| query.import_matches(db, info, false))
430+
}
431+
});
432+
res.extend(iter);
476433

477434
if res.len() >= query.limit {
478435
return res;
@@ -665,6 +622,7 @@ mod tests {
665622
main:
666623
- publ1 (t)
667624
- real_pu2 (t)
625+
- real_pu2::Pub (t)
668626
- real_pub (t)
669627
- real_pub::Pub (t)
670628
"#]],
@@ -690,6 +648,7 @@ mod tests {
690648
- sub (t)
691649
- sub::Def (t)
692650
- sub::subsub (t)
651+
- sub::subsub::Def (t)
693652
"#]],
694653
);
695654
}
@@ -789,7 +748,9 @@ mod tests {
789748
- module (t)
790749
- module::S (t)
791750
- module::S (v)
751+
- module::module (t)
792752
- sub (t)
753+
- sub::module (t)
793754
"#]],
794755
);
795756
}

0 commit comments

Comments
 (0)