Repository: rust-analyzer/rust-analyzer
Pull request #10738 (2021-11-10 15:11:50)

internal: Do not search through all three namespaces in `ItemScope::name_of`
Brings down `5ms - find_path_prefixed (46 calls)` to `1ms - find_path_prefixed (46 calls)` for me on the `integrated_completion_benchmark`.
Still `O(n)` but this should considerably cut down lookups nevertheless(as shown by the timings already).
bors r+


Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index f781e0987a..9c0f3093e1 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -132,8 +132,5 @@ jobs:
         run: npm --prefix ./editors/code test
         # working-directory: ./editors/code  # does not work: https://github.com/GabrielBB/xvfb-action/issues/8
 
-    - run: npm run pretest
-      working-directory: ./editors/code
-
     - run: npm run package --scripts-prepend-node-path
       working-directory: ./editors/code
diff --git a/Cargo.lock b/Cargo.lock
index ba355216a8..2e2fe7d14c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -171,9 +171,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chalk-derive"
-version = "0.73.0"
+version = "0.72.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f182e4c40ae0a36afff9904e46389df47d2f943bae70eab3d779c87aa5dd584"
+checksum = "50947a8c71b9a6ee75d6c3b74eb320f58668f872a5ca1347a2b664989fbc8ac8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -183,9 +183,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-ir"
-version = "0.73.0"
+version = "0.72.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f998dcab9f6975ce5fe69c28acba246f75f82c1a8faa4455facac82ee61bc14"
+checksum = "39fba0a2f05527fb93c5039803c1f1ffaff5d6cebdff936386e1a5cbe7646283"
 dependencies = [
  "bitflags",
  "chalk-derive",
@@ -194,9 +194,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-recursive"
-version = "0.73.0"
+version = "0.72.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c56b019577ff31fc12748cbe2ddcec47d2b9e647f98cce146bfeb69ad2263fb4"
+checksum = "d01108bc48af1d40e69b3b7f6923323e904c32476d4974750c474c1f94343e5c"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -207,9 +207,9 @@ dependencies = [
 
 [[package]]
 name = "chalk-solve"
-version = "0.73.0"
+version = "0.72.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "296c92cae565a4000e3eea00ece09e14ce24e6bdc14a5807d140a4cc7652b8d4"
+checksum = "ff759b94bbb114254ba01b7a7459f8fa78ae98801a814946ce7ed6d5973c8a06"
 dependencies = [
  "chalk-derive",
  "chalk-ir",
@@ -807,9 +807,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.107"
+version = "0.2.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
+checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
 
 [[package]]
 name = "libloading"
@@ -1065,9 +1065,9 @@ dependencies = [
 
 [[package]]
 name = "paste"
-version = "1.0.6"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
+checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
 
 [[package]]
 name = "paths"
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index b09c0e753b..0f63de9e72 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -329,10 +329,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.resolve_path(path)
     }
 
-    pub fn resolve_path_as_macro(&self, path: &ast::Path) -> Option<MacroDef> {
-        self.imp.resolve_path_as_macro(path)
-    }
-
     pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
         self.imp.resolve_extern_crate(extern_crate)
     }
@@ -849,12 +845,6 @@ impl<'db> SemanticsImpl<'db> {
         self.analyze(path.syntax()).resolve_path(self.db, path)
     }
 
-    // FIXME: This shouldn't exist, but is currently required to always resolve attribute paths in
-    // the IDE layer due to namespace collisions
-    fn resolve_path_as_macro(&self, path: &ast::Path) -> Option<MacroDef> {
-        self.analyze(path.syntax()).resolve_path_as_macro(self.db, path)
-    }
-
     fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
         let krate = self.scope(extern_crate.syntax()).krate()?;
         krate.dependencies(self.db).into_iter().find_map(|dep| {
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index b12461818e..08d0a02d79 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -246,18 +246,6 @@ impl SourceAnalyzer {
         }
     }
 
-    pub(crate) fn resolve_path_as_macro(
-        &self,
-        db: &dyn HirDatabase,
-        path: &ast::Path,
-    ) -> Option<MacroDef> {
-        // This must be a normal source file rather than macro file.
-        let hygiene = Hygiene::new(db.upcast(), self.file_id);
-        let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene);
-        let hir_path = Path::from_src(path.clone(), &ctx)?;
-        resolve_hir_path_as_macro(db, &self.resolver, &hir_path)
-    }
-
     pub(crate) fn resolve_path(
         &self,
         db: &dyn HirDatabase,
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index ec8c3a87c0..0a2a6719ed 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -136,12 +136,17 @@ impl ItemScope {
 
     /// XXX: this is O(N) rather than O(1), try to not introduce new usages.
     pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
-        for (name, per_ns) in self.entries() {
-            if let Some(vis) = item.match_with(per_ns) {
-                return Some((name, vis));
+        let (def, mut iter) = match item {
+            ItemInNs::Macros(def) => {
+                return self
+                    .macros
+                    .iter()
+                    .find_map(|(name, &(other_def, vis))| (other_def == def).then(|| (name, vis)));
             }
-        }
-        None
+            ItemInNs::Types(def) => (def, self.types.iter()),
+            ItemInNs::Values(def) => (def, self.values.iter()),
+        };
+        iter.find_map(|(name, &(other_def, vis))| (other_def == def).then(|| (name, vis)))
     }
 
     pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
@@ -386,20 +391,6 @@ pub enum ItemInNs {
 }
 
 impl ItemInNs {
-    fn match_with(self, per_ns: PerNs) -> Option<Visibility> {
-        match self {
-            ItemInNs::Types(def) => {
-                per_ns.types.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
-            }
-            ItemInNs::Values(def) => {
-                per_ns.values.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
-            }
-            ItemInNs::Macros(def) => {
-                per_ns.macros.filter(|(other_def, _)| *other_def == def).map(|(_, vis)| vis)
-            }
-        }
-    }
-
     pub fn as_module_def_id(self) -> Option<ModuleDefId> {
         match self {
             ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 48820d8c83..d0f22cdae3 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -18,9 +18,9 @@ ena = "0.14.0"
 tracing = "0.1"
 rustc-hash = "1.1.0"
 scoped-tls = "1"
-chalk-solve = { version = "0.73", default-features = false }
-chalk-ir = "0.73"
-chalk-recursive = { version = "0.73", default-features = false }
+chalk-solve = { version = "0.72", default-features = false }
+chalk-ir = "0.72"
+chalk-recursive = { version = "0.72", default-features = false }
 la-arena = { version = "0.3.0", path = "../../lib/arena" }
 once_cell = { version = "1.5.0" }
 
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index e4874c7c48..d95bca515f 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -433,20 +433,20 @@ impl NameRefClass {
                 .find_map(ast::Attr::cast)
                 .map(|attr| attr.path().as_ref() == Some(&top_path));
             return match is_attribute_path {
-                Some(true) if path == top_path => sema
-                    .resolve_path_as_macro(&path)
-                    .filter(|mac| mac.kind() == hir::MacroKind::Attr)
-                    .map(Definition::Macro)
-                    .map(NameRefClass::Definition),
-                // in case of the path being a qualifier, don't resolve to anything but a module
-                Some(true) => match sema.resolve_path(&path)? {
-                    PathResolution::Def(module @ ModuleDef::Module(_)) => {
-                        cov_mark::hit!(name_ref_classify_attr_path_qualifier);
-                        Some(NameRefClass::Definition(Definition::ModuleDef(module)))
+                Some(true) => sema.resolve_path(&path).and_then(|resolved| {
+                    match resolved {
+                        // Don't wanna collide with builtin attributes here like `test` hence guard
+                        // so only resolve to modules that aren't the last segment
+                        PathResolution::Def(module @ ModuleDef::Module(_)) if path != top_path => {
+                            cov_mark::hit!(name_ref_classify_attr_path_qualifier);
+                            Some(NameRefClass::Definition(Definition::ModuleDef(module)))
+                        }
+                        PathResolution::Macro(mac) if mac.kind() == hir::MacroKind::Attr => {
+                            Some(NameRefClass::Definition(Definition::Macro(mac)))
+                        }
+                        _ => None,
                     }
-                    _ => None,
-                },
-                // inside attribute, but our path isn't part of the attribute's path(might be in its expression only)
+                }),
                 Some(false) => None,
                 None => sema.resolve_path(&path).map(Into::into).map(NameRefClass::Definition),
             };
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 8f00c6f6df..4a1060596b 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -406,19 +406,7 @@ impl GlobalState {
                             // When we're running multiple flychecks, we have to include a disambiguator in
                             // the title, or the editor complains. Note that this is a user-facing string.
                             let title = if self.flycheck.len() == 1 {
-                                match self.config.flycheck() {
-                                    Some(flycheck::FlycheckConfig::CargoCommand {
-                                        command,
-                                        ..
-                                    }) => {
-                                        format!("cargo {}", command)
-                                    }
-                                    Some(flycheck::FlycheckConfig::CustomCommand {
-                                        command,
-                                        ..
-                                    }) => command,
-                                    None => "cargo check".to_string(),
-                                }
+                                "cargo check".to_string()
                             } else {
                                 format!("cargo check (#{})", id + 1)
                             };
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index e3372574b3..0b226a985d 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -28,7 +28,7 @@
                 "glob": "^7.1.6",
                 "mocha": "^9.0.2",
                 "tslib": "^2.3.0",
-                "typescript": "^4.4.4",
+                "typescript": "^4.3.5",
                 "typescript-formatter": "^7.2.2",
                 "vsce": "^1.95.1",
                 "vscode-test": "^1.5.1"
@@ -3541,9 +3541,9 @@
             }
         },
         "node_modules/typescript": {
-            "version": "4.4.4",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
-            "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
+            "version": "4.3.5",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
+            "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
             "dev": true,
             "bin": {
                 "tsc": "bin/tsc",
@@ -6647,9 +6647,9 @@
             }
         },
         "typescript": {
-            "version": "4.4.4",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz",
-            "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==",
+            "version": "4.3.5",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
+            "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
             "dev": true
         },
         "typescript-formatter": {
diff --git a/editors/code/package.json b/editors/code/package.json
index 4c718f0b79..336081e88c 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -32,7 +32,7 @@
         "watch": "npm run build-base -- --sourcemap --watch",
         "lint": "tsfmt --verify && eslint -c .eslintrc.js --ext ts ./src ./tests",
         "fix": " tsfmt -r       && eslint -c .eslintrc.js --ext ts ./src ./tests --fix",
-        "pretest": "tsc --noEmit && npm run build",
+        "pretest": "tsc && npm run build",
         "test": "node ./out/tests/runTests.js"
     },
     "dependencies": {
diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json
index 7c4fbd21eb..c9f348241a 100644
--- a/editors/code/tsconfig.json
+++ b/editors/code/tsconfig.json
@@ -9,7 +9,6 @@
         "sourceMap": true,
         "rootDir": ".",
         "strict": true,
-        "useUnknownInCatchVariables": false,
         "noUnusedLocals": true,
         "noUnusedParameters": true,
         "noImplicitReturns": true,


Test patch:
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index ab810aceca..1a10a78d24 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -43,7 +43,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="brace">}</span><span class="semicolon">;</span>
 <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
 
-<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="module attribute">proc_macros</span><span class="operator attribute">::</span><span class="macro attribute">identity</span><span class="attribute attribute">]</span>
+<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="module attribute">proc_macros</span><span class="operator attribute">::</span><span class="builtin_attr attribute">identity</span><span class="attribute attribute">]</span>
 <span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration public">ops</span> <span class="brace">{</span>
     <span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="builtin_attr attribute">lang</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"fn_once"</span><span class="attribute attribute">]</span>
     <span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration public">FnOnce</span><span class="angle">&lt;</span><span class="type_param declaration">Args</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>