From 21359c3ab5fc497d11b2c0f0435c7635336a726e Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 25 Dec 2019 18:05:16 +0100 Subject: Take visibility into account for glob imports --- crates/ra_hir_def/src/nameres/collector.rs | 80 +++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 24 deletions(-) (limited to 'crates/ra_hir_def/src/nameres/collector.rs') diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 5b8478037..51df44d2f 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -109,7 +109,7 @@ struct MacroDirective { struct DefCollector<'a, DB> { db: &'a DB, def_map: CrateDefMap, - glob_imports: FxHashMap>, + glob_imports: FxHashMap>, unresolved_imports: Vec, resolved_imports: Vec, unexpanded_macros: Vec, @@ -218,6 +218,7 @@ where self.update( self.def_map.root, &[(name, PerNs::macros(macro_, ResolvedVisibility::Public))], + ResolvedVisibility::Public, ); } } @@ -352,7 +353,6 @@ where fn record_resolved_import(&mut self, directive: &ImportDirective) { let module_id = directive.module_id; - let import_id = directive.import_id; let import = &directive.import; let def = directive.status.namespaces(); let vis = self @@ -373,28 +373,48 @@ where let item_map = self.db.crate_def_map(m.krate); let scope = &item_map[m.local_id].scope; - // TODO: only use names we can see - // Module scoped macros is included - let items = scope.collect_resolutions_with_vis(vis); - - self.update(module_id, &items); + let items = scope + .resolutions() + // only keep visible names... + .map(|(n, res)| { + ( + n, + res.filter_visibility(|v| { + v.visible_from_def_map(&self.def_map, module_id) + }), + ) + }) + .filter(|(_, res)| !res.is_none()) + .collect::>(); + + self.update(module_id, &items, vis); } else { // glob import from same crate => we do an initial // import, and then need to propagate any further // additions let scope = &self.def_map[m.local_id].scope; - // TODO: only use names we can see - // Module scoped macros is included - let items = scope.collect_resolutions_with_vis(vis); - - self.update(module_id, &items); + let items = scope + .resolutions() + // only keep visible names... + .map(|(n, res)| { + ( + n, + res.filter_visibility(|v| { + v.visible_from_def_map(&self.def_map, module_id) + }), + ) + }) + .filter(|(_, res)| !res.is_none()) + .collect::>(); + + self.update(module_id, &items, vis); // record the glob import in case we add further items let glob = self.glob_imports.entry(m.local_id).or_default(); - if !glob.iter().any(|it| *it == (module_id, import_id)) { - glob.push((module_id, import_id)); + if !glob.iter().any(|(mid, _)| *mid == module_id) { + glob.push((module_id, vis)); } } } @@ -412,7 +432,7 @@ where (name, res) }) .collect::>(); - self.update(module_id, &resolutions); + self.update(module_id, &resolutions, vis); } Some(d) => { log::debug!("glob import {:?} from non-module/enum {:?}", import, d); @@ -434,21 +454,29 @@ where } } - self.update(module_id, &[(name, def.with_visibility(vis))]); + self.update(module_id, &[(name, def)], vis); } None => tested_by!(bogus_paths), } } } - fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)]) { - self.update_recursive(module_id, resolutions, 0) + fn update( + &mut self, + module_id: LocalModuleId, + resolutions: &[(Name, PerNs)], + vis: ResolvedVisibility, + ) { + self.update_recursive(module_id, resolutions, vis, 0) } fn update_recursive( &mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)], + // All resolutions are imported with this visibility; the visibilies in + // the `PerNs` values are ignored and overwritten + vis: ResolvedVisibility, depth: usize, ) { if depth > 100 { @@ -458,7 +486,7 @@ where let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - changed |= scope.push_res(name.clone(), *res); + changed |= scope.push_res(name.clone(), res.with_visibility(vis)); } if !changed { @@ -471,9 +499,13 @@ where .flat_map(|v| v.iter()) .cloned() .collect::>(); - for (glob_importing_module, _glob_import) in glob_imports { - // We pass the glob import so that the tracked import in those modules is that glob import - self.update_recursive(glob_importing_module, resolutions, depth + 1); + for (glob_importing_module, glob_import_vis) in glob_imports { + // we know all resolutions have the same visibility (`vis`), so we + // just need to check that once + if !vis.visible_from_def_map(&self.def_map, glob_importing_module) { + continue; + } + self.update_recursive(glob_importing_module, resolutions, glob_import_vis, depth + 1); } } @@ -715,7 +747,7 @@ where let def: ModuleDefId = module.into(); let vis = ResolvedVisibility::Public; // TODO handle module visibility self.def_collector.def_map.modules[self.module_id].scope.define_def(def); - self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))]); + self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis); res } @@ -780,7 +812,7 @@ where .def_map .resolve_visibility(self.def_collector.db, self.module_id, vis) .unwrap_or(ResolvedVisibility::Public); - self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))]) + self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis) } fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { -- cgit v1.2.3