Skip to content

Commit

Permalink
Restructure ImportMap collection
Browse files Browse the repository at this point in the history
  • Loading branch information
lowr committed Jun 30, 2023
1 parent d75d9d8 commit e6d0ef3
Showing 1 changed file with 50 additions and 47 deletions.
97 changes: 50 additions & 47 deletions crates/hir-def/src/import_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,12 @@ impl ImportMap {
pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
let _p = profile::span("import_map_query");

let mut import_map = collect_import_map(db, krate);
let map = collect_import_map(db, krate);

let mut importables: Vec<_> = import_map
.map
let mut importables: Vec<_> = map
.iter()
// We've only collected items, whose name cannot be tuple field.
.map(|(item, info)| (item, info.name.as_str().unwrap().to_ascii_lowercase()))
.map(|(&item, info)| (item, info.name.as_str().unwrap().to_ascii_lowercase()))
.collect();
importables.sort_by(|(_, lhs_name), (_, rhs_name)| lhs_name.cmp(rhs_name));

Expand All @@ -74,61 +73,30 @@ impl ImportMap {
let _ = builder.insert(path, start_idx as u64);
}

import_map.fst = builder.into_map();
import_map.importables = importables.into_iter().map(|(&item, _)| item).collect();

Arc::new(import_map)
Arc::new(ImportMap {
map,
fst: builder.into_map(),
importables: importables.into_iter().map(|(item, _)| item).collect(),
})
}

pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> {
self.map.get(&item)
}

fn collect_trait_assoc_items(
&mut self,
db: &dyn DefDatabase,
tr: TraitId,
is_type_in_ns: bool,
trait_import_info: &ImportInfo,
) {
let _p = profile::span("collect_trait_assoc_items");
for (assoc_item_name, item) in &db.trait_data(tr).items {
let module_def_id = match item {
AssocItemId::FunctionId(f) => ModuleDefId::from(*f),
AssocItemId::ConstId(c) => ModuleDefId::from(*c),
// cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias`
// qualifier, ergo no need to store it for imports in import_map
AssocItemId::TypeAliasId(_) => {
cov_mark::hit!(type_aliases_ignored);
continue;
}
};
let assoc_item = if is_type_in_ns {
ItemInNs::Types(module_def_id)
} else {
ItemInNs::Values(module_def_id)
};

let assoc_item_info = ImportInfo {
container: trait_import_info.container,
name: assoc_item_name.clone(),
is_trait_assoc_item: true,
};
self.map.insert(assoc_item, assoc_item_info);
}
}
}

fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap {
fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap<ItemInNs, ImportInfo> {
let _p = profile::span("collect_import_map");

let def_map = db.crate_def_map(krate);
let mut import_map = ImportMap::default();
let mut map = FxIndexMap::default();

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

while let Some((module, depth)) = worklist.pop() {
let ext_def_map;
let mod_data = if module.krate == krate {
Expand Down Expand Up @@ -170,15 +138,16 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap {
}

if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
import_map.collect_trait_assoc_items(
collect_trait_assoc_items(
db,
&mut map,
tr,
matches!(item, ItemInNs::Types(_)),
&import_info,
);
}

import_map.map.insert(item, import_info);
map.insert(item, import_info);

// If we've just added a path to a module, descend into it. We might traverse
// modules multiple times, but only if the new path to it is shorter than the
Expand All @@ -190,7 +159,41 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap {
}
}

import_map
map
}

fn collect_trait_assoc_items(
db: &dyn DefDatabase,
map: &mut FxIndexMap<ItemInNs, ImportInfo>,
tr: TraitId,
is_type_in_ns: bool,
trait_import_info: &ImportInfo,
) {
let _p = profile::span("collect_trait_assoc_items");
for (assoc_item_name, item) in &db.trait_data(tr).items {
let module_def_id = match item {
AssocItemId::FunctionId(f) => ModuleDefId::from(*f),
AssocItemId::ConstId(c) => ModuleDefId::from(*c),
// cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias`
// qualifier, ergo no need to store it for imports in import_map
AssocItemId::TypeAliasId(_) => {
cov_mark::hit!(type_aliases_ignored);
continue;
}
};
let assoc_item = if is_type_in_ns {
ItemInNs::Types(module_def_id)
} else {
ItemInNs::Values(module_def_id)
};

let assoc_item_info = ImportInfo {
container: trait_import_info.container,
name: assoc_item_name.clone(),
is_trait_assoc_item: true,
};
map.insert(assoc_item, assoc_item_info);
}
}

impl PartialEq for ImportMap {
Expand Down

0 comments on commit e6d0ef3

Please sign in to comment.