From c23353d3f9279e9606600bcf2248ecdaa9888fbb Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Wed, 4 Dec 2019 01:33:50 +0800 Subject: [PATCH] Add optimalization on resolve import --- crates/ra_hir_def/src/nameres/collector.rs | 64 +++++++++++++++---- .../ra_hir_def/src/nameres/path_resolution.rs | 13 ++-- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index f7c9b1336ef1..16878e029e55 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -95,12 +95,18 @@ impl MacroStackMonitor { } } +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +enum PartialResolvedImport { + Unresolved, + Resolved(PerNs), +} + /// Walks the tree of module recursively struct DefCollector<'a, DB> { db: &'a DB, def_map: CrateDefMap, glob_imports: FxHashMap>, - unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData, ReachedFixedPoint)>, + unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData, PartialResolvedImport)>, unexpanded_macros: Vec<(LocalModuleId, AstId, Path)>, mod_dirs: FxHashMap, @@ -158,8 +164,8 @@ where let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); // show unresolved imports in completion, etc for (module_id, import, import_data, status) in unresolved_imports { - if status == ReachedFixedPoint::No { - self.record_resolved_import(module_id, PerNs::none(), import, &import_data) + if status == PartialResolvedImport::Unresolved { + self.record_resolved_import(module_id, PerNs::none(), import, &import_data, status) } } } @@ -267,13 +273,20 @@ where let mut previous_resolved = 0; imports.retain(|(module_id, import, import_data, status)| { - if *status == ReachedFixedPoint::Yes { + if let PartialResolvedImport::Resolved(_) = status { previous_resolved += 1; } - let (def, fp) = self.resolve_import(*module_id, import_data); + let (def, fp, krate) = self.resolve_import(*module_id, import_data); if fp == ReachedFixedPoint::Yes { - resolved.push((*module_id, def, *import, import_data.clone())) + resolved.push(( + *module_id, + def, + *import, + import_data.clone(), + krate, + status.clone(), + )) } fp == ReachedFixedPoint::No }); @@ -284,24 +297,39 @@ where } else { ReachedFixedPoint::No }; - for (module_id, def, import, import_data) in resolved { - self.record_resolved_import(module_id, def, import, &import_data); + for (module_id, def, import, import_data, krate, status) in resolved { + self.record_resolved_import(module_id, def, import, &import_data, status); + + // external crate graphs can't change in other crates. + if import_data.is_extern_crate { + continue; + } + if let Some(krate) = krate { + if krate != self.def_map.krate { + continue; + } + } // Reput resolved into unresolved_imports // This is because other unresolved imports and macros will bring in another PerNSs, // so we can only assume that it has been partially resolved. // We must try to solve it again in the next round. - self.unresolved_imports.push((module_id, import, import_data, ReachedFixedPoint::Yes)); + self.unresolved_imports.push(( + module_id, + import, + import_data, + PartialResolvedImport::Resolved(def), + )); } - result + return result; } fn resolve_import( &self, module_id: LocalModuleId, import: &raw::ImportData, - ) -> (PerNs, ReachedFixedPoint) { + ) -> (PerNs, ReachedFixedPoint, Option) { log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); if import.is_extern_crate { let res = self.def_map.resolve_name_in_extern_prelude( @@ -310,7 +338,7 @@ where .as_ident() .expect("extern crate should have been desugared to one-element path"), ); - (res, ReachedFixedPoint::Yes) + (res, ReachedFixedPoint::Yes, None) } else { let res = self.def_map.resolve_path_fp_with_macro( self.db, @@ -320,7 +348,7 @@ where BuiltinShadowMode::Module, ); - (res.resolved_def, res.reached_fixedpoint) + (res.resolved_def, res.reached_fixedpoint, res.krate) } } @@ -330,7 +358,15 @@ where def: PerNs, import_id: LocalImportId, import: &raw::ImportData, + status: PartialResolvedImport, ) { + // record import if it was changed + if let PartialResolvedImport::Resolved(ns) = status { + if ns == def { + return; + } + } + if import.is_glob { log::debug!("glob import: {:?}", import); match def.take_types() { @@ -606,7 +642,7 @@ where self.module_id, import_id, self.raw_items[import_id].clone(), - ReachedFixedPoint::No, + PartialResolvedImport::Unresolved, )) } raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 42a75226ba51..aab4b1dd9767 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -19,7 +19,7 @@ use crate::{ nameres::{BuiltinShadowMode, CrateDefMap}, path::{Path, PathKind}, per_ns::PerNs, - AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, + AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -39,19 +39,21 @@ pub(super) struct ResolvePathResult { pub(super) resolved_def: PerNs, pub(super) segment_index: Option, pub(super) reached_fixedpoint: ReachedFixedPoint, + pub(super) krate: Option, } impl ResolvePathResult { fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { - ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None) + ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None) } fn with( resolved_def: PerNs, reached_fixedpoint: ReachedFixedPoint, segment_index: Option, + krate: Option, ) -> ResolvePathResult { - ResolvePathResult { resolved_def, reached_fixedpoint, segment_index } + ResolvePathResult { resolved_def, reached_fixedpoint, segment_index, krate } } } @@ -175,6 +177,7 @@ impl CrateDefMap { def, ReachedFixedPoint::Yes, s.map(|s| s + i), + Some(module.krate), ); } @@ -201,6 +204,7 @@ impl CrateDefMap { PerNs::types(e.into()), ReachedFixedPoint::Yes, Some(i), + Some(self.krate), ); } } @@ -218,12 +222,13 @@ impl CrateDefMap { PerNs::types(s), ReachedFixedPoint::Yes, Some(i), + Some(self.krate), ); } }; } - ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) + ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate)) } fn resolve_name_in_module(