diff --git a/crates/base-db/src/change.rs b/crates/base-db/src/change.rs index a9d91d64ce..4fb6654b61 100644 --- a/crates/base-db/src/change.rs +++ b/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>, pub files_changed: Vec<(FileId, Option)>, pub crate_graph: Option, + pub ws_data: Option>>, } 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>) { + 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/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 20ef45d0b3..46e258d46f 100644 --- a/crates/base-db/src/lib.rs +++ b/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; - // 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; + fn crate_workspace_data(&self) -> Arc>>; #[salsa::transparent] fn toolchain_channel(&self, krate: CrateId) -> Option; } +/// 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, + // 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, +} + fn toolchain_channel(db: &dyn SourceDatabase, krate: CrateId) -> Option { - 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 { diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs index 198dc93f6b..c0547bc3c8 100644 --- a/crates/hir-def/src/attr.rs +++ b/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/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index f18083d387..e2312cd393 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -204,7 +204,7 @@ impl Body { pub fn blocks<'a>( &'a self, db: &'a dyn DefDatabase, - ) -> impl Iterator)> + '_ { + ) -> impl Iterator)> + 'a { self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block))) } diff --git a/crates/hir-expand/src/change.rs b/crates/hir-expand/src/change.rs index 8b3f69db02..de3a7b9f56 100644 --- a/crates/hir-expand/src/change.rs +++ b/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, - pub toolchains: Option>>, - pub target_data_layouts: Option>, } 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) { 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>, + ) { + 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>) { - self.toolchains = Some(toolchains); - } - - pub fn set_target_data_layouts(&mut self, target_data_layouts: Vec) { - self.target_data_layouts = Some(target_data_layouts); - } - pub fn set_roots(&mut self, roots: Vec) { self.source_change.set_roots(roots) } diff --git a/crates/hir-ty/src/layout/target.rs b/crates/hir-ty/src/layout/target.rs index 9b1424548c..7d77f6d073 100644 --- a/crates/hir-ty/src/layout/target.rs +++ b/crates/hir-ty/src/layout/target.rs @@ -11,8 +11,8 @@ pub fn target_data_layout_query( db: &dyn HirDatabase, krate: CrateId, ) -> Result, Arc> { - 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/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index cdadfeea4b..547286c3f4 100644 --- a/crates/ide/src/lib.rs +++ b/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/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index abad7e9f7d..e9bc87833f 100644 --- a/crates/load-cargo/src/lib.rs +++ b/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/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index c461ba2e9b..f6765715c5 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/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, mut load: impl FnMut(&AbsPath) -> Option, -) -> (CrateGraph, Vec, Vec, Arc>>, Vec>) { +) -> (CrateGraph, Vec, FxHashMap>) { 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/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs index faf9d22047..bbc109e881 100644 --- a/crates/test-fixture/src/lib.rs +++ b/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 }