Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #19337 from ChayimFriedman2/salsify-crate-graph-final
Salsify the crate graph
Chayim Refael Friedman 2025-03-13
parent 8d01570 · parent c94e9ef · commit 3fc655b
-rw-r--r--Cargo.lock1
-rw-r--r--crates/base-db/src/change.rs21
-rw-r--r--crates/base-db/src/input.rs510
-rw-r--r--crates/base-db/src/lib.rs86
-rw-r--r--crates/cfg/src/lib.rs12
-rw-r--r--crates/hir-def/src/attr.rs7
-rw-r--r--crates/hir-def/src/data.rs18
-rw-r--r--crates/hir-def/src/data/adt.rs12
-rw-r--r--crates/hir-def/src/db.rs41
-rw-r--r--crates/hir-def/src/expander.rs6
-rw-r--r--crates/hir-def/src/expr_store/body.rs3
-rw-r--r--crates/hir-def/src/expr_store/lower.rs19
-rw-r--r--crates/hir-def/src/expr_store/tests.rs4
-rw-r--r--crates/hir-def/src/find_path.rs20
-rw-r--r--crates/hir-def/src/generics.rs21
-rw-r--r--crates/hir-def/src/import_map.rs29
-rw-r--r--crates/hir-def/src/item_scope.rs4
-rw-r--r--crates/hir-def/src/item_tree.rs6
-rw-r--r--crates/hir-def/src/lang_item.rs31
-rw-r--r--crates/hir-def/src/lib.rs47
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mod.rs4
-rw-r--r--crates/hir-def/src/nameres.rs110
-rw-r--r--crates/hir-def/src/nameres/attr_resolution.rs10
-rw-r--r--crates/hir-def/src/nameres/collector.rs162
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs60
-rw-r--r--crates/hir-def/src/nameres/tests/incremental.rs75
-rw-r--r--crates/hir-def/src/nameres/tests/macros.rs4
-rw-r--r--crates/hir-def/src/pretty.rs11
-rw-r--r--crates/hir-def/src/resolver.rs102
-rw-r--r--crates/hir-def/src/src.rs4
-rw-r--r--crates/hir-def/src/test_db.rs28
-rw-r--r--crates/hir-expand/src/attrs.rs7
-rw-r--r--crates/hir-expand/src/builtin/fn_macro.rs8
-rw-r--r--crates/hir-expand/src/cfg_process.rs16
-rw-r--r--crates/hir-expand/src/change.rs23
-rw-r--r--crates/hir-expand/src/db.rs11
-rw-r--r--crates/hir-expand/src/declarative.rs10
-rw-r--r--crates/hir-expand/src/eager.rs10
-rw-r--r--crates/hir-expand/src/lib.rs12
-rw-r--r--crates/hir-expand/src/mod_path.rs6
-rw-r--r--crates/hir-expand/src/name.rs2
-rw-r--r--crates/hir-expand/src/prettify_macro_expansion_.rs9
-rw-r--r--crates/hir-expand/src/proc_macro.rs159
-rw-r--r--crates/hir-ty/src/chalk_db.rs22
-rw-r--r--crates/hir-ty/src/consteval.rs6
-rw-r--r--crates/hir-ty/src/consteval/tests.rs5
-rw-r--r--crates/hir-ty/src/db.rs43
-rw-r--r--crates/hir-ty/src/diagnostics/decl_check.rs2
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs4
-rw-r--r--crates/hir-ty/src/diagnostics/unsafe_check.rs2
-rw-r--r--crates/hir-ty/src/display.rs16
-rw-r--r--crates/hir-ty/src/infer/closure.rs6
-rw-r--r--crates/hir-ty/src/layout/target.rs6
-rw-r--r--crates/hir-ty/src/lower.rs11
-rw-r--r--crates/hir-ty/src/method_resolution.rs29
-rw-r--r--crates/hir-ty/src/mir.rs4
-rw-r--r--crates/hir-ty/src/mir/eval.rs6
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs2
-rw-r--r--crates/hir-ty/src/mir/lower.rs8
-rw-r--r--crates/hir-ty/src/test_db.rs16
-rw-r--r--crates/hir-ty/src/tests.rs8
-rw-r--r--crates/hir-ty/src/traits.rs16
-rw-r--r--crates/hir-ty/src/utils.rs7
-rw-r--r--crates/hir/src/from_id.rs2
-rw-r--r--crates/hir/src/lib.rs70
-rw-r--r--crates/hir/src/semantics.rs2
-rw-r--r--crates/hir/src/symbols.rs5
-rw-r--r--crates/ide-assists/src/handlers/inline_call.rs6
-rw-r--r--crates/ide-db/src/apply_change.rs8
-rw-r--r--crates/ide-db/src/famous_defs.rs5
-rw-r--r--crates/ide-db/src/lib.rs27
-rw-r--r--crates/ide-db/src/prime_caches.rs36
-rw-r--r--crates/ide-db/src/search.rs10
-rw-r--r--crates/ide-db/src/test_data/test_doc_alias.txt4
-rw-r--r--crates/ide-db/src/test_data/test_symbol_index_collection.txt20
-rw-r--r--crates/ide-diagnostics/src/lib.rs6
-rw-r--r--crates/ide-ssr/src/matching.rs10
-rw-r--r--crates/ide/src/doc_links.rs4
-rw-r--r--crates/ide/src/expand_macro.rs8
-rw-r--r--crates/ide/src/fetch_crates.rs21
-rw-r--r--crates/ide/src/hover/render.rs4
-rw-r--r--crates/ide/src/hover/tests.rs2
-rw-r--r--crates/ide/src/inlay_hints/bind_pat.rs8
-rw-r--r--crates/ide/src/lib.rs44
-rw-r--r--crates/ide/src/parent_module.rs4
-rw-r--r--crates/ide/src/runnables.rs5
-rw-r--r--crates/ide/src/static_index.rs4
-rw-r--r--crates/ide/src/status.rs23
-rw-r--r--crates/ide/src/test_explorer.rs37
-rw-r--r--crates/ide/src/view_crate_graph.rs60
-rw-r--r--crates/intern/src/symbol.rs14
-rw-r--r--crates/load-cargo/src/lib.rs31
-rw-r--r--crates/proc-macro-api/src/lib.rs10
-rw-r--r--crates/proc-macro-srv/src/tests/mod.rs130
-rw-r--r--crates/project-model/src/project_json.rs2
-rw-r--r--crates/project-model/src/tests.rs12
-rw-r--r--crates/project-model/src/workspace.rs184
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model.txt448
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt448
-rw-r--r--crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt448
-rw-r--r--crates/project-model/test_data/output/rust_project_cfg_groups.txt962
-rw-r--r--crates/project-model/test_data/output/rust_project_hello_world_project_model.txt832
-rw-r--r--crates/rust-analyzer/src/global_state.rs6
-rw-r--r--crates/rust-analyzer/src/main_loop.rs20
-rw-r--r--crates/rust-analyzer/src/reload.rs95
-rw-r--r--crates/rust-analyzer/src/target_spec.rs4
-rw-r--r--crates/test-fixture/Cargo.toml1
-rw-r--r--crates/test-fixture/src/lib.rs98
108 files changed, 3629 insertions, 2511 deletions
diff --git a/Cargo.lock b/Cargo.lock
index efd7362594..00da1c973d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2418,6 +2418,7 @@ dependencies = [
"span",
"stdx",
"test-utils",
+ "triomphe",
"tt",
]
diff --git a/crates/base-db/src/change.rs b/crates/base-db/src/change.rs
index 90413a573a..1f19556a76 100644
--- a/crates/base-db/src/change.rs
+++ b/crates/base-db/src/change.rs
@@ -3,20 +3,18 @@
use std::fmt;
-use rustc_hash::FxHashMap;
use salsa::Durability;
use triomphe::Arc;
use vfs::FileId;
-use crate::{CrateGraph, CrateId, CrateWorkspaceData, RootQueryDb, SourceRoot, SourceRootId};
+use crate::{CrateGraphBuilder, CratesIdMap, RootQueryDb, SourceRoot, SourceRootId};
/// Encapsulate a bunch of raw `.set` calls on the database.
#[derive(Default)]
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>>>,
+ pub crate_graph: Option<CrateGraphBuilder>,
}
impl fmt::Debug for FileChange {
@@ -48,15 +46,11 @@ impl FileChange {
self.files_changed.push((file_id, new_text))
}
- pub fn set_crate_graph(&mut self, graph: CrateGraph) {
+ pub fn set_crate_graph(&mut self, graph: CrateGraphBuilder) {
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 RootQueryDb) {
+ pub fn apply(self, db: &mut dyn RootQueryDb) -> Option<CratesIdMap> {
let _p = tracing::info_span!("FileChange::apply").entered();
if let Some(roots) = self.roots {
for (idx, root) in roots.into_iter().enumerate() {
@@ -79,12 +73,11 @@ impl FileChange {
let text = text.unwrap_or_default();
db.set_file_text_with_durability(file_id, &text, durability)
}
+
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);
+ return Some(crate_graph.set_in_db(db));
}
+ None
}
}
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index bd08387b58..c4e64b372f 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -6,17 +6,23 @@
//! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how
//! actual IO is done and lowered to input.
+use std::hash::BuildHasherDefault;
use std::{fmt, mem, ops};
-use cfg::CfgOptions;
+use cfg::{CfgOptions, HashableCfgOptions};
+use dashmap::mapref::entry::Entry;
+use dashmap::DashMap;
use intern::Symbol;
use la_arena::{Arena, Idx, RawIdx};
-use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
+use salsa::{Durability, Setter};
use span::{Edition, EditionedFileId};
use triomphe::Arc;
use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
-pub type ProcMacroPaths = FxHashMap<CrateId, Result<(String, AbsPathBuf), String>>;
+use crate::{CrateWorkspaceData, RootQueryDb};
+
+pub type ProcMacroPaths = FxHashMap<CrateBuilderId, Result<(String, AbsPathBuf), String>>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SourceRootId(pub u32);
@@ -64,30 +70,31 @@ impl SourceRoot {
}
}
-/// `CrateGraph` is a bit of information which turns a set of text files into a
-/// number of Rust crates.
-///
-/// Each crate is defined by the `FileId` of its root module, the set of enabled
-/// `cfg` flags and the set of dependencies.
-///
-/// Note that, due to cfg's, there might be several crates for a single `FileId`!
-///
-/// For the purposes of analysis, a crate does not have a name. Instead, names
-/// are specified on dependency edges. That is, a crate might be known under
-/// different names in different dependent crates.
-///
-/// Note that `CrateGraph` is build-system agnostic: it's a concept of the Rust
-/// language proper, not a concept of the build system. In practice, we get
-/// `CrateGraph` by lowering `cargo metadata` output.
-///
-/// `CrateGraph` is `!Serialize` by design, see
-/// <https://github.com/rust-lang/rust-analyzer/blob/master/docs/dev/architecture.md#serialization>
-#[derive(Clone, Default)]
-pub struct CrateGraph {
- arena: Arena<CrateData>,
+#[derive(Default, Clone)]
+pub struct CrateGraphBuilder {
+ arena: Arena<CrateBuilder>,
}
-impl fmt::Debug for CrateGraph {
+pub type CrateBuilderId = Idx<CrateBuilder>;
+
+impl ops::Index<CrateBuilderId> for CrateGraphBuilder {
+ type Output = CrateBuilder;
+
+ fn index(&self, index: CrateBuilderId) -> &Self::Output {
+ &self.arena[index]
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct CrateBuilder {
+ pub basic: CrateDataBuilder,
+ pub extra: ExtraCrateData,
+ pub cfg_options: Arc<CfgOptions>,
+ pub env: Env,
+ ws_data: Arc<CrateWorkspaceData>,
+}
+
+impl fmt::Debug for CrateGraphBuilder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map()
.entries(self.arena.iter().map(|(id, data)| (u32::from(id.into_raw()), data)))
@@ -95,8 +102,6 @@ impl fmt::Debug for CrateGraph {
}
}
-pub type CrateId = Idx<CrateData>;
-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CrateName(Symbol);
@@ -272,28 +277,34 @@ impl ReleaseChannel {
}
}
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct CrateData {
+/// The crate data from which we derive the `Crate`.
+///
+/// We want this to contain as little data as possible, because if it contains dependencies and
+/// something changes, this crate and all of its dependencies ids are invalidated, which causes
+/// pretty much everything to be recomputed. If the crate id is not invalidated, only this crate's
+/// information needs to be recomputed.
+///
+/// *Most* different crates have different root files (actually, pretty much all of them).
+/// Still, it is possible to have crates distinguished by other factors (e.g. dependencies).
+/// So we store only the root file - unless we find that this crate has the same root file as
+/// another crate, in which case we store all data for one of them (if one is a dependency of
+/// the other, we store for it, because it has more dependencies to be invalidated).
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct UniqueCrateData {
+ root_file_id: FileId,
+ disambiguator: Option<Box<(BuiltCrateData, HashableCfgOptions)>>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CrateData<Id> {
pub root_file_id: FileId,
pub edition: Edition,
- pub version: Option<String>,
- /// A name used in the package's project declaration: for Cargo projects,
- /// its `[package].name` can be different for other project types or even
- /// absent (a dummy crate for the code snippet, for example).
- ///
- /// For purposes of analysis, crates are anonymous (only names in
- /// `Dependency` matters), this name should only be used for UI.
- pub display_name: Option<CrateDisplayName>,
- pub cfg_options: Arc<CfgOptions>,
- /// The cfg options that could be used by the crate
- pub potential_cfg_options: Option<Arc<CfgOptions>>,
- pub env: Env,
/// The dependencies of this crate.
///
/// Note that this may contain more dependencies than the crate actually uses.
/// A common example is the test crate which is included but only actually is active when
/// declared in source via `extern crate test`.
- pub dependencies: Vec<Dependency>,
+ pub dependencies: Vec<Dependency<Id>>,
pub origin: CrateOrigin,
pub is_proc_macro: bool,
/// The working directory to run proc-macros in. This is the workspace root of the cargo workspace
@@ -301,6 +312,23 @@ pub struct CrateData {
pub proc_macro_cwd: Option<AbsPathBuf>,
}
+pub type CrateDataBuilder = CrateData<CrateBuilderId>;
+pub type BuiltCrateData = CrateData<Crate>;
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct ExtraCrateData {
+ pub version: Option<String>,
+ /// A name used in the package's project declaration: for Cargo projects,
+ /// its `[package].name` can be different for other project types or even
+ /// absent (a dummy crate for the code snippet, for example).
+ ///
+ /// For purposes of analysis, crates are anonymous (only names in
+ /// `Dependency` matters), this name should only be used for UI.
+ pub display_name: Option<CrateDisplayName>,
+ /// The cfg options that could be used by the crate
+ pub potential_cfg_options: Option<CfgOptions>,
+}
+
#[derive(Default, Clone, PartialEq, Eq)]
pub struct Env {
entries: FxHashMap<String, String>,
@@ -326,22 +354,32 @@ impl fmt::Debug for Env {
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Dependency {
- pub crate_id: CrateId,
+pub struct Dependency<Id> {
+ pub crate_id: Id,
pub name: CrateName,
prelude: bool,
sysroot: bool,
}
-impl Dependency {
- pub fn new(name: CrateName, crate_id: CrateId) -> Self {
+pub type DependencyBuilder = Dependency<CrateBuilderId>;
+pub type BuiltDependency = Dependency<Crate>;
+
+impl DependencyBuilder {
+ pub fn new(name: CrateName, crate_id: CrateBuilderId) -> Self {
Self { name, crate_id, prelude: true, sysroot: false }
}
- pub fn with_prelude(name: CrateName, crate_id: CrateId, prelude: bool, sysroot: bool) -> Self {
+ pub fn with_prelude(
+ name: CrateName,
+ crate_id: CrateBuilderId,
+ prelude: bool,
+ sysroot: bool,
+ ) -> Self {
Self { name, crate_id, prelude, sysroot }
}
+}
+impl BuiltDependency {
/// Whether this dependency is to be added to the depending crate's extern prelude.
pub fn is_prelude(&self) -> bool {
self.prelude
@@ -353,7 +391,32 @@ impl Dependency {
}
}
-impl CrateGraph {
+pub type CratesIdMap = FxHashMap<CrateBuilderId, Crate>;
+
+#[salsa::input]
+pub struct Crate {
+ #[return_ref]
+ pub data: BuiltCrateData,
+ /// Crate data that is not needed for analysis.
+ ///
+ /// This is split into a separate field to increase incrementality.
+ #[return_ref]
+ pub extra_data: ExtraCrateData,
+ // This is in `Arc` because it is shared for all crates in a workspace.
+ #[return_ref]
+ pub workspace_data: Arc<CrateWorkspaceData>,
+ // FIXME: Remove this `Arc`.
+ #[return_ref]
+ pub cfg_options: Arc<CfgOptions>,
+ #[return_ref]
+ pub env: Env,
+}
+
+/// The mapping from [`UniqueCrateData`] to their [`Crate`] input.
+#[derive(Debug, Default)]
+pub struct CratesMap(DashMap<UniqueCrateData, Crate, BuildHasherDefault<FxHasher>>);
+
+impl CrateGraphBuilder {
pub fn add_crate_root(
&mut self,
root_file_id: FileId,
@@ -361,33 +424,34 @@ impl CrateGraph {
display_name: Option<CrateDisplayName>,
version: Option<String>,
cfg_options: Arc<CfgOptions>,
- potential_cfg_options: Option<Arc<CfgOptions>>,
+ potential_cfg_options: Option<CfgOptions>,
mut env: Env,
origin: CrateOrigin,
is_proc_macro: bool,
proc_macro_cwd: Option<AbsPathBuf>,
- ) -> CrateId {
+ ws_data: Arc<CrateWorkspaceData>,
+ ) -> CrateBuilderId {
env.entries.shrink_to_fit();
- let data = CrateData {
- root_file_id,
- edition,
- version,
- display_name,
+ self.arena.alloc(CrateBuilder {
+ basic: CrateData {
+ root_file_id,
+ edition,
+ dependencies: Vec::new(),
+ origin,
+ is_proc_macro,
+ proc_macro_cwd,
+ },
+ extra: ExtraCrateData { version, display_name, potential_cfg_options },
cfg_options,
- potential_cfg_options,
env,
- dependencies: Vec::new(),
- origin,
- is_proc_macro,
- proc_macro_cwd,
- };
- self.arena.alloc(data)
+ ws_data,
+ })
}
pub fn add_dep(
&mut self,
- from: CrateId,
- dep: Dependency,
+ from: CrateBuilderId,
+ dep: DependencyBuilder,
) -> Result<(), CyclicDependenciesError> {
let _p = tracing::info_span!("add_dep").entered();
@@ -395,37 +459,160 @@ impl CrateGraph {
// that out, look for a path in the *opposite* direction, from `to` to
// `from`.
if let Some(path) = self.find_path(&mut FxHashSet::default(), dep.crate_id, from) {
- let path = path.into_iter().map(|it| (it, self[it].display_name.clone())).collect();
+ let path =
+ path.into_iter().map(|it| (it, self[it].extra.display_name.clone())).collect();
let err = CyclicDependenciesError { path };
assert!(err.from().0 == from && err.to().0 == dep.crate_id);
return Err(err);
}
- self.arena[from].add_dep(dep);
+ self.arena[from].basic.dependencies.push(dep);
Ok(())
}
- pub fn is_empty(&self) -> bool {
- self.arena.is_empty()
- }
+ pub fn set_in_db(self, db: &mut dyn RootQueryDb) -> CratesIdMap {
+ let mut all_crates = Vec::with_capacity(self.arena.len());
+ let mut visited = FxHashMap::default();
+ let mut visited_root_files = FxHashSet::default();
- pub fn len(&self) -> usize {
- self.arena.len()
+ let old_all_crates = db.all_crates();
+
+ let crates_map = db.crates_map();
+ // salsa doesn't compare new input to old input to see if they are the same, so here we are doing all the work ourselves.
+ for krate in self.iter() {
+ go(
+ &self,
+ db,
+ &crates_map,
+ &mut visited,
+ &mut visited_root_files,
+ &mut all_crates,
+ krate,
+ );
+ }
+
+ if **old_all_crates != *all_crates {
+ db.set_all_crates_with_durability(
+ Arc::new(all_crates.into_boxed_slice()),
+ Durability::HIGH,
+ );
+ }
+
+ return visited;
+
+ fn go(
+ graph: &CrateGraphBuilder,
+ db: &mut dyn RootQueryDb,
+ crates_map: &CratesMap,
+ visited: &mut FxHashMap<CrateBuilderId, Crate>,
+ visited_root_files: &mut FxHashSet<FileId>,
+ all_crates: &mut Vec<Crate>,
+ source: CrateBuilderId,
+ ) -> Crate {
+ if let Some(&crate_id) = visited.get(&source) {
+ return crate_id;
+ }
+ let krate = &graph[source];
+ let dependencies = krate
+ .basic
+ .dependencies
+ .iter()
+ .map(|dep| BuiltDependency {
+ crate_id: go(
+ graph,
+ db,
+ crates_map,
+ visited,
+ visited_root_files,
+ all_crates,
+ dep.crate_id,
+ ),
+ name: dep.name.clone(),
+ prelude: dep.prelude,
+ sysroot: dep.sysroot,
+ })
+ .collect::<Vec<_>>();
+ let crate_data = BuiltCrateData {
+ dependencies,
+ edition: krate.basic.edition,
+ is_proc_macro: krate.basic.is_proc_macro,
+ origin: krate.basic.origin.clone(),
+ root_file_id: krate.basic.root_file_id,
+ proc_macro_cwd: krate.basic.proc_macro_cwd.clone(),
+ };
+ let disambiguator = if visited_root_files.insert(krate.basic.root_file_id) {
+ None
+ } else {
+ Some(Box::new((crate_data.clone(), krate.cfg_options.to_hashable())))
+ };
+
+ let unique_crate_data =
+ UniqueCrateData { root_file_id: krate.basic.root_file_id, disambiguator };
+ let crate_input = match crates_map.0.entry(unique_crate_data) {
+ Entry::Occupied(entry) => {
+ let old_crate = *entry.get();
+ if crate_data != *old_crate.data(db) {
+ old_crate.set_data(db).with_durability(Durability::HIGH).to(crate_data);
+ }
+ if krate.extra != *old_crate.extra_data(db) {
+ old_crate
+ .set_extra_data(db)
+ .with_durability(Durability::HIGH)
+ .to(krate.extra.clone());
+ }
+ if krate.cfg_options != *old_crate.cfg_options(db) {
+ old_crate
+ .set_cfg_options(db)
+ .with_durability(Durability::HIGH)
+ .to(krate.cfg_options.clone());
+ }
+ if krate.env != *old_crate.env(db) {
+ old_crate
+ .set_env(db)
+ .with_durability(Durability::HIGH)
+ .to(krate.env.clone());
+ }
+ if krate.ws_data != *old_crate.workspace_data(db) {
+ old_crate
+ .set_workspace_data(db)
+ .with_durability(Durability::HIGH)
+ .to(krate.ws_data.clone());
+ }
+ old_crate
+ }
+ Entry::Vacant(entry) => {
+ let input = Crate::builder(
+ crate_data,
+ krate.extra.clone(),
+ krate.ws_data.clone(),
+ krate.cfg_options.clone(),
+ krate.env.clone(),
+ )
+ .durability(Durability::HIGH)
+ .new(db);
+ entry.insert(input);
+ input
+ }
+ };
+ all_crates.push(crate_input);
+ visited.insert(source, crate_input);
+ crate_input
+ }
}
- pub fn iter(&self) -> impl Iterator<Item = CrateId> + '_ {
+ pub fn iter(&self) -> impl Iterator<Item = CrateBuilderId> + '_ {
self.arena.iter().map(|(idx, _)| idx)
}
// FIXME: used for fixing up the toolchain sysroot, should be removed and done differently
#[doc(hidden)]
- pub fn iter_mut(&mut self) -> impl Iterator<Item = (CrateId, &mut CrateData)> + '_ {
+ pub fn iter_mut(&mut self) -> impl Iterator<Item = (CrateBuilderId, &mut CrateBuilder)> + '_ {
self.arena.iter_mut()
}
/// Returns an iterator over all transitive dependencies of the given crate,
/// including the crate itself.
- pub fn transitive_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> {
+ pub fn transitive_deps(&self, of: CrateBuilderId) -> impl Iterator<Item = CrateBuilderId> {
let mut worklist = vec![of];
let mut deps = FxHashSet::default();
@@ -434,42 +621,15 @@ impl CrateGraph {
continue;
}
- worklist.extend(self[krate].dependencies.iter().map(|dep| dep.crate_id));
+ worklist.extend(self[krate].basic.dependencies.iter().map(|dep| dep.crate_id));
}
deps.into_iter()
}
- /// Returns all transitive reverse dependencies of the given crate,
- /// including the crate itself.
- pub fn transitive_rev_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> {
- let mut worklist = vec![of];
- let mut rev_deps = FxHashSet::default();
- rev_deps.insert(of);
-
- let mut inverted_graph = FxHashMap::<_, Vec<_>>::default();
- self.arena.iter().for_each(|(krate, data)| {
- data.dependencies
- .iter()
- .for_each(|dep| inverted_graph.entry(dep.crate_id).or_default().push(krate))
- });
-
- while let Some(krate) = worklist.pop() {
- if let Some(krate_rev_deps) = inverted_graph.get(&krate) {
- krate_rev_deps
- .iter()
- .copied()
- .filter(|&rev_dep| rev_deps.insert(rev_dep))
- .for_each(|rev_dep| worklist.push(rev_dep));
- }
- }
-
- rev_deps.into_iter()
- }
-
/// Returns all crates in the graph, sorted in topological order (ie. dependencies of a crate
/// come before the crate itself).
- pub fn crates_in_topological_order(&self) -> Vec<CrateId> {
+ fn crates_in_topological_order(&self) -> Vec<CrateBuilderId> {
let mut res = Vec::new();
let mut visited = FxHashSet::default();
@@ -480,15 +640,15 @@ impl CrateGraph {
return res;
fn go(
- graph: &CrateGraph,
- visited: &mut FxHashSet<CrateId>,
- res: &mut Vec<CrateId>,
- source: CrateId,
+ graph: &CrateGraphBuilder,
+ visited: &mut FxHashSet<CrateBuilderId>,
+ res: &mut Vec<CrateBuilderId>,
+ source: CrateBuilderId,
) {
if !visited.insert(source) {
return;
}
- for dep in graph[source].dependencies.iter() {
+ for dep in graph[source].basic.dependencies.iter() {
go(graph, visited, res, dep.crate_id)
}
res.push(source)
@@ -504,23 +664,27 @@ impl CrateGraph {
/// Returns a map mapping `other`'s IDs to the new IDs in `self`.
pub fn extend(
&mut self,
- mut other: CrateGraph,
+ mut other: CrateGraphBuilder,
proc_macros: &mut ProcMacroPaths,
- ) -> FxHashMap<CrateId, CrateId> {
+ ) -> FxHashMap<CrateBuilderId, CrateBuilderId> {
// Sorting here is a bit pointless because the input is likely already sorted.
// However, the overhead is small and it makes the `extend` method harder to misuse.
self.arena
.iter_mut()
- .for_each(|(_, data)| data.dependencies.sort_by_key(|dep| dep.crate_id));
+ .for_each(|(_, data)| data.basic.dependencies.sort_by_key(|dep| dep.crate_id));
- let m = self.len();
+ let m = self.arena.len();
let topo = other.crates_in_topological_order();
- let mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default();
+ let mut id_map: FxHashMap<CrateBuilderId, CrateBuilderId> = FxHashMap::default();
for topo in topo {
let crate_data = &mut other.arena[topo];
- crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]);
- crate_data.dependencies.sort_by_key(|dep| dep.crate_id);
+ crate_data
+ .basic
+ .dependencies
+ .iter_mut()
+ .for_each(|dep| dep.crate_id = id_map[&dep.crate_id]);
+ crate_data.basic.dependencies.sort_by_key(|dep| dep.crate_id);
let find = self.arena.iter().take(m).find_map(|(k, v)| (v == crate_data).then_some(k));
let new_id = find.unwrap_or_else(|| self.arena.alloc(crate_data.clone()));
@@ -534,10 +698,10 @@ impl CrateGraph {
fn find_path(
&self,
- visited: &mut FxHashSet<CrateId>,
- from: CrateId,
- to: CrateId,
- ) -> Option<Vec<CrateId>> {
+ visited: &mut FxHashSet<CrateBuilderId>,
+ from: CrateBuilderId,
+ to: CrateBuilderId,
+ ) -> Option<Vec<CrateBuilderId>> {
if !visited.insert(from) {
return None;
}
@@ -546,7 +710,7 @@ impl CrateGraph {
return Some(vec![to]);
}
- for dep in &self[from].dependencies {
+ for dep in &self[from].basic.dependencies {
let crate_id = dep.crate_id;
if let Some(mut path) = self.find_path(visited, crate_id, to) {
path.push(from);
@@ -559,7 +723,10 @@ impl CrateGraph {
/// Removes all crates from this crate graph except for the ones in `to_keep` and fixes up the dependencies.
/// Returns a mapping from old crate ids to new crate ids.
- pub fn remove_crates_except(&mut self, to_keep: &[CrateId]) -> Vec<Option<CrateId>> {
+ pub fn remove_crates_except(
+ &mut self,
+ to_keep: &[CrateBuilderId],
+ ) -> Vec<Option<CrateBuilderId>> {
let mut id_map = vec![None; self.arena.len()];
self.arena = std::mem::take(&mut self.arena)
.into_iter()
@@ -567,12 +734,12 @@ impl CrateGraph {
.enumerate()
.map(|(new_id, (id, data))| {
id_map[id.into_raw().into_u32() as usize] =
- Some(CrateId::from_raw(RawIdx::from_u32(new_id as u32)));
+ Some(CrateBuilderId::from_raw(RawIdx::from_u32(new_id as u32)));
data
})
.collect();
for (_, data) in self.arena.iter_mut() {
- data.dependencies.iter_mut().for_each(|dep| {
+ data.basic.dependencies.iter_mut().for_each(|dep| {
dep.crate_id =
id_map[dep.crate_id.into_raw().into_u32() as usize].expect("crate was filtered")
});
@@ -585,20 +752,34 @@ impl CrateGraph {
}
}
-impl ops::Index<CrateId> for CrateGraph {
- type Output = CrateData;
- fn index(&self, crate_id: CrateId) -> &CrateData {
- &self.arena[crate_id]
+pub(crate) fn transitive_rev_deps(db: &dyn RootQueryDb, of: Crate) -> FxHashSet<Crate> {
+ let mut worklist = vec![of];
+ let mut rev_deps = FxHashSet::default();
+ rev_deps.insert(of);
+
+ let mut inverted_graph = FxHashMap::<_, Vec<_>>::default();
+ db.all_crates().iter().for_each(|&krate| {
+ krate
+ .data(db)
+ .dependencies
+ .iter()
+ .for_each(|dep| inverted_graph.entry(dep.crate_id).or_default().push(krate))
+ });
+
+ while let Some(krate) = worklist.pop() {
+ if let Some(crate_rev_deps) = inverted_graph.get(&krate) {
+ crate_rev_deps
+ .iter()
+ .copied()
+ .filter(|&rev_dep| rev_deps.insert(rev_dep))
+ .for_each(|rev_dep| worklist.push(rev_dep));
+ }
}
-}
-impl CrateData {
- /// Add a dependency to `self` without checking if the dependency
- // is existent among `self.dependencies`.
- fn add_dep(&mut self, dep: Dependency) {
- self.dependencies.push(dep)
- }
+ rev_deps
+}
+impl BuiltCrateData {
pub fn root_file_id(&self) -> EditionedFileId {
EditionedFileId::new(self.root_file_id, self.edition)
}
@@ -657,21 +838,21 @@ impl<'a> IntoIterator for &'a Env {
#[derive(Debug)]
pub struct CyclicDependenciesError {
- path: Vec<(CrateId, Option<CrateDisplayName>)>,
+ path: Vec<(CrateBuilderId, Option<CrateDisplayName>)>,
}
impl CyclicDependenciesError {
- fn from(&self) -> &(CrateId, Option<CrateDisplayName>) {
+ fn from(&self) -> &(CrateBuilderId, Option<CrateDisplayName>) {
self.path.first().unwrap()
}
- fn to(&self) -> &(CrateId, Option<CrateDisplayName>) {
+ fn to(&self) -> &(CrateBuilderId, Option<CrateDisplayName>) {
self.path.last().unwrap()
}
}
impl fmt::Display for CyclicDependenciesError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let render = |(id, name): &(CrateId, Option<CrateDisplayName>)| match name {
+ let render = |(id, name): &(CrateBuilderId, Option<CrateDisplayName>)| match name {
Some(it) => format!("{it}({id:?})"),
None => format!("{id:?}"),
};
@@ -688,13 +869,19 @@ impl fmt::Display for CyclicDependenciesError {
#[cfg(test)]
mod tests {
- use crate::CrateOrigin;
+ use triomphe::Arc;
+
+ use crate::{CrateWorkspaceData, DependencyBuilder};
- use super::{CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId};
+ use super::{CrateGraphBuilder, CrateName, CrateOrigin, Edition::Edition2018, Env, FileId};
+
+ fn empty_ws_data() -> Arc<CrateWorkspaceData> {
+ Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None })
+ }
#[test]
fn detect_cyclic_dependency_indirect() {
- let mut graph = CrateGraph::default();
+ let mut graph = CrateGraphBuilder::default();
let crate1 = graph.add_crate_root(
FileId::from_raw(1u32),
Edition2018,
@@ -706,6 +893,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
let crate2 = graph.add_crate_root(
FileId::from_raw(2u32),
@@ -718,6 +906,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
let crate3 = graph.add_crate_root(
FileId::from_raw(3u32),
@@ -730,21 +919,22 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
assert!(graph
- .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
+ .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,))
.is_ok());
assert!(graph
- .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,))
+ .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,))
.is_ok());
assert!(graph
- .add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1,))
+ .add_dep(crate3, DependencyBuilder::new(CrateName::new("crate1").unwrap(), crate1,))
.is_err());
}
#[test]
fn detect_cyclic_dependency_direct() {
- let mut graph = CrateGraph::default();
+ let mut graph = CrateGraphBuilder::default();
let crate1 = graph.add_crate_root(
FileId::from_raw(1u32),
Edition2018,
@@ -756,6 +946,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
let crate2 = graph.add_crate_root(
FileId::from_raw(2u32),
@@ -768,18 +959,19 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
assert!(graph
- .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
+ .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,))
.is_ok());
assert!(graph
- .add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
+ .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,))
.is_err());
}
#[test]
fn it_works() {
- let mut graph = CrateGraph::default();
+ let mut graph = CrateGraphBuilder::default();
let crate1 = graph.add_crate_root(
FileId::from_raw(1u32),
Edition2018,
@@ -791,6 +983,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
let crate2 = graph.add_crate_root(
FileId::from_raw(2u32),
@@ -803,6 +996,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
let crate3 = graph.add_crate_root(
FileId::from_raw(3u32),
@@ -815,18 +1009,19 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
assert!(graph
- .add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,))
+ .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,))
.is_ok());
assert!(graph
- .add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,))
+ .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,))
.is_ok());
}
#[test]
fn dashes_are_normalized() {
- let mut graph = CrateGraph::default();
+ let mut graph = CrateGraphBuilder::default();
let crate1 = graph.add_crate_root(
FileId::from_raw(1u32),
Edition2018,
@@ -838,6 +1033,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
let crate2 = graph.add_crate_root(
FileId::from_raw(2u32),
@@ -850,16 +1046,22 @@ mod tests {
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ empty_ws_data(),
);
assert!(graph
.add_dep(
crate1,
- Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2,)
+ DependencyBuilder::new(
+ CrateName::normalize_dashes("crate-name-with-dashes"),
+ crate2,
+ )
)
.is_ok());
assert_eq!(
- graph[crate1].dependencies,
- vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2,)]
+ graph.arena[crate1].basic.dependencies,
+ vec![
+ DependencyBuilder::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2,)
+ ]
);
}
}
diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs
index 9ec9100968..324979b2e4 100644
--- a/crates/base-db/src/lib.rs
+++ b/crates/base-db/src/lib.rs
@@ -8,14 +8,15 @@ use std::hash::BuildHasherDefault;
pub use crate::{
change::FileChange,
input::{
- CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env,
- LangCrateOrigin, ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId,
- TargetLayoutLoadResult,
+ BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
+ CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
+ DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroPaths, ReleaseChannel,
+ SourceRoot, SourceRootId, TargetLayoutLoadResult, UniqueCrateData,
},
};
use dashmap::{mapref::entry::Entry, DashMap};
pub use query_group::{self};
-use rustc_hash::{FxHashMap, FxHasher};
+use rustc_hash::{FxHashSet, FxHasher};
pub use salsa::{self};
use salsa::{Durability, Setter};
pub use semver::{BuildMetadata, Prerelease, Version, VersionReq};
@@ -200,21 +201,53 @@ pub trait RootQueryDb: SourceDatabase + salsa::Database {
/// Returns the set of errors obtained from parsing the file including validation errors.
fn parse_errors(&self, file_id: EditionedFileId) -> Option<Arc<[SyntaxError]>>;
- /// The crate graph.
- #[salsa::input]
- fn crate_graph(&self) -> Arc<CrateGraph>;
+ #[salsa::transparent]
+ fn toolchain_channel(&self, krate: Crate) -> Option<ReleaseChannel>;
- #[salsa::input]
- fn crate_workspace_data(&self) -> Arc<FxHashMap<CrateId, Arc<CrateWorkspaceData>>>;
+ /// Crates whose root file is in `id`.
+ fn source_root_crates(&self, id: SourceRootId) -> Arc<[Crate]>;
#[salsa::transparent]
- fn toolchain_channel(&self, krate: CrateId) -> Option<ReleaseChannel>;
+ fn relevant_crates(&self, file_id: FileId) -> Arc<[Crate]>;
- /// Crates whose root file is in `id`.
- fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>;
+ /// Returns the crates in topological order.
+ ///
+ /// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications.
+ #[salsa::input]
+ fn all_crates(&self) -> Arc<Box<[Crate]>>;
+
+ /// Returns an iterator over all transitive dependencies of the given crate,
+ /// including the crate itself.
+ ///
+ /// **Warning**: do not use this query in analysis! It kills incrementality across crate metadata modifications.
+ ///
+ #[salsa::transparent]
+ fn transitive_deps(&self, crate_id: Crate) -> FxHashSet<Crate>;
+ /// Returns all transitive reverse dependencies of the given crate,
+ /// including the crate itself.
+ ///
+ /// **Warning**: Do not use this query in analysis! It kills incrementality across crate metadata modifications.
+ #[salsa::invoke(input::transitive_rev_deps)]
#[salsa::transparent]
- fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>;
+ fn transitive_rev_deps(&self, of: Crate) -> FxHashSet<Crate>;
+}
+
+pub fn transitive_deps(db: &dyn SourceDatabase, crate_id: Crate) -> FxHashSet<Crate> {
+ // There is a bit of duplication here and in `CrateGraphBuilder` in the same method, but it's not terrible
+ // and removing that is a bit difficult.
+ let mut worklist = vec![crate_id];
+ let mut deps = FxHashSet::default();
+
+ while let Some(krate) = worklist.pop() {
+ if !deps.insert(krate) {
+ continue;
+ }
+
+ worklist.extend(krate.data(db).dependencies.iter().map(|dep| dep.crate_id));
+ }
+
+ deps
}
#[salsa::db]
@@ -257,6 +290,9 @@ pub trait SourceDatabase: salsa::Database {
let source_root = self.source_root(source_root.source_root_id(self));
source_root.source_root(self).resolve_path(path)
}
+
+ #[doc(hidden)]
+ fn crates_map(&self) -> Arc<CratesMap>;
}
/// Crate related data shared by the whole workspace.
@@ -268,12 +304,8 @@ pub struct CrateWorkspaceData {
pub toolchain: Option<Version>,
}
-fn toolchain_channel(db: &dyn RootQueryDb, krate: CrateId) -> Option<ReleaseChannel> {
- db.crate_workspace_data()
- .get(&krate)?
- .toolchain
- .as_ref()
- .and_then(|v| ReleaseChannel::from_str(&v.pre))
+fn toolchain_channel(db: &dyn RootQueryDb, krate: Crate) -> Option<ReleaseChannel> {
+ krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
}
fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse<ast::SourceFile> {
@@ -291,21 +323,19 @@ fn parse_errors(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Option<Arc<[S
}
}
-fn source_root_crates(db: &dyn RootQueryDb, id: SourceRootId) -> Arc<[CrateId]> {
- let graph = db.crate_graph();
- let mut crates = graph
+fn source_root_crates(db: &dyn RootQueryDb, id: SourceRootId) -> Arc<[Crate]> {
+ let crates = db.all_crates();
+ crates
.iter()
+ .copied()
.filter(|&krate| {
- let root_file = graph[krate].root_file_id;
+ let root_file = krate.data(db).root_file_id;
db.file_source_root(root_file).source_root_id(db) == id
})
- .collect::<Vec<_>>();
- crates.sort();
- crates.dedup();
- crates.into_iter().collect()
+ .collect()
}
-fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[CrateId]> {
+fn relevant_crates(db: &dyn RootQueryDb, file_id: FileId) -> Arc<[Crate]> {
let _p = tracing::info_span!("relevant_crates").entered();
let source_root = db.file_source_root(file_id);
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs
index 08545b6851..26860fb932 100644
--- a/crates/cfg/src/lib.rs
+++ b/crates/cfg/src/lib.rs
@@ -104,6 +104,12 @@ impl CfgOptions {
_ => None,
})
}
+
+ pub fn to_hashable(&self) -> HashableCfgOptions {
+ let mut enabled = self.enabled.iter().cloned().collect::<Box<[_]>>();
+ enabled.sort_unstable();
+ HashableCfgOptions { _enabled: enabled }
+ }
}
impl Extend<CfgAtom> for CfgOptions {
@@ -256,3 +262,9 @@ impl fmt::Display for InactiveReason {
Ok(())
}
}
+
+/// A `CfgOptions` that implements `Hash`, for the sake of hashing only.
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct HashableCfgOptions {
+ _enabled: Box<[CfgAtom]>,
+}
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index 52a72bce91..579ea12e6a 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -2,7 +2,7 @@
use std::{borrow::Cow, hash::Hash, ops};
-use base_db::CrateId;
+use base_db::Crate;
use cfg::{CfgExpr, CfgOptions};
use either::Either;
use hir_expand::{
@@ -44,7 +44,7 @@ impl Attrs {
(**self).iter().find(|attr| attr.id == id)
}
- pub(crate) fn filter(db: &dyn DefDatabase, krate: CrateId, raw_attrs: RawAttrs) -> Attrs {
+ pub(crate) fn filter(db: &dyn DefDatabase, krate: Crate, raw_attrs: RawAttrs) -> Attrs {
Attrs(raw_attrs.filter(db.upcast(), krate))
}
}
@@ -76,7 +76,6 @@ impl Attrs {
// FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
let mut res = ArenaMap::default();
- let crate_graph = db.crate_graph();
let item_tree;
let (parent, fields, krate) = match v {
VariantId::EnumVariantId(it) => {
@@ -102,7 +101,7 @@ impl Attrs {
}
};
- let cfg_options = &crate_graph[krate].cfg_options;
+ let cfg_options = krate.cfg_options(db);
let mut idx = 0;
for (id, _field) in fields.iter().enumerate() {
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index bec6627877..9c87dc31db 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -2,7 +2,7 @@
pub mod adt;
-use base_db::CrateId;
+use base_db::Crate;
use hir_expand::{
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
};
@@ -22,7 +22,7 @@ use crate::{
attr_resolution::ResolvedAttr,
diagnostics::{DefDiagnostic, DefDiagnostics},
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
- DefMap, MacroSubNs,
+ DefMap, LocalDefMap, MacroSubNs,
},
path::ImportAlias,
type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap},
@@ -57,8 +57,7 @@ impl FunctionData {
item_tree[func.visibility].clone()
};
- let crate_graph = db.crate_graph();
- let cfg_options = &crate_graph[krate].cfg_options;
+ let cfg_options = krate.cfg_options(db);
let attr_owner = |idx| {
item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32)))
};
@@ -525,7 +524,7 @@ pub struct ExternCrateDeclData {
pub name: Name,
pub alias: Option<ImportAlias>,
pub visibility: RawVisibility,
- pub crate_id: Option<CrateId>,
+ pub crate_id: Option<Crate>,
}
impl ExternCrateDeclData {
@@ -542,7 +541,7 @@ impl ExternCrateDeclData {
let crate_id = if name == sym::self_.clone() {
Some(krate)
} else {
- db.crate_graph()[krate].dependencies.iter().find_map(|dep| {
+ krate.data(db).dependencies.iter().find_map(|dep| {
if dep.name.symbol() == name.symbol() {
Some(dep.crate_id)
} else {
@@ -633,6 +632,7 @@ struct AssocItemCollector<'a> {
db: &'a dyn DefDatabase,
module_id: ModuleId,
def_map: Arc<DefMap>,
+ local_def_map: Arc<LocalDefMap>,
diagnostics: Vec<DefDiagnostic>,
container: ItemContainerId,
expander: Expander,
@@ -648,10 +648,12 @@ impl<'a> AssocItemCollector<'a> {
file_id: HirFileId,
container: ItemContainerId,
) -> Self {
+ let (def_map, local_def_map) = module_id.local_def_map(db);
Self {
db,
module_id,
- def_map: module_id.def_map(db),
+ def_map,
+ local_def_map,
container,
expander: Expander::new(db, file_id, module_id),
items: Vec::new(),
@@ -697,6 +699,7 @@ impl<'a> AssocItemCollector<'a> {
let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id };
match self.def_map.resolve_attr_macro(
+ &self.local_def_map,
self.db,
self.module_id.local_id,
ast_id_with_path,
@@ -780,6 +783,7 @@ impl<'a> AssocItemCollector<'a> {
let resolver = |path: &_| {
self.def_map
.resolve_path(
+ &self.local_def_map,
self.db,
module,
path,
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index 28992ec600..bf8f5024c2 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -1,6 +1,6 @@
//! Defines hir-level representation of structs, enums and unions
-use base_db::CrateId;
+use base_db::Crate;
use bitflags::bitflags;
use cfg::CfgOptions;
use either::Either;
@@ -90,7 +90,7 @@ pub struct FieldData {
fn repr_from_value(
db: &dyn DefDatabase,
- krate: CrateId,
+ krate: Crate,
item_tree: &ItemTree,
of: AttrOwner,
) -> Option<ReprOptions> {
@@ -222,7 +222,7 @@ impl StructData {
loc.container.local_id,
loc.id.tree_id(),
&item_tree,
- &db.crate_graph()[krate].cfg_options,
+ krate.cfg_options(db),
FieldParent::Struct(loc.id.value),
&strukt.fields,
None,
@@ -274,7 +274,7 @@ impl StructData {
loc.container.local_id,
loc.id.tree_id(),
&item_tree,
- &db.crate_graph()[krate].cfg_options,
+ krate.cfg_options(db),
FieldParent::Union(loc.id.value),
&union.fields,
None,
@@ -377,7 +377,7 @@ impl EnumVariantData {
container.local_id,
loc.id.tree_id(),
&item_tree,
- &db.crate_graph()[krate].cfg_options,
+ krate.cfg_options(db),
FieldParent::Variant(loc.id.value),
&variant.fields,
Some(item_tree[loc.parent.lookup(db).id.value].visibility),
@@ -448,7 +448,7 @@ pub enum StructKind {
fn lower_fields(
db: &dyn DefDatabase,
- krate: CrateId,
+ krate: Crate,
container: LocalModuleId,
tree_id: TreeId,
item_tree: &ItemTree,
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index 0772d00f03..b6707af618 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -1,5 +1,5 @@
//! Defines database & queries for name resolution.
-use base_db::{CrateId, RootQueryDb, SourceDatabase, Upcast};
+use base_db::{Crate, RootQueryDb, SourceDatabase, Upcast};
use either::Either;
use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId};
use intern::sym;
@@ -20,7 +20,7 @@ use crate::{
import_map::ImportMap,
item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps},
lang_item::{self, LangItem, LangItemTarget, LangItems},
- nameres::{diagnostics::DefDiagnostics, DefMap},
+ nameres::{diagnostics::DefDiagnostics, DefMap, LocalDefMap},
tt,
type_ref::TypesSourceMap,
visibility::{self, Visibility},
@@ -130,8 +130,11 @@ pub trait DefDatabase:
block_id: BlockId,
) -> (Arc<ItemTree>, Arc<ItemTreeSourceMaps>);
- #[salsa::invoke(DefMap::crate_def_map_query)]
- fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
+ #[salsa::invoke_actual(DefMap::crate_local_def_map_query)]
+ fn crate_local_def_map(&self, krate: Crate) -> (Arc<DefMap>, Arc<LocalDefMap>);
+
+ #[salsa::invoke_actual(DefMap::crate_def_map_query)]
+ fn crate_def_map(&self, krate: Crate) -> Arc<DefMap>;
/// Computes the block-level `DefMap`.
#[salsa::invoke_actual(DefMap::block_def_map_query)]
@@ -258,10 +261,10 @@ pub trait DefDatabase:
// endregion:attrs
#[salsa::invoke(LangItems::lang_item_query)]
- fn lang_item(&self, start_crate: CrateId, item: LangItem) -> Option<LangItemTarget>;
+ fn lang_item(&self, start_crate: Crate, item: LangItem) -> Option<LangItemTarget>;
- #[salsa::invoke(ImportMap::import_map_query)]
- fn import_map(&self, krate: CrateId) -> Arc<ImportMap>;
+ #[salsa::invoke_actual(ImportMap::import_map_query)]
+ fn import_map(&self, krate: Crate) -> Arc<ImportMap>;
// region:visibilities
@@ -277,23 +280,25 @@ pub trait DefDatabase:
// endregion:visibilities
- #[salsa::invoke(LangItems::crate_lang_items_query)]
- fn crate_lang_items(&self, krate: CrateId) -> Option<Arc<LangItems>>;
+ #[salsa::invoke_actual(LangItems::crate_lang_items_query)]
+ fn crate_lang_items(&self, krate: Crate) -> Option<Arc<LangItems>>;
- #[salsa::invoke(crate::lang_item::notable_traits_in_deps)]
- fn notable_traits_in_deps(&self, krate: CrateId) -> Arc<[Arc<[TraitId]>]>;
- #[salsa::invoke(crate::lang_item::crate_notable_traits)]
- fn crate_notable_traits(&self, krate: CrateId) -> Option<Arc<[TraitId]>>;
+ #[salsa::invoke_actual(crate::lang_item::notable_traits_in_deps)]
+ fn notable_traits_in_deps(&self, krate: Crate) -> Arc<[Arc<[TraitId]>]>;
+ #[salsa::invoke_actual(crate::lang_item::crate_notable_traits)]
+ fn crate_notable_traits(&self, krate: Crate) -> Option<Arc<[TraitId]>>;
- fn crate_supports_no_std(&self, crate_id: CrateId) -> bool;
+ #[salsa::invoke_actual(crate_supports_no_std)]
+ fn crate_supports_no_std(&self, crate_id: Crate) -> bool;
- fn include_macro_invoc(&self, crate_id: CrateId) -> Arc<[(MacroCallId, EditionedFileId)]>;
+ #[salsa::invoke_actual(include_macro_invoc)]
+ fn include_macro_invoc(&self, crate_id: Crate) -> Arc<[(MacroCallId, EditionedFileId)]>;
}
// return: macro call id and include file id
fn include_macro_invoc(
db: &dyn DefDatabase,
- krate: CrateId,
+ krate: Crate,
) -> Arc<[(MacroCallId, EditionedFileId)]> {
db.crate_def_map(krate)
.modules
@@ -307,8 +312,8 @@ fn include_macro_invoc(
.collect()
}
-fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
- let file = db.crate_graph()[crate_id].root_file_id();
+fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool {
+ let file = crate_id.data(db).root_file_id();
let item_tree = db.file_item_tree(file.into());
let attrs = item_tree.raw_attrs(AttrOwner::TopLevel);
for attr in &**attrs {
diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs
index a1b3123c99..c5ce8c454c 100644
--- a/crates/hir-def/src/expander.rs
+++ b/crates/hir-def/src/expander.rs
@@ -2,7 +2,7 @@
use std::cell::OnceCell;
-use base_db::CrateId;
+use base_db::Crate;
use cfg::CfgOptions;
use drop_bomb::DropBomb;
use hir_expand::{
@@ -44,7 +44,7 @@ impl Expander {
module,
recursion_depth: 0,
recursion_limit,
- cfg_options: db.crate_graph()[module.krate].cfg_options.clone(),
+ cfg_options: Arc::clone(module.krate.cfg_options(db)),
span_map: OnceCell::new(),
}
}
@@ -53,7 +53,7 @@ impl Expander {
self.span_map.get_or_init(|| db.span_map(self.current_file_id))
}
- pub fn krate(&self) -> CrateId {
+ pub fn krate(&self) -> Crate {
self.module.krate
}
diff --git a/crates/hir-def/src/expr_store/body.rs b/crates/hir-def/src/expr_store/body.rs
index a55fec4f8b..8aca4eb9bc 100644
--- a/crates/hir-def/src/expr_store/body.rs
+++ b/crates/hir-def/src/expr_store/body.rs
@@ -86,7 +86,6 @@ impl Body {
let item_tree = f.id.item_tree(db);
let func = &item_tree[f.id.value];
let krate = f.container.module(db).krate;
- let crate_graph = db.crate_graph();
(
param_list,
(0..func.params.len()).map(move |idx| {
@@ -99,7 +98,7 @@ impl Body {
Idx::from_raw(RawIdx::from(idx as u32)),
),
)
- .is_cfg_enabled(&crate_graph[krate].cfg_options)
+ .is_cfg_enabled(krate.cfg_options(db))
}),
)
});
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index c3ca610fae..c346cec242 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -5,7 +5,7 @@ mod asm;
use std::mem;
-use base_db::CrateId;
+use base_db::Crate;
use either::Either;
use hir_expand::{
mod_path::tool_path,
@@ -50,7 +50,7 @@ use crate::{
item_scope::BuiltinShadowMode,
lang_item::LangItem,
lower::LowerCtx,
- nameres::{DefMap, MacroSubNs},
+ nameres::{DefMap, LocalDefMap, MacroSubNs},
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
AdtId, BlockId, BlockLoc, ConstBlockLoc, DefWithBodyId, MacroId, ModuleDefId, UnresolvedMacro,
@@ -64,7 +64,7 @@ pub(super) fn lower_body(
expander: Expander,
parameters: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
body: Option<ast::Expr>,
- krate: CrateId,
+ krate: Crate,
is_async_fn: bool,
) -> (Body, BodySourceMap) {
// We cannot leave the root span map empty and let any identifier from it be treated as root,
@@ -189,7 +189,7 @@ pub(super) fn lower(
owner: ExprStoreOwnerId,
expander: Expander,
body: Option<ast::Expr>,
- krate: CrateId,
+ krate: Crate,
) -> (ExpressionStore, ExpressionStoreSourceMap) {
// We cannot leave the root span map empty and let any identifier from it be treated as root,
// because when inside nested macros `SyntaxContextId`s from the outer macro will be interleaved
@@ -214,8 +214,9 @@ struct ExprCollector<'a> {
expander: Expander,
owner: ExprStoreOwnerId,
def_map: Arc<DefMap>,
+ local_def_map: Arc<LocalDefMap>,
ast_id_map: Arc<AstIdMap>,
- krate: CrateId,
+ krate: Crate,
store: ExpressionStoreBuilder,
source_map: ExpressionStoreSourceMap,
@@ -327,14 +328,16 @@ impl ExprCollector<'_> {
db: &dyn DefDatabase,
owner: ExprStoreOwnerId,
expander: Expander,
- krate: CrateId,
+ krate: Crate,
span_map: Option<Arc<ExpansionSpanMap>>,
) -> ExprCollector<'_> {
+ let (def_map, local_def_map) = expander.module.local_def_map(db);
ExprCollector {
db,
owner,
krate,
- def_map: expander.module.def_map(db),
+ def_map,
+ local_def_map,
source_map: ExpressionStoreSourceMap::default(),
ast_id_map: db.ast_id_map(expander.current_file_id()),
store: ExpressionStoreBuilder::default(),
@@ -1306,6 +1309,7 @@ impl ExprCollector<'_> {
None => self.expander.enter_expand(self.db, mcall, |path| {
self.def_map
.resolve_path(
+ &self.local_def_map,
self.db,
module,
path,
@@ -1608,6 +1612,7 @@ impl ExprCollector<'_> {
// This could also be a single-segment path pattern. To
// decide that, we need to try resolving the name.
let (resolved, _) = self.def_map.resolve_path(
+ &self.local_def_map,
self.db,
self.expander.module.local_id,
&name.clone().into(),
diff --git a/crates/hir-def/src/expr_store/tests.rs b/crates/hir-def/src/expr_store/tests.rs
index 16bf46d3e3..7bf27747c4 100644
--- a/crates/hir-def/src/expr_store/tests.rs
+++ b/crates/hir-def/src/expr_store/tests.rs
@@ -293,7 +293,7 @@ impl SsrError {
assert_eq!(db.body_with_source_map(def).1.diagnostics(), &[]);
expect![[r#"
fn main() -> () {
- _ = $crate::error::SsrError::new(
+ _ = ra_test_fixture::error::SsrError::new(
builtin#lang(Arguments::new_v1_formatted)(
&[
"Failed to resolve path `", "`",
@@ -353,7 +353,7 @@ fn f(a: i32, b: u32) -> String {
expect![[r#"
fn f(a: i32, b: u32) -> String {
{
- $crate::panicking::panic_fmt(
+ core::panicking::panic_fmt(
builtin#lang(Arguments::new_v1_formatted)(
&[
"cc",
diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs
index c30ad0163b..48f31698dd 100644
--- a/crates/hir-def/src/find_path.rs
+++ b/crates/hir-def/src/find_path.rs
@@ -2,7 +2,7 @@
use std::{cell::Cell, cmp::Ordering, iter};
-use base_db::{CrateId, CrateOrigin, LangCrateOrigin};
+use base_db::{Crate, CrateOrigin, LangCrateOrigin};
use hir_expand::{
name::{AsName, Name},
Lookup,
@@ -50,7 +50,7 @@ pub fn find_path(
prefix: prefix_kind,
cfg,
ignore_local_imports,
- is_std_item: db.crate_graph()[item_module.krate()].origin.is_lang(),
+ is_std_item: item_module.krate().data(db).origin.is_lang(),
from,
from_def_map: &from.def_map(db),
fuel: Cell::new(FIND_PATH_FUEL),
@@ -174,9 +174,9 @@ fn find_path_for_module(
}
// - otherwise if the item is the crate root of a dependency crate, return the name from the extern prelude
- let root_def_map = ctx.from.derive_crate_root().def_map(ctx.db);
+ let root_local_def_map = ctx.from.derive_crate_root().local_def_map(ctx.db).1;
// rev here so we prefer looking at renamed extern decls first
- for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude().rev() {
+ for (name, (def_id, _extern_crate)) in root_local_def_map.extern_prelude().rev() {
if crate_root != def_id {
continue;
}
@@ -360,7 +360,7 @@ fn calculate_best_path(
// too (unless we can't name it at all). It could *also* be (re)exported by the same crate
// that wants to import it here, but we always prefer to use the external path here.
- ctx.db.crate_graph()[ctx.from.krate].dependencies.iter().for_each(|dep| {
+ ctx.from.krate.data(ctx.db).dependencies.iter().for_each(|dep| {
find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id)
});
}
@@ -373,11 +373,10 @@ fn find_in_sysroot(
max_len: usize,
best_choice: &mut Option<Choice>,
) {
- let crate_graph = ctx.db.crate_graph();
- let dependencies = &crate_graph[ctx.from.krate].dependencies;
+ let dependencies = &ctx.from.krate.data(ctx.db).dependencies;
let mut search = |lang, best_choice: &mut _| {
if let Some(dep) = dependencies.iter().filter(|it| it.is_sysroot()).find(|dep| {
- match crate_graph[dep.crate_id].origin {
+ match dep.crate_id.data(ctx.db).origin {
CrateOrigin::Lang(l) => l == lang,
_ => false,
}
@@ -419,7 +418,7 @@ fn find_in_dep(
item: ItemInNs,
max_len: usize,
best_choice: &mut Option<Choice>,
- dep: CrateId,
+ dep: Crate,
) {
let import_map = ctx.db.import_map(dep);
let Some(import_info_for) = import_map.import_info_for(item) else {
@@ -688,9 +687,10 @@ mod tests {
})
.unwrap();
- let def_map = module.def_map(&db);
+ let (def_map, local_def_map) = module.local_def_map(&db);
let resolved = def_map
.resolve_path(
+ &local_def_map,
&db,
module.local_id,
&mod_path,
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index ed5038c5ae..6f1650adeb 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -24,7 +24,7 @@ use crate::{
expander::Expander,
item_tree::{AttrOwner, FileItemTreeId, GenericModItem, GenericsItemTreeNode, ItemTree},
lower::LowerCtx,
- nameres::{DefMap, MacroSubNs},
+ nameres::{DefMap, LocalDefMap, MacroSubNs},
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
type_ref::{
ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId,
@@ -314,8 +314,7 @@ impl GenericParams {
let _p = tracing::info_span!("generic_params_query").entered();
let krate = def.krate(db);
- let cfg_options = db.crate_graph();
- let cfg_options = &cfg_options[krate].cfg_options;
+ let cfg_options = &krate.cfg_options(db);
// Returns the generic parameters that are enabled under the current `#[cfg]` options
let enabled_params =
@@ -414,7 +413,12 @@ impl GenericParams {
&mut types_source_maps,
&mut expander,
&mut || {
- (module.def_map(db), Expander::new(db, loc.id.file_id(), module))
+ let (def_map, local_def_map) = module.local_def_map(db);
+ (
+ def_map,
+ local_def_map,
+ Expander::new(db, loc.id.file_id(), module),
+ )
},
param,
&item.types_map,
@@ -638,8 +642,8 @@ impl GenericParamsCollector {
generics_types_map: &mut TypesMap,
generics_types_source_map: &mut TypesSourceMap,
// FIXME: Change this back to `LazyCell` if https://github.com/rust-lang/libs-team/issues/429 is accepted.
- exp: &mut Option<(Arc<DefMap>, Expander)>,
- exp_fill: &mut dyn FnMut() -> (Arc<DefMap>, Expander),
+ exp: &mut Option<(Arc<DefMap>, Arc<LocalDefMap>, Expander)>,
+ exp_fill: &mut dyn FnMut() -> (Arc<DefMap>, Arc<LocalDefMap>, Expander),
type_ref: TypeRefId,
types_map: &TypesMap,
types_source_map: &TypesSourceMap,
@@ -669,12 +673,13 @@ impl GenericParamsCollector {
if let TypeRef::Macro(mc) = type_ref {
let macro_call = mc.to_node(db.upcast());
- let (def_map, expander) = exp.get_or_insert_with(&mut *exp_fill);
+ let (def_map, local_def_map, expander) = exp.get_or_insert_with(&mut *exp_fill);
let module = expander.module.local_id;
let resolver = |path: &_| {
def_map
.resolve_path(
+ local_def_map,
db,
module,
path,
@@ -702,7 +707,7 @@ impl GenericParamsCollector {
&macro_types_map,
&macro_types_source_map,
);
- exp.get_or_insert_with(&mut *exp_fill).1.exit(mark);
+ exp.get_or_insert_with(&mut *exp_fill).2.exit(mark);
}
}
});
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index 64c1d0d274..1cdc4c0259 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -2,7 +2,7 @@
use std::fmt;
-use base_db::CrateId;
+use base_db::Crate;
use fst::{raw::IndexedValue, Automaton, Streamer};
use hir_expand::name::Name;
use itertools::Itertools;
@@ -78,7 +78,7 @@ impl ImportMap {
out
}
- pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
+ pub(crate) fn import_map_query(db: &dyn DefDatabase, krate: Crate) -> Arc<Self> {
let _p = tracing::info_span!("import_map_query").entered();
let map = Self::collect_import_map(db, krate);
@@ -129,7 +129,7 @@ impl ImportMap {
self.item_to_info_map.get(&item).map(|(info, _)| &**info)
}
- fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMapIndex {
+ fn collect_import_map(db: &dyn DefDatabase, krate: Crate) -> ImportMapIndex {
let _p = tracing::info_span!("collect_import_map").entered();
let def_map = db.crate_def_map(krate);
@@ -400,15 +400,13 @@ impl Query {
/// This returns a list of items that could be imported from dependencies of `krate`.
pub fn search_dependencies(
db: &dyn DefDatabase,
- krate: CrateId,
+ krate: Crate,
query: &Query,
) -> FxHashSet<ItemInNs> {
let _p = tracing::info_span!("search_dependencies", ?query).entered();
- let graph = db.crate_graph();
-
let import_maps: Vec<_> =
- graph[krate].dependencies.iter().map(|dep| db.import_map(dep.crate_id)).collect();
+ krate.data(db).dependencies.iter().map(|dep| db.import_map(dep.crate_id)).collect();
let mut op = fst::map::OpBuilder::new();
@@ -512,11 +510,13 @@ mod tests {
expect: Expect,
) {
let db = TestDB::with_files(ra_fixture);
- let crate_graph = db.crate_graph();
- let krate = crate_graph
+ let all_crates = db.all_crates();
+ let krate = all_crates
.iter()
+ .copied()
.find(|&krate| {
- crate_graph[krate]
+ krate
+ .extra_data(&db)
.display_name
.as_ref()
.is_some_and(|it| it.crate_name().as_str() == crate_name)
@@ -545,7 +545,7 @@ mod tests {
Some(format!(
"{}::{} ({})\n",
- crate_graph[dependency_krate].display_name.as_ref()?,
+ dependency_krate.extra_data(&db).display_name.as_ref()?,
path,
mark
))
@@ -590,12 +590,13 @@ mod tests {
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
let db = TestDB::with_files(ra_fixture);
- let crate_graph = db.crate_graph();
+ let all_crates = db.all_crates();
- let actual = crate_graph
+ let actual = all_crates
.iter()
+ .copied()
.filter_map(|krate| {
- let cdata = &crate_graph[krate];
+ let cdata = &krate.extra_data(&db);
let name = cdata.display_name.as_ref()?;
let map = db.import_map(krate);
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 0ca1eb9bcf..0c683f3531 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -3,7 +3,7 @@
use std::sync::LazyLock;
-use base_db::CrateId;
+use base_db::Crate;
use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId};
use indexmap::map::Entry;
use itertools::Itertools;
@@ -916,7 +916,7 @@ impl ItemInNs {
}
/// Returns the crate defining this item (or `None` if `self` is built-in).
- pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> {
+ pub fn krate(&self, db: &dyn DefDatabase) -> Option<Crate> {
match self {
ItemInNs::Types(id) | ItemInNs::Values(id) => id.module(db).map(|m| m.krate),
ItemInNs::Macros(id) => Some(id.module(db).krate),
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 382afbcb1d..9acf98e62c 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -44,7 +44,7 @@ use std::{
};
use ast::{AstNode, StructKind};
-use base_db::CrateId;
+use base_db::Crate;
use either::Either;
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
use intern::{Interned, Symbol};
@@ -202,7 +202,7 @@ impl ItemTree {
}
/// Returns the inner attributes of the source file.
- pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
+ pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: Crate) -> Attrs {
Attrs::filter(
db,
krate,
@@ -214,7 +214,7 @@ impl ItemTree {
self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY)
}
- pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
+ pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: Crate, of: AttrOwner) -> Attrs {
Attrs::filter(db, krate, self.raw_attrs(of).clone())
}
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index 59f51db9f7..70c28009f4 100644
--- a/crates/hir-def/src/lang_item.rs
+++ b/crates/hir-def/src/lang_item.rs
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
use triomphe::Arc;
use crate::{
- db::DefDatabase, path::Path, AdtId, AssocItemId, AttrDefId, CrateId, EnumId, EnumVariantId,
+ db::DefDatabase, path::Path, AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId,
FunctionId, ImplId, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
};
@@ -96,7 +96,7 @@ impl LangItems {
/// Salsa query. This will look for lang items in a specific crate.
pub(crate) fn crate_lang_items_query(
db: &dyn DefDatabase,
- krate: CrateId,
+ krate: Crate,
) -> Option<Arc<LangItems>> {
let _p = tracing::info_span!("crate_lang_items_query").entered();
@@ -175,7 +175,7 @@ impl LangItems {
/// traversing its dependencies.
pub(crate) fn lang_item_query(
db: &dyn DefDatabase,
- start_crate: CrateId,
+ start_crate: Crate,
item: LangItem,
) -> Option<LangItemTarget> {
let _p = tracing::info_span!("lang_item_query").entered();
@@ -184,10 +184,7 @@ impl LangItems {
{
return Some(target);
}
- db.crate_graph()[start_crate]
- .dependencies
- .iter()
- .find_map(|dep| db.lang_item(dep.crate_id, item))
+ start_crate.data(db).dependencies.iter().find_map(|dep| db.lang_item(dep.crate_id, item))
}
fn collect_lang_item<T>(
@@ -209,19 +206,14 @@ pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option<LangIte
db.attrs(item).lang_item()
}
-pub(crate) fn notable_traits_in_deps(
- db: &dyn DefDatabase,
- krate: CrateId,
-) -> Arc<[Arc<[TraitId]>]> {
+pub(crate) fn notable_traits_in_deps(db: &dyn DefDatabase, krate: Crate) -> Arc<[Arc<[TraitId]>]> {
let _p = tracing::info_span!("notable_traits_in_deps", ?krate).entered();
- let crate_graph = db.crate_graph();
-
Arc::from_iter(
- crate_graph.transitive_deps(krate).filter_map(|krate| db.crate_notable_traits(krate)),
+ db.transitive_deps(krate).into_iter().filter_map(|krate| db.crate_notable_traits(krate)),
)
}
-pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: CrateId) -> Option<Arc<[TraitId]>> {
+pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option<Arc<[TraitId]>> {
let _p = tracing::info_span!("crate_notable_traits", ?krate).entered();
let mut traits = Vec::new();
@@ -290,17 +282,12 @@ impl LangItem {
Self::from_symbol(name.symbol())
}
- pub fn path(&self, db: &dyn DefDatabase, start_crate: CrateId) -> Option<Path> {
+ pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option<Path> {
let t = db.lang_item(start_crate, *self)?;
Some(Path::LangItem(t, None))
}
- pub fn ty_rel_path(
- &self,
- db: &dyn DefDatabase,
- start_crate: CrateId,
- seg: Name,
- ) -> Option<Path> {
+ pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option<Path> {
let t = db.lang_item(start_crate, *self)?;
Some(Path::LangItem(t, Some(seg)))
}
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 15ef8364ed..fbbeb4beb9 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -71,7 +71,7 @@ mod test_db;
use std::hash::{Hash, Hasher};
-use base_db::{impl_intern_key, CrateId};
+use base_db::{impl_intern_key, Crate};
use hir_expand::{
builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
db::ExpandDatabase,
@@ -99,10 +99,10 @@ use crate::{
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
},
+ nameres::LocalDefMap,
};
-type FxIndexMap<K, V> =
- indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
+type FxIndexMap<K, V> = indexmap::IndexMap<K, V, rustc_hash::FxBuildHasher>;
/// A wrapper around three booleans
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub struct ImportPathConfig {
@@ -338,7 +338,7 @@ pub struct ConstBlockLoc {
/// A `ModuleId` that is always a crate's root module.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CrateRootModuleId {
- krate: CrateId,
+ krate: Crate,
}
impl CrateRootModuleId {
@@ -346,7 +346,11 @@ impl CrateRootModuleId {
db.crate_def_map(self.krate)
}
- pub fn krate(self) -> CrateId {
+ pub(crate) fn local_def_map(&self, db: &dyn DefDatabase) -> (Arc<DefMap>, Arc<LocalDefMap>) {
+ db.crate_local_def_map(self.krate)
+ }
+
+ pub fn krate(self) -> Crate {
self.krate
}
}
@@ -374,8 +378,8 @@ impl From<CrateRootModuleId> for ModuleDefId {
}
}
-impl From<CrateId> for CrateRootModuleId {
- fn from(krate: CrateId) -> Self {
+impl From<Crate> for CrateRootModuleId {
+ fn from(krate: Crate) -> Self {
CrateRootModuleId { krate }
}
}
@@ -394,7 +398,7 @@ impl TryFrom<ModuleId> for CrateRootModuleId {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ModuleId {
- krate: CrateId,
+ krate: Crate,
/// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the
/// `BlockId` of that block expression. If `None`, this module is part of the crate-level
/// `DefMap` of `krate`.
@@ -411,11 +415,22 @@ impl ModuleId {
}
}
+ pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (Arc<DefMap>, Arc<LocalDefMap>) {
+ match self.block {
+ Some(block) => (db.block_def_map(block), self.only_local_def_map(db)),
+ None => db.crate_local_def_map(self.krate),
+ }
+ }
+
+ pub(crate) fn only_local_def_map(self, db: &dyn DefDatabase) -> Arc<LocalDefMap> {
+ db.crate_local_def_map(self.krate).1
+ }
+
pub fn crate_def_map(self, db: &dyn DefDatabase) -> Arc<DefMap> {
db.crate_def_map(self.krate)
}
- pub fn krate(self) -> CrateId {
+ pub fn krate(self) -> Crate {
self.krate
}
@@ -982,7 +997,7 @@ impl From<CallableDefId> for ModuleDefId {
}
impl CallableDefId {
- pub fn krate(self, db: &dyn DefDatabase) -> CrateId {
+ pub fn krate(self, db: &dyn DefDatabase) -> Crate {
match self {
CallableDefId::FunctionId(f) => f.krate(db),
CallableDefId::StructId(s) => s.krate(db),
@@ -1119,7 +1134,7 @@ pub trait HasModule {
/// Returns the crate this thing is defined within.
#[inline]
#[doc(alias = "crate")]
- fn krate(&self, db: &dyn DefDatabase) -> CrateId {
+ fn krate(&self, db: &dyn DefDatabase) -> Crate {
self.module(db).krate
}
}
@@ -1367,7 +1382,7 @@ pub trait AsMacroCall {
fn as_call_id(
&self,
db: &dyn ExpandDatabase,
- krate: CrateId,
+ krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Option<MacroCallId> {
self.as_call_id_with_errors(db, krate, resolver).ok()?.value
@@ -1376,7 +1391,7 @@ pub trait AsMacroCall {
fn as_call_id_with_errors(
&self,
db: &dyn ExpandDatabase,
- krate: CrateId,
+ krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>;
}
@@ -1385,7 +1400,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
fn as_call_id_with_errors(
&self,
db: &dyn ExpandDatabase,
- krate: CrateId,
+ krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
@@ -1442,7 +1457,7 @@ fn macro_call_as_call_id(
call: &AstIdWithPath<ast::MacroCall>,
call_site: SyntaxContextId,
expand_to: ExpandTo,
- krate: CrateId,
+ krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<Option<MacroCallId>, UnresolvedMacro> {
macro_call_as_call_id_with_eager(
@@ -1464,7 +1479,7 @@ fn macro_call_as_call_id_with_eager(
path: &path::ModPath,
call_site: SyntaxContextId,
expand_to: ExpandTo,
- krate: CrateId,
+ krate: Crate,
resolver: impl FnOnce(&path::ModPath) -> Option<MacroDefId>,
eager_resolver: impl Fn(&path::ModPath) -> Option<MacroDefId>,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index d0678a4065..70b512c014 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -376,4 +376,8 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
panic!("got invalid macro input: {:?}", parse.errors());
}
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 5b3d75c4ee..054c285fa2 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -59,7 +59,7 @@ mod tests;
use std::ops::Deref;
-use base_db::CrateId;
+use base_db::Crate;
use hir_expand::{
name::Name, proc_macro::ProcMacroKind, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId,
};
@@ -69,7 +69,7 @@ use la_arena::Arena;
use rustc_hash::{FxHashMap, FxHashSet};
use span::{Edition, EditionedFileId, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID};
use stdx::format_to;
-use syntax::{ast, AstNode, SmolStr, SyntaxNode};
+use syntax::{ast, AstNode, SmolStr, SyntaxNode, ToSmolStr};
use triomphe::Arc;
use tt::TextRange;
@@ -95,6 +95,39 @@ const PREDEFINED_TOOLS: &[SmolStr] = &[
SmolStr::new_static("rust_analyzer"),
];
+/// Parts of the def map that are only needed when analyzing code in the same crate.
+///
+/// There are some data in the def map (e.g. extern prelude) that is only needed when analyzing
+/// things in the same crate (and maybe in the IDE layer), e.g. the extern prelude. If we put
+/// it in the DefMap dependant DefMaps will be invalidated when they change (e.g. when we add
+/// a dependency to the crate). Instead we split them out of the DefMap into a LocalDefMap struct.
+/// `crate_local_def_map()` returns both, and `crate_def_map()` returns only the external-relevant
+/// DefMap.
+#[derive(Debug, PartialEq, Eq, Default)]
+pub struct LocalDefMap {
+ // FIXME: There are probably some other things that could be here, but this is less severe and you
+ // need to be careful with things that block def maps also have.
+ /// The extern prelude which contains all root modules of external crates that are in scope.
+ extern_prelude: FxIndexMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
+}
+
+impl LocalDefMap {
+ pub(crate) const EMPTY: &Self =
+ &Self { extern_prelude: FxIndexMap::with_hasher(rustc_hash::FxBuildHasher) };
+
+ fn shrink_to_fit(&mut self) {
+ let Self { extern_prelude } = self;
+ extern_prelude.shrink_to_fit();
+ }
+
+ pub(crate) fn extern_prelude(
+ &self,
+ ) -> impl DoubleEndedIterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_
+ {
+ self.extern_prelude.iter().map(|(name, &def)| (name, def))
+ }
+}
+
/// Contains the results of (early) name resolution.
///
/// A `DefMap` stores the module tree and the definitions that are in scope in every module after
@@ -107,7 +140,7 @@ const PREDEFINED_TOOLS: &[SmolStr] = &[
#[derive(Debug, PartialEq, Eq)]
pub struct DefMap {
/// The crate this `DefMap` belongs to.
- krate: CrateId,
+ krate: Crate,
/// When this is a block def map, this will hold the block id of the block and module that
/// contains this block.
block: Option<BlockInfo>,
@@ -141,9 +174,6 @@ pub struct DefMap {
/// Data that belongs to a crate which is shared between a crate's def map and all its block def maps.
#[derive(Clone, Debug, PartialEq, Eq)]
struct DefMapCrateData {
- /// The extern prelude which contains all root modules of external crates that are in scope.
- extern_prelude: FxIndexMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
-
/// Side table for resolving derive helpers.
exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
fn_proc_macro_mapping: FxHashMap<FunctionId, ProcMacroId>,
@@ -166,7 +196,6 @@ struct DefMapCrateData {
impl DefMapCrateData {
fn new(edition: Edition) -> Self {
Self {
- extern_prelude: FxIndexMap::default(),
exported_derives: FxHashMap::default(),
fn_proc_macro_mapping: FxHashMap::default(),
registered_attrs: Vec::new(),
@@ -182,7 +211,6 @@ impl DefMapCrateData {
fn shrink_to_fit(&mut self) {
let Self {
- extern_prelude,
exported_derives,
fn_proc_macro_mapping,
registered_attrs,
@@ -194,7 +222,6 @@ impl DefMapCrateData {
edition: _,
recursion_limit: _,
} = self;
- extern_prelude.shrink_to_fit();
exported_derives.shrink_to_fit();
fn_proc_macro_mapping.shrink_to_fit();
registered_attrs.shrink_to_fit();
@@ -219,11 +246,11 @@ struct BlockRelativeModuleId {
}
impl BlockRelativeModuleId {
- fn def_map(self, db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
+ fn def_map(self, db: &dyn DefDatabase, krate: Crate) -> Arc<DefMap> {
self.into_module(krate).def_map(db)
}
- fn into_module(self, krate: CrateId) -> ModuleId {
+ fn into_module(self, krate: Crate) -> ModuleId {
ModuleId { krate, block: self.block, local_id: self.local_id }
}
@@ -337,11 +364,25 @@ impl DefMap {
self.data.edition
}
- pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc<DefMap> {
- let crate_graph = db.crate_graph();
- let krate = &crate_graph[crate_id];
- let name = krate.display_name.as_deref().map(Symbol::as_str).unwrap_or_default();
- let _p = tracing::info_span!("crate_def_map_query", ?name).entered();
+ pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: Crate) -> Arc<DefMap> {
+ db.crate_local_def_map(crate_id).0
+ }
+
+ pub(crate) fn crate_local_def_map_query(
+ db: &dyn DefDatabase,
+ crate_id: Crate,
+ ) -> (Arc<DefMap>, Arc<LocalDefMap>) {
+ let krate = crate_id.data(db);
+ let _p = tracing::info_span!(
+ "crate_def_map_query",
+ name=?crate_id
+ .extra_data(db)
+ .display_name
+ .as_ref()
+ .map(|it| it.crate_name().to_smolstr())
+ .unwrap_or_default()
+ )
+ .entered();
let module_data = ModuleData::new(
ModuleOrigin::CrateRoot { definition: krate.root_file_id() },
@@ -354,10 +395,14 @@ impl DefMap {
module_data,
None,
);
- let def_map =
- collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id().into(), None));
+ let (def_map, local_def_map) = collector::collect_defs(
+ db,
+ def_map,
+ TreeId::new(krate.root_file_id().into(), None),
+ None,
+ );
- Arc::new(def_map)
+ (Arc::new(def_map), Arc::new(local_def_map))
}
pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
@@ -370,10 +415,10 @@ impl DefMap {
let module_data =
ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
- let parent_map = module.def_map(db);
+ let (crate_map, crate_local_map) = db.crate_local_def_map(module.krate);
let def_map = DefMap::empty(
module.krate,
- parent_map.data.clone(),
+ crate_map.data.clone(),
module_data,
Some(BlockInfo {
block: block_id,
@@ -381,13 +426,17 @@ impl DefMap {
}),
);
- let def_map =
- collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id)));
+ let (def_map, _) = collector::collect_defs(
+ db,
+ def_map,
+ TreeId::new(ast_id.file_id, Some(block_id)),
+ Some(crate_local_map),
+ );
Arc::new(def_map)
}
fn empty(
- krate: CrateId,
+ krate: Crate,
crate_data: Arc<DefMapCrateData>,
module_data: ModuleData,
block: Option<BlockInfo>,
@@ -479,7 +528,7 @@ impl DefMap {
self.data.fn_proc_macro_mapping.get(&id).copied()
}
- pub fn krate(&self) -> CrateId {
+ pub fn krate(&self) -> Crate {
self.krate
}
@@ -590,19 +639,13 @@ impl DefMap {
self.prelude
}
- pub(crate) fn extern_prelude(
- &self,
- ) -> impl DoubleEndedIterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_
- {
- self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
- }
-
pub(crate) fn macro_use_prelude(&self) -> &FxHashMap<Name, (MacroId, Option<ExternCrateId>)> {
&self.macro_use_prelude
}
pub(crate) fn resolve_path(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
original_module: LocalModuleId,
path: &ModPath,
@@ -610,6 +653,7 @@ impl DefMap {
expected_macro_subns: Option<MacroSubNs>,
) -> (PerNs, Option<usize>) {
let res = self.resolve_path_fp_with_macro(
+ local_def_map,
db,
ResolveMode::Other,
original_module,
@@ -624,12 +668,14 @@ impl DefMap {
/// points at the unresolved segments.
pub(crate) fn resolve_path_locally(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
original_module: LocalModuleId,
path: &ModPath,
shadow: BuiltinShadowMode,
) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
let res = self.resolve_path_fp_with_macro_single(
+ local_def_map,
db,
ResolveMode::Other,
original_module,
diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs
index d1f6ed023c..289b9e2fb7 100644
--- a/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/crates/hir-def/src/nameres/attr_resolution.rs
@@ -1,6 +1,6 @@
//! Post-nameres attribute resolution.
-use base_db::CrateId;
+use base_db::Crate;
use hir_expand::{
attrs::{Attr, AttrId, AttrInput},
inert_attr_macro::find_builtin_attr_idx,
@@ -13,7 +13,7 @@ use triomphe::Arc;
use crate::{
db::DefDatabase,
item_scope::BuiltinShadowMode,
- nameres::path_resolution::ResolveMode,
+ nameres::{path_resolution::ResolveMode, LocalDefMap},
path::{self, ModPath, PathKind},
AstIdWithPath, LocalModuleId, MacroId, UnresolvedMacro,
};
@@ -30,6 +30,7 @@ pub enum ResolvedAttr {
impl DefMap {
pub(crate) fn resolve_attr_macro(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
original_module: LocalModuleId,
ast_id: AstIdWithPath<ast::Item>,
@@ -42,6 +43,7 @@ impl DefMap {
}
let resolved_res = self.resolve_path_fp_with_macro(
+ local_def_map,
db,
ResolveMode::Other,
original_module,
@@ -105,7 +107,7 @@ pub(super) fn attr_macro_as_call_id(
db: &dyn DefDatabase,
item_attr: &AstIdWithPath<ast::Item>,
macro_attr: &Attr,
- krate: CrateId,
+ krate: Crate,
def: MacroDefId,
) -> MacroCallId {
let arg = match macro_attr.input.as_deref() {
@@ -136,7 +138,7 @@ pub(super) fn derive_macro_as_call_id(
derive_attr_index: AttrId,
derive_pos: u32,
call_site: SyntaxContextId,
- krate: CrateId,
+ krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<(MacroId, MacroDefId)>,
derive_macro_id: MacroCallId,
) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> {
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index bf013c25ef..371e994334 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -5,7 +5,7 @@
use std::{cmp::Ordering, iter, mem, ops::Not};
-use base_db::{CrateId, CrateOrigin, Dependency, LangCrateOrigin};
+use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin};
use cfg::{CfgAtom, CfgExpr, CfgOptions};
use either::Either;
use hir_expand::{
@@ -39,8 +39,8 @@ use crate::{
mod_resolution::ModDir,
path_resolution::ReachedFixedPoint,
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
- sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin,
- ResolveMode,
+ sub_namespace_match, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData,
+ ModuleOrigin, ResolveMode,
},
path::{ImportAlias, ModPath, PathKind},
per_ns::{Item, PerNs},
@@ -57,10 +57,14 @@ use crate::{
const GLOB_RECURSION_LIMIT: usize = 100;
const FIXED_POINT_LIMIT: usize = 8192;
-pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap {
- let crate_graph = db.crate_graph();
-
- let krate = &crate_graph[def_map.krate];
+pub(super) fn collect_defs(
+ db: &dyn DefDatabase,
+ def_map: DefMap,
+ tree_id: TreeId,
+ crate_local_def_map: Option<Arc<LocalDefMap>>,
+) -> (DefMap, LocalDefMap) {
+ let krate = &def_map.krate.data(db);
+ let cfg_options = def_map.krate.cfg_options(db);
// populate external prelude and dependency list
let mut deps =
@@ -72,8 +76,10 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
}
let proc_macros = if krate.is_proc_macro {
- db.proc_macros()
- .for_crate(def_map.krate, db.syntax_context(tree_id.file_id(), krate.edition))
+ db.proc_macros_for_crate(def_map.krate)
+ .and_then(|proc_macros| {
+ proc_macros.list(db.syntax_context(tree_id.file_id(), krate.edition))
+ })
.unwrap_or_default()
} else {
Default::default()
@@ -82,13 +88,15 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
let mut collector = DefCollector {
db,
def_map,
+ local_def_map: LocalDefMap::default(),
+ crate_local_def_map,
deps,
glob_imports: FxHashMap::default(),
unresolved_imports: Vec::new(),
indeterminate_imports: Vec::new(),
unresolved_macros: Vec::new(),
mod_dirs: FxHashMap::default(),
- cfg_options: &krate.cfg_options,
+ cfg_options,
proc_macros,
from_glob_import: Default::default(),
skip_attrs: Default::default(),
@@ -101,9 +109,10 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
collector.seed_with_top_level();
}
collector.collect();
- let mut def_map = collector.finish();
+ let (mut def_map, mut local_def_map) = collector.finish();
def_map.shrink_to_fit();
- def_map
+ local_def_map.shrink_to_fit();
+ (def_map, local_def_map)
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -205,8 +214,11 @@ enum MacroDirectiveKind {
struct DefCollector<'a> {
db: &'a dyn DefDatabase,
def_map: DefMap,
+ local_def_map: LocalDefMap,
+ /// Set only in case of blocks.
+ crate_local_def_map: Option<Arc<LocalDefMap>>,
// The dependencies of the current crate, including optional deps like `test`.
- deps: FxHashMap<Name, Dependency>,
+ deps: FxHashMap<Name, BuiltDependency>,
glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
unresolved_imports: Vec<ImportDirective>,
indeterminate_imports: Vec<(ImportDirective, PerNs)>,
@@ -238,8 +250,7 @@ impl DefCollector<'_> {
fn seed_with_top_level(&mut self) {
let _p = tracing::info_span!("seed_with_top_level").entered();
- let crate_graph = self.db.crate_graph();
- let file_id = crate_graph[self.def_map.krate].root_file_id();
+ let file_id = self.def_map.krate.data(self.db).root_file_id();
let item_tree = self.db.file_item_tree(file_id.into());
let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
@@ -310,20 +321,24 @@ impl DefCollector<'_> {
// don't do pre-configured attribute resolution yet.
// So here check if we are no_core / no_std and we are trying to add the
// corresponding dep from the sysroot
- let skip = match crate_graph[dep.crate_id].origin {
- CrateOrigin::Lang(LangCrateOrigin::Core) => {
- crate_data.no_core && dep.is_sysroot()
- }
- CrateOrigin::Lang(LangCrateOrigin::Std) => {
- crate_data.no_std && dep.is_sysroot()
- }
- _ => false,
- };
+
+ // Depending on the crate data of a dependency seems bad for incrementality, but
+ // we only do that for sysroot crates (this is why the order of the `&&` is important)
+ // - which are normally standard library crate, which realistically aren't going
+ // to have their crate ID invalidated, because they stay on the same root file and
+ // they're dependencies of everything else, so if some collision miraculously occurs
+ // we will resolve it by disambiguating the other crate.
+ let skip = dep.is_sysroot()
+ && match dep.crate_id.data(self.db).origin {
+ CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core,
+ CrateOrigin::Lang(LangCrateOrigin::Std) => crate_data.no_std,
+ _ => false,
+ };
if skip {
continue;
}
- crate_data
+ self.local_def_map
.extern_prelude
.insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None));
}
@@ -494,7 +509,7 @@ impl DefCollector<'_> {
let krate = if self.def_map.data.no_std {
Name::new_symbol_root(sym::core.clone())
- } else if self.def_map.extern_prelude().any(|(name, _)| *name == sym::std.clone()) {
+ } else if self.local_def_map().extern_prelude().any(|(name, _)| *name == sym::std.clone()) {
Name::new_symbol_root(sym::std.clone())
} else {
// If `std` does not exist for some reason, fall back to core. This mostly helps
@@ -518,8 +533,14 @@ impl DefCollector<'_> {
[krate, Name::new_symbol_root(sym::prelude.clone()), edition],
);
- let (per_ns, _) =
- self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None);
+ let (per_ns, _) = self.def_map.resolve_path(
+ self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
+ self.db,
+ DefMap::ROOT,
+ &path,
+ BuiltinShadowMode::Other,
+ None,
+ );
match per_ns.types {
Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => {
@@ -535,6 +556,10 @@ impl DefCollector<'_> {
}
}
+ fn local_def_map(&mut self) -> &LocalDefMap {
+ self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map)
+ }
+
/// Adds a definition of procedural macro `name` to the root module.
///
/// # Notes on procedural macro resolution
@@ -660,7 +685,13 @@ impl DefCollector<'_> {
) {
let vis = self
.def_map
- .resolve_visibility(self.db, module_id, vis, false)
+ .resolve_visibility(
+ self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
+ self.db,
+ module_id,
+ vis,
+ false,
+ )
.unwrap_or(Visibility::Public);
self.def_map.modules[module_id].scope.declare(macro_.into());
self.update(
@@ -694,7 +725,7 @@ impl DefCollector<'_> {
/// created by `use` in the root module, ignoring the visibility of `use`.
fn import_macros_from_extern_crate(
&mut self,
- krate: CrateId,
+ krate: Crate,
names: Option<Vec<Name>>,
extern_crate: Option<ExternCrateId>,
) {
@@ -779,6 +810,7 @@ impl DefCollector<'_> {
.entered();
tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
let res = self.def_map.resolve_path_fp_with_macro(
+ self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
self.db,
ResolveMode::Import,
module_id,
@@ -814,7 +846,13 @@ impl DefCollector<'_> {
let mut def = directive.status.namespaces();
let vis = self
.def_map
- .resolve_visibility(self.db, module_id, &directive.import.visibility, false)
+ .resolve_visibility(
+ self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
+ self.db,
+ module_id,
+ &directive.import.visibility,
+ false,
+ )
.unwrap_or(Visibility::Public);
match import.source {
@@ -1210,6 +1248,7 @@ impl DefCollector<'_> {
};
let resolver = |path: &_| {
let resolved_res = self.def_map.resolve_path_fp_with_macro(
+ self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
self.db,
ResolveMode::Other,
directive.module_id,
@@ -1495,7 +1534,7 @@ impl DefCollector<'_> {
.collect(item_tree.top_level_items(), container);
}
- fn finish(mut self) -> DefMap {
+ fn finish(mut self) -> (DefMap, LocalDefMap) {
// Emit diagnostics for all remaining unexpanded macros.
let _p = tracing::info_span!("DefCollector::finish").entered();
@@ -1511,6 +1550,7 @@ impl DefCollector<'_> {
self.def_map.krate,
|path| {
let resolved_res = self.def_map.resolve_path_fp_with_macro(
+ self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
self.db,
ResolveMode::Other,
directive.module_id,
@@ -1582,7 +1622,7 @@ impl DefCollector<'_> {
));
}
- self.def_map
+ (self.def_map, self.local_def_map)
}
}
@@ -1635,9 +1675,9 @@ impl ModCollector<'_, '_> {
None,
)
};
- let resolve_vis = |def_map: &DefMap, visibility| {
+ let resolve_vis = |def_map: &DefMap, local_def_map: &LocalDefMap, visibility| {
def_map
- .resolve_visibility(db, module_id, visibility, false)
+ .resolve_visibility(local_def_map, db, module_id, visibility, false)
.unwrap_or(Visibility::Public)
};
@@ -1658,6 +1698,11 @@ impl ModCollector<'_, '_> {
let module = self.def_collector.def_map.module_id(module_id);
let def_map = &mut self.def_collector.def_map;
+ let local_def_map = self
+ .def_collector
+ .crate_local_def_map
+ .as_deref()
+ .unwrap_or(&self.def_collector.local_def_map);
match item {
ModItem::Mod(m) => self.collect_module(m, &attrs),
@@ -1711,13 +1756,13 @@ impl ModCollector<'_, '_> {
};
if let Some(resolved) = resolved {
- let vis = resolve_vis(def_map, &self.item_tree[*visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[*visibility]);
if is_crate_root {
// extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
if let Some(name) = name {
- Arc::get_mut(&mut def_map.data)
- .unwrap()
+ self.def_collector
+ .local_def_map
.extern_prelude
.insert(name.clone(), (resolved, Some(id)));
}
@@ -1784,7 +1829,7 @@ impl ModCollector<'_, '_> {
let fn_id =
FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
if self.def_collector.def_map.block.is_none()
&& self.def_collector.is_proc_macro
@@ -1804,7 +1849,7 @@ impl ModCollector<'_, '_> {
ModItem::Struct(id) => {
let it = &self.item_tree[id];
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
update_def(
self.def_collector,
StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@@ -1818,7 +1863,7 @@ impl ModCollector<'_, '_> {
ModItem::Union(id) => {
let it = &self.item_tree[id];
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
update_def(
self.def_collector,
UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@@ -1835,7 +1880,7 @@ impl ModCollector<'_, '_> {
EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
.intern(db);
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
update_def(self.def_collector, enum_.into(), &it.name, vis, false);
let mut index = 0;
@@ -1878,7 +1923,8 @@ impl ModCollector<'_, '_> {
match &it.name {
Some(name) => {
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis =
+ resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
update_def(self.def_collector, const_id.into(), name, vis, false);
}
None => {
@@ -1892,7 +1938,7 @@ impl ModCollector<'_, '_> {
ModItem::Static(id) => {
let it = &self.item_tree[id];
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
update_def(
self.def_collector,
StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
@@ -1906,7 +1952,7 @@ impl ModCollector<'_, '_> {
ModItem::Trait(id) => {
let it = &self.item_tree[id];
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
update_def(
self.def_collector,
TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@@ -1920,7 +1966,7 @@ impl ModCollector<'_, '_> {
ModItem::TraitAlias(id) => {
let it = &self.item_tree[id];
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
update_def(
self.def_collector,
TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@@ -1934,7 +1980,7 @@ impl ModCollector<'_, '_> {
ModItem::TypeAlias(id) => {
let it = &self.item_tree[id];
- let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
+ let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
update_def(
self.def_collector,
TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
@@ -1971,7 +2017,7 @@ impl ModCollector<'_, '_> {
&mut self,
extern_crate_id: ExternCrateId,
macro_use_attrs: impl Iterator<Item = &'a Attr>,
- target_crate: CrateId,
+ target_crate: Crate,
) {
cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
let mut single_imports = Vec::new();
@@ -2115,7 +2161,16 @@ impl ModCollector<'_, '_> {
) -> LocalModuleId {
let def_map = &mut self.def_collector.def_map;
let vis = def_map
- .resolve_visibility(self.def_collector.db, self.module_id, visibility, false)
+ .resolve_visibility(
+ self.def_collector
+ .crate_local_def_map
+ .as_deref()
+ .unwrap_or(&self.def_collector.local_def_map),
+ self.def_collector.db,
+ self.module_id,
+ visibility,
+ false,
+ )
.unwrap_or(Visibility::Public);
let origin = match definition {
None => ModuleOrigin::Inline {
@@ -2417,6 +2472,10 @@ impl ModCollector<'_, '_> {
},
|path| {
let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro(
+ self.def_collector
+ .crate_local_def_map
+ .as_deref()
+ .unwrap_or(&self.def_collector.local_def_map),
db,
ResolveMode::Other,
self.module_id,
@@ -2517,7 +2576,6 @@ impl ModCollector<'_, '_> {
#[cfg(test)]
mod tests {
- use base_db::RootQueryDb;
use test_fixture::WithFixture;
use crate::{nameres::DefMapCrateData, test_db::TestDB};
@@ -2528,6 +2586,8 @@ mod tests {
let mut collector = DefCollector {
db,
def_map,
+ local_def_map: LocalDefMap::default(),
+ crate_local_def_map: None,
deps: FxHashMap::default(),
glob_imports: FxHashMap::default(),
unresolved_imports: Vec::new(),
@@ -2550,7 +2610,7 @@ mod tests {
let (db, file_id) = TestDB::with_single_file(not_ra_fixture);
let krate = db.test_crate();
- let edition = db.crate_graph()[krate].edition;
+ let edition = krate.data(&db).edition;
let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
let def_map = DefMap::empty(
krate,
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index 47c08d3d1d..977bc16adf 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -19,7 +19,7 @@ use crate::{
db::DefDatabase,
item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
item_tree::FieldsShape,
- nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
+ nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs},
path::{ModPath, PathKind},
per_ns::PerNs,
visibility::{RawVisibility, Visibility},
@@ -91,6 +91,7 @@ impl PerNs {
impl DefMap {
pub(crate) fn resolve_visibility(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
// module to import to
original_module: LocalModuleId,
@@ -101,8 +102,14 @@ impl DefMap {
) -> Option<Visibility> {
let mut vis = match visibility {
RawVisibility::Module(path, explicitness) => {
- let (result, remaining) =
- self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None);
+ let (result, remaining) = self.resolve_path(
+ local_def_map,
+ db,
+ original_module,
+ path,
+ BuiltinShadowMode::Module,
+ None,
+ );
if remaining.is_some() {
return None;
}
@@ -137,6 +144,7 @@ impl DefMap {
// the result.
pub(super) fn resolve_path_fp_with_macro(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
mode: ResolveMode,
// module to import to
@@ -148,6 +156,7 @@ impl DefMap {
expected_macro_subns: Option<MacroSubNs>,
) -> ResolvePathResult {
let mut result = self.resolve_path_fp_with_macro_single(
+ local_def_map,
db,
mode,
original_module,
@@ -196,6 +205,7 @@ impl DefMap {
current_map = &arc;
let new = current_map.resolve_path_fp_in_all_preludes(
+ local_def_map,
db,
mode,
original_module,
@@ -210,6 +220,7 @@ impl DefMap {
}
let new = current_map.resolve_path_fp_with_macro_single(
+ local_def_map,
db,
mode,
original_module,
@@ -224,6 +235,7 @@ impl DefMap {
pub(super) fn resolve_path_fp_with_macro_single(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
mode: ResolveMode,
original_module: LocalModuleId,
@@ -258,7 +270,12 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
};
tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
- self.resolve_name_in_crate_root_or_extern_prelude(db, original_module, segment)
+ self.resolve_name_in_crate_root_or_extern_prelude(
+ local_def_map,
+ db,
+ original_module,
+ segment,
+ )
}
PathKind::Plain => {
let (_, segment) = match segments.next() {
@@ -276,6 +293,7 @@ impl DefMap {
tracing::debug!("resolving {:?} in module", segment);
self.resolve_name_in_module(
+ local_def_map,
db,
original_module,
segment,
@@ -321,7 +339,9 @@ impl DefMap {
// with), resolve the remaining path segments in that `DefMap`.
let path =
ModPath::from_segments(PathKind::SELF, path.segments().iter().cloned());
+ // This is the same crate, so the local def map is the same.
return def_map.resolve_path_fp_with_macro(
+ local_def_map,
db,
mode,
local_id,
@@ -333,7 +353,7 @@ impl DefMap {
PerNs::types(module.into(), Visibility::Public, None)
}
- PathKind::Abs => match self.resolve_path_abs(&mut segments, path) {
+ PathKind::Abs => match self.resolve_path_abs(local_def_map, &mut segments, path) {
Either::Left(it) => it,
Either::Right(reached_fixed_point) => {
return ResolvePathResult::empty(reached_fixed_point)
@@ -347,6 +367,7 @@ impl DefMap {
/// Resolves a path only in the preludes, without accounting for item scopes.
pub(super) fn resolve_path_fp_in_all_preludes(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
mode: ResolveMode,
original_module: LocalModuleId,
@@ -368,7 +389,7 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
};
tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
- self.resolve_name_in_extern_prelude(segment)
+ self.resolve_name_in_extern_prelude(local_def_map, segment)
}
PathKind::Plain => {
let (_, segment) = match segments.next() {
@@ -376,9 +397,9 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
};
tracing::debug!("resolving {:?} in module", segment);
- self.resolve_name_in_all_preludes(db, segment)
+ self.resolve_name_in_all_preludes(local_def_map, db, segment)
}
- PathKind::Abs => match self.resolve_path_abs(&mut segments, path) {
+ PathKind::Abs => match self.resolve_path_abs(local_def_map, &mut segments, path) {
Either::Left(it) => it,
Either::Right(reached_fixed_point) => {
return ResolvePathResult::empty(reached_fixed_point)
@@ -395,6 +416,7 @@ impl DefMap {
/// 2018-style absolute path -- only extern prelude
fn resolve_path_abs<'a>(
&self,
+ local_def_map: &LocalDefMap,
segments: &mut impl Iterator<Item = (usize, &'a Name)>,
path: &ModPath,
) -> Either<PerNs, ReachedFixedPoint> {
@@ -402,7 +424,7 @@ impl DefMap {
Some((_, segment)) => segment,
None => return Either::Right(ReachedFixedPoint::Yes),
};
- if let Some(&(def, extern_crate)) = self.data.extern_prelude.get(segment) {
+ if let Some(&(def, extern_crate)) = local_def_map.extern_prelude.get(segment) {
tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def);
Either::Left(PerNs::types(
def.into(),
@@ -451,6 +473,7 @@ impl DefMap {
// this point, we know we're resolving a multi-segment path so macro kind
// expectation is discarded.
let resolution = defp_map.resolve_path_fp_with_macro(
+ LocalDefMap::EMPTY,
db,
ResolveMode::Other,
module.local_id,
@@ -568,6 +591,7 @@ impl DefMap {
fn resolve_name_in_module(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
module: LocalModuleId,
name: &Name,
@@ -611,7 +635,7 @@ impl DefMap {
// they might been shadowed by local names.
return PerNs::none();
}
- self.resolve_name_in_extern_prelude(name)
+ self.resolve_name_in_extern_prelude(local_def_map, name)
};
let macro_use_prelude = || self.resolve_in_macro_use_prelude(name);
let prelude = || {
@@ -628,19 +652,24 @@ impl DefMap {
.or_else(prelude)
}
- fn resolve_name_in_all_preludes(&self, db: &dyn DefDatabase, name: &Name) -> PerNs {
+ fn resolve_name_in_all_preludes(
+ &self,
+ local_def_map: &LocalDefMap,
+ db: &dyn DefDatabase,
+ name: &Name,
+ ) -> PerNs {
// Resolve in:
// - extern prelude / macro_use prelude
// - std prelude
- let extern_prelude = self.resolve_name_in_extern_prelude(name);
+ let extern_prelude = self.resolve_name_in_extern_prelude(local_def_map, name);
let macro_use_prelude = || self.resolve_in_macro_use_prelude(name);
let prelude = || self.resolve_in_prelude(db, name);
extern_prelude.or_else(macro_use_prelude).or_else(prelude)
}
- fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
- self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
+ fn resolve_name_in_extern_prelude(&self, local_def_map: &LocalDefMap, name: &Name) -> PerNs {
+ local_def_map.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
PerNs::types(
it.into(),
Visibility::Public,
@@ -662,6 +691,7 @@ impl DefMap {
fn resolve_name_in_crate_root_or_extern_prelude(
&self,
+ local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
module: LocalModuleId,
name: &Name,
@@ -678,7 +708,7 @@ impl DefMap {
// Don't resolve extern prelude in pseudo-module of a block.
return PerNs::none();
}
- self.resolve_name_in_extern_prelude(name)
+ self.resolve_name_in_extern_prelude(local_def_map, name)
};
from_crate_root.or_else(from_extern_prelude)
diff --git a/crates/hir-def/src/nameres/tests/incremental.rs b/crates/hir-def/src/nameres/tests/incremental.rs
index cd59020576..9a601e0f01 100644
--- a/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/crates/hir-def/src/nameres/tests/incremental.rs
@@ -1,5 +1,11 @@
-use base_db::SourceDatabase;
+use base_db::{
+ CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData,
+ DependencyBuilder, Env, RootQueryDb, SourceDatabase,
+};
+use intern::Symbol;
+use span::Edition;
use test_fixture::WithFixture;
+use triomphe::Arc;
use crate::{db::DefDatabase, nameres::tests::TestDB, AdtId, ModuleDefId};
@@ -23,6 +29,73 @@ fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change:
}
#[test]
+fn crate_metadata_changes_should_not_invalidate_unrelated_def_maps() {
+ let (mut db, files) = TestDB::with_many_files(
+ r#"
+//- /a.rs crate:a
+pub fn foo() {}
+
+//- /b.rs crate:b
+pub struct Bar;
+
+//- /c.rs crate:c deps:b
+pub const BAZ: u32 = 0;
+ "#,
+ );
+
+ for &krate in db.all_crates().iter() {
+ db.crate_def_map(krate);
+ }
+
+ let all_crates_before = db.all_crates();
+
+ {
+ // Add a dependency a -> b.
+ let mut new_crate_graph = CrateGraphBuilder::default();
+ let mut add_crate = |crate_name, root_file_idx: usize| {
+ new_crate_graph.add_crate_root(
+ files[root_file_idx].file_id(),
+ Edition::CURRENT,
+ Some(CrateDisplayName::from_canonical_name(crate_name)),
+ None,
+ Arc::default(),
+ None,
+ Env::default(),
+ CrateOrigin::Local { repo: None, name: Some(Symbol::intern(crate_name)) },
+ false,
+ None,
+ Arc::new(CrateWorkspaceData { data_layout: Err("".into()), toolchain: None }),
+ )
+ };
+ let a = add_crate("a", 0);
+ let b = add_crate("b", 1);
+ let c = add_crate("c", 2);
+ new_crate_graph
+ .add_dep(c, DependencyBuilder::new(CrateName::new("b").unwrap(), b))
+ .unwrap();
+ new_crate_graph
+ .add_dep(b, DependencyBuilder::new(CrateName::new("a").unwrap(), a))
+ .unwrap();
+ new_crate_graph.set_in_db(&mut db);
+ }
+
+ let all_crates_after = db.all_crates();
+ assert!(
+ Arc::ptr_eq(&all_crates_before, &all_crates_after),
+ "the all_crates list should not have been invalidated"
+ );
+
+ let events = db.log_executed(|| {
+ for &krate in db.all_crates().iter() {
+ db.crate_def_map(krate);
+ }
+ });
+ let invalidated_def_maps =
+ events.iter().filter(|event| event.contains("crate_def_map")).count();
+ assert_eq!(invalidated_def_maps, 1, "{events:#?}")
+}
+
+#[test]
fn typing_inside_a_function_should_not_invalidate_def_map() {
check_def_map_is_not_recomputed(
r"
diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs
index 610886d55f..0348a7076a 100644
--- a/crates/hir-def/src/nameres/tests/macros.rs
+++ b/crates/hir-def/src/nameres/tests/macros.rs
@@ -1095,7 +1095,7 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
}
"#,
);
- let krate = db.crate_graph().iter().next().unwrap();
+ let krate = *db.all_crates().last().unwrap();
let def_map = db.crate_def_map(krate);
assert_eq!(def_map.data.exported_derives.len(), 1);
@@ -1445,7 +1445,7 @@ struct TokenStream;
fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
"#,
);
- let krate = db.crate_graph().iter().next().unwrap();
+ let krate = *db.all_crates().last().unwrap();
let def_map = db.crate_def_map(krate);
let root_module = &def_map[DefMap::ROOT].scope;
diff --git a/crates/hir-def/src/pretty.rs b/crates/hir-def/src/pretty.rs
index eb9488feaa..c431b45dc7 100644
--- a/crates/hir-def/src/pretty.rs
+++ b/crates/hir-def/src/pretty.rs
@@ -80,7 +80,16 @@ pub(crate) fn print_path(
}
PathKind::Crate => write!(buf, "crate")?,
PathKind::Abs => {}
- PathKind::DollarCrate(_) => write!(buf, "$crate")?,
+ PathKind::DollarCrate(krate) => write!(
+ buf,
+ "{}",
+ krate
+ .extra_data(db)
+ .display_name
+ .as_ref()
+ .map(|it| it.crate_name().symbol().as_str())
+ .unwrap_or("$crate")
+ )?,
},
}
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index f4773de085..72723499fc 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -1,7 +1,7 @@
//! Name resolution façade.
use std::{fmt, iter, mem};
-use base_db::CrateId;
+use base_db::Crate;
use hir_expand::{name::Name, MacroDefId};
use intern::{sym, Symbol};
use itertools::Itertools as _;
@@ -22,7 +22,7 @@ use crate::{
hir::{BindingId, ExprId, LabelId},
item_scope::{BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, BUILTIN_SCOPE},
lang_item::LangItemTarget,
- nameres::{DefMap, MacroSubNs, ResolvePathResultPrefixInfo},
+ nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo},
path::{ModPath, Path, PathKind},
per_ns::PerNs,
type_ref::{LifetimeRef, TypesMap},
@@ -47,6 +47,7 @@ pub struct Resolver {
#[derive(Clone)]
struct ModuleItemMap {
def_map: Arc<DefMap>,
+ local_def_map: Arc<LocalDefMap>,
module_id: LocalModuleId,
}
@@ -278,8 +279,8 @@ impl Resolver {
let within_impl = self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_)));
match visibility {
RawVisibility::Module(_, _) => {
- let (item_map, module) = self.item_scope();
- item_map.resolve_visibility(db, module, visibility, within_impl)
+ let (item_map, item_local_map, module) = self.item_scope();
+ item_map.resolve_visibility(item_local_map, db, module, visibility, within_impl)
}
RawVisibility::Public => Some(Visibility::Public),
}
@@ -474,9 +475,16 @@ impl Resolver {
path: &ModPath,
expected_macro_kind: Option<MacroSubNs>,
) -> Option<(MacroId, Option<ImportOrGlob>)> {
- let (item_map, module) = self.item_scope();
+ let (item_map, item_local_map, module) = self.item_scope();
item_map
- .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind)
+ .resolve_path(
+ item_local_map,
+ db,
+ module,
+ path,
+ BuiltinShadowMode::Other,
+ expected_macro_kind,
+ )
.0
.take_macros_import()
}
@@ -550,7 +558,7 @@ impl Resolver {
for scope in self.scopes() {
scope.process_names(&mut res, db);
}
- let ModuleItemMap { ref def_map, module_id } = self.module_scope;
+ let ModuleItemMap { ref def_map, module_id, ref local_def_map } = self.module_scope;
// FIXME: should we provide `self` here?
// f(
// Name::self_param(),
@@ -572,7 +580,7 @@ impl Resolver {
res.add(name, ScopeDef::ModuleDef(def.into()));
},
);
- def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| {
+ local_def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| {
res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into())));
});
BUILTIN_SCOPE.iter().for_each(|(name, &def)| {
@@ -599,7 +607,7 @@ impl Resolver {
pub fn extern_crates_in_scope(&self) -> impl Iterator<Item = (Name, ModuleId)> + '_ {
self.module_scope
- .def_map
+ .local_def_map
.extern_prelude()
.map(|(name, module_id)| (name.clone(), module_id.0.into()))
}
@@ -647,11 +655,11 @@ impl Resolver {
}
pub fn module(&self) -> ModuleId {
- let (def_map, local_id) = self.item_scope();
+ let (def_map, _, local_id) = self.item_scope();
def_map.module_id(local_id)
}
- pub fn krate(&self) -> CrateId {
+ pub fn krate(&self) -> Crate {
self.module_scope.def_map.krate()
}
@@ -844,9 +852,12 @@ impl Resolver {
}));
if let Some(block) = expr_scopes.block(scope_id) {
let def_map = db.block_def_map(block);
- resolver
- .scopes
- .push(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT }));
+ let local_def_map = block.lookup(db).module.only_local_def_map(db);
+ resolver.scopes.push(Scope::BlockScope(ModuleItemMap {
+ def_map,
+ local_def_map,
+ module_id: DefMap::ROOT,
+ }));
// FIXME: This adds as many module scopes as there are blocks, but resolving in each
// already traverses all parents, so this is O(n²). I think we could only store the
// innermost module scope instead?
@@ -933,9 +944,10 @@ impl Resolver {
path: &ModPath,
shadow: BuiltinShadowMode,
) -> PerNs {
- let (item_map, module) = self.item_scope();
+ let (item_map, item_local_map, module) = self.item_scope();
// This method resolves `path` just like import paths, so no expected macro subns is given.
- let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow, None);
+ let (module_res, segment_index) =
+ item_map.resolve_path(item_local_map, db, module, path, shadow, None);
if segment_index.is_some() {
return PerNs::none();
}
@@ -943,13 +955,17 @@ impl Resolver {
}
/// The innermost block scope that contains items or the module scope that contains this resolver.
- fn item_scope(&self) -> (&DefMap, LocalModuleId) {
+ fn item_scope(&self) -> (&DefMap, &LocalDefMap, LocalModuleId) {
self.scopes()
.find_map(|scope| match scope {
- Scope::BlockScope(m) => Some((&*m.def_map, m.module_id)),
+ Scope::BlockScope(m) => Some((&*m.def_map, &*m.local_def_map, m.module_id)),
_ => None,
})
- .unwrap_or((&self.module_scope.def_map, self.module_scope.module_id))
+ .unwrap_or((
+ &self.module_scope.def_map,
+ &self.module_scope.local_def_map,
+ self.module_scope.module_id,
+ ))
}
}
@@ -1050,7 +1066,8 @@ fn resolver_for_scope_(
for scope in scope_chain.into_iter().rev() {
if let Some(block) = scopes.block(scope) {
let def_map = db.block_def_map(block);
- r = r.push_block_scope(def_map);
+ let local_def_map = block.lookup(db).module.only_local_def_map(db);
+ r = r.push_block_scope(def_map, local_def_map);
// FIXME: This adds as many module scopes as there are blocks, but resolving in each
// already traverses all parents, so this is O(n²). I think we could only store the
// innermost module scope instead?
@@ -1079,9 +1096,12 @@ impl Resolver {
self.push_scope(Scope::ImplDefScope(impl_def))
}
- fn push_block_scope(self, def_map: Arc<DefMap>) -> Resolver {
- debug_assert!(def_map.block_id().is_some());
- self.push_scope(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT }))
+ fn push_block_scope(self, def_map: Arc<DefMap>, local_def_map: Arc<LocalDefMap>) -> Resolver {
+ self.push_scope(Scope::BlockScope(ModuleItemMap {
+ def_map,
+ local_def_map,
+ module_id: DefMap::ROOT,
+ }))
}
fn push_expr_scope(
@@ -1100,8 +1120,13 @@ impl ModuleItemMap {
db: &dyn DefDatabase,
path: &ModPath,
) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> {
- let (module_def, unresolved_idx, prefix_info) =
- self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
+ let (module_def, unresolved_idx, prefix_info) = self.def_map.resolve_path_locally(
+ &self.local_def_map,
+ db,
+ self.module_id,
+ path,
+ BuiltinShadowMode::Other,
+ );
match unresolved_idx {
None => {
let (value, import) = to_value_ns(module_def)?;
@@ -1134,8 +1159,13 @@ impl ModuleItemMap {
path: &ModPath,
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)>
{
- let (module_def, idx, prefix_info) =
- self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
+ let (module_def, idx, prefix_info) = self.def_map.resolve_path_locally(
+ &self.local_def_map,
+ db,
+ self.module_id,
+ path,
+ BuiltinShadowMode::Other,
+ );
let (res, import) = to_type_ns(module_def)?;
Some((res, idx, import, prefix_info))
}
@@ -1230,11 +1260,14 @@ pub trait HasResolver: Copy {
impl HasResolver for ModuleId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
- let mut def_map = self.def_map(db);
+ let (mut def_map, local_def_map) = self.local_def_map(db);
let mut module_id = self.local_id;
if !self.is_block_module() {
- return Resolver { scopes: vec![], module_scope: ModuleItemMap { def_map, module_id } };
+ return Resolver {
+ scopes: vec![],
+ module_scope: ModuleItemMap { def_map, local_def_map, module_id },
+ };
}
let mut modules: SmallVec<[_; 1]> = smallvec![];
@@ -1248,10 +1281,14 @@ impl HasResolver for ModuleId {
}
let mut resolver = Resolver {
scopes: Vec::with_capacity(modules.len()),
- module_scope: ModuleItemMap { def_map, module_id },
+ module_scope: ModuleItemMap {
+ def_map,
+ local_def_map: local_def_map.clone(),
+ module_id,
+ },
};
for def_map in modules.into_iter().rev() {
- resolver = resolver.push_block_scope(def_map);
+ resolver = resolver.push_block_scope(def_map, local_def_map.clone());
}
resolver
}
@@ -1259,9 +1296,10 @@ impl HasResolver for ModuleId {
impl HasResolver for CrateRootModuleId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+ let (def_map, local_def_map) = self.local_def_map(db);
Resolver {
scopes: vec![],
- module_scope: ModuleItemMap { def_map: self.def_map(db), module_id: DefMap::ROOT },
+ module_scope: ModuleItemMap { def_map, local_def_map, module_id: DefMap::ROOT },
}
}
}
diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs
index c7ebfeecf5..43d31aa503 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -158,7 +158,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
let mut map = ArenaMap::new();
match &src.value {
ast::StructKind::Tuple(fl) => {
- let cfg_options = &db.crate_graph()[container.krate].cfg_options;
+ let cfg_options = container.krate.cfg_options(db);
let mut idx = 0;
for (i, fd) in fl.fields().enumerate() {
let attrs = item_tree.attrs(
@@ -177,7 +177,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
}
}
ast::StructKind::Record(fl) => {
- let cfg_options = &db.crate_graph()[container.krate].cfg_options;
+ let cfg_options = container.krate.cfg_options(db);
let mut idx = 0;
for (i, fd) in fl.fields().enumerate() {
let attrs = item_tree.attrs(
diff --git a/crates/hir-def/src/test_db.rs b/crates/hir-def/src/test_db.rs
index b6f08c0caf..0b97e6c9ce 100644
--- a/crates/hir-def/src/test_db.rs
+++ b/crates/hir-def/src/test_db.rs
@@ -3,8 +3,8 @@
use std::{fmt, panic, sync::Mutex};
use base_db::{
- CrateId, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId,
- SourceRootInput, Upcast,
+ Crate, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb,
+ SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast,
};
use hir_expand::{db::ExpandDatabase, files::FilePosition, InFile};
use salsa::{AsDynDatabase, Durability};
@@ -24,6 +24,7 @@ use crate::{
pub(crate) struct TestDB {
storage: salsa::Storage<Self>,
files: Arc<base_db::Files>,
+ crates_map: Arc<CratesMap>,
events: Arc<Mutex<Option<Vec<salsa::Event>>>>,
}
@@ -33,8 +34,12 @@ impl Default for TestDB {
storage: Default::default(),
events: Default::default(),
files: Default::default(),
+ crates_map: Default::default(),
};
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
+ // This needs to be here otherwise `CrateGraphBuilder` panics.
+ this.set_all_crates(Arc::new(Box::new([])));
+ CrateGraphBuilder::default().set_in_db(&mut this);
this
}
}
@@ -133,20 +138,23 @@ impl SourceDatabase for TestDB {
let files = Arc::clone(&self.files);
files.set_file_source_root_with_durability(self, id, source_root_id, durability);
}
+
+ fn crates_map(&self) -> Arc<CratesMap> {
+ self.crates_map.clone()
+ }
}
impl TestDB {
- pub(crate) fn fetch_test_crate(&self) -> CrateId {
- let crate_graph = self.crate_graph();
- let it = crate_graph
+ pub(crate) fn fetch_test_crate(&self) -> Crate {
+ let all_crates = self.all_crates();
+ all_crates
.iter()
- .find(|&idx| {
- crate_graph[idx].display_name.as_ref().map(|it| it.canonical_name().as_str())
+ .copied()
+ .find(|&krate| {
+ krate.extra_data(self).display_name.as_ref().map(|it| it.canonical_name().as_str())
== Some("ra_test_fixture")
})
- .or_else(|| crate_graph.iter().next())
- .unwrap();
- it
+ .unwrap_or(*all_crates.last().unwrap())
}
pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId {
diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs
index c9c793d54f..64b9b49b3e 100644
--- a/crates/hir-expand/src/attrs.rs
+++ b/crates/hir-expand/src/attrs.rs
@@ -1,7 +1,7 @@
//! A higher level attributes based on TokenTree, with also some shortcuts.
use std::{borrow::Cow, fmt, ops};
-use base_db::CrateId;
+use base_db::Crate;
use cfg::CfgExpr;
use either::Either;
use intern::{sym, Interned, Symbol};
@@ -119,7 +119,7 @@ impl RawAttrs {
/// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
// FIXME: This should return a different type, signaling it was filtered?
- pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs {
+ pub fn filter(self, db: &dyn ExpandDatabase, krate: Crate) -> RawAttrs {
let has_cfg_attrs = self
.iter()
.any(|attr| attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr.clone()));
@@ -127,7 +127,7 @@ impl RawAttrs {
return self;
}
- let crate_graph = db.crate_graph();
+ let cfg_options = krate.cfg_options(db);
let new_attrs =
self.iter()
.flat_map(|attr| -> SmallVec<[_; 1]> {
@@ -151,7 +151,6 @@ impl RawAttrs {
|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)),
);
- let cfg_options = &crate_graph[krate].cfg_options;
let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg);
let cfg = CfgExpr::parse(&cfg);
if cfg_options.check(&cfg) == Some(false) {
diff --git a/crates/hir-expand/src/builtin/fn_macro.rs b/crates/hir-expand/src/builtin/fn_macro.rs
index d8b3f40e8f..b56ec3d04c 100644
--- a/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/crates/hir-expand/src/builtin/fn_macro.rs
@@ -231,7 +231,7 @@ fn assert_expand(
let cond = expect_fragment(
&mut iter,
parser::PrefixEntryPoint::Expr,
- db.crate_graph()[id.lookup(db).krate].edition,
+ id.lookup(db).krate.data(db).edition,
tt.top_subtree().delimiter.delim_span(),
);
_ = iter.expect_char(',');
@@ -333,7 +333,7 @@ fn cfg_expand(
) -> ExpandResult<tt::TopSubtree> {
let loc = db.lookup_intern_macro_call(id);
let expr = CfgExpr::parse(tt);
- let enabled = db.crate_graph()[loc.krate].cfg_options.check(&expr) != Some(false);
+ let enabled = loc.krate.cfg_options(db).check(&expr) != Some(false);
let expanded = if enabled { quote!(span=>true) } else { quote!(span=>false) };
ExpandResult::ok(expanded)
}
@@ -669,7 +669,7 @@ fn relative_file(
if res == call_site && !allow_recursion {
Err(ExpandError::other(err_span, format!("recursive inclusion of `{path_str}`")))
} else {
- Ok(EditionedFileId::new(res, db.crate_graph()[lookup.krate].edition))
+ Ok(EditionedFileId::new(res, lookup.krate.data(db).edition))
}
}
@@ -812,7 +812,7 @@ fn include_str_expand(
fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &Symbol) -> Option<String> {
let krate = db.lookup_intern_macro_call(arg_id).krate;
- db.crate_graph()[krate].env.get(key.as_str())
+ krate.env(db).get(key.as_str())
}
fn env_expand(
diff --git a/crates/hir-expand/src/cfg_process.rs b/crates/hir-expand/src/cfg_process.rs
index 626a82ae08..0ceab3c890 100644
--- a/crates/hir-expand/src/cfg_process.rs
+++ b/crates/hir-expand/src/cfg_process.rs
@@ -1,7 +1,7 @@
//! Processes out #[cfg] and #[cfg_attr] attributes from the input for the derive macro
use std::iter::Peekable;
-use base_db::CrateId;
+use base_db::Crate;
use cfg::{CfgAtom, CfgExpr};
use intern::{sym, Symbol};
use rustc_hash::FxHashSet;
@@ -13,16 +13,16 @@ use tracing::{debug, warn};
use crate::{db::ExpandDatabase, proc_macro::ProcMacroKind, MacroCallLoc, MacroDefKind};
-fn check_cfg(db: &dyn ExpandDatabase, attr: &Attr, krate: CrateId) -> Option<bool> {
+fn check_cfg(db: &dyn ExpandDatabase, attr: &Attr, krate: Crate) -> Option<bool> {
if !attr.simple_name().as_deref().map(|v| v == "cfg")? {
return None;
}
let cfg = parse_from_attr_token_tree(&attr.meta()?.token_tree()?)?;
- let enabled = db.crate_graph()[krate].cfg_options.check(&cfg) != Some(false);
+ let enabled = krate.cfg_options(db).check(&cfg) != Some(false);
Some(enabled)
}
-fn check_cfg_attr(db: &dyn ExpandDatabase, attr: &Attr, krate: CrateId) -> Option<bool> {
+fn check_cfg_attr(db: &dyn ExpandDatabase, attr: &Attr, krate: Crate) -> Option<bool> {
if !attr.simple_name().as_deref().map(|v| v == "cfg_attr")? {
return None;
}
@@ -32,17 +32,17 @@ fn check_cfg_attr(db: &dyn ExpandDatabase, attr: &Attr, krate: CrateId) -> Optio
pub fn check_cfg_attr_value(
db: &dyn ExpandDatabase,
attr: &TokenTree,
- krate: CrateId,
+ krate: Crate,
) -> Option<bool> {
let cfg_expr = parse_from_attr_token_tree(attr)?;
- let enabled = db.crate_graph()[krate].cfg_options.check(&cfg_expr) != Some(false);
+ let enabled = krate.cfg_options(db).check(&cfg_expr) != Some(false);
Some(enabled)
}
fn process_has_attrs_with_possible_comma<I: HasAttrs>(
db: &dyn ExpandDatabase,
items: impl Iterator<Item = I>,
- krate: CrateId,
+ krate: Crate,
remove: &mut FxHashSet<SyntaxElement>,
) -> Option<()> {
for item in items {
@@ -144,7 +144,7 @@ fn remove_possible_comma(item: &impl AstNode, res: &mut FxHashSet<SyntaxElement>
fn process_enum(
db: &dyn ExpandDatabase,
variants: VariantList,
- krate: CrateId,
+ krate: Crate,
remove: &mut FxHashSet<SyntaxElement>,
) -> Option<()> {
'variant: for variant in variants.variants() {
diff --git a/crates/hir-expand/src/change.rs b/crates/hir-expand/src/change.rs
index 7a42d66260..3f5b8fdc9b 100644
--- a/crates/hir-expand/src/change.rs
+++ b/crates/hir-expand/src/change.rs
@@ -1,17 +1,16 @@
//! Defines a unit of change that can applied to the database to get the next
//! state. Changes are transactional.
-use base_db::{CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot};
-use rustc_hash::FxHashMap;
+use base_db::{CrateGraphBuilder, FileChange, SourceRoot};
use salsa::Durability;
use span::FileId;
use triomphe::Arc;
-use crate::{db::ExpandDatabase, proc_macro::ProcMacros};
+use crate::{db::ExpandDatabase, proc_macro::ProcMacrosBuilder};
#[derive(Debug, Default)]
pub struct ChangeWithProcMacros {
pub source_change: FileChange,
- pub proc_macros: Option<ProcMacros>,
+ pub proc_macros: Option<ProcMacrosBuilder>,
}
impl ChangeWithProcMacros {
@@ -20,8 +19,13 @@ impl ChangeWithProcMacros {
}
pub fn apply(self, db: &mut impl ExpandDatabase) {
- self.source_change.apply(db);
+ let crates_id_map = self.source_change.apply(db);
if let Some(proc_macros) = self.proc_macros {
+ let proc_macros = proc_macros.build(
+ crates_id_map
+ .as_ref()
+ .expect("cannot set proc macros without setting the crate graph too"),
+ );
db.set_proc_macros_with_durability(Arc::new(proc_macros), Durability::HIGH);
}
}
@@ -30,16 +34,11 @@ impl ChangeWithProcMacros {
self.source_change.change_file(file_id, new_text)
}
- pub fn set_crate_graph(
- &mut self,
- graph: CrateGraph,
- ws_data: FxHashMap<CrateId, Arc<CrateWorkspaceData>>,
- ) {
+ pub fn set_crate_graph(&mut self, graph: CrateGraphBuilder) {
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) {
+ pub fn set_proc_macros(&mut self, proc_macros: ProcMacrosBuilder) {
self.proc_macros = Some(proc_macros);
}
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index 2f97cceab5..112327f11e 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -1,6 +1,6 @@
//! Defines database & queries for macro expansion.
-use base_db::{CrateId, RootQueryDb};
+use base_db::{Crate, RootQueryDb};
use either::Either;
use mbe::MatchedArmIndex;
use rustc_hash::FxHashSet;
@@ -23,7 +23,7 @@ use crate::{
span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt,
SyntaxContextExt as _,
},
- proc_macro::{CustomProcMacroExpander, ProcMacros},
+ proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros},
span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef},
tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo,
EagerExpander, ExpandError, ExpandResult, ExpandTo, MacroCallKind, MacroCallLoc, MacroDefId,
@@ -57,10 +57,13 @@ pub enum TokenExpander {
#[query_group::query_group]
pub trait ExpandDatabase: RootQueryDb {
- /// The proc macros.
+ /// The proc macros. Do not use this! Use `proc_macros_for_crate()` instead.
#[salsa::input]
fn proc_macros(&self) -> Arc<ProcMacros>;
+ #[salsa::invoke_actual(crate::proc_macro::proc_macros_for_crate)]
+ fn proc_macros_for_crate(&self, krate: Crate) -> Option<Arc<CrateProcMacros>>;
+
fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
#[salsa::transparent]
@@ -120,7 +123,7 @@ pub trait ExpandDatabase: RootQueryDb {
#[salsa::invoke(DeclarativeMacroExpander::expander)]
fn decl_macro_expander(
&self,
- def_crate: CrateId,
+ def_crate: Crate,
id: AstId<ast::Macro>,
) -> Arc<DeclarativeMacroExpander>;
diff --git a/crates/hir-expand/src/declarative.rs b/crates/hir-expand/src/declarative.rs
index 91cbbc3736..fbce320756 100644
--- a/crates/hir-expand/src/declarative.rs
+++ b/crates/hir-expand/src/declarative.rs
@@ -1,6 +1,6 @@
//! Compiled declarative macro expanders (`macro_rules!` and `macro`)
-use base_db::CrateId;
+use base_db::Crate;
use intern::sym;
use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId};
use stdx::TupleExt;
@@ -70,7 +70,7 @@ impl DeclarativeMacroExpander {
pub(crate) fn expander(
db: &dyn ExpandDatabase,
- def_crate: CrateId,
+ def_crate: Crate,
id: AstId<ast::Macro>,
) -> Arc<DeclarativeMacroExpander> {
let (root, map) = crate::db::parse_with_map(db, id.file_id);
@@ -101,14 +101,12 @@ impl DeclarativeMacroExpander {
}
};
let ctx_edition = |ctx: SyntaxContextId| {
- let crate_graph = db.crate_graph();
-
if ctx.is_root() {
- crate_graph[def_crate].edition
+ def_crate.data(db).edition
} else {
// UNWRAP-SAFETY: Only the root context has no outer expansion
let krate = db.lookup_intern_macro_call(ctx.outer_expn(db).unwrap()).def.krate;
- crate_graph[krate].edition
+ krate.data(db).edition
}
};
let (mac, transparency) = match id.to_ptr(db).to_node(&root) {
diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs
index 4a98b455ca..02dc75a4a6 100644
--- a/crates/hir-expand/src/eager.rs
+++ b/crates/hir-expand/src/eager.rs
@@ -18,7 +18,7 @@
//!
//!
//! See the full discussion : <https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Eager.20expansion.20of.20built-in.20macros>
-use base_db::CrateId;
+use base_db::Crate;
use span::SyntaxContextId;
use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent};
use syntax_bridge::DocCommentDesugarMode;
@@ -34,7 +34,7 @@ use crate::{
pub fn expand_eager_macro_input(
db: &dyn ExpandDatabase,
- krate: CrateId,
+ krate: Crate,
macro_call: &ast::MacroCall,
ast_id: AstId<ast::MacroCall>,
def: MacroDefId,
@@ -115,7 +115,7 @@ fn lazy_expand(
def: &MacroDefId,
macro_call: &ast::MacroCall,
ast_id: AstId<ast::MacroCall>,
- krate: CrateId,
+ krate: Crate,
call_site: SyntaxContextId,
) -> ExpandResult<(InFile<Parse<SyntaxNode>>, Arc<ExpansionSpanMap>)> {
let expand_to = ExpandTo::from_call_site(macro_call);
@@ -137,7 +137,7 @@ fn eager_macro_recur(
expanded_map: &mut ExpansionSpanMap,
mut offset: TextSize,
curr: InFile<SyntaxNode>,
- krate: CrateId,
+ krate: Crate,
call_site: SyntaxContextId,
macro_resolver: &dyn Fn(&ModPath) -> Option<MacroDefId>,
) -> ExpandResult<Option<(SyntaxNode, TextSize)>> {
@@ -176,7 +176,7 @@ fn eager_macro_recur(
Some(path) => match macro_resolver(&path) {
Some(def) => def,
None => {
- let edition = db.crate_graph()[krate].edition;
+ let edition = krate.data(db).edition;
error = Some(ExpandError::other(
span_map.span_at(call.syntax().text_range().start()),
format!("unresolved macro {}", path.display(db, edition)),
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index f8c83dce55..a1e484c08b 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -33,7 +33,7 @@ use triomphe::Arc;
use core::fmt;
use std::hash::Hash;
-use base_db::CrateId;
+use base_db::Crate;
use either::Either;
use span::{
Edition, EditionedFileId, ErasedFileAstId, FileAstId, HirFileIdRepr, Span, SpanAnchor,
@@ -157,7 +157,7 @@ impl ExpandError {
pub enum ExpandErrorKind {
/// Attribute macro expansion is disabled.
ProcMacroAttrExpansionDisabled,
- MissingProcMacroExpander(CrateId),
+ MissingProcMacroExpander(Crate),
/// The macro for this call is disabled.
MacroDisabled,
/// The macro definition has errors.
@@ -200,7 +200,7 @@ impl ExpandErrorKind {
kind: RenderedExpandError::DISABLED,
},
&ExpandErrorKind::MissingProcMacroExpander(def_crate) => {
- match db.proc_macros().get_error_for_crate(def_crate) {
+ match db.proc_macros_for_crate(def_crate).as_ref().and_then(|it| it.get_error()) {
Some((e, hard_err)) => RenderedExpandError {
message: e.to_owned(),
error: hard_err,
@@ -250,14 +250,14 @@ impl From<mbe::ExpandError> for ExpandError {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroCallLoc {
pub def: MacroDefId,
- pub krate: CrateId,
+ pub krate: Crate,
pub kind: MacroCallKind,
pub ctxt: SyntaxContextId,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroDefId {
- pub krate: CrateId,
+ pub krate: Crate,
pub edition: Edition,
pub kind: MacroDefKind,
pub local_inner: bool,
@@ -525,7 +525,7 @@ impl MacroDefId {
pub fn make_call(
self,
db: &dyn ExpandDatabase,
- krate: CrateId,
+ krate: Crate,
kind: MacroCallKind,
ctxt: SyntaxContextId,
) -> MacroCallId {
diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs
index 6f6f41f322..40b10cb438 100644
--- a/crates/hir-expand/src/mod_path.rs
+++ b/crates/hir-expand/src/mod_path.rs
@@ -11,7 +11,7 @@ use crate::{
name::{AsName, Name},
tt,
};
-use base_db::CrateId;
+use base_db::Crate;
use intern::sym;
use smallvec::SmallVec;
use span::{Edition, SyntaxContextId};
@@ -33,7 +33,7 @@ pub enum PathKind {
Abs,
// FIXME: Can we remove this somehow?
/// `$crate` from macro expansion
- DollarCrate(CrateId),
+ DollarCrate(Crate),
}
impl PathKind {
@@ -333,7 +333,7 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: tt::TokenTreesView<'_>) -> Optio
Some(ModPath { kind, segments })
}
-pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContextId) -> Option<CrateId> {
+pub fn resolve_crate_root(db: &dyn ExpandDatabase, mut ctxt: SyntaxContextId) -> Option<Crate> {
// When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
// we don't want to pretend that the `macro_rules!` definition is in the `macro`
// as described in `SyntaxContextId::apply_mark`, so we ignore prepended opaque marks.
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index 0758bd4515..51721effa3 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -260,7 +260,7 @@ impl AsName for ast::FieldKind {
}
}
-impl AsName for base_db::Dependency {
+impl AsName for base_db::BuiltDependency {
fn as_name(&self) -> Name {
Name::new_symbol_root((*self.name).clone())
}
diff --git a/crates/hir-expand/src/prettify_macro_expansion_.rs b/crates/hir-expand/src/prettify_macro_expansion_.rs
index 944341ec3f..f398b070f7 100644
--- a/crates/hir-expand/src/prettify_macro_expansion_.rs
+++ b/crates/hir-expand/src/prettify_macro_expansion_.rs
@@ -1,6 +1,6 @@
//! Pretty printing of macros output.
-use base_db::CrateId;
+use base_db::Crate;
use rustc_hash::FxHashMap;
use syntax::NodeOrToken;
use syntax::{ast::make, SyntaxNode};
@@ -13,13 +13,12 @@ pub fn prettify_macro_expansion(
db: &dyn ExpandDatabase,
syn: SyntaxNode,
span_map: &ExpansionSpanMap,
- target_crate_id: CrateId,
+ target_crate_id: Crate,
) -> SyntaxNode {
// Because `syntax_bridge::prettify_macro_expansion::prettify_macro_expansion()` clones subtree for `syn`,
// that means it will be offsetted to the beginning.
let span_offset = syn.text_range().start();
- let crate_graph = db.crate_graph();
- let target_crate = &crate_graph[target_crate_id];
+ let target_crate = target_crate_id.data(db);
let mut syntax_ctx_id_to_dollar_crate_replacement = FxHashMap::default();
syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(syn, &mut |dollar_crate| {
let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx;
@@ -41,7 +40,7 @@ pub fn prettify_macro_expansion(
target_crate.dependencies.iter().find(|dep| dep.crate_id == macro_def_crate)
{
make::tokens::ident(dep.name.as_str())
- } else if let Some(crate_name) = &crate_graph[macro_def_crate].display_name {
+ } else if let Some(crate_name) = &macro_def_crate.extra_data(db).display_name {
make::tokens::ident(crate_name.crate_name().as_str())
} else {
return dollar_crate.clone();
diff --git a/crates/hir-expand/src/proc_macro.rs b/crates/hir-expand/src/proc_macro.rs
index 3dc3dcd760..cdf63e92a8 100644
--- a/crates/hir-expand/src/proc_macro.rs
+++ b/crates/hir-expand/src/proc_macro.rs
@@ -1,24 +1,36 @@
//! Proc Macro Expander stuff
use core::fmt;
+use std::any::Any;
use std::{panic::RefUnwindSafe, sync};
-use base_db::{CrateId, Env};
+use base_db::{Crate, CrateBuilderId, CratesIdMap, Env};
use intern::Symbol;
use rustc_hash::FxHashMap;
use span::Span;
+use triomphe::Arc;
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandErrorKind, ExpandResult};
-#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Hash)]
pub enum ProcMacroKind {
CustomDerive,
Bang,
Attr,
}
+pub trait AsAny: Any {
+ fn as_any(&self) -> &dyn Any;
+}
+
+impl<T: Any> AsAny for T {
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+}
+
/// A proc-macro expander implementation.
-pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
+pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + AsAny {
/// Run the expander with the given input subtree, optional attribute input subtree (for
/// [`ProcMacroKind::Attr`]), environment variables, and span information.
fn expand(
@@ -31,8 +43,18 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
mixed_site: Span,
current_dir: Option<String>,
) -> Result<tt::TopSubtree, ProcMacroExpansionError>;
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool;
}
+impl PartialEq for dyn ProcMacroExpander {
+ fn eq(&self, other: &Self) -> bool {
+ self.eq_dyn(other)
+ }
+}
+
+impl Eq for dyn ProcMacroExpander {}
+
#[derive(Debug)]
pub enum ProcMacroExpansionError {
/// The proc-macro panicked.
@@ -45,41 +67,68 @@ pub type ProcMacroLoadResult = Result<Vec<ProcMacro>, (String, bool)>;
type StoredProcMacroLoadResult = Result<Box<[ProcMacro]>, (Box<str>, bool)>;
#[derive(Default, Debug)]
-pub struct ProcMacrosBuilder(FxHashMap<CrateId, StoredProcMacroLoadResult>);
+pub struct ProcMacrosBuilder(FxHashMap<CrateBuilderId, Arc<CrateProcMacros>>);
+
impl ProcMacrosBuilder {
- pub fn insert(&mut self, proc_macros_crate: CrateId, proc_macro: ProcMacroLoadResult) {
+ pub fn insert(
+ &mut self,
+ proc_macros_crate: CrateBuilderId,
+ mut proc_macro: ProcMacroLoadResult,
+ ) {
+ if let Ok(proc_macros) = &mut proc_macro {
+ // Sort proc macros to improve incrementality when only their order has changed (ideally the build system
+ // will not change their order, but just to be sure).
+ proc_macros
+ .sort_unstable_by_key(|proc_macro| (proc_macro.name.clone(), proc_macro.kind));
+ }
self.0.insert(
proc_macros_crate,
match proc_macro {
- Ok(it) => Ok(it.into_boxed_slice()),
- Err((e, hard_err)) => Err((e.into_boxed_str(), hard_err)),
+ Ok(it) => Arc::new(CrateProcMacros(Ok(it.into_boxed_slice()))),
+ Err((e, hard_err)) => {
+ Arc::new(CrateProcMacros(Err((e.into_boxed_str(), hard_err))))
+ }
},
);
}
- pub fn build(mut self) -> ProcMacros {
- self.0.shrink_to_fit();
- ProcMacros(self.0)
+
+ pub(crate) fn build(self, crates_id_map: &CratesIdMap) -> ProcMacros {
+ let mut map = self
+ .0
+ .into_iter()
+ .map(|(krate, proc_macro)| (crates_id_map[&krate], proc_macro))
+ .collect::<FxHashMap<_, _>>();
+ map.shrink_to_fit();
+ ProcMacros(map)
}
}
-#[derive(Default, Debug)]
-pub struct ProcMacros(FxHashMap<CrateId, StoredProcMacroLoadResult>);
-
-impl FromIterator<(CrateId, ProcMacroLoadResult)> for ProcMacros {
- fn from_iter<T: IntoIterator<Item = (CrateId, ProcMacroLoadResult)>>(iter: T) -> Self {
+impl FromIterator<(CrateBuilderId, ProcMacroLoadResult)> for ProcMacrosBuilder {
+ fn from_iter<T: IntoIterator<Item = (CrateBuilderId, ProcMacroLoadResult)>>(iter: T) -> Self {
let mut builder = ProcMacrosBuilder::default();
for (k, v) in iter {
builder.insert(k, v);
}
- builder.build()
+ builder
}
}
+#[derive(Debug, PartialEq, Eq)]
+pub struct CrateProcMacros(StoredProcMacroLoadResult);
+
+#[derive(Default, Debug)]
+pub struct ProcMacros(FxHashMap<Crate, Arc<CrateProcMacros>>);
impl ProcMacros {
- fn get(&self, krate: CrateId, idx: u32, err_span: Span) -> Result<&ProcMacro, ExpandError> {
- let proc_macros = match self.0.get(&krate) {
- Some(Ok(proc_macros)) => proc_macros,
- Some(Err(_)) | None => {
+ fn get(&self, krate: Crate) -> Option<Arc<CrateProcMacros>> {
+ self.0.get(&krate).cloned()
+ }
+}
+
+impl CrateProcMacros {
+ fn get(&self, idx: u32, err_span: Span) -> Result<&ProcMacro, ExpandError> {
+ let proc_macros = match &self.0 {
+ Ok(proc_macros) => proc_macros,
+ Err(_) => {
return Err(ExpandError::other(
err_span,
"internal error: no proc macros for crate",
@@ -98,18 +147,17 @@ impl ProcMacros {
)
}
- pub fn get_error_for_crate(&self, krate: CrateId) -> Option<(&str, bool)> {
- self.0.get(&krate).and_then(|it| it.as_ref().err()).map(|(e, hard_err)| (&**e, *hard_err))
+ pub fn get_error(&self) -> Option<(&str, bool)> {
+ self.0.as_ref().err().map(|(e, hard_err)| (&**e, *hard_err))
}
/// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate.
- pub fn for_crate(
+ pub fn list(
&self,
- krate: CrateId,
def_site_ctx: span::SyntaxContextId,
) -> Option<Box<[(crate::name::Name, CustomProcMacroExpander, bool)]>> {
- match self.0.get(&krate) {
- Some(Ok(proc_macros)) => Some({
+ match &self.0 {
+ Ok(proc_macros) => Some(
proc_macros
.iter()
.enumerate()
@@ -117,15 +165,15 @@ impl ProcMacros {
let name = crate::name::Name::new_symbol(it.name.clone(), def_site_ctx);
(name, CustomProcMacroExpander::new(idx as u32), it.disabled)
})
- .collect()
- }),
+ .collect(),
+ ),
_ => None,
}
}
}
/// A loaded proc-macro.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Eq)]
pub struct ProcMacro {
/// The name of the proc macro.
pub name: Symbol,
@@ -137,6 +185,23 @@ pub struct ProcMacro {
pub disabled: bool,
}
+// `#[derive(PartialEq)]` generates a strange "cannot move" error.
+impl PartialEq for ProcMacro {
+ fn eq(&self, other: &Self) -> bool {
+ let Self { name, kind, expander, disabled } = self;
+ let Self {
+ name: other_name,
+ kind: other_kind,
+ expander: other_expander,
+ disabled: other_disabled,
+ } = other;
+ name == other_name
+ && kind == other_kind
+ && expander == other_expander
+ && disabled == other_disabled
+ }
+}
+
/// A custom proc-macro expander handle. This handle together with its crate resolves to a [`ProcMacro`]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct CustomProcMacroExpander {
@@ -187,7 +252,7 @@ impl CustomProcMacroExpander {
}
/// The macro is explicitly disabled due to proc-macro attribute expansion being disabled.
- pub fn as_expand_error(&self, def_crate: CrateId) -> Option<ExpandErrorKind> {
+ pub fn as_expand_error(&self, def_crate: Crate) -> Option<ExpandErrorKind> {
match self.proc_macro_id {
Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandErrorKind::ProcMacroAttrExpansionDisabled),
Self::DISABLED_ID => Some(ExpandErrorKind::MacroDisabled),
@@ -199,8 +264,8 @@ impl CustomProcMacroExpander {
pub fn expand(
self,
db: &dyn ExpandDatabase,
- def_crate: CrateId,
- calling_crate: CrateId,
+ def_crate: Crate,
+ calling_crate: Crate,
tt: &tt::TopSubtree,
attr_arg: Option<&tt::TopSubtree>,
def_site: Span,
@@ -221,8 +286,22 @@ impl CustomProcMacroExpander {
ExpandError::new(call_site, ExpandErrorKind::MacroDisabled),
),
id => {
- let proc_macros = db.proc_macros();
- let proc_macro = match proc_macros.get(def_crate, id, call_site) {
+ let proc_macros = match db.proc_macros_for_crate(def_crate) {
+ Some(it) => it,
+ None => {
+ return ExpandResult::new(
+ tt::TopSubtree::empty(tt::DelimSpan {
+ open: call_site,
+ close: call_site,
+ }),
+ ExpandError::other(
+ call_site,
+ "internal error: no proc macros for crate",
+ ),
+ )
+ }
+ };
+ let proc_macro = match proc_macros.get(id, call_site) {
Ok(proc_macro) => proc_macro,
Err(e) => {
return ExpandResult::new(
@@ -235,11 +314,10 @@ impl CustomProcMacroExpander {
}
};
- let krate_graph = db.crate_graph();
// Proc macros have access to the environment variables of the invoking crate.
- let env = &krate_graph[calling_crate].env;
+ let env = calling_crate.env(db);
let current_dir =
- krate_graph[calling_crate].proc_macro_cwd.as_deref().map(ToString::to_string);
+ calling_crate.data(db).proc_macro_cwd.as_deref().map(ToString::to_string);
match proc_macro.expander.expand(
tt,
@@ -278,3 +356,10 @@ impl CustomProcMacroExpander {
}
}
}
+
+pub(crate) fn proc_macros_for_crate(
+ db: &dyn ExpandDatabase,
+ krate: Crate,
+) -> Option<Arc<CrateProcMacros>> {
+ db.proc_macros().get(krate)
+}
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index 2be3217330..84eb964d56 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -11,7 +11,7 @@ use tracing::debug;
use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds};
use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
-use base_db::CrateId;
+use base_db::Crate;
use hir_def::{
data::{adt::StructFlags, TraitFlags},
hir::Movability,
@@ -523,7 +523,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
impl ChalkContext<'_> {
fn edition(&self) -> Edition {
- self.db.crate_graph()[self.krate].edition
+ self.krate.data(self.db).edition
}
fn for_trait_impls(
@@ -593,7 +593,7 @@ impl chalk_ir::UnificationDatabase<Interner> for &dyn HirDatabase {
pub(crate) fn program_clauses_for_chalk_env_query(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
block: Option<BlockId>,
environment: chalk_ir::Environment<Interner>,
) -> chalk_ir::ProgramClauses<Interner> {
@@ -665,7 +665,7 @@ pub(crate) fn associated_ty_data_query(
pub(crate) fn trait_datum_query(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
trait_id: TraitId,
) -> Arc<TraitDatum> {
debug!("trait_datum {:?}", trait_id);
@@ -750,7 +750,7 @@ fn lang_item_from_well_known_trait(trait_: WellKnownTrait) -> LangItem {
pub(crate) fn adt_datum_query(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
chalk_ir::AdtId(adt_id): AdtId,
) -> Arc<AdtDatum> {
debug!("adt_datum {:?}", adt_id);
@@ -824,7 +824,7 @@ pub(crate) fn adt_datum_query(
pub(crate) fn impl_datum_query(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
impl_id: ImplId,
) -> Arc<ImplDatum> {
let _p = tracing::info_span!("impl_datum_query").entered();
@@ -833,11 +833,7 @@ pub(crate) fn impl_datum_query(
impl_def_datum(db, krate, impl_)
}
-fn impl_def_datum(
- db: &dyn HirDatabase,
- krate: CrateId,
- impl_id: hir_def::ImplId,
-) -> Arc<ImplDatum> {
+fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId) -> Arc<ImplDatum> {
let trait_ref = db
.impl_trait(impl_id)
// ImplIds for impls where the trait ref can't be resolved should never reach Chalk
@@ -887,7 +883,7 @@ fn impl_def_datum(
pub(crate) fn associated_ty_value_query(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
id: AssociatedTyValueId,
) -> Arc<AssociatedTyValue> {
let type_alias: TypeAliasAsValue = from_chalk(db, id);
@@ -896,7 +892,7 @@ pub(crate) fn associated_ty_value_query(
fn type_alias_associated_ty_value(
db: &dyn HirDatabase,
- _krate: CrateId,
+ _krate: Crate,
type_alias: TypeAliasId,
) -> Arc<AssociatedTyValue> {
let type_alias_data = db.type_alias_data(type_alias);
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index b3c604015a..525672bc39 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -1,6 +1,6 @@
//! Constant evaluation details
-use base_db::CrateId;
+use base_db::Crate;
use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex};
use hir_def::{
expr_store::{Body, HygieneId},
@@ -162,7 +162,7 @@ pub fn intern_const_ref(
db: &dyn HirDatabase,
value: &LiteralConstRef,
ty: Ty,
- krate: CrateId,
+ krate: Crate,
) -> Const {
let layout = db.layout_of_ty(ty.clone(), TraitEnvironment::empty(krate));
let bytes = match value {
@@ -185,7 +185,7 @@ pub fn intern_const_ref(
}
/// Interns a possibly-unknown target usize
-pub fn usize_const(db: &dyn HirDatabase, value: Option<u128>, krate: CrateId) -> Const {
+pub fn usize_const(db: &dyn HirDatabase, value: Option<u128>, krate: Crate) -> Const {
intern_const_ref(
db,
&value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt),
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index f2673dc58f..37e7df6f4b 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -101,10 +101,7 @@ fn check_answer(
fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
let mut err = String::new();
let span_formatter = |file, range| format!("{file:?} {range:?}");
- let display_target = DisplayTarget::from_crate(
- &db,
- *db.crate_graph().crates_in_topological_order().last().unwrap(),
- );
+ let display_target = DisplayTarget::from_crate(&db, *db.all_crates().last().unwrap());
match e {
ConstEvalError::MirLowerError(e) => {
e.pretty_print(&mut err, &db, span_formatter, display_target)
diff --git a/crates/hir-ty/src/db.rs b/crates/hir-ty/src/db.rs
index 5817ed2ef2..8f48cfc432 100644
--- a/crates/hir-ty/src/db.rs
+++ b/crates/hir-ty/src/db.rs
@@ -3,7 +3,7 @@
use std::sync;
-use base_db::{impl_intern_key, CrateId, Upcast};
+use base_db::{impl_intern_key, Crate, Upcast};
use hir_def::{
db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, CallableDefId,
ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId,
@@ -103,8 +103,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> + std::fmt::Debug {
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
- #[salsa::invoke(crate::layout::target_data_layout_query)]
- fn target_data_layout(&self, krate: CrateId) -> Result<Arc<TargetDataLayout>, Arc<str>>;
+ #[salsa::invoke_actual(crate::layout::target_data_layout_query)]
+ fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, Arc<str>>;
#[salsa::invoke_actual(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>;
@@ -196,8 +196,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> + std::fmt::Debug {
#[salsa::invoke_actual(crate::lower::generic_defaults_query)]
fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults;
- #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
- fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
+ #[salsa::invoke_actual(InherentImpls::inherent_impls_in_crate_query)]
+ fn inherent_impls_in_crate(&self, krate: Crate) -> Arc<InherentImpls>;
#[salsa::invoke_actual(InherentImpls::inherent_impls_in_block_query)]
fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>;
@@ -209,18 +209,18 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> + std::fmt::Debug {
#[salsa::invoke(crate::method_resolution::incoherent_inherent_impl_crates)]
fn incoherent_inherent_impl_crates(
&self,
- krate: CrateId,
+ krate: Crate,
fp: TyFingerprint,
- ) -> SmallVec<[CrateId; 2]>;
+ ) -> SmallVec<[Crate; 2]>;
- #[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
- fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
+ #[salsa::invoke_actual(TraitImpls::trait_impls_in_crate_query)]
+ fn trait_impls_in_crate(&self, krate: Crate) -> Arc<TraitImpls>;
#[salsa::invoke_actual(TraitImpls::trait_impls_in_block_query)]
fn trait_impls_in_block(&self, block: BlockId) -> Option<Arc<TraitImpls>>;
- #[salsa::invoke(TraitImpls::trait_impls_in_deps_query)]
- fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<[Arc<TraitImpls>]>;
+ #[salsa::invoke_actual(TraitImpls::trait_impls_in_deps_query)]
+ fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc<TraitImpls>]>;
// Interned IDs for Chalk integration
#[salsa::interned]
@@ -253,23 +253,16 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> + std::fmt::Debug {
#[salsa::invoke(chalk_db::trait_datum_query)]
fn trait_datum(
&self,
- krate: CrateId,
+ krate: Crate,
trait_id: chalk_db::TraitId,
) -> sync::Arc<chalk_db::TraitDatum>;
#[salsa::invoke(chalk_db::adt_datum_query)]
- fn adt_datum(
- &self,
- krate: CrateId,
- struct_id: chalk_db::AdtId,
- ) -> sync::Arc<chalk_db::AdtDatum>;
+ fn adt_datum(&self, krate: Crate, struct_id: chalk_db::AdtId) -> sync::Arc<chalk_db::AdtDatum>;
#[salsa::invoke(chalk_db::impl_datum_query)]
- fn impl_datum(
- &self,
- krate: CrateId,
- impl_id: chalk_db::ImplId,
- ) -> sync::Arc<chalk_db::ImplDatum>;
+ fn impl_datum(&self, krate: Crate, impl_id: chalk_db::ImplId)
+ -> sync::Arc<chalk_db::ImplDatum>;
#[salsa::invoke(chalk_db::fn_def_datum_query)]
fn fn_def_datum(&self, fn_def_id: FnDefId) -> sync::Arc<chalk_db::FnDefDatum>;
@@ -287,7 +280,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> + std::fmt::Debug {
#[salsa::invoke(chalk_db::associated_ty_value_query)]
fn associated_ty_value(
&self,
- krate: CrateId,
+ krate: Crate,
id: chalk_db::AssociatedTyValueId,
) -> sync::Arc<chalk_db::AssociatedTyValue>;
@@ -302,7 +295,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> + std::fmt::Debug {
#[salsa::invoke(crate::traits::trait_solve_query)]
fn trait_solve(
&self,
- krate: CrateId,
+ krate: Crate,
block: Option<BlockId>,
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
) -> Option<crate::Solution>;
@@ -310,7 +303,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> + std::fmt::Debug {
#[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
fn program_clauses_for_chalk_env(
&self,
- krate: CrateId,
+ krate: Crate,
block: Option<BlockId>,
env: chalk_ir::Environment<Interner>,
) -> chalk_ir::ProgramClauses<Interner>;
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index eed74e1eee..a0b1fe32ce 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -288,7 +288,7 @@ impl<'a> DeclValidator<'a> {
fn edition(&self, id: impl HasModule) -> span::Edition {
let krate = id.krate(self.db.upcast());
- self.db.crate_graph()[krate].edition
+ krate.data(self.db).edition
}
fn validate_struct(&mut self, struct_id: StructId) {
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 975143b29f..053d1cd41e 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -4,7 +4,7 @@
use std::fmt;
-use base_db::CrateId;
+use base_db::Crate;
use chalk_solve::rust_ir::AdtKind;
use either::Either;
use hir_def::{
@@ -630,7 +630,7 @@ fn missing_match_arms<'p>(
scrut_ty: &Ty,
witnesses: Vec<WitnessPat<'p>>,
arms_is_empty: bool,
- krate: CrateId,
+ krate: Crate,
) -> String {
struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, DisplayTarget);
impl fmt::Display for DisplayWitness<'_, '_> {
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index d2b908839c..84dd4be67f 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -160,7 +160,7 @@ impl<'a> UnsafeVisitor<'a> {
DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())),
_ => TargetFeatures::default(),
};
- let edition = db.crate_graph()[resolver.module().krate()].edition;
+ let edition = resolver.module().krate().data(db).edition;
Self {
db,
infer,
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 95ce36390d..2ae7e746ba 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -7,7 +7,7 @@ use std::{
mem,
};
-use base_db::CrateId;
+use base_db::Crate;
use chalk_ir::{BoundVar, Safety, TyKind};
use either::Either;
use hir_def::{
@@ -339,7 +339,7 @@ pub trait HirDisplay {
}
impl HirFormatter<'_> {
- pub fn krate(&self) -> CrateId {
+ pub fn krate(&self) -> Crate {
self.display_target.krate
}
@@ -408,13 +408,13 @@ impl HirFormatter<'_> {
#[derive(Debug, Clone, Copy)]
pub struct DisplayTarget {
- krate: CrateId,
+ krate: Crate,
pub edition: Edition,
}
impl DisplayTarget {
- pub fn from_crate(db: &dyn HirDatabase, krate: CrateId) -> Self {
- let edition = db.crate_graph()[krate].edition;
+ pub fn from_crate(db: &dyn HirDatabase, krate: Crate) -> Self {
+ let edition = krate.data(db).edition;
Self { krate, edition }
}
}
@@ -1711,7 +1711,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SizedByDefault {
NotSized,
- Sized { anchor: CrateId },
+ Sized { anchor: Crate },
}
impl SizedByDefault {
@@ -2266,8 +2266,8 @@ impl HirDisplayWithTypesMap for Path {
// Resolve `$crate` to the crate's display name.
// FIXME: should use the dependency name instead if available, but that depends on
// the crate invoking `HirDisplay`
- let crate_graph = f.db.crate_graph();
- let name = crate_graph[*id]
+ let crate_data = id.extra_data(f.db);
+ let name = crate_data
.display_name
.as_ref()
.map(|name| name.canonical_name())
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 9283c46d0f..50cac034e4 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -307,7 +307,7 @@ impl CapturedItem {
}
}
}
- if is_raw_identifier(&result, db.crate_graph()[owner.module(db.upcast()).krate()].edition) {
+ if is_raw_identifier(&result, owner.module(db.upcast()).krate().data(db).edition) {
result.insert_str(0, "r#");
}
result
@@ -316,7 +316,7 @@ impl CapturedItem {
pub fn display_place_source_code(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
let body = db.body(owner);
let krate = owner.krate(db.upcast());
- let edition = db.crate_graph()[krate].edition;
+ let edition = krate.data(db).edition;
let mut result = body[self.place.local].name.display(db.upcast(), edition).to_string();
for proj in &self.place.projections {
match proj {
@@ -368,7 +368,7 @@ impl CapturedItem {
pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
let body = db.body(owner);
let krate = owner.krate(db.upcast());
- let edition = db.crate_graph()[krate].edition;
+ let edition = krate.data(db).edition;
let mut result = body[self.place.local].name.display(db.upcast(), edition).to_string();
let mut field_need_paren = false;
for proj in &self.place.projections {
diff --git a/crates/hir-ty/src/layout/target.rs b/crates/hir-ty/src/layout/target.rs
index 7d77f6d073..e1e1c44996 100644
--- a/crates/hir-ty/src/layout/target.rs
+++ b/crates/hir-ty/src/layout/target.rs
@@ -1,6 +1,6 @@
//! Target dependent parameters needed for layouts
-use base_db::CrateId;
+use base_db::Crate;
use hir_def::layout::TargetDataLayout;
use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors};
use triomphe::Arc;
@@ -9,9 +9,9 @@ use crate::db::HirDatabase;
pub fn target_data_layout_query(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
) -> Result<Arc<TargetDataLayout>, Arc<str>> {
- match &db.crate_workspace_data()[&krate].data_layout {
+ match &krate.workspace_data(db).data_layout {
Ok(it) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) {
Ok(it) => Ok(Arc::new(it)),
Err(e) => {
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index ff7f034963..29ab0251f8 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -14,7 +14,7 @@ use std::{
ops::{self, Not as _},
};
-use base_db::CrateId;
+use base_db::Crate;
use chalk_ir::{
cast::Cast,
fold::{Shift, TypeFoldable},
@@ -801,7 +801,7 @@ impl<'a> TyLoweringContext<'a> {
}
}
- fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: CrateId) -> ImplTrait {
+ fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: Crate) -> ImplTrait {
cov_mark::hit!(lower_rpit);
let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
@@ -1863,8 +1863,11 @@ pub(crate) fn const_or_path_to_chalk<'g>(
.unwrap_or_else(|| unknown_const(expected_ty))
}
&ConstRef::Complex(it) => {
- let crate_data = &db.crate_graph()[resolver.krate()];
- if crate_data.env.get("__ra_is_test_fixture").is_none() && crate_data.origin.is_local()
+ let krate = resolver.krate();
+ // Keep the `&&` this way, because it's better to access the crate data, as we access it for
+ // a bunch of other things nevertheless.
+ if krate.data(db).origin.is_local()
+ && krate.env(db).get("__ra_is_test_fixture").is_none()
{
// FIXME: current `InTypeConstId` is very unstable, so we only use it in non local crate
// that are unlikely to be edited.
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index c5ad808acc..50b0fce62f 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -5,7 +5,7 @@
use std::ops::ControlFlow;
use arrayvec::ArrayVec;
-use base_db::CrateId;
+use base_db::Crate;
use chalk_ir::{cast::Cast, UniverseIndex, WithKind};
use hir_def::{
data::{adt::StructFlags, ImplData, TraitFlags},
@@ -148,7 +148,7 @@ pub struct TraitImpls {
}
impl TraitImpls {
- pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
+ pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: Crate) -> Arc<Self> {
let _p = tracing::info_span!("trait_impls_in_crate_query", ?krate).entered();
let mut impls = FxHashMap::default();
@@ -175,13 +175,11 @@ impl TraitImpls {
pub(crate) fn trait_impls_in_deps_query(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
) -> Arc<[Arc<Self>]> {
let _p = tracing::info_span!("trait_impls_in_deps_query", ?krate).entered();
- let crate_graph = db.crate_graph();
-
Arc::from_iter(
- crate_graph.transitive_deps(krate).map(|krate| db.trait_impls_in_crate(krate)),
+ db.transitive_deps(krate).into_iter().map(|krate| db.trait_impls_in_crate(krate)),
)
}
@@ -282,7 +280,7 @@ pub struct InherentImpls {
}
impl InherentImpls {
- pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
+ pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: Crate) -> Arc<Self> {
let _p = tracing::info_span!("inherent_impls_in_crate_query", ?krate).entered();
let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
@@ -367,16 +365,15 @@ impl InherentImpls {
pub(crate) fn incoherent_inherent_impl_crates(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
fp: TyFingerprint,
-) -> SmallVec<[CrateId; 2]> {
+) -> SmallVec<[Crate; 2]> {
let _p = tracing::info_span!("incoherent_inherent_impl_crates").entered();
let mut res = SmallVec::new();
- let crate_graph = db.crate_graph();
// should pass crate for finger print and do reverse deps
- for krate in crate_graph.transitive_deps(krate) {
+ for krate in db.transitive_deps(krate) {
let impls = db.inherent_impls_in_crate(krate);
if impls.map.get(&fp).is_some_and(|v| !v.is_empty()) {
res.push(krate);
@@ -386,11 +383,7 @@ pub(crate) fn incoherent_inherent_impl_crates(
res
}
-pub fn def_crates(
- db: &dyn HirDatabase,
- ty: &Ty,
- cur_crate: CrateId,
-) -> Option<SmallVec<[CrateId; 2]>> {
+pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<SmallVec<[Crate; 2]>> {
match ty.kind(Interner) {
&TyKind::Adt(AdtId(def_id), _) => {
let rustc_has_incoherent_inherent_impls = match def_id {
@@ -1226,7 +1219,7 @@ fn iterate_trait_method_candidates(
{
// FIXME: this should really be using the edition of the method name's span, in case it
// comes from a macro
- if !db.crate_graph()[krate].edition.at_least_2021() {
+ if !krate.data(db).edition.at_least_2021() {
continue;
}
}
@@ -1239,7 +1232,7 @@ fn iterate_trait_method_candidates(
{
// FIXME: this should really be using the edition of the method name's span, in case it
// comes from a macro
- if !db.crate_graph()[krate].edition.at_least_2024() {
+ if !krate.data(db).edition.at_least_2024() {
continue;
}
}
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index ae454fbe52..7faa23f818 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -12,7 +12,7 @@ use crate::{
CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap,
Substitution, TraitEnvironment, Ty, TyExt, TyKind,
};
-use base_db::CrateId;
+use base_db::Crate;
use chalk_ir::Mutability;
use either::Either;
use hir_def::{
@@ -143,7 +143,7 @@ impl<V, T> ProjectionElem<V, T> {
mut base: Ty,
db: &dyn HirDatabase,
closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
- krate: CrateId,
+ krate: Crate,
) -> Ty {
// we only bail on mir building when there are type mismatches
// but error types may pop up resulting in us still attempting to build the mir
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index c9d62f566c..597e6a3ef0 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -2,7 +2,7 @@
use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range};
-use base_db::CrateId;
+use base_db::Crate;
use chalk_ir::{cast::Cast, Mutability};
use either::Either;
use hir_def::{
@@ -186,7 +186,7 @@ pub struct Evaluator<'a> {
cached_fn_trait_func: Option<FunctionId>,
cached_fn_mut_trait_func: Option<FunctionId>,
cached_fn_once_trait_func: Option<FunctionId>,
- crate_id: CrateId,
+ crate_id: Crate,
// FIXME: This is a workaround, see the comment on `interpret_mir`
assert_placeholder_ty_is_unused: bool,
/// A general limit on execution, to prevent non terminating programs from breaking r-a main process
@@ -2785,7 +2785,7 @@ impl Evaluator<'_> {
let db = self.db.upcast();
let loc = variant.lookup(db);
let enum_loc = loc.parent.lookup(db);
- let edition = self.db.crate_graph()[self.crate_id].edition;
+ let edition = self.crate_id.data(self.db).edition;
let name = format!(
"{}::{}",
enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast(), edition),
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index f61ecabb7e..346dea8252 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -569,7 +569,7 @@ impl Evaluator<'_> {
}
String::from_utf8_lossy(&name_buf)
};
- let value = self.db.crate_graph()[self.crate_id].env.get(&name);
+ let value = self.crate_id.env(self.db).get(&name);
match value {
None => {
// Write null as fail
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 17f1da0c9f..57d4baa137 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -2,7 +2,7 @@
use std::{fmt::Write, iter, mem};
-use base_db::{salsa::Cycle, CrateId};
+use base_db::{salsa::Cycle, Crate};
use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind};
use hir_def::{
data::adt::{StructKind, VariantData},
@@ -1920,10 +1920,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
}
fn edition(&self) -> Edition {
- self.db.crate_graph()[self.krate()].edition
+ self.krate().data(self.db).edition
}
- fn krate(&self) -> CrateId {
+ fn krate(&self) -> Crate {
self.owner.krate(self.db.upcast())
}
@@ -2121,7 +2121,7 @@ pub fn mir_body_for_closure_query(
pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<MirBody>> {
let krate = def.krate(db.upcast());
- let edition = db.crate_graph()[krate].edition;
+ let edition = krate.data(db).edition;
let detail = match def {
DefWithBodyId::FunctionId(it) => {
db.function_data(it).name.display(db.upcast(), edition).to_string()
diff --git a/crates/hir-ty/src/test_db.rs b/crates/hir-ty/src/test_db.rs
index b18a057ba0..68d0c8cd5a 100644
--- a/crates/hir-ty/src/test_db.rs
+++ b/crates/hir-ty/src/test_db.rs
@@ -3,8 +3,8 @@
use std::{fmt, panic, sync::Mutex};
use base_db::{
- FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId,
- SourceRootInput, Upcast,
+ CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase,
+ SourceRoot, SourceRootId, SourceRootInput, Upcast,
};
use hir_def::{db::DefDatabase, ModuleId};
@@ -21,6 +21,7 @@ use triomphe::Arc;
pub(crate) struct TestDB {
storage: salsa::Storage<Self>,
files: Arc<base_db::Files>,
+ crates_map: Arc<CratesMap>,
events: Arc<Mutex<Option<Vec<salsa::Event>>>>,
}
@@ -30,8 +31,12 @@ impl Default for TestDB {
storage: Default::default(),
events: Default::default(),
files: Default::default(),
+ crates_map: Default::default(),
};
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
+ // This needs to be here otherwise `CrateGraphBuilder` panics.
+ this.set_all_crates(Arc::new(Box::new([])));
+ CrateGraphBuilder::default().set_in_db(&mut this);
this
}
}
@@ -115,6 +120,10 @@ impl SourceDatabase for TestDB {
let files = Arc::clone(&self.files);
files.set_file_source_root_with_durability(self, id, source_root_id, durability);
}
+
+ fn crates_map(&self) -> Arc<CratesMap> {
+ self.crates_map.clone()
+ }
}
#[salsa::db]
@@ -151,8 +160,7 @@ impl TestDB {
&self,
) -> FxHashMap<EditionedFileId, Vec<(TextRange, String)>> {
let mut files = Vec::new();
- let crate_graph = self.crate_graph();
- for krate in crate_graph.iter() {
+ for &krate in self.all_crates().iter() {
let crate_def_map = self.crate_def_map(krate);
for (module_id, _) in crate_def_map.modules() {
let file_id = crate_def_map[module_id].origin.file_id();
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 2622904058..cdb9e9edf8 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -15,7 +15,7 @@ mod type_alias_impl_traits;
use std::env;
use std::sync::LazyLock;
-use base_db::{CrateId, SourceDatabase};
+use base_db::{Crate, SourceDatabase};
use expect_test::Expect;
use hir_def::{
db::DefDatabase,
@@ -124,7 +124,7 @@ fn check_impl(
}
assert!(had_annotations || allow_none, "no `//^` annotations found");
- let mut defs: Vec<(DefWithBodyId, CrateId)> = Vec::new();
+ let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
for file_id in files {
let module = db.module_for_file_opt(file_id);
let module = match module {
@@ -302,7 +302,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let mut infer_def = |inference_result: Arc<InferenceResult>,
body: Arc<Body>,
body_source_map: Arc<BodySourceMap>,
- krate: CrateId| {
+ krate: Crate| {
let display_target = DisplayTarget::from_crate(&db, krate);
let mut types: Vec<(InFile<SyntaxNode>, &Ty)> = Vec::new();
let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch)> = Vec::new();
@@ -391,7 +391,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let module = db.module_for_file(file_id);
let def_map = module.def_map(&db);
- let mut defs: Vec<(DefWithBodyId, CrateId)> = Vec::new();
+ let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
visit_module(&db, &def_map, module.local_id, &mut |it| {
let def = match it {
ModuleDefId::FunctionId(it) => it.into(),
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 0135e0a409..f8db6a8298 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -7,7 +7,7 @@ use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData};
use chalk_recursive::Cache;
use chalk_solve::{logging_db::LoggingRustIrDatabase, rust_ir, Solver};
-use base_db::CrateId;
+use base_db::Crate;
use hir_def::{
lang_item::{LangItem, LangItemTarget},
BlockId, TraitId,
@@ -30,7 +30,7 @@ const CHALK_SOLVER_FUEL: i32 = 1000;
#[derive(Debug, Copy, Clone)]
pub(crate) struct ChalkContext<'a> {
pub(crate) db: &'a dyn HirDatabase,
- pub(crate) krate: CrateId,
+ pub(crate) krate: Crate,
pub(crate) block: Option<BlockId>,
}
@@ -48,7 +48,7 @@ fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
/// we assume that `T: Default`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TraitEnvironment {
- pub krate: CrateId,
+ pub krate: Crate,
pub block: Option<BlockId>,
// FIXME make this a BTreeMap
traits_from_clauses: Box<[(Ty, TraitId)]>,
@@ -56,7 +56,7 @@ pub struct TraitEnvironment {
}
impl TraitEnvironment {
- pub fn empty(krate: CrateId) -> Arc<Self> {
+ pub fn empty(krate: Crate) -> Arc<Self> {
Arc::new(TraitEnvironment {
krate,
block: None,
@@ -66,7 +66,7 @@ impl TraitEnvironment {
}
pub fn new(
- krate: CrateId,
+ krate: Crate,
block: Option<BlockId>,
traits_from_clauses: Box<[(Ty, TraitId)]>,
env: chalk_ir::Environment<Interner>,
@@ -109,7 +109,7 @@ pub(crate) fn normalize_projection_query(
/// Solve a trait goal using Chalk.
pub(crate) fn trait_solve_query(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
block: Option<BlockId>,
goal: Canonical<InEnvironment<Goal>>,
) -> Option<Solution> {
@@ -148,7 +148,7 @@ pub(crate) fn trait_solve_query(
fn solve(
db: &dyn HirDatabase,
- krate: CrateId,
+ krate: Crate,
block: Option<BlockId>,
goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>>,
) -> Option<chalk_solve::Solution<Interner>> {
@@ -294,7 +294,7 @@ impl FnTrait {
}
}
- pub fn get_id(self, db: &dyn HirDatabase, krate: CrateId) -> Option<TraitId> {
+ pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<TraitId> {
let target = db.lang_item(krate, self.lang_item())?;
match target {
LangItemTarget::Trait(t) => Some(t),
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 89d89fe223..b90f4e4d7f 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -3,7 +3,7 @@
use std::{hash::Hash, iter};
-use base_db::CrateId;
+use base_db::Crate;
use chalk_ir::{
fold::{FallibleTypeFolder, Shift},
DebruijnIndex,
@@ -34,10 +34,7 @@ use crate::{
TraitRefExt, Ty, WhereClause,
};
-pub(crate) fn fn_traits(
- db: &dyn DefDatabase,
- krate: CrateId,
-) -> impl Iterator<Item = TraitId> + '_ {
+pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator<Item = TraitId> + '_ {
[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]
.into_iter()
.filter_map(move |lang| db.lang_item(krate, lang))
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 72df07ef8c..891d2fd2ba 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -30,7 +30,7 @@ macro_rules! from_id {
}
from_id![
- (base_db::CrateId, crate::Crate),
+ (base_db::Crate, crate::Crate),
(hir_def::ModuleId, crate::Module),
(hir_def::StructId, crate::Struct),
(hir_def::UnionId, crate::Union),
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index dbe743e7e2..5da2b5ed09 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -39,7 +39,7 @@ use std::{
};
use arrayvec::ArrayVec;
-use base_db::{CrateDisplayName, CrateId, CrateOrigin, LangCrateOrigin};
+use base_db::{CrateDisplayName, CrateOrigin, LangCrateOrigin};
use either::Either;
use hir_def::{
data::{adt::VariantData, TraitFlags},
@@ -176,7 +176,7 @@ use {
/// root module.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Crate {
- pub(crate) id: CrateId,
+ pub(crate) id: base_db::Crate,
}
#[derive(Debug)]
@@ -187,7 +187,7 @@ pub struct CrateDependency {
impl Crate {
pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
- db.crate_graph()[self.id].origin.clone()
+ self.id.data(db).origin.clone()
}
pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
@@ -195,7 +195,8 @@ impl Crate {
}
pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
- db.crate_graph()[self.id]
+ self.id
+ .data(db)
.dependencies
.iter()
.map(|dep| {
@@ -207,12 +208,11 @@ impl Crate {
}
pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
- let crate_graph = db.crate_graph();
- crate_graph
+ let all_crates = db.all_crates();
+ all_crates
.iter()
- .filter(|&krate| {
- crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id)
- })
+ .copied()
+ .filter(|&krate| krate.data(db).dependencies.iter().any(|it| it.crate_id == self.id))
.map(|id| Crate { id })
.collect()
}
@@ -221,7 +221,7 @@ impl Crate {
self,
db: &dyn HirDatabase,
) -> impl Iterator<Item = Crate> {
- db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
+ db.transitive_rev_deps(self.id).into_iter().map(|id| Crate { id })
}
pub fn root_module(self) -> Module {
@@ -234,19 +234,19 @@ impl Crate {
}
pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
- db.crate_graph()[self.id].root_file_id
+ self.id.data(db).root_file_id
}
pub fn edition(self, db: &dyn HirDatabase) -> Edition {
- db.crate_graph()[self.id].edition
+ self.id.data(db).edition
}
pub fn version(self, db: &dyn HirDatabase) -> Option<String> {
- db.crate_graph()[self.id].version.clone()
+ self.id.extra_data(db).version.clone()
}
pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
- db.crate_graph()[self.id].display_name.clone()
+ self.id.extra_data(db).display_name.clone()
}
pub fn query_external_importables(
@@ -264,7 +264,7 @@ impl Crate {
}
pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
- db.crate_graph().iter().map(|id| Crate { id }).collect()
+ db.all_crates().iter().map(|&id| Crate { id }).collect()
}
/// Try to get the root URL of the documentation of a crate.
@@ -276,12 +276,12 @@ impl Crate {
}
pub fn cfg(&self, db: &dyn HirDatabase) -> Arc<CfgOptions> {
- db.crate_graph()[self.id].cfg_options.clone()
+ Arc::clone(self.id.cfg_options(db))
}
- pub fn potential_cfg(&self, db: &dyn HirDatabase) -> Arc<CfgOptions> {
- let data = &db.crate_graph()[self.id];
- data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone())
+ pub fn potential_cfg<'db>(&self, db: &'db dyn HirDatabase) -> &'db CfgOptions {
+ let data = self.id.extra_data(db);
+ data.potential_cfg_options.as_ref().unwrap_or_else(|| self.id.cfg_options(db))
}
pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget {
@@ -289,11 +289,12 @@ impl Crate {
}
fn core(db: &dyn HirDatabase) -> Option<Crate> {
- let crate_graph = db.crate_graph();
- let result = crate_graph
+ let result = db
+ .all_crates()
.iter()
+ .copied()
.find(|&krate| {
- matches!(crate_graph[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core))
+ matches!(krate.data(db).origin, CrateOrigin::Lang(LangCrateOrigin::Core))
})
.map(Crate::from);
result
@@ -490,9 +491,7 @@ impl HasCrate for ModuleDef {
fn krate(&self, db: &dyn HirDatabase) -> Crate {
match self.module(db) {
Some(module) => module.krate(),
- None => Crate::core(db).unwrap_or_else(|| {
- (*db.crate_graph().crates_in_topological_order().last().unwrap()).into()
- }),
+ None => Crate::core(db).unwrap_or_else(|| db.all_crates()[0].into()),
}
}
}
@@ -611,7 +610,7 @@ impl Module {
style_lints: bool,
) {
let _p = tracing::info_span!("diagnostics", name = ?self.name(db)).entered();
- let edition = db.crate_graph()[self.id.krate()].edition;
+ let edition = self.id.krate().data(db).edition;
let def_map = self.id.def_map(db.upcast());
for diag in def_map.diagnostics() {
if diag.in_module != self.id.local_id {
@@ -970,7 +969,7 @@ fn emit_macro_def_diagnostics(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>
return;
};
let krate = HasModule::krate(&m.id, db.upcast());
- let edition = db.crate_graph()[krate].edition;
+ let edition = krate.data(db).edition;
emit_def_diagnostic_(
db,
acc,
@@ -3027,7 +3026,8 @@ impl BuiltinType {
}
pub fn ty(self, db: &dyn HirDatabase) -> Type {
- Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner))
+ let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]);
+ Type::new_for_crate(core, TyBuilder::builtin(self.inner))
}
pub fn name(self) -> Name {
@@ -3968,7 +3968,7 @@ impl DeriveHelper {
// FIXME: Wrong name? This is could also be a registered attribute
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct BuiltinAttr {
- krate: Option<CrateId>,
+ krate: Option<base_db::Crate>,
idx: u32,
}
@@ -4014,7 +4014,7 @@ impl BuiltinAttr {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ToolModule {
- krate: CrateId,
+ krate: base_db::Crate,
idx: u32,
}
@@ -4732,7 +4732,7 @@ impl Type {
Type { env: environment, ty }
}
- pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type {
+ pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty) -> Type {
Type { env: TraitEnvironment::empty(krate), ty }
}
@@ -4794,7 +4794,7 @@ impl Type {
Type { env: ty.env, ty: TyBuilder::slice(ty.ty) }
}
- pub fn new_tuple(krate: CrateId, tys: &[Type]) -> Type {
+ pub fn new_tuple(krate: base_db::Crate, tys: &[Type]) -> Type {
let tys = tys.iter().map(|it| it.ty.clone());
Type { env: TraitEnvironment::empty(krate), ty: TyBuilder::tuple_with(tys) }
}
@@ -4826,7 +4826,7 @@ impl Type {
pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool {
return go(db, self.env.krate, &self.ty);
- fn go(db: &dyn HirDatabase, krate: CrateId, ty: &Ty) -> bool {
+ fn go(db: &dyn HirDatabase, krate: base_db::Crate, ty: &Ty) -> bool {
match ty.kind(Interner) {
// Reference itself
TyKind::Ref(_, _, _) => true,
@@ -6209,7 +6209,7 @@ impl HasContainer for Module {
let def_map = self.id.def_map(db.upcast());
match def_map[self.id.local_id].parent {
Some(parent_id) => ItemContainer::Module(Module { id: def_map.module_id(parent_id) }),
- None => ItemContainer::Crate(def_map.krate()),
+ None => ItemContainer::Crate(def_map.krate().into()),
}
}
}
@@ -6289,7 +6289,7 @@ pub enum ItemContainer {
Impl(Impl),
Module(Module),
ExternBlock(ExternBlock),
- Crate(CrateId),
+ Crate(Crate),
}
/// Subset of `ide_db::Definition` that doc links can resolve to.
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index aeeb3f9790..6378eebd24 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -318,7 +318,7 @@ impl<'db> SemanticsImpl<'db> {
pub fn first_crate_or_default(&self, file: FileId) -> Crate {
match self.file_to_module_defs(file).next() {
Some(module) => module.krate(),
- None => (*self.db.crate_graph().crates_in_topological_order().last().unwrap()).into(),
+ None => (*self.db.all_crates().last().unwrap()).into(),
}
}
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index fa8153ad21..cc8aa1f1a1 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -77,10 +77,7 @@ impl<'a> SymbolCollector<'a> {
symbols: Default::default(),
work: Default::default(),
current_container_name: None,
- display_target: DisplayTarget::from_crate(
- db,
- *db.crate_graph().crates_in_topological_order().last().unwrap(),
- ),
+ display_target: DisplayTarget::from_crate(db, *db.all_crates().last().unwrap()),
}
}
diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs
index 9e09f198fe..5a791c58bf 100644
--- a/crates/ide-assists/src/handlers/inline_call.rs
+++ b/crates/ide-assists/src/handlers/inline_call.rs
@@ -7,7 +7,7 @@ use hir::{
sym, FileRange, PathResolution, Semantics, TypeInfo,
};
use ide_db::{
- base_db::CrateId,
+ base_db::Crate,
defs::Definition,
imports::insert_use::remove_path_if_in_use_stmt,
path_transform::PathTransform,
@@ -251,11 +251,11 @@ struct CallInfo {
node: ast::CallableExpr,
arguments: Vec<ast::Expr>,
generic_arg_list: Option<ast::GenericArgList>,
- krate: CrateId,
+ krate: Crate,
}
impl CallInfo {
- fn from_name_ref(name_ref: ast::NameRef, krate: CrateId) -> Option<CallInfo> {
+ fn from_name_ref(name_ref: ast::NameRef, krate: Crate) -> Option<CallInfo> {
let parent = name_ref.syntax().parent()?;
if let Some(call) = ast::MethodCallExpr::cast(parent.clone()) {
let receiver = call.receiver()?;
diff --git a/crates/ide-db/src/apply_change.rs b/crates/ide-db/src/apply_change.rs
index d8b2656782..4c8940db95 100644
--- a/crates/ide-db/src/apply_change.rs
+++ b/crates/ide-db/src/apply_change.rs
@@ -233,7 +233,13 @@ impl RootDatabase {
// // SourceDatabase
// base_db::ParseQuery
// base_db::ParseErrorsQuery
- // base_db::CrateGraphQuery
+ // base_db::AllCratesQuery
+ // base_db::InternUniqueCrateDataQuery
+ // base_db::InternUniqueCrateDataLookupQuery
+ // base_db::CrateDataQuery
+ // base_db::ExtraCrateDataQuery
+ // base_db::CrateCfgQuery
+ // base_db::CrateEnvQuery
// base_db::CrateWorkspaceDataQuery
// // SourceDatabaseExt
diff --git a/crates/ide-db/src/famous_defs.rs b/crates/ide-db/src/famous_defs.rs
index af4c10f8ea..fe4662785a 100644
--- a/crates/ide-db/src/famous_defs.rs
+++ b/crates/ide-db/src/famous_defs.rs
@@ -1,6 +1,6 @@
//! See [`FamousDefs`].
-use base_db::{CrateOrigin, LangCrateOrigin, RootQueryDb as _};
+use base_db::{CrateOrigin, LangCrateOrigin};
use hir::{Crate, Enum, Function, Macro, Module, ScopeDef, Semantics, Trait};
use crate::RootDatabase;
@@ -198,11 +198,10 @@ impl FamousDefs<'_, '_> {
fn find_lang_crate(&self, origin: LangCrateOrigin) -> Option<Crate> {
let krate = self.1;
let db = self.0.db;
- let crate_graph = self.0.db.crate_graph();
let res = krate
.dependencies(db)
.into_iter()
- .find(|dep| crate_graph[dep.krate.into()].origin == CrateOrigin::Lang(origin))?
+ .find(|dep| dep.krate.origin(db) == CrateOrigin::Lang(origin))?
.krate;
Some(res)
}
diff --git a/crates/ide-db/src/lib.rs b/crates/ide-db/src/lib.rs
index 2516a9d0aa..414cc6cd18 100644
--- a/crates/ide-db/src/lib.rs
+++ b/crates/ide-db/src/lib.rs
@@ -51,9 +51,8 @@ use salsa::Durability;
use std::{fmt, mem::ManuallyDrop};
use base_db::{
- query_group::{self},
- FileSourceRootInput, FileText, Files, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId,
- SourceRootInput, Upcast,
+ query_group, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, RootQueryDb,
+ SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast,
};
use hir::{
db::{DefDatabase, ExpandDatabase, HirDatabase},
@@ -85,6 +84,7 @@ pub struct RootDatabase {
// compile times of all `ide_*` and downstream crates suffer greatly.
storage: ManuallyDrop<salsa::Storage<Self>>,
files: Arc<Files>,
+ crates_map: Arc<CratesMap>,
}
impl std::panic::RefUnwindSafe for RootDatabase {}
@@ -102,7 +102,11 @@ impl Drop for RootDatabase {
impl Clone for RootDatabase {
fn clone(&self) -> Self {
- Self { storage: self.storage.clone(), files: self.files.clone() }
+ Self {
+ storage: self.storage.clone(),
+ files: self.files.clone(),
+ crates_map: self.crates_map.clone(),
+ }
}
}
@@ -194,6 +198,10 @@ impl SourceDatabase for RootDatabase {
let files = Arc::clone(&self.files);
files.set_file_source_root_with_durability(self, id, source_root_id, durability);
}
+
+ fn crates_map(&self) -> Arc<CratesMap> {
+ self.crates_map.clone()
+ }
}
impl Default for RootDatabase {
@@ -207,8 +215,11 @@ impl RootDatabase {
let mut db = RootDatabase {
storage: ManuallyDrop::new(salsa::Storage::default()),
files: Default::default(),
+ crates_map: Default::default(),
};
- db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
+ // This needs to be here otherwise `CrateGraphBuilder` will panic.
+ db.set_all_crates(Arc::new(Box::new([])));
+ CrateGraphBuilder::default().set_in_db(&mut db);
db.set_proc_macros_with_durability(Default::default(), Durability::HIGH);
db.set_local_roots_with_durability(Default::default(), Durability::HIGH);
db.set_library_roots_with_durability(Default::default(), Durability::HIGH);
@@ -258,7 +269,11 @@ impl RootDatabase {
}
pub fn snapshot(&self) -> Self {
- Self { storage: self.storage.clone(), files: self.files.clone() }
+ Self {
+ storage: self.storage.clone(),
+ files: self.files.clone(),
+ crates_map: self.crates_map.clone(),
+ }
}
}
diff --git a/crates/ide-db/src/prime_caches.rs b/crates/ide-db/src/prime_caches.rs
index 74d79cd695..cd3099fe93 100644
--- a/crates/ide-db/src/prime_caches.rs
+++ b/crates/ide-db/src/prime_caches.rs
@@ -11,7 +11,7 @@ use itertools::Itertools;
use salsa::{Cancelled, Database};
use crate::{
- base_db::{CrateId, RootQueryDb},
+ base_db::{Crate, RootQueryDb},
symbol_index::SymbolsDatabase,
FxIndexMap, RootDatabase,
};
@@ -35,20 +35,22 @@ pub fn parallel_prime_caches(
) {
let _p = tracing::info_span!("parallel_prime_caches").entered();
- let graph = db.crate_graph();
let mut crates_to_prime = {
+ // FIXME: We already have the crate list topologically sorted (but without the things
+ // `TopologicalSortIter` gives us). Maybe there is a way to avoid using it and rip it out
+ // of the codebase?
let mut builder = topologic_sort::TopologicalSortIter::builder();
- for crate_id in graph.iter() {
- builder.add(crate_id, graph[crate_id].dependencies.iter().map(|d| d.crate_id));
+ for &crate_id in db.all_crates().iter() {
+ builder.add(crate_id, crate_id.data(db).dependencies.iter().map(|d| d.crate_id));
}
builder.build()
};
enum ParallelPrimeCacheWorkerProgress {
- BeginCrate { crate_id: CrateId, crate_name: Symbol },
- EndCrate { crate_id: CrateId },
+ BeginCrate { crate_id: Crate, crate_name: Symbol },
+ EndCrate { crate_id: Crate },
}
// We split off def map computation from other work,
@@ -108,16 +110,14 @@ pub fn parallel_prime_caches(
while crates_done < crates_total {
db.unwind_if_revision_cancelled();
- for crate_id in &mut crates_to_prime {
- let krate = &graph[crate_id];
- let name = krate
- .display_name
- .as_deref()
- .cloned()
- .unwrap_or_else(|| Symbol::integer(crate_id.into_raw().into_u32() as usize));
- if krate.origin.is_lang() {
- additional_phases.push((crate_id, name.clone(), PrimingPhase::ImportMap));
- } else if krate.origin.is_local() {
+ for krate in &mut crates_to_prime {
+ let name = krate.extra_data(db).display_name.as_deref().cloned().unwrap_or_else(|| {
+ Symbol::integer(salsa::plumbing::AsId::as_id(&krate).as_u32() as usize)
+ });
+ let origin = &krate.data(db).origin;
+ if origin.is_lang() {
+ additional_phases.push((krate, name.clone(), PrimingPhase::ImportMap));
+ } else if origin.is_local() {
// Compute the symbol search index.
// This primes the cache for `ide_db::symbol_index::world_symbols()`.
//
@@ -127,10 +127,10 @@ pub fn parallel_prime_caches(
// FIXME: We should do it unconditionally if the configuration is set to default to
// searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we
// would need to pipe that configuration information down here.
- additional_phases.push((crate_id, name.clone(), PrimingPhase::CrateSymbols));
+ additional_phases.push((krate, name.clone(), PrimingPhase::CrateSymbols));
}
- work_sender.send((crate_id, name, PrimingPhase::DefMap)).ok();
+ work_sender.send((krate, name, PrimingPhase::DefMap)).ok();
}
// recv_timeout is somewhat a hack, we need a way to from this thread check to see if the current salsa revision
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 81df0c0f0f..4f9ef05b20 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -162,13 +162,13 @@ impl SearchScope {
fn crate_graph(db: &RootDatabase) -> SearchScope {
let mut entries = FxHashMap::default();
- let graph = db.crate_graph();
- for krate in graph.iter() {
- let root_file = graph[krate].root_file_id;
- let source_root = db.file_source_root(root_file).source_root_id(db);
+ let all_crates = db.all_crates();
+ for &krate in all_crates.iter() {
+ let crate_data = krate.data(db);
+ let source_root = db.file_source_root(crate_data.root_file_id).source_root_id(db);
let source_root = db.source_root(source_root).source_root(db);
entries.extend(
- source_root.iter().map(|id| (EditionedFileId::new(id, graph[krate].edition), None)),
+ source_root.iter().map(|id| (EditionedFileId::new(id, crate_data.edition), None)),
);
}
SearchScope { entries }
diff --git a/crates/ide-db/src/test_data/test_doc_alias.txt b/crates/ide-db/src/test_data/test_doc_alias.txt
index 0cae7f367c..1e2d4f1ab9 100644
--- a/crates/ide-db/src/test_data/test_doc_alias.txt
+++ b/crates/ide-db/src/test_data/test_doc_alias.txt
@@ -2,7 +2,9 @@
(
Module {
id: ModuleId {
- krate: Idx::<CrateData>(0),
+ krate: Crate {
+ [salsa id]: Id(2c00),
+ },
block: None,
local_id: Idx::<ModuleData>(0),
},
diff --git a/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 48de1fb837..1a77052b18 100644
--- a/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -2,7 +2,9 @@
(
Module {
id: ModuleId {
- krate: Idx::<CrateData>(0),
+ krate: Crate {
+ [salsa id]: Id(2c00),
+ },
block: None,
local_id: Idx::<ModuleData>(0),
},
@@ -532,7 +534,9 @@
def: Module(
Module {
id: ModuleId {
- krate: Idx::<CrateData>(0),
+ krate: Crate {
+ [salsa id]: Id(2c00),
+ },
block: None,
local_id: Idx::<ModuleData>(1),
},
@@ -565,7 +569,9 @@
def: Module(
Module {
id: ModuleId {
- krate: Idx::<CrateData>(0),
+ krate: Crate {
+ [salsa id]: Id(2c00),
+ },
block: None,
local_id: Idx::<ModuleData>(2),
},
@@ -827,7 +833,9 @@
(
Module {
id: ModuleId {
- krate: Idx::<CrateData>(0),
+ krate: Crate {
+ [salsa id]: Id(2c00),
+ },
block: None,
local_id: Idx::<ModuleData>(1),
},
@@ -871,7 +879,9 @@
(
Module {
id: ModuleId {
- krate: Idx::<CrateData>(0),
+ krate: Crate {
+ [salsa id]: Id(2c00),
+ },
block: None,
local_id: Idx::<ModuleData>(2),
},
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 5ce3336eb4..f4ced736b3 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -389,9 +389,9 @@ pub fn semantic_diagnostics(
module.and_then(|m| db.toolchain_channel(m.krate().into())),
Some(ReleaseChannel::Nightly) | None
);
- let krate = module.map(|module| module.krate()).unwrap_or_else(|| {
- (*db.crate_graph().crates_in_topological_order().last().unwrap()).into()
- });
+ let krate = module
+ .map(|module| module.krate())
+ .unwrap_or_else(|| (*db.all_crates().last().unwrap()).into());
let display_target = krate.to_display_target(db);
let ctx = DiagnosticsContext { config, sema, resolve, edition, is_nightly, display_target };
diff --git a/crates/ide-ssr/src/matching.rs b/crates/ide-ssr/src/matching.rs
index d32ba06f1e..48d2431a11 100644
--- a/crates/ide-ssr/src/matching.rs
+++ b/crates/ide-ssr/src/matching.rs
@@ -626,11 +626,11 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
match_error!("Failed to get receiver type for `{}`", expr.syntax().text())
})?
.original;
- let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| {
- hir::Crate::from(
- *self.sema.db.crate_graph().crates_in_topological_order().last().unwrap(),
- )
- });
+ let krate = self
+ .sema
+ .scope(expr.syntax())
+ .map(|it| it.krate())
+ .unwrap_or_else(|| hir::Crate::from(*self.sema.db.all_crates().last().unwrap()));
let res = code_type
.autoderef(self.sema.db)
.enumerate()
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 0acb129e93..9bdc2e7d13 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -504,9 +504,7 @@ fn get_doc_base_urls(
let Some(krate) = krate else { return Default::default() };
let Some(display_name) = krate.display_name(db) else { return Default::default() };
- let crate_data = &db.crate_graph()[krate.into()];
-
- let (web_base, local_base) = match &crate_data.origin {
+ let (web_base, local_base) = match krate.origin(db) {
// std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself.
// FIXME: Use the toolchains channel instead of nightly
CrateOrigin::Lang(
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index 2347e2e8a3..3771efc17b 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -1,8 +1,8 @@
use hir::db::ExpandDatabase;
use hir::{ExpandResult, InFile, MacroFileIdExt, Semantics};
-use ide_db::base_db::CrateId;
use ide_db::{
- helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, FileId, RootDatabase,
+ base_db::Crate, helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, FileId,
+ RootDatabase,
};
use span::{Edition, SpanMap, SyntaxContextId, TextRange, TextSize};
use stdx::format_to;
@@ -208,7 +208,7 @@ fn format(
file_id: FileId,
expanded: SyntaxNode,
span_map: &SpanMap<SyntaxContextId>,
- krate: CrateId,
+ krate: Crate,
) -> String {
let expansion = prettify_macro_expansion(db, expanded, span_map, krate).to_string();
@@ -249,7 +249,7 @@ fn _format(
let upcast_db = ide_db::base_db::Upcast::<dyn ide_db::base_db::RootQueryDb>::upcast(db);
let &crate_id = upcast_db.relevant_crates(file_id).iter().next()?;
- let edition = upcast_db.crate_graph()[crate_id].edition;
+ let edition = crate_id.data(upcast_db).edition;
#[allow(clippy::disallowed_methods)]
let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path());
diff --git a/crates/ide/src/fetch_crates.rs b/crates/ide/src/fetch_crates.rs
index 0e5bb89b6b..b682c4bc0f 100644
--- a/crates/ide/src/fetch_crates.rs
+++ b/crates/ide/src/fetch_crates.rs
@@ -20,21 +20,24 @@ pub struct CrateInfo {
//
// ![Show Dependency Tree](https://user-images.githubusercontent.com/5748995/229394139-2625beab-f4c9-484b-84ed-ad5dee0b1e1a.png)
pub(crate) fn fetch_crates(db: &RootDatabase) -> FxIndexSet<CrateInfo> {
- let crate_graph = db.crate_graph();
- crate_graph
+ db.all_crates()
.iter()
- .map(|crate_id| &crate_graph[crate_id])
- .filter(|&data| !matches!(data.origin, CrateOrigin::Local { .. }))
- .map(crate_info)
+ .copied()
+ .map(|crate_id| (crate_id.data(db), crate_id.extra_data(db)))
+ .filter(|(data, _)| !matches!(data.origin, CrateOrigin::Local { .. }))
+ .map(|(data, extra_data)| crate_info(data, extra_data))
.collect()
}
-fn crate_info(data: &ide_db::base_db::CrateData) -> CrateInfo {
- let crate_name = crate_name(data);
- let version = data.version.clone();
+fn crate_info(
+ data: &ide_db::base_db::BuiltCrateData,
+ extra_data: &ide_db::base_db::ExtraCrateData,
+) -> CrateInfo {
+ let crate_name = crate_name(extra_data);
+ let version = extra_data.version.clone();
CrateInfo { name: crate_name, version, root_file_id: data.root_file_id }
}
-fn crate_name(data: &ide_db::base_db::CrateData) -> Option<String> {
+fn crate_name(data: &ide_db::base_db::ExtraCrateData) -> Option<String> {
data.display_name.as_ref().map(|it| it.canonical_name().as_str().to_owned())
}
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 5d888ceb5e..1d807fb14c 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -8,7 +8,6 @@ use hir::{
MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef,
};
use ide_db::{
- base_db::RootQueryDb,
defs::Definition,
documentation::HasDocs,
famous_defs::FamousDefs,
@@ -466,8 +465,7 @@ pub(super) fn path(
item_name: Option<String>,
edition: Edition,
) -> String {
- let crate_name =
- db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
+ let crate_name = module.krate().display_name(db).as_ref().map(|it| it.to_string());
let module_path = module
.path_to_root(db)
.into_iter()
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 736d355ef2..afddeb6dea 100644
--- a/crates/ide/src/hover/tests.rs
+++ b/crates/ide/src/hover/tests.rs
@@ -9252,7 +9252,7 @@ fn main() {
S
```
___
- Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S>"#]],
+ Implements notable traits: Future<Output = u32>, Iterator<Item = S>, Notable"#]],
);
}
diff --git a/crates/ide/src/inlay_hints/bind_pat.rs b/crates/ide/src/inlay_hints/bind_pat.rs
index 592c860396..aab8a3f873 100644
--- a/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/crates/ide/src/inlay_hints/bind_pat.rs
@@ -868,15 +868,15 @@ fn main() {
//- minicore: fn
fn main() {
let x = || 2;
- //^ {closure#26624}
+ //^ {closure#25600}
let y = |t: i32| x() + t;
- //^ {closure#26625}
+ //^ {closure#25601}
let mut t = 5;
//^ i32
let z = |k: i32| { t += k; };
- //^ {closure#26626}
+ //^ {closure#25602}
let p = (y, z);
- //^ ({closure#26625}, {closure#26626})
+ //^ ({closure#25601}, {closure#25602})
}
"#,
);
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index dcb170f3f7..79863f4680 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -57,7 +57,7 @@ mod view_memory_layout;
mod view_mir;
mod view_syntax_tree;
-use std::{iter, panic::UnwindSafe};
+use std::panic::UnwindSafe;
use cfg::CfgOptions;
use fetch_crates::CrateInfo;
@@ -125,7 +125,7 @@ pub use ide_completion::{
};
pub use ide_db::text_edit::{Indel, TextEdit};
pub use ide_db::{
- base_db::{CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId},
+ base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId},
documentation::Documentation,
label::Label,
line_index::{LineCol, LineIndex},
@@ -239,7 +239,7 @@ impl Analysis {
let mut change = ChangeWithProcMacros::new();
change.set_roots(vec![source_root]);
- let mut crate_graph = CrateGraph::default();
+ let mut crate_graph = CrateGraphBuilder::default();
// FIXME: cfg options
// Default to enable test for single file.
let mut cfg_options = CfgOptions::default();
@@ -255,16 +255,13 @@ impl Analysis {
CrateOrigin::Local { repo: None, name: None },
false,
None,
- );
- change.change_file(file_id, Some(text));
- let ws_data = crate_graph
- .iter()
- .zip(iter::repeat(Arc::new(CrateWorkspaceData {
+ Arc::new(CrateWorkspaceData {
data_layout: Err("fixture has no layout".into()),
toolchain: None,
- })))
- .collect();
- change.set_crate_graph(crate_graph, ws_data);
+ }),
+ );
+ change.change_file(file_id, Some(text));
+ change.set_crate_graph(crate_graph);
host.apply_change(change);
(host.analysis(), file_id)
@@ -372,7 +369,7 @@ impl Analysis {
self.with_db(|db| test_explorer::discover_tests_in_crate_by_test_id(db, crate_id))
}
- pub fn discover_tests_in_crate(&self, crate_id: CrateId) -> Cancellable<Vec<TestItem>> {
+ pub fn discover_tests_in_crate(&self, crate_id: Crate) -> Cancellable<Vec<TestItem>> {
self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id))
}
@@ -602,17 +599,17 @@ impl Analysis {
}
/// Returns crates that this file belongs to.
- pub fn crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
+ pub fn crates_for(&self, file_id: FileId) -> Cancellable<Vec<Crate>> {
self.with_db(|db| parent_module::crates_for(db, file_id))
}
/// Returns crates that this file belongs to.
- pub fn transitive_rev_deps(&self, crate_id: CrateId) -> Cancellable<Vec<CrateId>> {
- self.with_db(|db| db.crate_graph().transitive_rev_deps(crate_id).collect())
+ pub fn transitive_rev_deps(&self, crate_id: Crate) -> Cancellable<Vec<Crate>> {
+ self.with_db(|db| Vec::from_iter(db.transitive_rev_deps(crate_id)))
}
/// Returns crates that this file *might* belong to.
- pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
+ pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable<Vec<Crate>> {
self.with_db(|db| {
let db = Upcast::<dyn RootQueryDb>::upcast(db);
db.relevant_crates(file_id).iter().copied().collect()
@@ -620,18 +617,23 @@ impl Analysis {
}
/// Returns the edition of the given crate.
- pub fn crate_edition(&self, crate_id: CrateId) -> Cancellable<Edition> {
- self.with_db(|db| db.crate_graph()[crate_id].edition)
+ pub fn crate_edition(&self, crate_id: Crate) -> Cancellable<Edition> {
+ self.with_db(|db| crate_id.data(db).edition)
+ }
+
+ /// Returns whether the given crate is a proc macro.
+ pub fn is_proc_macro_crate(&self, crate_id: Crate) -> Cancellable<bool> {
+ self.with_db(|db| crate_id.data(db).is_proc_macro)
}
/// Returns true if this crate has `no_std` or `no_core` specified.
- pub fn is_crate_no_std(&self, crate_id: CrateId) -> Cancellable<bool> {
+ pub fn is_crate_no_std(&self, crate_id: Crate) -> Cancellable<bool> {
self.with_db(|db| hir::db::DefDatabase::crate_def_map(db, crate_id).is_no_std())
}
/// Returns the root file of the given crate.
- pub fn crate_root(&self, crate_id: CrateId) -> Cancellable<FileId> {
- self.with_db(|db| db.crate_graph()[crate_id].root_file_id)
+ pub fn crate_root(&self, crate_id: Crate) -> Cancellable<FileId> {
+ self.with_db(|db| crate_id.data(db).root_file_id)
}
/// Returns the set of possible targets to run for the current file.
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs
index 90cccca5e8..06ab4750ac 100644
--- a/crates/ide/src/parent_module.rs
+++ b/crates/ide/src/parent_module.rs
@@ -1,6 +1,6 @@
use hir::{db::DefDatabase, Semantics};
use ide_db::{
- base_db::{CrateId, RootQueryDb, Upcast},
+ base_db::{Crate, RootQueryDb, Upcast},
FileId, FilePosition, RootDatabase,
};
use itertools::Itertools;
@@ -53,7 +53,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
}
/// This returns `Vec` because a module may be included from several places.
-pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
+pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec<Crate> {
let root_db = Upcast::<dyn RootQueryDb>::upcast(db);
root_db
.relevant_crates(file_id)
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 33eef6d75c..baa7ee6897 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -498,9 +498,8 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
};
let krate = def.krate(db);
let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
- let display_target = krate
- .unwrap_or_else(|| (*db.crate_graph().crates_in_topological_order().last().unwrap()).into())
- .to_display_target(db);
+ let display_target =
+ krate.unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()).to_display_target(db);
if !has_runnable_doc_test(&attrs) {
return None;
}
diff --git a/crates/ide/src/static_index.rs b/crates/ide/src/static_index.rs
index ceea34b721..5a2b09b513 100644
--- a/crates/ide/src/static_index.rs
+++ b/crates/ide/src/static_index.rs
@@ -119,9 +119,7 @@ fn documentation_for_definition(
sema.db,
famous_defs.as_ref(),
def.krate(sema.db)
- .unwrap_or_else(|| {
- (*sema.db.crate_graph().crates_in_topological_order().last().unwrap()).into()
- })
+ .unwrap_or_else(|| (*sema.db.all_crates().last().unwrap()).into())
.to_display_target(sema.db),
)
}
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs
index 47ac4ebf20..52d38041ec 100644
--- a/crates/ide/src/status.rs
+++ b/crates/ide/src/status.rs
@@ -1,4 +1,4 @@
-use ide_db::base_db::{CrateData, RootQueryDb, Upcast};
+use ide_db::base_db::{BuiltCrateData, ExtraCrateData};
use ide_db::RootDatabase;
use itertools::Itertools;
use span::FileId;
@@ -34,28 +34,25 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
if crates.is_empty() {
format_to!(buf, "Does not belong to any crate");
}
-
- let crate_graph = Upcast::<dyn RootQueryDb>::upcast(db).crate_graph();
for crate_id in crates {
- let CrateData {
+ let BuiltCrateData {
root_file_id,
edition,
- version,
- display_name,
- cfg_options,
- potential_cfg_options,
- env,
dependencies,
origin,
is_proc_macro,
proc_macro_cwd,
- } = &crate_graph[crate_id];
+ } = crate_id.data(db);
+ let ExtraCrateData { version, display_name, potential_cfg_options } =
+ crate_id.extra_data(db);
+ let cfg_options = crate_id.cfg_options(db);
+ let env = crate_id.env(db);
format_to!(
buf,
"Crate: {}\n",
match display_name {
- Some(it) => format!("{it}({})", crate_id.into_raw()),
- None => format!("{}", crate_id.into_raw()),
+ Some(it) => format!("{it}({:?})", crate_id),
+ None => format!("{:?}", crate_id),
}
);
format_to!(buf, " Root module file id: {}\n", root_file_id.index());
@@ -69,7 +66,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
format_to!(buf, " Proc macro cwd: {:?}\n", proc_macro_cwd);
let deps = dependencies
.iter()
- .map(|dep| format!("{}={}", dep.name, dep.crate_id.into_raw()))
+ .map(|dep| format!("{}={:?}", dep.name, dep.crate_id))
.format(", ");
format_to!(buf, " Dependencies: {}\n", deps);
}
diff --git a/crates/ide/src/test_explorer.rs b/crates/ide/src/test_explorer.rs
index 68f5c72d20..d22133c856 100644
--- a/crates/ide/src/test_explorer.rs
+++ b/crates/ide/src/test_explorer.rs
@@ -1,17 +1,15 @@
//! Discovers tests
use hir::{Crate, Module, ModuleDef, Semantics};
-use ide_db::{
- base_db::{CrateGraph, CrateId, RootQueryDb},
- FileId, RootDatabase,
-};
+use ide_db::base_db;
+use ide_db::{base_db::RootQueryDb, FileId, RootDatabase};
use syntax::TextRange;
use crate::{runnables::runnable_fn, NavigationTarget, Runnable, TryToNav};
#[derive(Debug)]
pub enum TestItemKind {
- Crate(CrateId),
+ Crate(base_db::Crate),
Module,
Function,
}
@@ -28,12 +26,12 @@ pub struct TestItem {
}
pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> {
- let crate_graph = db.crate_graph();
- crate_graph
+ db.all_crates()
.iter()
- .filter(|&id| crate_graph[id].origin.is_local())
+ .copied()
+ .filter(|&id| id.data(db).origin.is_local())
.filter_map(|id| {
- let test_id = crate_graph[id].display_name.as_ref()?.to_string();
+ let test_id = id.extra_data(db).display_name.as_ref()?.to_string();
Some(TestItem {
kind: TestItemKind::Crate(id),
label: test_id.clone(),
@@ -47,12 +45,12 @@ pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> {
.collect()
}
-fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option<CrateId> {
+fn find_crate_by_id(db: &RootDatabase, crate_id: &str) -> Option<base_db::Crate> {
// here, we use display_name as the crate id. This is not super ideal, but it works since we
// only show tests for the local crates.
- crate_graph.iter().find(|&id| {
- crate_graph[id].origin.is_local()
- && crate_graph[id].display_name.as_ref().is_some_and(|x| x.to_string() == crate_id)
+ db.all_crates().iter().copied().find(|&id| {
+ id.data(db).origin.is_local()
+ && id.extra_data(db).display_name.as_ref().is_some_and(|x| x.to_string() == crate_id)
})
}
@@ -115,8 +113,7 @@ pub(crate) fn discover_tests_in_crate_by_test_id(
db: &RootDatabase,
crate_test_id: &str,
) -> Vec<TestItem> {
- let crate_graph = db.crate_graph();
- let Some(crate_id) = find_crate_by_id(&crate_graph, crate_test_id) else {
+ let Some(crate_id) = find_crate_by_id(db, crate_test_id) else {
return vec![];
};
discover_tests_in_crate(db, crate_id)
@@ -171,12 +168,14 @@ fn find_module_id_and_test_parents(
Some((r, id))
}
-pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec<TestItem> {
- let crate_graph = db.crate_graph();
- if !crate_graph[crate_id].origin.is_local() {
+pub(crate) fn discover_tests_in_crate(
+ db: &RootDatabase,
+ crate_id: base_db::Crate,
+) -> Vec<TestItem> {
+ if !crate_id.data(db).origin.is_local() {
return vec![];
}
- let Some(crate_test_id) = &crate_graph[crate_id].display_name else {
+ let Some(crate_test_id) = &crate_id.extra_data(db).display_name else {
return vec![];
};
let kind = TestItemKind::Crate(crate_id);
diff --git a/crates/ide/src/view_crate_graph.rs b/crates/ide/src/view_crate_graph.rs
index eeb65ac038..09f21ecfe4 100644
--- a/crates/ide/src/view_crate_graph.rs
+++ b/crates/ide/src/view_crate_graph.rs
@@ -1,9 +1,10 @@
use dot::{Id, LabelText};
use ide_db::{
- base_db::{CrateGraph, CrateId, Dependency, RootQueryDb, SourceDatabase, Upcast},
- FxHashSet, RootDatabase,
+ base_db::{
+ BuiltCrateData, BuiltDependency, Crate, ExtraCrateData, RootQueryDb, SourceDatabase,
+ },
+ FxHashMap, RootDatabase,
};
-use triomphe::Arc;
// Feature: View Crate Graph
//
@@ -16,77 +17,80 @@ use triomphe::Arc;
// |---------|-------------|
// | VS Code | **rust-analyzer: View Crate Graph** |
pub(crate) fn view_crate_graph(db: &RootDatabase, full: bool) -> Result<String, String> {
- let crate_graph = Upcast::<dyn RootQueryDb>::upcast(db).crate_graph();
- let crates_to_render = crate_graph
+ let all_crates = db.all_crates();
+ let crates_to_render = all_crates
.iter()
- .filter(|krate| {
+ .copied()
+ .map(|krate| (krate, (krate.data(db), krate.extra_data(db))))
+ .filter(|(_, (crate_data, _))| {
if full {
true
} else {
// Only render workspace crates
- let root_id =
- db.file_source_root(crate_graph[*krate].root_file_id).source_root_id(db);
+ let root_id = db.file_source_root(crate_data.root_file_id).source_root_id(db);
!db.source_root(root_id).source_root(db).is_library
}
})
.collect();
- let graph = DotCrateGraph { graph: crate_graph, crates_to_render };
+ let graph = DotCrateGraph { crates_to_render };
let mut dot = Vec::new();
dot::render(&graph, &mut dot).unwrap();
Ok(String::from_utf8(dot).unwrap())
}
-struct DotCrateGraph {
- graph: Arc<CrateGraph>,
- crates_to_render: FxHashSet<CrateId>,
+struct DotCrateGraph<'db> {
+ crates_to_render: FxHashMap<Crate, (&'db BuiltCrateData, &'db ExtraCrateData)>,
}
-type Edge<'a> = (CrateId, &'a Dependency);
+type Edge<'a> = (Crate, &'a BuiltDependency);
-impl<'a> dot::GraphWalk<'a, CrateId, Edge<'a>> for DotCrateGraph {
- fn nodes(&'a self) -> dot::Nodes<'a, CrateId> {
- self.crates_to_render.iter().copied().collect()
+impl<'a> dot::GraphWalk<'a, Crate, Edge<'a>> for DotCrateGraph<'_> {
+ fn nodes(&'a self) -> dot::Nodes<'a, Crate> {
+ self.crates_to_render.keys().copied().collect()
}
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
self.crates_to_render
.iter()
- .flat_map(|krate| {
- self.graph[*krate]
+ .flat_map(|(krate, (crate_data, _))| {
+ crate_data
.dependencies
.iter()
- .filter(|dep| self.crates_to_render.contains(&dep.crate_id))
+ .filter(|dep| self.crates_to_render.contains_key(&dep.crate_id))
.map(move |dep| (*krate, dep))
})
.collect()
}
- fn source(&'a self, edge: &Edge<'a>) -> CrateId {
+ fn source(&'a self, edge: &Edge<'a>) -> Crate {
edge.0
}
- fn target(&'a self, edge: &Edge<'a>) -> CrateId {
+ fn target(&'a self, edge: &Edge<'a>) -> Crate {
edge.1.crate_id
}
}
-impl<'a> dot::Labeller<'a, CrateId, Edge<'a>> for DotCrateGraph {
+impl<'a> dot::Labeller<'a, Crate, Edge<'a>> for DotCrateGraph<'_> {
fn graph_id(&'a self) -> Id<'a> {
Id::new("rust_analyzer_crate_graph").unwrap()
}
- fn node_id(&'a self, n: &CrateId) -> Id<'a> {
- Id::new(format!("_{}", u32::from(n.into_raw()))).unwrap()
+ fn node_id(&'a self, n: &Crate) -> Id<'a> {
+ Id::new(format!("_{:?}", n)).unwrap()
}
- fn node_shape(&'a self, _node: &CrateId) -> Option<LabelText<'a>> {
+ fn node_shape(&'a self, _node: &Crate) -> Option<LabelText<'a>> {
Some(LabelText::LabelStr("box".into()))
}
- fn node_label(&'a self, n: &CrateId) -> LabelText<'a> {
- let name =
- self.graph[*n].display_name.as_ref().map_or("(unnamed crate)", |name| name.as_str());
+ fn node_label(&'a self, n: &Crate) -> LabelText<'a> {
+ let name = self.crates_to_render[n]
+ .1
+ .display_name
+ .as_ref()
+ .map_or("(unnamed crate)", |name| name.as_str());
LabelText::LabelStr(name.into())
}
}
diff --git a/crates/intern/src/symbol.rs b/crates/intern/src/symbol.rs
index 0fa6701ca3..f6a74d9741 100644
--- a/crates/intern/src/symbol.rs
+++ b/crates/intern/src/symbol.rs
@@ -42,6 +42,18 @@ struct TaggedArcPtr {
unsafe impl Send for TaggedArcPtr {}
unsafe impl Sync for TaggedArcPtr {}
+impl Ord for TaggedArcPtr {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ self.as_str().cmp(other.as_str())
+ }
+}
+
+impl PartialOrd for TaggedArcPtr {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
impl TaggedArcPtr {
const BOOL_BITS: usize = true as usize;
@@ -113,7 +125,7 @@ impl TaggedArcPtr {
}
}
-#[derive(PartialEq, Eq, Hash)]
+#[derive(PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Symbol {
repr: TaggedArcPtr,
}
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index fbb0043ad2..01d29d88df 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -2,15 +2,15 @@
//! for incorporating changes.
// Note, don't remove any public api from this. This API is consumed by external tools
// to run rust-analyzer as a library.
-use std::{collections::hash_map::Entry, iter, mem, path::Path, sync};
+use std::{collections::hash_map::Entry, mem, path::Path, sync};
use crossbeam_channel::{unbounded, Receiver};
use hir_expand::proc_macro::{
ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacroLoadResult,
- ProcMacros,
+ ProcMacrosBuilder,
};
use ide_db::{
- base_db::{CrateGraph, CrateWorkspaceData, Env, SourceRoot, SourceRootId},
+ base_db::{CrateGraphBuilder, Env, SourceRoot, SourceRootId},
prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase,
};
use itertools::Itertools;
@@ -139,7 +139,6 @@ pub fn load_workspace(
});
let db = load_crate_graph(
- &ws,
crate_graph,
proc_macros,
project_folders.source_root_config,
@@ -418,15 +417,12 @@ pub fn load_proc_macro(
}
fn load_crate_graph(
- ws: &ProjectWorkspace,
- crate_graph: CrateGraph,
- proc_macros: ProcMacros,
+ crate_graph: CrateGraphBuilder,
+ proc_macros: ProcMacrosBuilder,
source_root_config: SourceRootConfig,
vfs: &mut vfs::Vfs,
receiver: &Receiver<vfs::loader::Message>,
) -> RootDatabase {
- let ProjectWorkspace { toolchain, target_layout, .. } = ws;
-
let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<u16>().ok());
let mut db = RootDatabase::new(lru_cap);
let mut analysis_change = ChangeWithProcMacros::new();
@@ -461,14 +457,7 @@ fn load_crate_graph(
let source_roots = source_root_config.partition(vfs);
analysis_change.set_roots(source_roots);
- let ws_data = crate_graph
- .iter()
- .zip(iter::repeat(From::from(CrateWorkspaceData {
- data_layout: target_layout.clone(),
- toolchain: toolchain.clone(),
- })))
- .collect();
- analysis_change.set_crate_graph(crate_graph, ws_data);
+ analysis_change.set_crate_graph(crate_graph);
analysis_change.set_proc_macros(proc_macros);
db.apply_change(analysis_change);
@@ -494,7 +483,7 @@ fn expander_to_proc_macro(
}
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
struct Expander(proc_macro_api::ProcMacro);
impl ProcMacroExpander for Expander {
@@ -522,6 +511,10 @@ impl ProcMacroExpander for Expander {
Err(err) => Err(ProcMacroExpansionError::System(err.to_string())),
}
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().downcast_ref::<Self>().is_some_and(|other| self == other)
+ }
}
#[cfg(test)]
@@ -543,7 +536,7 @@ mod tests {
let (db, _vfs, _proc_macro) =
load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {}).unwrap();
- let n_crates = db.crate_graph().iter().count();
+ let n_crates = db.all_crates().len();
// RA has quite a few crates, but the exact count doesn't matter
assert!(n_crates > 20);
}
diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs
index dc3328ebcd..571ceaabe6 100644
--- a/crates/proc-macro-api/src/lib.rs
+++ b/crates/proc-macro-api/src/lib.rs
@@ -13,7 +13,7 @@ mod process;
use paths::{AbsPath, AbsPathBuf};
use span::Span;
-use std::{fmt, io, sync::Arc};
+use std::{fmt, io, sync::Arc, time::SystemTime};
use crate::{
legacy_protocol::msg::{
@@ -66,6 +66,7 @@ pub struct ProcMacro {
dylib_path: Arc<AbsPathBuf>,
name: Box<str>,
kind: ProcMacroKind,
+ dylib_last_modified: Option<SystemTime>,
}
impl Eq for ProcMacro {}
@@ -73,7 +74,8 @@ impl PartialEq for ProcMacro {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
&& self.kind == other.kind
- && Arc::ptr_eq(&self.dylib_path, &other.dylib_path)
+ && self.dylib_path == other.dylib_path
+ && self.dylib_last_modified == other.dylib_last_modified
&& Arc::ptr_eq(&self.process, &other.process)
}
}
@@ -116,6 +118,9 @@ impl ProcMacroClient {
let macros = self.process.find_proc_macros(&dylib.path)?;
let dylib_path = Arc::new(dylib.path);
+ let dylib_last_modified = std::fs::metadata(dylib_path.as_path())
+ .ok()
+ .and_then(|metadata| metadata.modified().ok());
match macros {
Ok(macros) => Ok(macros
.into_iter()
@@ -124,6 +129,7 @@ impl ProcMacroClient {
name: name.into(),
kind,
dylib_path: dylib_path.clone(),
+ dylib_last_modified,
})
.collect()),
Err(message) => Err(ServerError { message, io: None }),
diff --git a/crates/proc-macro-srv/src/tests/mod.rs b/crates/proc-macro-srv/src/tests/mod.rs
index 15de88ea65..716d351271 100644
--- a/crates/proc-macro-srv/src/tests/mod.rs
+++ b/crates/proc-macro-srv/src/tests/mod.rs
@@ -12,7 +12,7 @@ fn test_derive_empty() {
"DeriveEmpty",
r#"struct S;"#,
expect!["SUBTREE $$ 1 1"],
- expect!["SUBTREE $$ 42:[email protected]#2 42:[email protected]#2"],
+ expect!["SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037"],
);
}
@@ -29,12 +29,12 @@ fn test_derive_error() {
LITERAL Str #[derive(DeriveError)] struct S ; 1
PUNCH ; [alone] 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- IDENT compile_error 42:[email protected]#2
- PUNCH ! [alone] 42:[email protected]#2
- SUBTREE () 42:[email protected]#2 42:[email protected]#2
- LITERAL Str #[derive(DeriveError)] struct S ; 42:[email protected]#2
- PUNCH ; [alone] 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ IDENT compile_error 42:[email protected]#4294967037
+ PUNCH ! [alone] 42:[email protected]#4294967037
+ SUBTREE () 42:[email protected]#4294967037 42:[email protected]#4294967037
+ LITERAL Str #[derive(DeriveError)] struct S ; 42:[email protected]#4294967037
+ PUNCH ; [alone] 42:[email protected]#4294967037"#]],
);
}
@@ -53,14 +53,14 @@ fn test_fn_like_macro_noop() {
PUNCH , [alone] 1
SUBTREE [] 1 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- IDENT ident 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL Integer 0 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL Integer 1 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- SUBTREE [] 42:[email protected]#2 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ IDENT ident 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL Integer 0 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL Integer 1 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ SUBTREE [] 42:[email protected]#4294967037 42:[email protected]#4294967037"#]],
);
}
@@ -75,10 +75,10 @@ fn test_fn_like_macro_clone_ident_subtree() {
PUNCH , [alone] 1
SUBTREE [] 1 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- IDENT ident 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- SUBTREE [] 42:[email protected]#2 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ IDENT ident 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ SUBTREE [] 42:[email protected]#4294967037 42:[email protected]#4294967037"#]],
);
}
@@ -91,8 +91,8 @@ fn test_fn_like_macro_clone_raw_ident() {
SUBTREE $$ 1 1
IDENT r#async 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- IDENT r#async 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ IDENT r#async 42:[email protected]#4294967037"#]],
);
}
@@ -105,8 +105,8 @@ fn test_fn_like_fn_like_span_join() {
SUBTREE $$ 1 1
IDENT r#joined 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- IDENT r#joined 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ IDENT r#joined 42:[email protected]#4294967037"#]],
);
}
@@ -121,10 +121,10 @@ fn test_fn_like_fn_like_span_ops() {
IDENT resolved_at_def_site 1
IDENT start_span 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- IDENT set_def_site 41:[email protected]#2
- IDENT resolved_at_def_site 42:[email protected]#2
- IDENT start_span 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ IDENT set_def_site 41:[email protected]#4294967037
+ IDENT resolved_at_def_site 42:[email protected]#4294967037
+ IDENT start_span 42:[email protected]#4294967037"#]],
);
}
@@ -143,14 +143,14 @@ fn test_fn_like_mk_literals() {
LITERAL Integer 123i64 1
LITERAL Integer 123 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- LITERAL ByteStr byte_string 42:[email protected]#2
- LITERAL Char c 42:[email protected]#2
- LITERAL Str string 42:[email protected]#2
- LITERAL Float 3.14f64 42:[email protected]#2
- LITERAL Float 3.14 42:[email protected]#2
- LITERAL Integer 123i64 42:[email protected]#2
- LITERAL Integer 123 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ LITERAL ByteStr byte_string 42:[email protected]#4294967037
+ LITERAL Char c 42:[email protected]#4294967037
+ LITERAL Str string 42:[email protected]#4294967037
+ LITERAL Float 3.14f64 42:[email protected]#4294967037
+ LITERAL Float 3.14 42:[email protected]#4294967037
+ LITERAL Integer 123i64 42:[email protected]#4294967037
+ LITERAL Integer 123 42:[email protected]#4294967037"#]],
);
}
@@ -164,9 +164,9 @@ fn test_fn_like_mk_idents() {
IDENT standard 1
IDENT r#raw 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- IDENT standard 42:[email protected]#2
- IDENT r#raw 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ IDENT standard 42:[email protected]#4294967037
+ IDENT r#raw 42:[email protected]#4294967037"#]],
);
}
@@ -198,27 +198,27 @@ fn test_fn_like_macro_clone_literals() {
PUNCH , [alone] 1
LITERAL CStr null 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- LITERAL Integer 1u16 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL Integer 2_u32 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- PUNCH - [alone] 42:[email protected]#2
- LITERAL Integer 4i64 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL Float 3.14f32 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL Str hello bridge 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL Str suffixedsuffix 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL StrRaw(2) raw 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL Char a 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL Byte b 42:[email protected]#2
- PUNCH , [alone] 42:[email protected]#2
- LITERAL CStr null 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ LITERAL Integer 1u16 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL Integer 2_u32 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ PUNCH - [alone] 42:[email protected]#4294967037
+ LITERAL Integer 4i64 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL Float 3.14f32 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL Str hello bridge 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL Str suffixedsuffix 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL StrRaw(2) raw 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL Char a 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL Byte b 42:[email protected]#4294967037
+ PUNCH , [alone] 42:[email protected]#4294967037
+ LITERAL CStr null 42:[email protected]#4294967037"#]],
);
}
@@ -239,12 +239,12 @@ fn test_attr_macro() {
LITERAL Str #[attr_error(some arguments)] mod m {} 1
PUNCH ; [alone] 1"#]],
expect![[r#"
- SUBTREE $$ 42:[email protected]#2 42:[email protected]#2
- IDENT compile_error 42:[email protected]#2
- PUNCH ! [alone] 42:[email protected]#2
- SUBTREE () 42:[email protected]#2 42:[email protected]#2
- LITERAL Str #[attr_error(some arguments)] mod m {} 42:[email protected]#2
- PUNCH ; [alone] 42:[email protected]#2"#]],
+ SUBTREE $$ 42:[email protected]#4294967037 42:[email protected]#4294967037
+ IDENT compile_error 42:[email protected]#4294967037
+ PUNCH ! [alone] 42:[email protected]#4294967037
+ SUBTREE () 42:[email protected]#4294967037 42:[email protected]#4294967037
+ LITERAL Str #[attr_error(some arguments)] mod m {} 42:[email protected]#4294967037
+ PUNCH ; [alone] 42:[email protected]#4294967037"#]],
);
}
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index b2df8e4703..3c14e6e627 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -452,7 +452,7 @@ pub enum TargetKindData {
}
/// Identifies a crate by position in the crates array.
///
-/// This will differ from `CrateId` when multiple `ProjectJson`
+/// This will differ from `Crate` when multiple `ProjectJson`
/// workspaces are loaded.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)]
#[serde(transparent)]
diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs
index 8374062273..d4c93b0e9b 100644
--- a/crates/project-model/src/tests.rs
+++ b/crates/project-model/src/tests.rs
@@ -1,4 +1,4 @@
-use base_db::{CrateGraph, ProcMacroPaths};
+use base_db::{CrateGraphBuilder, ProcMacroPaths};
use cargo_metadata::Metadata;
use cfg::{CfgAtom, CfgDiff};
use expect_test::{expect_file, ExpectFile};
@@ -15,7 +15,7 @@ use crate::{
Sysroot, WorkspaceBuildScripts,
};
-fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
+fn load_cargo(file: &str) -> (CrateGraphBuilder, ProcMacroPaths) {
let project_workspace = load_workspace_from_metadata(file);
to_crate_graph(project_workspace, &mut Default::default())
}
@@ -23,7 +23,7 @@ fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
fn load_cargo_with_overrides(
file: &str,
cfg_overrides: CfgOverrides,
-) -> (CrateGraph, ProcMacroPaths) {
+) -> (CrateGraphBuilder, ProcMacroPaths) {
let project_workspace =
ProjectWorkspace { cfg_overrides, ..load_workspace_from_metadata(file) };
to_crate_graph(project_workspace, &mut Default::default())
@@ -51,7 +51,7 @@ fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace {
}
}
-fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
+fn load_rust_project(file: &str) -> (CrateGraphBuilder, ProcMacroPaths) {
let data = get_test_json_file(file);
let project = rooted_project_json(data);
let sysroot = get_fake_sysroot();
@@ -142,7 +142,7 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
fn to_crate_graph(
project_workspace: ProjectWorkspace,
file_map: &mut FxHashMap<AbsPathBuf, FileId>,
-) -> (CrateGraph, ProcMacroPaths) {
+) -> (CrateGraphBuilder, ProcMacroPaths) {
project_workspace.to_crate_graph(
&mut {
|path| {
@@ -154,7 +154,7 @@ fn to_crate_graph(
)
}
-fn check_crate_graph(crate_graph: CrateGraph, expect: ExpectFile) {
+fn check_crate_graph(crate_graph: CrateGraphBuilder, expect: ExpectFile) {
let mut crate_graph = format!("{crate_graph:#?}");
replace_root(&mut crate_graph, false);
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index 62c13c7d9e..114c2551e1 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -6,8 +6,9 @@ use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync, thread};
use anyhow::Context;
use base_db::{
- CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env,
- LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
+ CrateBuilderId, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin,
+ CrateWorkspaceData, DependencyBuilder, Env, LangCrateOrigin, ProcMacroPaths,
+ TargetLayoutLoadResult,
};
use cfg::{CfgAtom, CfgDiff, CfgOptions};
use intern::{sym, Symbol};
@@ -848,10 +849,14 @@ impl ProjectWorkspace {
&self,
load: FileLoader<'_>,
extra_env: &FxHashMap<String, String>,
- ) -> (CrateGraph, ProcMacroPaths) {
+ ) -> (CrateGraphBuilder, ProcMacroPaths) {
let _p = tracing::info_span!("ProjectWorkspace::to_crate_graph").entered();
let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self;
+ let crate_ws_data = Arc::new(CrateWorkspaceData {
+ toolchain: self.toolchain.clone(),
+ data_layout: self.target_layout.clone(),
+ });
let (crate_graph, proc_macros) = match kind {
ProjectWorkspaceKind::Json(project) => project_json_to_crate_graph(
rustc_cfg.clone(),
@@ -861,6 +866,7 @@ impl ProjectWorkspace {
extra_env,
cfg_overrides,
self.set_test,
+ crate_ws_data,
),
ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _ } => {
cargo_to_crate_graph(
@@ -872,6 +878,7 @@ impl ProjectWorkspace {
cfg_overrides,
build_scripts,
self.set_test,
+ crate_ws_data,
)
}
ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => {
@@ -885,6 +892,7 @@ impl ProjectWorkspace {
cfg_overrides,
build_scripts,
self.set_test,
+ crate_ws_data,
)
} else {
detached_file_to_crate_graph(
@@ -894,6 +902,7 @@ impl ProjectWorkspace {
sysroot,
cfg_overrides,
self.set_test,
+ crate_ws_data,
)
}
}
@@ -959,15 +968,22 @@ fn project_json_to_crate_graph(
extra_env: &FxHashMap<String, String>,
override_cfg: &CfgOverrides,
set_test: bool,
-) -> (CrateGraph, ProcMacroPaths) {
- let mut res = (CrateGraph::default(), ProcMacroPaths::default());
+ crate_ws_data: Arc<CrateWorkspaceData>,
+) -> (CrateGraphBuilder, ProcMacroPaths) {
+ let mut res = (CrateGraphBuilder::default(), ProcMacroPaths::default());
let (crate_graph, proc_macros) = &mut res;
- let (public_deps, libproc_macro) =
- sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load);
+ let (public_deps, libproc_macro) = sysroot_to_crate_graph(
+ crate_graph,
+ sysroot,
+ rustc_cfg.clone(),
+ load,
+ // FIXME: This looks incorrect but I don't think this matters.
+ crate_ws_data.clone(),
+ );
let mut cfg_cache: FxHashMap<&str, Vec<CfgAtom>> = FxHashMap::default();
- let idx_to_crate_id: FxHashMap<CrateArrayIdx, CrateId> = project
+ let idx_to_crate_id: FxHashMap<CrateArrayIdx, _> = project
.crates()
.filter_map(|(idx, krate)| Some((idx, krate, load(&krate.root_module)?)))
.map(
@@ -1042,6 +1058,7 @@ fn project_json_to_crate_graph(
},
*is_proc_macro,
proc_macro_cwd.clone(),
+ crate_ws_data.clone(),
);
debug!(
?crate_graph_crate_id,
@@ -1092,12 +1109,19 @@ fn cargo_to_crate_graph(
override_cfg: &CfgOverrides,
build_scripts: &WorkspaceBuildScripts,
set_test: bool,
-) -> (CrateGraph, ProcMacroPaths) {
+ crate_ws_data: Arc<CrateWorkspaceData>,
+) -> (CrateGraphBuilder, ProcMacroPaths) {
let _p = tracing::info_span!("cargo_to_crate_graph").entered();
- let mut res = (CrateGraph::default(), ProcMacroPaths::default());
+ let mut res = (CrateGraphBuilder::default(), ProcMacroPaths::default());
let (crate_graph, proc_macros) = &mut res;
- let (public_deps, libproc_macro) =
- sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load);
+ let (public_deps, libproc_macro) = sysroot_to_crate_graph(
+ crate_graph,
+ sysroot,
+ rustc_cfg.clone(),
+ load,
+ // FIXME: This looks incorrect but I don't think this causes problems.
+ crate_ws_data.clone(),
+ );
let cfg_options = CfgOptions::from_iter(rustc_cfg);
@@ -1163,6 +1187,7 @@ fn cargo_to_crate_graph(
name: Symbol::intern(&pkg_data.name),
}
},
+ crate_ws_data.clone(),
);
if let TargetKind::Lib { .. } = kind {
lib_tgt = Some((crate_id, name.clone()));
@@ -1267,6 +1292,8 @@ fn cargo_to_crate_graph(
} else {
rustc_build_scripts
},
+ // FIXME: This looks incorrect but I don't think this causes problems.
+ crate_ws_data,
);
}
}
@@ -1280,11 +1307,18 @@ fn detached_file_to_crate_graph(
sysroot: &Sysroot,
override_cfg: &CfgOverrides,
set_test: bool,
-) -> (CrateGraph, ProcMacroPaths) {
+ crate_ws_data: Arc<CrateWorkspaceData>,
+) -> (CrateGraphBuilder, ProcMacroPaths) {
let _p = tracing::info_span!("detached_file_to_crate_graph").entered();
- let mut crate_graph = CrateGraph::default();
- let (public_deps, _libproc_macro) =
- sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load);
+ let mut crate_graph = CrateGraphBuilder::default();
+ let (public_deps, _libproc_macro) = sysroot_to_crate_graph(
+ &mut crate_graph,
+ sysroot,
+ rustc_cfg.clone(),
+ load,
+ // FIXME: This looks incorrect but I don't think this causes problems.
+ crate_ws_data.clone(),
+ );
let mut cfg_options = CfgOptions::from_iter(rustc_cfg);
if set_test {
@@ -1316,6 +1350,7 @@ fn detached_file_to_crate_graph(
},
false,
None,
+ crate_ws_data,
);
public_deps.add_to_crate_graph(&mut crate_graph, detached_file_crate);
@@ -1323,18 +1358,19 @@ fn detached_file_to_crate_graph(
}
fn handle_rustc_crates(
- crate_graph: &mut CrateGraph,
+ crate_graph: &mut CrateGraphBuilder,
proc_macros: &mut ProcMacroPaths,
- pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>,
+ pkg_to_lib_crate: &mut FxHashMap<Package, CrateBuilderId>,
load: FileLoader<'_>,
rustc_workspace: &CargoWorkspace,
cargo: &CargoWorkspace,
public_deps: &SysrootPublicDeps,
- libproc_macro: Option<CrateId>,
- pkg_crates: &FxHashMap<Package, Vec<(CrateId, TargetKind)>>,
+ libproc_macro: Option<CrateBuilderId>,
+ pkg_crates: &FxHashMap<Package, Vec<(CrateBuilderId, TargetKind)>>,
cfg_options: &CfgOptions,
override_cfg: &CfgOverrides,
build_scripts: &WorkspaceBuildScripts,
+ crate_ws_data: Arc<CrateWorkspaceData>,
) {
let mut rustc_pkg_crates = FxHashMap::default();
// The root package of the rustc-dev component is rustc_driver, so we match that
@@ -1377,6 +1413,7 @@ fn handle_rustc_crates(
&rustc_workspace[tgt].name,
kind,
CrateOrigin::Rustc { name: Symbol::intern(&rustc_workspace[pkg].name) },
+ crate_ws_data.clone(),
);
pkg_to_lib_crate.insert(pkg, crate_id);
// Add dependencies on core / std / alloc for this crate
@@ -1417,7 +1454,7 @@ fn handle_rustc_crates(
// This avoids the situation where `from` depends on e.g. `arrayvec`, but
// `rust_analyzer` thinks that it should use the one from the `rustc_source`
// instead of the one from `crates.io`
- if !crate_graph[*from].dependencies.iter().any(|d| d.name == name) {
+ if !crate_graph[*from].basic.dependencies.iter().any(|d| d.name == name) {
add_dep(crate_graph, *from, name.clone(), to);
}
}
@@ -1427,7 +1464,7 @@ fn handle_rustc_crates(
}
fn add_target_crate_root(
- crate_graph: &mut CrateGraph,
+ crate_graph: &mut CrateGraphBuilder,
proc_macros: &mut ProcMacroPaths,
cargo: &CargoWorkspace,
pkg: &PackageData,
@@ -1437,7 +1474,8 @@ fn add_target_crate_root(
cargo_name: &str,
kind: TargetKind,
origin: CrateOrigin,
-) -> CrateId {
+ crate_ws_data: Arc<CrateWorkspaceData>,
+) -> CrateBuilderId {
let edition = pkg.edition;
let potential_cfg_options = if pkg.features.is_empty() {
None
@@ -1474,7 +1512,7 @@ fn add_target_crate_root(
Some(CrateDisplayName::from_canonical_name(cargo_name)),
Some(pkg.version.to_string()),
Arc::new(cfg_options),
- potential_cfg_options.map(Arc::new),
+ potential_cfg_options,
env,
origin,
matches!(kind, TargetKind::Lib { is_proc_macro: true }),
@@ -1483,6 +1521,7 @@ fn add_target_crate_root(
} else {
pkg.manifest.parent().to_path_buf()
}),
+ crate_ws_data,
);
if let TargetKind::Lib { is_proc_macro: true } = kind {
let proc_macro = match build_data {
@@ -1503,12 +1542,12 @@ fn add_target_crate_root(
#[derive(Default, Debug)]
struct SysrootPublicDeps {
- deps: Vec<(CrateName, CrateId, bool)>,
+ deps: Vec<(CrateName, CrateBuilderId, bool)>,
}
impl SysrootPublicDeps {
/// Makes `from` depend on the public sysroot crates.
- fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) {
+ fn add_to_crate_graph(&self, crate_graph: &mut CrateGraphBuilder, from: CrateBuilderId) {
for (name, krate, prelude) in &self.deps {
add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude, true);
}
@@ -1516,10 +1555,10 @@ impl SysrootPublicDeps {
}
fn extend_crate_graph_with_sysroot(
- crate_graph: &mut CrateGraph,
- mut sysroot_crate_graph: CrateGraph,
+ crate_graph: &mut CrateGraphBuilder,
+ mut sysroot_crate_graph: CrateGraphBuilder,
mut sysroot_proc_macros: ProcMacroPaths,
-) -> (SysrootPublicDeps, Option<CrateId>) {
+) -> (SysrootPublicDeps, Option<CrateBuilderId>) {
let mut pub_deps = vec![];
let mut libproc_macro = None;
let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]);
@@ -1527,11 +1566,11 @@ fn extend_crate_graph_with_sysroot(
// uninject `test` flag so `core` keeps working.
Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
// patch the origin
- if c.origin.is_local() {
+ if c.basic.origin.is_local() {
let lang_crate = LangCrateOrigin::from(
- c.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()),
+ c.extra.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()),
);
- c.origin = CrateOrigin::Lang(lang_crate);
+ c.basic.origin = CrateOrigin::Lang(lang_crate);
match lang_crate {
LangCrateOrigin::Test
| LangCrateOrigin::Alloc
@@ -1579,11 +1618,12 @@ fn extend_crate_graph_with_sysroot(
}
fn sysroot_to_crate_graph(
- crate_graph: &mut CrateGraph,
+ crate_graph: &mut CrateGraphBuilder,
sysroot: &Sysroot,
rustc_cfg: Vec<CfgAtom>,
load: FileLoader<'_>,
-) -> (SysrootPublicDeps, Option<CrateId>) {
+ crate_ws_data: Arc<CrateWorkspaceData>,
+) -> (SysrootPublicDeps, Option<CrateBuilderId>) {
let _p = tracing::info_span!("sysroot_to_crate_graph").entered();
match sysroot.workspace() {
RustLibSrcWorkspace::Workspace(cargo) => {
@@ -1605,6 +1645,7 @@ fn sysroot_to_crate_graph(
},
&WorkspaceBuildScripts::default(),
false,
+ crate_ws_data,
);
extend_crate_graph_with_sysroot(crate_graph, cg, pm)
@@ -1627,6 +1668,7 @@ fn sysroot_to_crate_graph(
..Default::default()
},
false,
+ crate_ws_data,
);
extend_crate_graph_with_sysroot(crate_graph, cg, pm)
@@ -1639,29 +1681,31 @@ fn sysroot_to_crate_graph(
cfg_options.insert_atom(sym::miri.clone());
cfg_options
});
- let sysroot_crates: FxHashMap<crate::sysroot::stitched::RustLibSrcCrate, CrateId> =
- stitched
- .crates()
- .filter_map(|krate| {
- let file_id = load(&stitched[krate].root)?;
-
- let display_name =
- CrateDisplayName::from_canonical_name(&stitched[krate].name);
- let crate_id = crate_graph.add_crate_root(
- file_id,
- Edition::CURRENT_FIXME,
- Some(display_name),
- None,
- cfg_options.clone(),
- None,
- Env::default(),
- CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
- false,
- None,
- );
- Some((krate, crate_id))
- })
- .collect();
+ let sysroot_crates: FxHashMap<
+ crate::sysroot::stitched::RustLibSrcCrate,
+ CrateBuilderId,
+ > = stitched
+ .crates()
+ .filter_map(|krate| {
+ let file_id = load(&stitched[krate].root)?;
+
+ let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name);
+ let crate_id = crate_graph.add_crate_root(
+ file_id,
+ Edition::CURRENT_FIXME,
+ Some(display_name),
+ None,
+ cfg_options.clone(),
+ None,
+ Env::default(),
+ CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
+ false,
+ None,
+ crate_ws_data.clone(),
+ );
+ Some((krate, crate_id))
+ })
+ .collect();
for from in stitched.crates() {
for &to in stitched[from].deps.iter() {
@@ -1691,22 +1735,32 @@ fn sysroot_to_crate_graph(
}
}
-fn add_dep(graph: &mut CrateGraph, from: CrateId, name: CrateName, to: CrateId) {
- add_dep_inner(graph, from, Dependency::new(name, to))
+fn add_dep(
+ graph: &mut CrateGraphBuilder,
+ from: CrateBuilderId,
+ name: CrateName,
+ to: CrateBuilderId,
+) {
+ add_dep_inner(graph, from, DependencyBuilder::new(name, to))
}
fn add_dep_with_prelude(
- graph: &mut CrateGraph,
- from: CrateId,
+ graph: &mut CrateGraphBuilder,
+ from: CrateBuilderId,
name: CrateName,
- to: CrateId,
+ to: CrateBuilderId,
prelude: bool,
sysroot: bool,
) {
- add_dep_inner(graph, from, Dependency::with_prelude(name, to, prelude, sysroot))
+ add_dep_inner(graph, from, DependencyBuilder::with_prelude(name, to, prelude, sysroot))
}
-fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId, prelude: bool) {
+fn add_proc_macro_dep(
+ crate_graph: &mut CrateGraphBuilder,
+ from: CrateBuilderId,
+ to: CrateBuilderId,
+ prelude: bool,
+) {
add_dep_with_prelude(
crate_graph,
from,
@@ -1717,7 +1771,7 @@ fn add_proc_macro_dep(crate_graph: &mut CrateGraph, from: CrateId, to: CrateId,
);
}
-fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) {
+fn add_dep_inner(graph: &mut CrateGraphBuilder, from: CrateBuilderId, dep: DependencyBuilder) {
if let Err(err) = graph.add_dep(from, dep) {
tracing::warn!("{}", err)
}
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index fae0b6fcca..ae842bf704 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -1,20 +1,47 @@
{
- 0: CrateData {
- root_file_id: FileId(
- 1,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "hello_world",
+ 0: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 1,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- canonical_name: "hello-world",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
+ ),
+ ),
+ },
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
+ ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello-world",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -22,7 +49,6 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -44,45 +70,64 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
),
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
- ),
- ),
},
- 1: CrateData {
- root_file_id: FileId(
- 2,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "hello_world",
+ 1: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 2,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- canonical_name: "hello-world",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
+ ),
+ ),
+ },
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
+ ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello-world",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -90,7 +135,6 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -112,53 +156,64 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 2: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 3,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- prelude: true,
- sysroot: false,
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
),
- ),
- },
- 2: CrateData {
- root_file_id: FileId(
- 3,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "an_example",
- ),
- canonical_name: "an-example",
- },
- ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "an_example",
+ ),
+ canonical_name: "an-example",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -166,7 +221,6 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -188,53 +242,64 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 3: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 4,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- prelude: true,
- sysroot: false,
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
),
- ),
- },
- 3: CrateData {
- root_file_id: FileId(
- 4,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "it",
- ),
- canonical_name: "it",
- },
- ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "it",
+ ),
+ canonical_name: "it",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -242,7 +307,6 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -264,53 +328,60 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 4: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 5,
+ ),
+ edition: Edition2015,
+ dependencies: [],
+ origin: Library {
+ repo: Some(
+ "https://github.com/rust-lang/libc",
),
- prelude: true,
- sysroot: false,
+ name: "libc",
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.2.98",
),
- ),
- },
- 4: CrateData {
- root_file_id: FileId(
- 5,
- ),
- edition: Edition2015,
- version: Some(
- "0.2.98",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "libc",
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "libc",
+ ),
+ canonical_name: "libc",
+ },
+ ),
+ potential_cfg_options: Some(
+ CfgOptions(
+ [
+ "feature=align",
+ "feature=const-extern-fn",
+ "feature=default",
+ "feature=extra_traits",
+ "feature=rustc-dep-of-std",
+ "feature=std",
+ "feature=use_std",
+ "true",
+ ],
),
- canonical_name: "libc",
- },
- ),
+ ),
+ },
cfg_options: CfgOptions(
[
"feature=default",
@@ -318,20 +389,6 @@
"true",
],
),
- potential_cfg_options: Some(
- CfgOptions(
- [
- "feature=align",
- "feature=const-extern-fn",
- "feature=default",
- "feature=extra_traits",
- "feature=rustc-dep-of-std",
- "feature=std",
- "feature=use_std",
- "true",
- ],
- ),
- ),
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -353,18 +410,11 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [],
- origin: Library {
- repo: Some(
- "https://github.com/rust-lang/libc",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
),
- name: "libc",
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
- ),
- ),
},
} \ No newline at end of file
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index fae0b6fcca..ae842bf704 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -1,20 +1,47 @@
{
- 0: CrateData {
- root_file_id: FileId(
- 1,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "hello_world",
+ 0: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 1,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- canonical_name: "hello-world",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
+ ),
+ ),
+ },
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
+ ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello-world",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -22,7 +49,6 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -44,45 +70,64 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
),
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
- ),
- ),
},
- 1: CrateData {
- root_file_id: FileId(
- 2,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "hello_world",
+ 1: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 2,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- canonical_name: "hello-world",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
+ ),
+ ),
+ },
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
+ ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello-world",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -90,7 +135,6 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -112,53 +156,64 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 2: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 3,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- prelude: true,
- sysroot: false,
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
),
- ),
- },
- 2: CrateData {
- root_file_id: FileId(
- 3,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "an_example",
- ),
- canonical_name: "an-example",
- },
- ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "an_example",
+ ),
+ canonical_name: "an-example",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -166,7 +221,6 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -188,53 +242,64 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 3: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 4,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- prelude: true,
- sysroot: false,
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
),
- ),
- },
- 3: CrateData {
- root_file_id: FileId(
- 4,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "it",
- ),
- canonical_name: "it",
- },
- ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "it",
+ ),
+ canonical_name: "it",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -242,7 +307,6 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -264,53 +328,60 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 4: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 5,
+ ),
+ edition: Edition2015,
+ dependencies: [],
+ origin: Library {
+ repo: Some(
+ "https://github.com/rust-lang/libc",
),
- prelude: true,
- sysroot: false,
+ name: "libc",
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.2.98",
),
- ),
- },
- 4: CrateData {
- root_file_id: FileId(
- 5,
- ),
- edition: Edition2015,
- version: Some(
- "0.2.98",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "libc",
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "libc",
+ ),
+ canonical_name: "libc",
+ },
+ ),
+ potential_cfg_options: Some(
+ CfgOptions(
+ [
+ "feature=align",
+ "feature=const-extern-fn",
+ "feature=default",
+ "feature=extra_traits",
+ "feature=rustc-dep-of-std",
+ "feature=std",
+ "feature=use_std",
+ "true",
+ ],
),
- canonical_name: "libc",
- },
- ),
+ ),
+ },
cfg_options: CfgOptions(
[
"feature=default",
@@ -318,20 +389,6 @@
"true",
],
),
- potential_cfg_options: Some(
- CfgOptions(
- [
- "feature=align",
- "feature=const-extern-fn",
- "feature=default",
- "feature=extra_traits",
- "feature=rustc-dep-of-std",
- "feature=std",
- "feature=use_std",
- "true",
- ],
- ),
- ),
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -353,18 +410,11 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [],
- origin: Library {
- repo: Some(
- "https://github.com/rust-lang/libc",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
),
- name: "libc",
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
- ),
- ),
},
} \ No newline at end of file
diff --git a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index 566174882d..272cd69cb1 100644
--- a/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -1,27 +1,53 @@
{
- 0: CrateData {
- root_file_id: FileId(
- 1,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "hello_world",
+ 0: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 1,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- canonical_name: "hello-world",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
+ ),
+ ),
+ },
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
+ ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello-world",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -43,52 +69,70 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
),
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
- ),
- ),
},
- 1: CrateData {
- root_file_id: FileId(
- 2,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "hello_world",
+ 1: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 2,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- canonical_name: "hello-world",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
+ ),
+ ),
+ },
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
+ ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello-world",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -110,60 +154,70 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 2: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 3,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- prelude: true,
- sysroot: false,
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
),
- ),
- },
- 2: CrateData {
- root_file_id: FileId(
- 3,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "an_example",
- ),
- canonical_name: "an-example",
- },
- ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "an_example",
+ ),
+ canonical_name: "an-example",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -185,60 +239,70 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 3: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 4,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "hello_world",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "libc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
+ "hello-world",
),
- prelude: true,
- sysroot: false,
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$hello-world",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.1.0",
),
- ),
- },
- 3: CrateData {
- root_file_id: FileId(
- 4,
- ),
- edition: Edition2018,
- version: Some(
- "0.1.0",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "it",
- ),
- canonical_name: "it",
- },
- ),
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "it",
+ ),
+ canonical_name: "it",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -260,53 +324,60 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
+ ),
+ toolchain: None,
+ },
+ },
+ 4: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 5,
+ ),
+ edition: Edition2015,
+ dependencies: [],
+ origin: Library {
+ repo: Some(
+ "https://github.com/rust-lang/libc",
),
- prelude: true,
- sysroot: false,
+ name: "libc",
},
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "libc",
+ is_proc_macro: false,
+ proc_macro_cwd: Some(
+ AbsPathBuf(
+ "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello-world",
),
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$hello-world",
+ extra: ExtraCrateData {
+ version: Some(
+ "0.2.98",
),
- ),
- },
- 4: CrateData {
- root_file_id: FileId(
- 5,
- ),
- edition: Edition2015,
- version: Some(
- "0.2.98",
- ),
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "libc",
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "libc",
+ ),
+ canonical_name: "libc",
+ },
+ ),
+ potential_cfg_options: Some(
+ CfgOptions(
+ [
+ "feature=align",
+ "feature=const-extern-fn",
+ "feature=default",
+ "feature=extra_traits",
+ "feature=rustc-dep-of-std",
+ "feature=std",
+ "feature=use_std",
+ "true",
+ ],
),
- canonical_name: "libc",
- },
- ),
+ ),
+ },
cfg_options: CfgOptions(
[
"feature=default",
@@ -314,20 +385,6 @@
"true",
],
),
- potential_cfg_options: Some(
- CfgOptions(
- [
- "feature=align",
- "feature=const-extern-fn",
- "feature=default",
- "feature=extra_traits",
- "feature=rustc-dep-of-std",
- "feature=std",
- "feature=use_std",
- "true",
- ],
- ),
- ),
env: Env {
entries: {
"CARGO": "$CARGO$",
@@ -349,18 +406,11 @@
"CARGO_PKG_VERSION_PRE": "",
},
},
- dependencies: [],
- origin: Library {
- repo: Some(
- "https://github.com/rust-lang/libc",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "target_data_layout not loaded",
),
- name: "libc",
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: Some(
- AbsPathBuf(
- "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
- ),
- ),
},
} \ No newline at end of file
diff --git a/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/crates/project-model/test_data/output/rust_project_cfg_groups.txt
index 9b4be19c41..2b8e521f34 100644
--- a/crates/project-model/test_data/output/rust_project_cfg_groups.txt
+++ b/crates/project-model/test_data/output/rust_project_cfg_groups.txt
@@ -1,18 +1,38 @@
{
- 0: CrateData {
- root_file_id: FileId(
- 1,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "alloc",
- ),
- canonical_name: "alloc",
- },
- ),
+ 0: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 1,
+ ),
+ edition: Edition2021,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ Alloc,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "alloc",
+ ),
+ canonical_name: "alloc",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -20,40 +40,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Lang(
- Alloc,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 1: CrateData {
- root_file_id: FileId(
- 2,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "core",
- ),
- canonical_name: "core",
- },
- ),
+ 1: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 2,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Core,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "core",
+ ),
+ canonical_name: "core",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -61,31 +82,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Core,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 2: CrateData {
- root_file_id: FileId(
- 3,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "panic_abort",
- ),
- canonical_name: "panic_abort",
- },
- ),
+ 2: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 3,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "panic_abort",
+ ),
+ canonical_name: "panic_abort",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -93,31 +124,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 3: CrateData {
- root_file_id: FileId(
- 4,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "panic_unwind",
- ),
- canonical_name: "panic_unwind",
- },
- ),
+ 3: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 4,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "panic_unwind",
+ ),
+ canonical_name: "panic_unwind",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -125,31 +166,58 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 4: CrateData {
- root_file_id: FileId(
- 5,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "proc_macro",
- ),
- canonical_name: "proc_macro",
- },
- ),
+ 4: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 5,
+ ),
+ edition: Edition2021,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(6),
+ name: CrateName(
+ "std",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ ProcMacro,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "proc_macro",
+ ),
+ canonical_name: "proc_macro",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -157,48 +225,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(6),
- name: CrateName(
- "std",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Lang(
- ProcMacro,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 5: CrateData {
- root_file_id: FileId(
- 6,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "profiler_builtins",
- ),
- canonical_name: "profiler_builtins",
- },
- ),
+ 5: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 6,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "profiler_builtins",
+ ),
+ canonical_name: "profiler_builtins",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -206,31 +267,106 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 6: CrateData {
- root_file_id: FileId(
- 7,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "std",
- ),
- canonical_name: "std",
- },
- ),
+ 6: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 7,
+ ),
+ edition: Edition2021,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "alloc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(3),
+ name: CrateName(
+ "panic_unwind",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(2),
+ name: CrateName(
+ "panic_abort",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(5),
+ name: CrateName(
+ "profiler_builtins",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(9),
+ name: CrateName(
+ "unwind",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(7),
+ name: CrateName(
+ "std_detect",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(8),
+ name: CrateName(
+ "test",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ Std,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "std",
+ ),
+ canonical_name: "std",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -238,96 +374,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "alloc",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(3),
- name: CrateName(
- "panic_unwind",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(2),
- name: CrateName(
- "panic_abort",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(5),
- name: CrateName(
- "profiler_builtins",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(9),
- name: CrateName(
- "unwind",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(7),
- name: CrateName(
- "std_detect",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(8),
- name: CrateName(
- "test",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Lang(
- Std,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 7: CrateData {
- root_file_id: FileId(
- 8,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "std_detect",
- ),
- canonical_name: "std_detect",
- },
- ),
+ 7: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 8,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "std_detect",
+ ),
+ canonical_name: "std_detect",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -335,31 +416,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 8: CrateData {
- root_file_id: FileId(
- 9,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "test",
- ),
- canonical_name: "test",
- },
- ),
+ 8: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 9,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Test,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "test",
+ ),
+ canonical_name: "test",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -367,31 +458,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Test,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 9: CrateData {
- root_file_id: FileId(
- 10,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "unwind",
- ),
- canonical_name: "unwind",
- },
- ),
+ 9: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 10,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "unwind",
+ ),
+ canonical_name: "unwind",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -399,31 +500,85 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 10: CrateData {
- root_file_id: FileId(
- 11,
- ),
- edition: Edition2018,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
+ 10: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 11,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "alloc",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(6),
+ name: CrateName(
+ "std",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(8),
+ name: CrateName(
+ "test",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "proc_macro",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
"hello_world",
),
- canonical_name: "hello_world",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello_world",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"group1_cfg=some_config",
@@ -434,75 +589,85 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "alloc",
- ),
- prelude: false,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(6),
- name: CrateName(
- "std",
- ),
- prelude: true,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(8),
- name: CrateName(
- "test",
- ),
- prelude: false,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "proc_macro",
- ),
- prelude: false,
- sysroot: true,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
),
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: None,
},
- 11: CrateData {
- root_file_id: FileId(
- 11,
- ),
- edition: Edition2018,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
+ 11: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 11,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "alloc",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(6),
+ name: CrateName(
+ "std",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(8),
+ name: CrateName(
+ "test",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "proc_macro",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
"other_crate",
),
- canonical_name: "other_crate",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "other_crate",
+ ),
+ canonical_name: "other_crate",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"group2_cfg=fourth_config",
@@ -513,59 +678,14 @@
"unrelated_cfg",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "alloc",
- ),
- prelude: false,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(6),
- name: CrateName(
- "std",
- ),
- prelude: true,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(8),
- name: CrateName(
- "test",
- ),
- prelude: false,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "proc_macro",
- ),
- prelude: false,
- sysroot: true,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "other_crate",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
),
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: None,
},
} \ No newline at end of file
diff --git a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index 4c8e66e8e9..053e9473cf 100644
--- a/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -1,18 +1,38 @@
{
- 0: CrateData {
- root_file_id: FileId(
- 1,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "alloc",
- ),
- canonical_name: "alloc",
- },
- ),
+ 0: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 1,
+ ),
+ edition: Edition2021,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ Alloc,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "alloc",
+ ),
+ canonical_name: "alloc",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -20,40 +40,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Lang(
- Alloc,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 1: CrateData {
- root_file_id: FileId(
- 2,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "core",
- ),
- canonical_name: "core",
- },
- ),
+ 1: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 2,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Core,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "core",
+ ),
+ canonical_name: "core",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -61,31 +82,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Core,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 2: CrateData {
- root_file_id: FileId(
- 3,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "panic_abort",
- ),
- canonical_name: "panic_abort",
- },
- ),
+ 2: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 3,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "panic_abort",
+ ),
+ canonical_name: "panic_abort",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -93,31 +124,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 3: CrateData {
- root_file_id: FileId(
- 4,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "panic_unwind",
- ),
- canonical_name: "panic_unwind",
- },
- ),
+ 3: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 4,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "panic_unwind",
+ ),
+ canonical_name: "panic_unwind",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -125,31 +166,58 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 4: CrateData {
- root_file_id: FileId(
- 5,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "proc_macro",
- ),
- canonical_name: "proc_macro",
- },
- ),
+ 4: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 5,
+ ),
+ edition: Edition2021,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(6),
+ name: CrateName(
+ "std",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ ProcMacro,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "proc_macro",
+ ),
+ canonical_name: "proc_macro",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -157,48 +225,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(6),
- name: CrateName(
- "std",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Lang(
- ProcMacro,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 5: CrateData {
- root_file_id: FileId(
- 6,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "profiler_builtins",
- ),
- canonical_name: "profiler_builtins",
- },
- ),
+ 5: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 6,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "profiler_builtins",
+ ),
+ canonical_name: "profiler_builtins",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -206,31 +267,106 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 6: CrateData {
- root_file_id: FileId(
- 7,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "std",
- ),
- canonical_name: "std",
- },
- ),
+ 6: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 7,
+ ),
+ edition: Edition2021,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "alloc",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(3),
+ name: CrateName(
+ "panic_unwind",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(2),
+ name: CrateName(
+ "panic_abort",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(5),
+ name: CrateName(
+ "profiler_builtins",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(9),
+ name: CrateName(
+ "unwind",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(7),
+ name: CrateName(
+ "std_detect",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(8),
+ name: CrateName(
+ "test",
+ ),
+ prelude: true,
+ sysroot: false,
+ },
+ ],
+ origin: Lang(
+ Std,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "std",
+ ),
+ canonical_name: "std",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -238,96 +374,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "alloc",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(3),
- name: CrateName(
- "panic_unwind",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(2),
- name: CrateName(
- "panic_abort",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(5),
- name: CrateName(
- "profiler_builtins",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(9),
- name: CrateName(
- "unwind",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(7),
- name: CrateName(
- "std_detect",
- ),
- prelude: true,
- sysroot: false,
- },
- Dependency {
- crate_id: Idx::<CrateData>(8),
- name: CrateName(
- "test",
- ),
- prelude: true,
- sysroot: false,
- },
- ],
- origin: Lang(
- Std,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 7: CrateData {
- root_file_id: FileId(
- 8,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "std_detect",
- ),
- canonical_name: "std_detect",
- },
- ),
+ 7: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 8,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "std_detect",
+ ),
+ canonical_name: "std_detect",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -335,31 +416,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 8: CrateData {
- root_file_id: FileId(
- 9,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "test",
- ),
- canonical_name: "test",
- },
- ),
+ 8: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 9,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Test,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "test",
+ ),
+ canonical_name: "test",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -367,31 +458,41 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Test,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 9: CrateData {
- root_file_id: FileId(
- 10,
- ),
- edition: Edition2021,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
- "unwind",
- ),
- canonical_name: "unwind",
- },
- ),
+ 9: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 10,
+ ),
+ edition: Edition2021,
+ dependencies: [],
+ origin: Lang(
+ Other,
+ ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "unwind",
+ ),
+ canonical_name: "unwind",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"debug_assertions",
@@ -399,31 +500,85 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [],
- origin: Lang(
- Other,
- ),
- is_proc_macro: false,
- proc_macro_cwd: None,
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
+ ),
+ toolchain: None,
+ },
},
- 10: CrateData {
- root_file_id: FileId(
- 11,
- ),
- edition: Edition2018,
- version: None,
- display_name: Some(
- CrateDisplayName {
- crate_name: CrateName(
+ 10: CrateBuilder {
+ basic: CrateData {
+ root_file_id: FileId(
+ 11,
+ ),
+ edition: Edition2018,
+ dependencies: [
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(1),
+ name: CrateName(
+ "core",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(0),
+ name: CrateName(
+ "alloc",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(6),
+ name: CrateName(
+ "std",
+ ),
+ prelude: true,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(8),
+ name: CrateName(
+ "test",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ Dependency {
+ crate_id: Idx::<CrateBuilder>(4),
+ name: CrateName(
+ "proc_macro",
+ ),
+ prelude: false,
+ sysroot: true,
+ },
+ ],
+ origin: Local {
+ repo: None,
+ name: Some(
"hello_world",
),
- canonical_name: "hello_world",
},
- ),
+ is_proc_macro: false,
+ proc_macro_cwd: None,
+ },
+ extra: ExtraCrateData {
+ version: None,
+ display_name: Some(
+ CrateDisplayName {
+ crate_name: CrateName(
+ "hello_world",
+ ),
+ canonical_name: "hello_world",
+ },
+ ),
+ potential_cfg_options: None,
+ },
cfg_options: CfgOptions(
[
"rust_analyzer",
@@ -431,59 +586,14 @@
"true",
],
),
- potential_cfg_options: None,
env: Env {
entries: {},
},
- dependencies: [
- Dependency {
- crate_id: Idx::<CrateData>(1),
- name: CrateName(
- "core",
- ),
- prelude: true,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(0),
- name: CrateName(
- "alloc",
- ),
- prelude: false,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(6),
- name: CrateName(
- "std",
- ),
- prelude: true,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(8),
- name: CrateName(
- "test",
- ),
- prelude: false,
- sysroot: true,
- },
- Dependency {
- crate_id: Idx::<CrateData>(4),
- name: CrateName(
- "proc_macro",
- ),
- prelude: false,
- sysroot: true,
- },
- ],
- origin: Local {
- repo: None,
- name: Some(
- "hello_world",
+ ws_data: CrateWorkspaceData {
+ data_layout: Err(
+ "test has no data layout",
),
+ toolchain: None,
},
- is_proc_macro: false,
- proc_macro_cwd: None,
},
} \ No newline at end of file
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index f114a4454e..a6aa0376b0 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -8,7 +8,7 @@ use std::{ops::Not as _, time::Instant};
use crossbeam_channel::{unbounded, Receiver, Sender};
use hir::ChangeWithProcMacros;
use ide::{Analysis, AnalysisHost, Cancellable, FileId, SourceRootId};
-use ide_db::base_db::{CrateId, ProcMacroPaths, SourceDatabase};
+use ide_db::base_db::{Crate, ProcMacroPaths, SourceDatabase};
use itertools::Itertools;
use load_cargo::SourceRootConfig;
use lsp_types::{SemanticTokens, Url};
@@ -158,7 +158,7 @@ pub(crate) struct GlobalState {
// op queues
pub(crate) fetch_workspaces_queue: OpQueue<FetchWorkspaceRequest, FetchWorkspaceResponse>,
pub(crate) fetch_build_data_queue: OpQueue<(), FetchBuildDataResponse>,
- pub(crate) fetch_proc_macros_queue: OpQueue<Vec<ProcMacroPaths>, bool>,
+ pub(crate) fetch_proc_macros_queue: OpQueue<(ChangeWithProcMacros, Vec<ProcMacroPaths>), bool>,
pub(crate) prime_caches_queue: OpQueue,
pub(crate) discover_workspace_queue: OpQueue,
@@ -714,7 +714,7 @@ impl GlobalStateSnapshot {
self.vfs_read().file_path(file_id).clone()
}
- pub(crate) fn target_spec_for_crate(&self, crate_id: CrateId) -> Option<TargetSpec> {
+ pub(crate) fn target_spec_for_crate(&self, crate_id: Crate) -> Option<TargetSpec> {
let file_id = self.analysis.crate_root(crate_id).ok()?;
let path = self.vfs_read().file_path(file_id).clone();
let path = path.as_path()?;
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index b47a126424..7244fbc4aa 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -10,7 +10,7 @@ use std::{
use always_assert::always;
use crossbeam_channel::{select, Receiver};
-use ide_db::base_db::{RootQueryDb, SourceDatabase, VfsPath};
+use ide_db::base_db::{SourceDatabase, VfsPath};
use lsp_server::{Connection, Notification, Request};
use lsp_types::{notification::Notification as _, TextDocumentIdentifier};
use stdx::thread::ThreadIntent;
@@ -504,8 +504,10 @@ impl GlobalState {
if !self.fetch_workspaces_queue.op_in_progress() {
if let Some((cause, ())) = self.fetch_build_data_queue.should_start_op() {
self.fetch_build_data(cause);
- } else if let Some((cause, paths)) = self.fetch_proc_macros_queue.should_start_op() {
- self.fetch_proc_macros(cause, paths);
+ } else if let Some((cause, (change, paths))) =
+ self.fetch_proc_macros_queue.should_start_op()
+ {
+ self.fetch_proc_macros(cause, change, paths);
}
}
@@ -804,9 +806,10 @@ impl GlobalState {
let (state, msg) = match progress {
ProcMacroProgress::Begin => (Some(Progress::Begin), None),
ProcMacroProgress::Report(msg) => (Some(Progress::Report), Some(msg)),
- ProcMacroProgress::End(proc_macro_load_result) => {
+ ProcMacroProgress::End(change) => {
self.fetch_proc_macros_queue.op_completed(true);
- self.set_proc_macros(proc_macro_load_result);
+ self.analysis_host.apply_change(change);
+ self.finish_loading_crate_graph();
(Some(Progress::End), None)
}
};
@@ -909,16 +912,15 @@ impl GlobalState {
});
}
QueuedTask::CheckProcMacroSources(modified_rust_files) => {
- let crate_graph = self.analysis_host.raw_database().crate_graph();
let analysis = AssertUnwindSafe(self.snapshot().analysis);
self.task_pool.handle.spawn_with_sender(stdx::thread::ThreadIntent::Worker, {
move |sender| {
if modified_rust_files.into_iter().any(|file_id| {
// FIXME: Check whether these files could be build script related
match analysis.crates_for(file_id) {
- Ok(crates) => {
- crates.iter().any(|&krate| crate_graph[krate].is_proc_macro)
- }
+ Ok(crates) => crates.iter().any(|&krate| {
+ analysis.is_proc_macro_crate(krate).is_ok_and(|it| it)
+ }),
_ => false,
}
}) {
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 1a60fa06c9..d6a99fbe55 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -15,10 +15,9 @@
// FIXME: This is a mess that needs some untangling work
use std::{iter, mem};
-use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros, ProcMacrosBuilder};
-use ide::CrateId;
+use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacrosBuilder};
use ide_db::{
- base_db::{salsa::Durability, CrateGraph, CrateWorkspaceData, ProcMacroPaths},
+ base_db::{salsa::Durability, CrateGraphBuilder, ProcMacroPaths, RootQueryDb},
FxHashMap,
};
use itertools::Itertools;
@@ -60,7 +59,7 @@ pub(crate) enum BuildDataProgress {
pub(crate) enum ProcMacroProgress {
Begin,
Report(String),
- End(ProcMacros),
+ End(ChangeWithProcMacros),
}
impl GlobalState {
@@ -387,7 +386,12 @@ impl GlobalState {
});
}
- pub(crate) fn fetch_proc_macros(&mut self, cause: Cause, paths: Vec<ProcMacroPaths>) {
+ pub(crate) fn fetch_proc_macros(
+ &mut self,
+ cause: Cause,
+ mut change: ChangeWithProcMacros,
+ paths: Vec<ProcMacroPaths>,
+ ) {
info!(%cause, "will load proc macros");
let ignored_proc_macros = self.config.ignored_proc_macros(None).clone();
let proc_macro_clients = self.proc_macro_clients.clone();
@@ -440,16 +444,11 @@ impl GlobalState {
.for_each(|(krate, res)| builder.insert(krate, res));
}
- sender.send(Task::LoadProcMacros(ProcMacroProgress::End(builder.build()))).unwrap();
+ change.set_proc_macros(builder);
+ sender.send(Task::LoadProcMacros(ProcMacroProgress::End(change))).unwrap();
});
}
- pub(crate) fn set_proc_macros(&mut self, proc_macros: ProcMacros) {
- let mut change = ChangeWithProcMacros::new();
- change.set_proc_macros(proc_macros);
- self.analysis_host.apply_change(change);
- }
-
pub(crate) fn switch_workspaces(&mut self, cause: Cause) {
let _p = tracing::info_span!("GlobalState::switch_workspaces").entered();
tracing::info!(%cause, "will switch workspaces");
@@ -528,6 +527,14 @@ impl GlobalState {
if self.config.run_build_scripts(None) {
self.build_deps_changed = false;
self.fetch_build_data_queue.request_op("workspace updated".to_owned(), ());
+
+ let initial_build = self.analysis_host.raw_database().all_crates().is_empty();
+ if !initial_build {
+ // `switch_workspaces()` will be called again when build scripts already run, which should
+ // take a short time. If we update the workspace now we will invalidate proc macros and cfgs,
+ // and then when build scripts complete we will invalidate them again.
+ return;
+ }
}
}
@@ -711,7 +718,7 @@ impl GlobalState {
})
.collect();
- let (crate_graph, proc_macro_paths, ws_data) = {
+ let (crate_graph, proc_macro_paths) = {
// Create crate graph from all the workspaces
let vfs = &self.vfs.read().0;
let load = |path: &AbsPath| {
@@ -725,24 +732,35 @@ impl GlobalState {
ws_to_crate_graph(&self.workspaces, self.config.extra_env(None), load)
};
let mut change = ChangeWithProcMacros::new();
- if self.config.expand_proc_macros() {
- change.set_proc_macros(
- crate_graph
- .iter()
- .map(|id| (id, Err(("proc-macro has not been built yet".to_owned(), true))))
- .collect(),
- );
- self.fetch_proc_macros_queue.request_op(cause, proc_macro_paths);
- } else {
- change.set_proc_macros(
- crate_graph
- .iter()
- .map(|id| (id, Err(("proc-macro expansion is disabled".to_owned(), false))))
- .collect(),
- );
+ let initial_build = self.analysis_host.raw_database().all_crates().is_empty();
+ if initial_build || !self.config.expand_proc_macros() {
+ if self.config.expand_proc_macros() {
+ change.set_proc_macros(
+ crate_graph
+ .iter()
+ .map(|id| (id, Err(("proc-macro has not been built yet".to_owned(), true))))
+ .collect(),
+ );
+ } else {
+ change.set_proc_macros(
+ crate_graph
+ .iter()
+ .map(|id| (id, Err(("proc-macro expansion is disabled".to_owned(), false))))
+ .collect(),
+ );
+ }
+
+ change.set_crate_graph(crate_graph);
+ self.analysis_host.apply_change(change);
+
+ self.finish_loading_crate_graph();
+ return;
}
- change.set_crate_graph(crate_graph, ws_data);
- self.analysis_host.apply_change(change);
+ change.set_crate_graph(crate_graph);
+ self.fetch_proc_macros_queue.request_op(cause, (change, proc_macro_paths));
+ }
+
+ pub(crate) fn finish_loading_crate_graph(&mut self) {
self.report_progress(
"Building CrateGraph",
crate::lsp::utils::Progress::End,
@@ -883,26 +901,19 @@ pub fn ws_to_crate_graph(
workspaces: &[ProjectWorkspace],
extra_env: &FxHashMap<String, String>,
mut load: impl FnMut(&AbsPath) -> Option<vfs::FileId>,
-) -> (CrateGraph, Vec<ProcMacroPaths>, FxHashMap<CrateId, Arc<CrateWorkspaceData>>) {
- let mut crate_graph = CrateGraph::default();
+) -> (CrateGraphBuilder, Vec<ProcMacroPaths>) {
+ let mut crate_graph = CrateGraphBuilder::default();
let mut proc_macro_paths = Vec::default();
- 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 ProjectWorkspace { toolchain, target_layout, .. } = ws;
-
- let mapping = crate_graph.extend(other, &mut crate_proc_macros);
- // Populate the side tables for the newly merged crates
- ws_data.extend(mapping.values().copied().zip(iter::repeat(Arc::new(CrateWorkspaceData {
- toolchain: toolchain.clone(),
- data_layout: target_layout.clone(),
- }))));
+
+ crate_graph.extend(other, &mut crate_proc_macros);
proc_macro_paths.push(crate_proc_macros);
}
crate_graph.shrink_to_fit();
proc_macro_paths.shrink_to_fit();
- (crate_graph, proc_macro_paths, ws_data)
+ (crate_graph, proc_macro_paths)
}
pub(crate) fn should_refresh_for_change(
diff --git a/crates/rust-analyzer/src/target_spec.rs b/crates/rust-analyzer/src/target_spec.rs
index b28567fe09..abb70ebe36 100644
--- a/crates/rust-analyzer/src/target_spec.rs
+++ b/crates/rust-analyzer/src/target_spec.rs
@@ -4,7 +4,7 @@ use std::mem;
use cfg::{CfgAtom, CfgExpr};
use hir::sym;
-use ide::{Cancellable, CrateId, FileId, RunnableKind, TestId};
+use ide::{Cancellable, Crate, FileId, RunnableKind, TestId};
use project_model::project_json::Runnable;
use project_model::{CargoFeatures, ManifestPath, TargetKind};
use rustc_hash::FxHashSet;
@@ -54,7 +54,7 @@ pub(crate) struct CargoTargetSpec {
pub(crate) package: String,
pub(crate) target: String,
pub(crate) target_kind: TargetKind,
- pub(crate) crate_id: CrateId,
+ pub(crate) crate_id: Crate,
pub(crate) required_features: Vec<String>,
pub(crate) features: FxHashSet<String>,
pub(crate) sysroot_root: Option<vfs::AbsPathBuf>,
diff --git a/crates/test-fixture/Cargo.toml b/crates/test-fixture/Cargo.toml
index 95f4cb9d67..2547a02a29 100644
--- a/crates/test-fixture/Cargo.toml
+++ b/crates/test-fixture/Cargo.toml
@@ -18,6 +18,7 @@ rustc-hash.workspace = true
span.workspace = true
stdx.workspace = true
intern.workspace = true
+triomphe.workspace = true
[lints]
workspace = true
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index 4b5c2ff4cf..51d6179a62 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -1,10 +1,10 @@
//! A set of high-level utility fixture methods to use in tests.
-use std::{iter, mem, str::FromStr, sync};
+use std::{mem, str::FromStr, sync};
use base_db::{
- CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, CrateWorkspaceData, Dependency,
- Env, FileChange, FileSet, LangCrateOrigin, RootQueryDb, SourceDatabase, SourceRoot, Version,
- VfsPath,
+ Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData,
+ DependencyBuilder, Env, FileChange, FileSet, LangCrateOrigin, SourceDatabase, SourceRoot,
+ Version, VfsPath,
};
use cfg::CfgOptions;
use hir_expand::{
@@ -26,6 +26,7 @@ use test_utils::{
extract_range_or_offset, Fixture, FixtureWithProjectMeta, RangeOrOffset, CURSOR_MARKER,
ESCAPED_CURSOR_MARKER,
};
+use triomphe::Arc;
pub const WORKSPACE: base_db::SourceRootId = base_db::SourceRootId(0);
@@ -101,14 +102,8 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static {
(db, file_id, range_or_offset)
}
- fn test_crate(&self) -> CrateId {
- let crate_graph = RootQueryDb::crate_graph(self);
- let mut it = crate_graph.iter();
- let mut res = it.next().unwrap();
- while crate_graph[res].origin.is_lang() {
- res = it.next().unwrap();
- }
- res
+ fn test_crate(&self) -> Crate {
+ self.all_crates().iter().copied().find(|&krate| !krate.data(self).origin.is_lang()).unwrap()
}
}
@@ -146,7 +141,7 @@ impl ChangeFixture {
let mut source_change = FileChange::new();
let mut files = Vec::new();
- let mut crate_graph = CrateGraph::default();
+ let mut crate_graph = CrateGraphBuilder::default();
let mut crates = FxHashMap::default();
let mut crate_deps = Vec::new();
let mut default_crate_root: Option<FileId> = None;
@@ -163,6 +158,9 @@ impl ChangeFixture {
let mut file_position = None;
+ let crate_ws_data =
+ Arc::new(CrateWorkspaceData { data_layout: target_data_layout, toolchain });
+
for entry in fixture {
let mut range_or_offset = None;
let text = if entry.text.contains(CURSOR_MARKER) {
@@ -210,11 +208,12 @@ impl ChangeFixture {
Some(crate_name.clone().into()),
version,
From::from(meta.cfg.clone()),
- Some(From::from(meta.cfg)),
+ Some(meta.cfg),
meta.env,
origin,
false,
None,
+ crate_ws_data.clone(),
);
let prev = crates.insert(crate_name.clone(), crate_id);
assert!(prev.is_none(), "multiple crates with same name: {crate_name}");
@@ -249,19 +248,23 @@ impl ChangeFixture {
Some(CrateName::new("ra_test_fixture").unwrap().into()),
None,
From::from(default_cfg.clone()),
- Some(From::from(default_cfg)),
+ Some(default_cfg),
default_env,
CrateOrigin::Local { repo: None, name: None },
false,
None,
+ crate_ws_data.clone(),
);
} else {
for (from, to, prelude) in crate_deps {
let from_id = crates[&from];
let to_id = crates[&to];
- let sysroot = crate_graph[to_id].origin.is_lang();
+ let sysroot = crate_graph[to_id].basic.origin.is_lang();
crate_graph
- .add_dep(from_id, Dependency::with_prelude(to.clone(), to_id, prelude, sysroot))
+ .add_dep(
+ from_id,
+ DependencyBuilder::with_prelude(to.clone(), to_id, prelude, sysroot),
+ )
.unwrap();
}
}
@@ -276,7 +279,7 @@ impl ChangeFixture {
source_change.change_file(core_file, Some(mini_core.source_code()));
- let all_crates = crate_graph.crates_in_topological_order();
+ let all_crates = crate_graph.iter().collect::<Vec<_>>();
let core_crate = crate_graph.add_crate_root(
core_file,
@@ -292,13 +295,14 @@ impl ChangeFixture {
CrateOrigin::Lang(LangCrateOrigin::Core),
false,
None,
+ crate_ws_data.clone(),
);
for krate in all_crates {
crate_graph
.add_dep(
krate,
- Dependency::with_prelude(
+ DependencyBuilder::with_prelude(
CrateName::new("core").unwrap(),
core_crate,
true,
@@ -324,7 +328,7 @@ impl ChangeFixture {
source_change.change_file(proc_lib_file, Some(source));
- let all_crates = crate_graph.crates_in_topological_order();
+ let all_crates = crate_graph.iter().collect::<Vec<_>>();
let proc_macros_crate = crate_graph.add_crate_root(
proc_lib_file,
@@ -340,6 +344,7 @@ impl ChangeFixture {
CrateOrigin::Local { repo: None, name: None },
true,
None,
+ crate_ws_data,
);
proc_macros.insert(proc_macros_crate, Ok(proc_macro));
@@ -347,7 +352,10 @@ impl ChangeFixture {
crate_graph
.add_dep(
krate,
- Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate),
+ DependencyBuilder::new(
+ CrateName::new("proc_macros").unwrap(),
+ proc_macros_crate,
+ ),
)
.unwrap();
}
@@ -359,19 +367,9 @@ impl ChangeFixture {
};
roots.push(root);
- let mut change =
- ChangeWithProcMacros { source_change, proc_macros: Some(proc_macros.build()) };
+ let mut change = ChangeWithProcMacros { source_change, proc_macros: Some(proc_macros) };
change.source_change.set_roots(roots);
- change.source_change.set_ws_data(
- crate_graph
- .iter()
- .zip(iter::repeat(From::from(CrateWorkspaceData {
- data_layout: target_data_layout,
- toolchain,
- })))
- .collect(),
- );
change.source_change.set_crate_graph(crate_graph);
ChangeFixture { file_position, files, change }
@@ -654,6 +652,10 @@ impl ProcMacroExpander for IdentityProcMacroExpander {
) -> Result<TopSubtree, ProcMacroExpansionError> {
Ok(subtree.clone())
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
// Expands to a macro_rules! macro, for issue #18089.
@@ -685,6 +687,10 @@ impl ProcMacroExpander for Issue18089ProcMacroExpander {
#subtree
})
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
// Pastes the attribute input as its output
@@ -705,6 +711,10 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander {
.cloned()
.ok_or_else(|| ProcMacroExpansionError::Panic("Expected attribute input".into()))
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
#[derive(Debug)]
@@ -736,6 +746,10 @@ impl ProcMacroExpander for Issue18840ProcMacroExpander {
top_subtree_delimiter_mut.close = def_site;
Ok(result)
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
#[derive(Debug)]
@@ -767,6 +781,10 @@ impl ProcMacroExpander for MirrorProcMacroExpander {
traverse(&mut builder, input.iter());
Ok(builder.build())
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
// Replaces every literal with an empty string literal and every identifier with its first letter,
@@ -807,6 +825,10 @@ impl ProcMacroExpander for ShortenProcMacroExpander {
}
}
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
// Reads ident type within string quotes, for issue #17479.
@@ -832,6 +854,10 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander {
#symbol()
})
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
// Reads ident type within string quotes, for issue #17479.
@@ -883,6 +909,10 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander {
}
})
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}
// Reads ident type within string quotes, for issue #17479.
@@ -910,4 +940,8 @@ impl ProcMacroExpander for DisallowCfgProcMacroExpander {
}
Ok(subtree.clone())
}
+
+ fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+ other.as_any().type_id() == std::any::TypeId::of::<Self>()
+ }
}