diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-01-14 10:00:46 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-14 10:00:46 +0000 |
| commit | 184f4cbf5df909146b05aaa3b7f2f0b27ac36590 (patch) | |
| tree | c9d803d2fefdc31278338fc67f6df8d1bf747a12 | |
| parent | 39167b97d8a62adadecc9b67caac65ec556768cf (diff) | |
| parent | cca0dfa79ed968d41464eb7beb7aaa970e2d429f (diff) | |
| download | rust-184f4cbf5df909146b05aaa3b7f2f0b27ac36590.tar.gz rust-184f4cbf5df909146b05aaa3b7f2f0b27ac36590.zip | |
Merge #7110
7110: Deduplicate macros when offering completion r=matklad a=AdnoC Closes https://github.com/rust-analyzer/rust-analyzer/issues/7081 When iterating over the names within the `hir_def::resolver::Scope` for a module, track what macros are in the `hir_def::item_scope::ItemScope::legacy_macros` collection for the module. When iterating over names from the prelude, do not proccess the name if it had been in the `legacy_macros` collection. This is implemented with a `FxHashSet` in the `Scope::process_names` function that is populated when iterating over `legacy_macros` and checked when iterating over the prelude. Alternative implementation could instead query the `legacy_macros` `FxHashMap` directly when processing names in the prelude. Also, I'd like to add a test for this, but I'm not sure where it could be added. Co-authored-by: AdnoC <adam.r.cutler@gmail.com>
| -rw-r--r-- | crates/hir_def/src/per_ns.rs | 2 | ||||
| -rw-r--r-- | crates/hir_def/src/resolver.rs | 10 | ||||
| -rw-r--r-- | crates/hir_def/src/visibility.rs | 2 |
3 files changed, 10 insertions, 4 deletions
diff --git a/crates/hir_def/src/per_ns.rs b/crates/hir_def/src/per_ns.rs index 74665c58851..a594afce668 100644 --- a/crates/hir_def/src/per_ns.rs +++ b/crates/hir_def/src/per_ns.rs @@ -7,7 +7,7 @@ use hir_expand::MacroDefId; use crate::{item_scope::ItemInNs, visibility::Visibility, ModuleDefId}; -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct PerNs { pub types: Option<(ModuleDefId, Visibility)>, pub values: Option<(ModuleDefId, Visibility)>, diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index e4152a0be4b..61059c3499f 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -490,6 +490,7 @@ pub enum ScopeDef { impl Scope { fn process_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { + let mut seen = FxHashSet::default(); match self { Scope::ModuleScope(m) => { // FIXME: should we provide `self` here? @@ -503,7 +504,9 @@ impl Scope { f(name.clone(), ScopeDef::PerNs(def)); }); m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { - f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_, Visibility::Public))); + let scope = PerNs::macros(macro_, Visibility::Public); + seen.insert((name.clone(), scope)); + f(name.clone(), ScopeDef::PerNs(scope)); }); m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); @@ -514,7 +517,10 @@ impl Scope { if let Some(prelude) = m.crate_def_map.prelude { let prelude_def_map = db.crate_def_map(prelude.krate); prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { - f(name.clone(), ScopeDef::PerNs(def)); + let seen_tuple = (name.clone(), def); + if !seen.contains(&seen_tuple) { + f(seen_tuple.0, ScopeDef::PerNs(def)); + } }); } } diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index e6e0853a30a..f3bc9d68003 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs @@ -85,7 +85,7 @@ impl RawVisibility { } /// Visibility of an item, with the path resolved. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Visibility { /// Visibility is restricted to a certain module. Module(ModuleId), |
