about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/semantics.rs16
-rw-r--r--crates/hir_def/src/resolver.rs18
-rw-r--r--crates/ide_completion/src/completions/lifetime.rs4
-rw-r--r--crates/ide_completion/src/context.rs35
4 files changed, 38 insertions, 35 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 236487d8e52..7857edb521a 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -1327,14 +1327,14 @@ impl<'a> SemanticsScope<'a> {
                     resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
                     resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
                     resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(id.into()),
-                    resolver::ScopeDef::Local(pat_id) => {
-                        let parent = self.resolver.body_owner().unwrap();
-                        ScopeDef::Local(Local { parent, pat_id })
-                    }
-                    resolver::ScopeDef::Label(label_id) => {
-                        let parent = self.resolver.body_owner().unwrap();
-                        ScopeDef::Label(Label { parent, label_id })
-                    }
+                    resolver::ScopeDef::Local(pat_id) => match self.resolver.body_owner() {
+                        Some(parent) => ScopeDef::Local(Local { parent, pat_id }),
+                        None => continue,
+                    },
+                    resolver::ScopeDef::Label(label_id) => match self.resolver.body_owner() {
+                        Some(parent) => ScopeDef::Label(Label { parent, label_id }),
+                        None => continue,
+                    },
                 };
                 f(name.clone(), def)
             }
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 72856a1bfe7..b8c88282d67 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -1,5 +1,5 @@
 //! Name resolution façade.
-use std::sync::Arc;
+use std::{hash::BuildHasherDefault, sync::Arc};
 
 use base_db::CrateId;
 use hir_expand::name::{name, Name};
@@ -343,7 +343,7 @@ impl Resolver {
     /// Returns a set of names available in the current scope.
     ///
     /// Note that this is a somewhat fuzzy concept -- internally, the compiler
-    /// doesn't necessary follow a strict scoping discipline. Rathe, it just
+    /// doesn't necessary follow a strict scoping discipline. Rather, it just
     /// tells for each ident what it resolves to.
     ///
     /// A good example is something like `str::from_utf8`. From scopes point of
@@ -378,10 +378,13 @@ impl Resolver {
     /// The result is ordered *roughly* from the innermost scope to the
     /// outermost: when the name is introduced in two namespaces in two scopes,
     /// we use the position of the first scope.
-    pub fn names_in_scope(&self, db: &dyn DefDatabase) -> IndexMap<Name, SmallVec<[ScopeDef; 1]>> {
+    pub fn names_in_scope(
+        &self,
+        db: &dyn DefDatabase,
+    ) -> FxIndexMap<Name, SmallVec<[ScopeDef; 1]>> {
         let mut res = ScopeNames::default();
         for scope in self.scopes() {
-            scope.process_names(db, &mut res);
+            scope.process_names(&mut res, db);
         }
         res.map
     }
@@ -466,7 +469,7 @@ impl Resolver {
     }
 }
 
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum ScopeDef {
     ModuleDef(ModuleDefId),
     Unknown,
@@ -478,7 +481,7 @@ pub enum ScopeDef {
 }
 
 impl Scope {
-    fn process_names(&self, db: &dyn DefDatabase, acc: &mut ScopeNames) {
+    fn process_names(&self, acc: &mut ScopeNames, db: &dyn DefDatabase) {
         match self {
             Scope::ModuleScope(m) => {
                 // FIXME: should we provide `self` here?
@@ -691,9 +694,10 @@ fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
     Some(res)
 }
 
+type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>;
 #[derive(Default)]
 struct ScopeNames {
-    map: IndexMap<Name, SmallVec<[ScopeDef; 1]>>,
+    map: FxIndexMap<Name, SmallVec<[ScopeDef; 1]>>,
 }
 
 impl ScopeNames {
diff --git a/crates/ide_completion/src/completions/lifetime.rs b/crates/ide_completion/src/completions/lifetime.rs
index b8a50442bc6..4fffd1aa0c4 100644
--- a/crates/ide_completion/src/completions/lifetime.rs
+++ b/crates/ide_completion/src/completions/lifetime.rs
@@ -30,7 +30,7 @@ pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext)
     let param_lifetime = param_lifetime.as_ref().map(ast::Lifetime::text);
     let param_lifetime = param_lifetime.as_ref().map(TokenText::as_str);
 
-    ctx.scope.process_all_names(&mut |name, res| {
+    ctx.process_all_names_raw(&mut |name, res| {
         if matches!(
             res,
             ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_))
@@ -49,7 +49,7 @@ pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
     if !matches!(ctx.lifetime_ctx, Some(LifetimeContext::LabelRef)) {
         return;
     }
-    ctx.scope.process_all_names(&mut |name, res| {
+    ctx.process_all_names_raw(&mut |name, res| {
         if let ScopeDef::Label(_) = res {
             acc.add_label(ctx, name);
         }
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index a203ebd45a0..ba664a29dae 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -12,7 +12,7 @@ use ide_db::{
     famous_defs::FamousDefs,
     RootDatabase,
 };
-use rustc_hash::FxHashSet;
+use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::{
     algo::{find_node_at_offset, non_trivia_sibling},
     ast::{self, AttrKind, HasName, NameOrNameRef},
@@ -146,7 +146,7 @@ pub(crate) struct CompletionContext<'a> {
 
     pub(super) existing_derives: FxHashSet<hir::Macro>,
 
-    pub(super) locals: Vec<(Name, Local)>,
+    pub(super) locals: FxHashMap<Name, Local>,
 }
 
 impl<'a> CompletionContext<'a> {
@@ -293,6 +293,10 @@ impl<'a> CompletionContext<'a> {
         self.path_context.as_ref().and_then(|it| it.kind)
     }
 
+    pub(crate) fn is_immediately_after_macro_bang(&self) -> bool {
+        self.token.kind() == BANG && self.token.parent().map_or(false, |it| it.kind() == MACRO_CALL)
+    }
+
     /// Checks if an item is visible and not `doc(hidden)` at the completion site.
     pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
     where
@@ -318,11 +322,6 @@ impl<'a> CompletionContext<'a> {
             _ => false,
         }
     }
-
-    pub(crate) fn is_immediately_after_macro_bang(&self) -> bool {
-        self.token.kind() == BANG && self.token.parent().map_or(false, |it| it.kind() == MACRO_CALL)
-    }
-
     /// Whether the given trait is an operator trait or not.
     pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
         match trait_.attrs(self.db).lang() {
@@ -340,7 +339,12 @@ impl<'a> CompletionContext<'a> {
             }
 
             f(name, def);
-        })
+        });
+    }
+
+    pub(crate) fn process_all_names_raw(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
+        let _p = profile::span("CompletionContext::process_all_names_raw");
+        self.scope.process_all_names(&mut |name, def| f(name, def));
     }
 
     fn is_visible_impl(
@@ -372,16 +376,11 @@ impl<'a> CompletionContext<'a> {
     }
 
     fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
-        let krate = match self.krate {
-            Some(it) => it,
-            None => return true,
-        };
-        if krate != defining_crate && attrs.has_doc_hidden() {
+        match self.krate {
             // `doc(hidden)` items are only completed within the defining crate.
-            return true;
+            Some(krate) => krate != defining_crate && attrs.has_doc_hidden(),
+            None => true,
         }
-
-        false
     }
 }
 
@@ -413,10 +412,10 @@ impl<'a> CompletionContext<'a> {
         let scope = sema.scope_at_offset(&token.parent()?, offset);
         let krate = scope.krate();
         let module = scope.module();
-        let mut locals = vec![];
+        let mut locals = FxHashMap::default();
         scope.process_all_names(&mut |name, scope| {
             if let ScopeDef::Local(local) = scope {
-                locals.push((name, local));
+                locals.insert(name, local);
             }
         });