about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2024-09-09 08:32:32 +0200
committerLukas Wirth <lukastw97@gmail.com>2024-09-11 12:16:41 +0200
commitaa883b421e93733e8691bc8fd19bd829851710db (patch)
tree6646074998cc76cdabf9d1335bda7583b784bf1a
parent69ab8c2f26267e4f0969630e4ec8f7170e72ce85 (diff)
downloadrust-aa883b421e93733e8691bc8fd19bd829851710db.tar.gz
rust-aa883b421e93733e8691bc8fd19bd829851710db.zip
Lift out workspace related data into a separate query to preserve crategraph deduplication
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/change.rs14
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/change.rs43
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs18
-rw-r--r--src/tools/rust-analyzer/crates/load-cargo/src/lib.rs16
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs42
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs24
10 files changed, 98 insertions, 97 deletions
diff --git a/src/tools/rust-analyzer/crates/base-db/src/change.rs b/src/tools/rust-analyzer/crates/base-db/src/change.rs
index a9d91d64ceb..4fb6654b612 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/change.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/change.rs
@@ -3,11 +3,15 @@
 
 use std::fmt;
 
+use rustc_hash::FxHashMap;
 use salsa::Durability;
 use triomphe::Arc;
 use vfs::FileId;
 
-use crate::{CrateGraph, SourceDatabaseFileInputExt, SourceRoot, SourceRootDatabase, SourceRootId};
+use crate::{
+    CrateGraph, CrateId, CrateWorkspaceData, SourceDatabaseFileInputExt, SourceRoot,
+    SourceRootDatabase, SourceRootId,
+};
 
 /// Encapsulate a bunch of raw `.set` calls on the database.
 #[derive(Default)]
@@ -15,6 +19,7 @@ pub struct FileChange {
     pub roots: Option<Vec<SourceRoot>>,
     pub files_changed: Vec<(FileId, Option<String>)>,
     pub crate_graph: Option<CrateGraph>,
+    pub ws_data: Option<FxHashMap<CrateId, Arc<CrateWorkspaceData>>>,
 }
 
 impl fmt::Debug for FileChange {
@@ -50,6 +55,10 @@ impl FileChange {
         self.crate_graph = Some(graph);
     }
 
+    pub fn set_ws_data(&mut self, data: FxHashMap<CrateId, Arc<CrateWorkspaceData>>) {
+        self.ws_data = Some(data);
+    }
+
     pub fn apply(self, db: &mut dyn SourceRootDatabase) {
         let _p = tracing::info_span!("FileChange::apply").entered();
         if let Some(roots) = self.roots {
@@ -74,6 +83,9 @@ impl FileChange {
         if let Some(crate_graph) = self.crate_graph {
             db.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH);
         }
+        if let Some(data) = self.ws_data {
+            db.set_crate_workspace_data_with_durability(Arc::new(data), Durability::HIGH);
+        }
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index 20ef45d0b37..46e258d46f5 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -5,11 +5,12 @@ mod input;
 
 use std::panic;
 
+use rustc_hash::FxHashMap;
 use salsa::Durability;
 use span::EditionedFileId;
 use syntax::{ast, Parse, SourceFile, SyntaxError};
 use triomphe::Arc;
-use vfs::FileId;
+use vfs::{AbsPathBuf, FileId};
 
 pub use crate::{
     change::FileChange,
@@ -74,19 +75,30 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
     #[salsa::input]
     fn crate_graph(&self) -> Arc<CrateGraph>;
 
-    // FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
-    #[salsa::input]
-    fn data_layout(&self, krate: CrateId) -> TargetLayoutLoadResult;
-
     #[salsa::input]
-    fn toolchain(&self, krate: CrateId) -> Option<Version>;
+    fn crate_workspace_data(&self) -> Arc<FxHashMap<CrateId, Arc<CrateWorkspaceData>>>;
 
     #[salsa::transparent]
     fn toolchain_channel(&self, krate: CrateId) -> Option<ReleaseChannel>;
 }
 
+/// Crate related data shared by the whole workspace.
+#[derive(Debug, PartialEq, Eq, Hash, Clone)]
+pub struct CrateWorkspaceData {
+    /// The working directory to run proc-macros in. This is usually the workspace root of cargo workspaces.
+    pub proc_macro_cwd: Option<AbsPathBuf>,
+    // FIXME: Consider removing this, making HirDatabase::target_data_layout an input query
+    pub data_layout: TargetLayoutLoadResult,
+    /// Toolchain version used to compile the crate.
+    pub toolchain: Option<Version>,
+}
+
 fn toolchain_channel(db: &dyn SourceDatabase, krate: CrateId) -> Option<ReleaseChannel> {
-    db.toolchain(krate).as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
+    db.crate_workspace_data()
+        .get(&krate)?
+        .toolchain
+        .as_ref()
+        .and_then(|v| ReleaseChannel::from_str(&v.pre))
 }
 
 fn parse(db: &dyn SourceDatabase, file_id: EditionedFileId) -> Parse<ast::SourceFile> {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index 198dc93f6b1..c0547bc3c8d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -117,7 +117,7 @@ impl Attrs {
 }
 
 impl Attrs {
-    pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'_> {
+    pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'attrs> {
         AttrQuery { attrs: self, key }
     }
 
@@ -594,7 +594,7 @@ impl<'attr> AttrQuery<'attr> {
     /// #[doc(html_root_url = "url")]
     ///       ^^^^^^^^^^^^^ key
     /// ```
-    pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&str> {
+    pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&'attr str> {
         self.tt_values().find_map(|tt| {
             let name = tt.token_trees.iter()
                 .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key))
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index f18083d3873..e2312cd393e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -204,7 +204,7 @@ impl Body {
     pub fn blocks<'a>(
         &'a self,
         db: &'a dyn DefDatabase,
-    ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ {
+    ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + 'a {
         self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block)))
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
index 8b3f69db027..de3a7b9f561 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
@@ -1,10 +1,10 @@
 //! Defines a unit of change that can applied to the database to get the next
 //! state. Changes are transactional.
 use base_db::{
-    salsa::Durability, CrateGraph, CrateId, FileChange, SourceRoot, SourceRootDatabase,
-    TargetLayoutLoadResult, Version,
+    salsa::Durability, CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot,
+    SourceRootDatabase,
 };
-use la_arena::RawIdx;
+use rustc_hash::FxHashMap;
 use span::FileId;
 use triomphe::Arc;
 
@@ -14,8 +14,6 @@ use crate::{db::ExpandDatabase, proc_macro::ProcMacros};
 pub struct ChangeWithProcMacros {
     pub source_change: FileChange,
     pub proc_macros: Option<ProcMacros>,
-    pub toolchains: Option<Vec<Option<Version>>>,
-    pub target_data_layouts: Option<Vec<TargetLayoutLoadResult>>,
 }
 
 impl ChangeWithProcMacros {
@@ -28,46 +26,25 @@ impl ChangeWithProcMacros {
         if let Some(proc_macros) = self.proc_macros {
             db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH);
         }
-        if let Some(target_data_layouts) = self.target_data_layouts {
-            for (id, val) in target_data_layouts.into_iter().enumerate() {
-                db.set_data_layout_with_durability(
-                    CrateId::from_raw(RawIdx::from(id as u32)),
-                    val,
-                    Durability::HIGH,
-                );
-            }
-        }
-        if let Some(toolchains) = self.toolchains {
-            for (id, val) in toolchains.into_iter().enumerate() {
-                db.set_toolchain_with_durability(
-                    CrateId::from_raw(RawIdx::from(id as u32)),
-                    val,
-                    Durability::HIGH,
-                );
-            }
-        }
     }
 
     pub fn change_file(&mut self, file_id: FileId, new_text: Option<String>) {
         self.source_change.change_file(file_id, new_text)
     }
 
-    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
-        self.source_change.set_crate_graph(graph)
+    pub fn set_crate_graph(
+        &mut self,
+        graph: CrateGraph,
+        ws_data: FxHashMap<CrateId, Arc<CrateWorkspaceData>>,
+    ) {
+        self.source_change.set_crate_graph(graph);
+        self.source_change.set_ws_data(ws_data);
     }
 
     pub fn set_proc_macros(&mut self, proc_macros: ProcMacros) {
         self.proc_macros = Some(proc_macros);
     }
 
-    pub fn set_toolchains(&mut self, toolchains: Vec<Option<Version>>) {
-        self.toolchains = Some(toolchains);
-    }
-
-    pub fn set_target_data_layouts(&mut self, target_data_layouts: Vec<TargetLayoutLoadResult>) {
-        self.target_data_layouts = Some(target_data_layouts);
-    }
-
     pub fn set_roots(&mut self, roots: Vec<SourceRoot>) {
         self.source_change.set_roots(roots)
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
index 9b1424548c2..7d77f6d0731 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/target.rs
@@ -11,8 +11,8 @@ pub fn target_data_layout_query(
     db: &dyn HirDatabase,
     krate: CrateId,
 ) -> Result<Arc<TargetDataLayout>, Arc<str>> {
-    match db.data_layout(krate) {
-        Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(&it) {
+    match &db.crate_workspace_data()[&krate].data_layout {
+        Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) {
             Ok(it) => Ok(Arc::new(it)),
             Err(e) => {
                 Err(match e {
@@ -42,6 +42,6 @@ pub fn target_data_layout_query(
                 }.into())
             }
         },
-        Err(e) => Err(e),
+        Err(e) => Err(e.clone()),
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index cdadfeea4b9..547286c3f4d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -57,7 +57,7 @@ mod view_item_tree;
 mod view_memory_layout;
 mod view_mir;
 
-use std::panic::UnwindSafe;
+use std::{iter, panic::UnwindSafe};
 
 use cfg::CfgOptions;
 use fetch_crates::CrateInfo;
@@ -65,7 +65,8 @@ use hir::{sym, ChangeWithProcMacros};
 use ide_db::{
     base_db::{
         salsa::{self, ParallelDatabase},
-        CrateOrigin, Env, FileLoader, FileSet, SourceDatabase, SourceRootDatabase, VfsPath,
+        CrateOrigin, CrateWorkspaceData, Env, FileLoader, FileSet, SourceDatabase,
+        SourceRootDatabase, VfsPath,
     },
     prime_caches, symbol_index, FxHashMap, FxIndexSet, LineIndexDatabase,
 };
@@ -256,9 +257,16 @@ impl Analysis {
             CrateOrigin::Local { repo: None, name: None },
         );
         change.change_file(file_id, Some(text));
-        change.set_crate_graph(crate_graph);
-        change.set_target_data_layouts(vec![Err("fixture has no layout".into())]);
-        change.set_toolchains(vec![None]);
+        let ws_data = crate_graph
+            .iter()
+            .zip(iter::repeat(Arc::new(CrateWorkspaceData {
+                proc_macro_cwd: None,
+                data_layout: Err("fixture has no layout".into()),
+                toolchain: None,
+            })))
+            .collect();
+        change.set_crate_graph(crate_graph, ws_data);
+
         host.apply_change(change);
         (host.analysis(), file_id)
     }
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index abad7e9f7d2..e9bc87833f3 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -10,7 +10,7 @@ use hir_expand::proc_macro::{
     ProcMacros,
 };
 use ide_db::{
-    base_db::{CrateGraph, Env, SourceRoot, SourceRootId},
+    base_db::{CrateGraph, CrateWorkspaceData, Env, SourceRoot, SourceRootId},
     prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase,
 };
 use itertools::Itertools;
@@ -447,12 +447,16 @@ fn load_crate_graph(
     let source_roots = source_root_config.partition(vfs);
     analysis_change.set_roots(source_roots);
 
-    let num_crates = crate_graph.len();
-    analysis_change.set_crate_graph(crate_graph);
+    let ws_data = crate_graph
+        .iter()
+        .zip(iter::repeat(From::from(CrateWorkspaceData {
+            proc_macro_cwd: None,
+            data_layout: target_layout.clone(),
+            toolchain: toolchain.clone(),
+        })))
+        .collect();
+    analysis_change.set_crate_graph(crate_graph, ws_data);
     analysis_change.set_proc_macros(proc_macros);
-    analysis_change
-        .set_target_data_layouts(iter::repeat(target_layout.clone()).take(num_crates).collect());
-    analysis_change.set_toolchains(iter::repeat(toolchain.clone()).take(num_crates).collect());
 
     db.apply_change(analysis_change);
     db
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index c461ba2e9b9..f6765715c5a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -16,8 +16,9 @@
 use std::{iter, mem};
 
 use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros, ProcMacrosBuilder};
+use ide::CrateId;
 use ide_db::{
-    base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version},
+    base_db::{salsa::Durability, CrateGraph, CrateWorkspaceData, ProcMacroPaths},
     FxHashMap,
 };
 use itertools::Itertools;
@@ -692,7 +693,7 @@ impl GlobalState {
             })
             .collect();
 
-        let (crate_graph, proc_macro_paths, layouts, toolchains) = {
+        let (crate_graph, proc_macro_paths, ws_data) = {
             // Create crate graph from all the workspaces
             let vfs = &mut self.vfs.write().0;
 
@@ -721,9 +722,7 @@ impl GlobalState {
                     .collect(),
             );
         }
-        change.set_crate_graph(crate_graph);
-        change.set_target_data_layouts(layouts);
-        change.set_toolchains(toolchains);
+        change.set_crate_graph(crate_graph, ws_data);
         self.analysis_host.apply_change(change);
         self.report_progress(
             "Building CrateGraph",
@@ -863,42 +862,27 @@ pub fn ws_to_crate_graph(
     workspaces: &[ProjectWorkspace],
     extra_env: &FxHashMap<String, String>,
     mut load: impl FnMut(&AbsPath) -> Option<vfs::FileId>,
-) -> (CrateGraph, Vec<ProcMacroPaths>, Vec<Result<Arc<str>, Arc<str>>>, Vec<Option<Version>>) {
+) -> (CrateGraph, Vec<ProcMacroPaths>, FxHashMap<CrateId, Arc<CrateWorkspaceData>>) {
     let mut crate_graph = CrateGraph::default();
     let mut proc_macro_paths = Vec::default();
-    let mut layouts = Vec::default();
-    let mut toolchains = Vec::default();
-    let e = Err(Arc::from("missing layout"));
+    let mut ws_data = FxHashMap::default();
     for ws in workspaces {
         let (other, mut crate_proc_macros) = ws.to_crate_graph(&mut load, extra_env);
-        let num_layouts = layouts.len();
-        let num_toolchains = toolchains.len();
         let ProjectWorkspace { toolchain, target_layout, .. } = ws;
 
         let mapping = crate_graph.extend(other, &mut crate_proc_macros);
         // Populate the side tables for the newly merged crates
-        mapping.values().for_each(|val| {
-            let idx = val.into_raw().into_u32() as usize;
-            // we only need to consider crates that were not merged and remapped, as the
-            // ones that were remapped already have the correct layout and toolchain
-            if idx >= num_layouts {
-                if layouts.len() <= idx {
-                    layouts.resize(idx + 1, e.clone());
-                }
-                layouts[idx].clone_from(target_layout);
-            }
-            if idx >= num_toolchains {
-                if toolchains.len() <= idx {
-                    toolchains.resize(idx + 1, None);
-                }
-                toolchains[idx].clone_from(toolchain);
-            }
-        });
+        ws_data.extend(mapping.values().copied().zip(iter::repeat(Arc::new(CrateWorkspaceData {
+            toolchain: toolchain.clone(),
+            data_layout: target_layout.clone(),
+            proc_macro_cwd: Some(ws.workspace_root().to_owned()),
+        }))));
         proc_macro_paths.push(crate_proc_macros);
     }
+
     crate_graph.shrink_to_fit();
     proc_macro_paths.shrink_to_fit();
-    (crate_graph, proc_macro_paths, layouts, toolchains)
+    (crate_graph, proc_macro_paths, ws_data)
 }
 
 pub(crate) fn should_refresh_for_change(
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index faf9d22047d..bbc109e8817 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -2,8 +2,8 @@
 use std::{iter, mem, str::FromStr, sync};
 
 use base_db::{
-    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileChange,
-    FileSet, LangCrateOrigin, SourceRoot, SourceRootDatabase, Version, VfsPath,
+    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, CrateWorkspaceData, Dependency,
+    Env, FileChange, FileSet, LangCrateOrigin, SourceRoot, SourceRootDatabase, Version, VfsPath,
 };
 use cfg::CfgOptions;
 use hir_expand::{
@@ -354,16 +354,20 @@ impl ChangeFixture {
         };
         roots.push(root);
 
-        let mut change = ChangeWithProcMacros {
-            source_change,
-            proc_macros: Some(proc_macros.build()),
-            toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()),
-            target_data_layouts: Some(
-                iter::repeat(target_data_layout).take(crate_graph.len()).collect(),
-            ),
-        };
+        let mut change =
+            ChangeWithProcMacros { source_change, proc_macros: Some(proc_macros.build()) };
 
         change.source_change.set_roots(roots);
+        change.source_change.set_ws_data(
+            crate_graph
+                .iter()
+                .zip(iter::repeat(From::from(CrateWorkspaceData {
+                    proc_macro_cwd: None,
+                    data_layout: target_data_layout,
+                    toolchain,
+                })))
+                .collect(),
+        );
         change.source_change.set_crate_graph(crate_graph);
 
         ChangeFixture { file_position, files, change }