Salsify the crate graph

I.e. make it not one giant input but multiple, for incrementality and decreased memory usage for Salsa 3 reasons.
This commit is contained in:
Chayim Refael Friedman 2025-01-02 01:45:32 +02:00
parent 44f18c3d05
commit c94e9efbef
108 changed files with 3630 additions and 2512 deletions

1
Cargo.lock generated
View file

@ -2418,6 +2418,7 @@ dependencies = [
"span", "span",
"stdx", "stdx",
"test-utils", "test-utils",
"triomphe",
"tt", "tt",
] ]

View file

@ -3,20 +3,18 @@
use std::fmt; use std::fmt;
use rustc_hash::FxHashMap;
use salsa::Durability; use salsa::Durability;
use triomphe::Arc; use triomphe::Arc;
use vfs::FileId; 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. /// Encapsulate a bunch of raw `.set` calls on the database.
#[derive(Default)] #[derive(Default)]
pub struct FileChange { pub struct FileChange {
pub roots: Option<Vec<SourceRoot>>, pub roots: Option<Vec<SourceRoot>>,
pub files_changed: Vec<(FileId, Option<String>)>, pub files_changed: Vec<(FileId, Option<String>)>,
pub crate_graph: Option<CrateGraph>, pub crate_graph: Option<CrateGraphBuilder>,
pub ws_data: Option<FxHashMap<CrateId, Arc<CrateWorkspaceData>>>,
} }
impl fmt::Debug for FileChange { impl fmt::Debug for FileChange {
@ -48,15 +46,11 @@ impl FileChange {
self.files_changed.push((file_id, new_text)) 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); self.crate_graph = Some(graph);
} }
pub fn set_ws_data(&mut self, data: FxHashMap<CrateId, Arc<CrateWorkspaceData>>) { pub fn apply(self, db: &mut dyn RootQueryDb) -> Option<CratesIdMap> {
self.ws_data = Some(data);
}
pub fn apply(self, db: &mut dyn RootQueryDb) {
let _p = tracing::info_span!("FileChange::apply").entered(); let _p = tracing::info_span!("FileChange::apply").entered();
if let Some(roots) = self.roots { if let Some(roots) = self.roots {
for (idx, root) in roots.into_iter().enumerate() { for (idx, root) in roots.into_iter().enumerate() {
@ -79,12 +73,11 @@ impl FileChange {
let text = text.unwrap_or_default(); let text = text.unwrap_or_default();
db.set_file_text_with_durability(file_id, &text, durability) db.set_file_text_with_durability(file_id, &text, durability)
} }
if let Some(crate_graph) = self.crate_graph { if let Some(crate_graph) = self.crate_graph {
db.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH); return Some(crate_graph.set_in_db(db));
}
if let Some(data) = self.ws_data {
db.set_crate_workspace_data_with_durability(Arc::new(data), Durability::HIGH);
} }
None
} }
} }

View file

@ -6,17 +6,23 @@
//! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how //! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how
//! actual IO is done and lowered to input. //! actual IO is done and lowered to input.
use std::hash::BuildHasherDefault;
use std::{fmt, mem, ops}; use std::{fmt, mem, ops};
use cfg::CfgOptions; use cfg::{CfgOptions, HashableCfgOptions};
use dashmap::mapref::entry::Entry;
use dashmap::DashMap;
use intern::Symbol; use intern::Symbol;
use la_arena::{Arena, Idx, RawIdx}; 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 span::{Edition, EditionedFileId};
use triomphe::Arc; use triomphe::Arc;
use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath}; 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SourceRootId(pub u32); 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 #[derive(Default, Clone)]
/// number of Rust crates. pub struct CrateGraphBuilder {
/// arena: Arena<CrateBuilder>,
/// 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>,
} }
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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map() f.debug_map()
.entries(self.arena.iter().map(|(id, data)| (u32::from(id.into_raw()), data))) .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)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CrateName(Symbol); pub struct CrateName(Symbol);
@ -272,10 +277,46 @@ impl ReleaseChannel {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] /// The crate data from which we derive the `Crate`.
pub struct CrateData { ///
/// 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 root_file_id: FileId,
pub edition: Edition, pub edition: Edition,
/// 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<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
/// for workspace members, the crate manifest dir otherwise.
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>, pub version: Option<String>,
/// A name used in the package's project declaration: for Cargo projects, /// A name used in the package's project declaration: for Cargo projects,
/// its `[package].name` can be different for other project types or even /// its `[package].name` can be different for other project types or even
@ -284,21 +325,8 @@ pub struct CrateData {
/// For purposes of analysis, crates are anonymous (only names in /// For purposes of analysis, crates are anonymous (only names in
/// `Dependency` matters), this name should only be used for UI. /// `Dependency` matters), this name should only be used for UI.
pub display_name: Option<CrateDisplayName>, pub display_name: Option<CrateDisplayName>,
pub cfg_options: Arc<CfgOptions>,
/// The cfg options that could be used by the crate /// The cfg options that could be used by the crate
pub potential_cfg_options: Option<Arc<CfgOptions>>, pub potential_cfg_options: Option<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 origin: CrateOrigin,
pub is_proc_macro: bool,
/// The working directory to run proc-macros in. This is the workspace root of the cargo workspace
/// for workspace members, the crate manifest dir otherwise.
pub proc_macro_cwd: Option<AbsPathBuf>,
} }
#[derive(Default, Clone, PartialEq, Eq)] #[derive(Default, Clone, PartialEq, Eq)]
@ -326,22 +354,32 @@ impl fmt::Debug for Env {
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Dependency { pub struct Dependency<Id> {
pub crate_id: CrateId, pub crate_id: Id,
pub name: CrateName, pub name: CrateName,
prelude: bool, prelude: bool,
sysroot: bool, sysroot: bool,
} }
impl Dependency { pub type DependencyBuilder = Dependency<CrateBuilderId>;
pub fn new(name: CrateName, crate_id: CrateId) -> Self { pub type BuiltDependency = Dependency<Crate>;
impl DependencyBuilder {
pub fn new(name: CrateName, crate_id: CrateBuilderId) -> Self {
Self { name, crate_id, prelude: true, sysroot: false } 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 } Self { name, crate_id, prelude, sysroot }
} }
}
impl BuiltDependency {
/// Whether this dependency is to be added to the depending crate's extern prelude. /// Whether this dependency is to be added to the depending crate's extern prelude.
pub fn is_prelude(&self) -> bool { pub fn is_prelude(&self) -> bool {
self.prelude 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( pub fn add_crate_root(
&mut self, &mut self,
root_file_id: FileId, root_file_id: FileId,
@ -361,33 +424,34 @@ impl CrateGraph {
display_name: Option<CrateDisplayName>, display_name: Option<CrateDisplayName>,
version: Option<String>, version: Option<String>,
cfg_options: Arc<CfgOptions>, cfg_options: Arc<CfgOptions>,
potential_cfg_options: Option<Arc<CfgOptions>>, potential_cfg_options: Option<CfgOptions>,
mut env: Env, mut env: Env,
origin: CrateOrigin, origin: CrateOrigin,
is_proc_macro: bool, is_proc_macro: bool,
proc_macro_cwd: Option<AbsPathBuf>, proc_macro_cwd: Option<AbsPathBuf>,
) -> CrateId { ws_data: Arc<CrateWorkspaceData>,
) -> CrateBuilderId {
env.entries.shrink_to_fit(); env.entries.shrink_to_fit();
let data = CrateData { self.arena.alloc(CrateBuilder {
root_file_id, basic: CrateData {
edition, root_file_id,
version, edition,
display_name, dependencies: Vec::new(),
origin,
is_proc_macro,
proc_macro_cwd,
},
extra: ExtraCrateData { version, display_name, potential_cfg_options },
cfg_options, cfg_options,
potential_cfg_options,
env, env,
dependencies: Vec::new(), ws_data,
origin, })
is_proc_macro,
proc_macro_cwd,
};
self.arena.alloc(data)
} }
pub fn add_dep( pub fn add_dep(
&mut self, &mut self,
from: CrateId, from: CrateBuilderId,
dep: Dependency, dep: DependencyBuilder,
) -> Result<(), CyclicDependenciesError> { ) -> Result<(), CyclicDependenciesError> {
let _p = tracing::info_span!("add_dep").entered(); 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 // that out, look for a path in the *opposite* direction, from `to` to
// `from`. // `from`.
if let Some(path) = self.find_path(&mut FxHashSet::default(), dep.crate_id, 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 }; let err = CyclicDependenciesError { path };
assert!(err.from().0 == from && err.to().0 == dep.crate_id); assert!(err.from().0 == from && err.to().0 == dep.crate_id);
return Err(err); return Err(err);
} }
self.arena[from].add_dep(dep); self.arena[from].basic.dependencies.push(dep);
Ok(()) Ok(())
} }
pub fn is_empty(&self) -> bool { pub fn set_in_db(self, db: &mut dyn RootQueryDb) -> CratesIdMap {
self.arena.is_empty() let mut all_crates = Vec::with_capacity(self.arena.len());
let mut visited = FxHashMap::default();
let mut visited_root_files = FxHashSet::default();
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 len(&self) -> usize { pub fn iter(&self) -> impl Iterator<Item = CrateBuilderId> + '_ {
self.arena.len()
}
pub fn iter(&self) -> impl Iterator<Item = CrateId> + '_ {
self.arena.iter().map(|(idx, _)| idx) self.arena.iter().map(|(idx, _)| idx)
} }
// FIXME: used for fixing up the toolchain sysroot, should be removed and done differently // FIXME: used for fixing up the toolchain sysroot, should be removed and done differently
#[doc(hidden)] #[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() self.arena.iter_mut()
} }
/// Returns an iterator over all transitive dependencies of the given crate, /// Returns an iterator over all transitive dependencies of the given crate,
/// including the crate itself. /// 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 worklist = vec![of];
let mut deps = FxHashSet::default(); let mut deps = FxHashSet::default();
@ -434,42 +621,15 @@ impl CrateGraph {
continue; 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() 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 /// Returns all crates in the graph, sorted in topological order (ie. dependencies of a crate
/// come before the crate itself). /// 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 res = Vec::new();
let mut visited = FxHashSet::default(); let mut visited = FxHashSet::default();
@ -480,15 +640,15 @@ impl CrateGraph {
return res; return res;
fn go( fn go(
graph: &CrateGraph, graph: &CrateGraphBuilder,
visited: &mut FxHashSet<CrateId>, visited: &mut FxHashSet<CrateBuilderId>,
res: &mut Vec<CrateId>, res: &mut Vec<CrateBuilderId>,
source: CrateId, source: CrateBuilderId,
) { ) {
if !visited.insert(source) { if !visited.insert(source) {
return; return;
} }
for dep in graph[source].dependencies.iter() { for dep in graph[source].basic.dependencies.iter() {
go(graph, visited, res, dep.crate_id) go(graph, visited, res, dep.crate_id)
} }
res.push(source) res.push(source)
@ -504,23 +664,27 @@ impl CrateGraph {
/// Returns a map mapping `other`'s IDs to the new IDs in `self`. /// Returns a map mapping `other`'s IDs to the new IDs in `self`.
pub fn extend( pub fn extend(
&mut self, &mut self,
mut other: CrateGraph, mut other: CrateGraphBuilder,
proc_macros: &mut ProcMacroPaths, proc_macros: &mut ProcMacroPaths,
) -> FxHashMap<CrateId, CrateId> { ) -> FxHashMap<CrateBuilderId, CrateBuilderId> {
// Sorting here is a bit pointless because the input is likely already sorted. // 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. // However, the overhead is small and it makes the `extend` method harder to misuse.
self.arena self.arena
.iter_mut() .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 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 { for topo in topo {
let crate_data = &mut other.arena[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
crate_data.dependencies.sort_by_key(|dep| dep.crate_id); .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 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())); let new_id = find.unwrap_or_else(|| self.arena.alloc(crate_data.clone()));
@ -534,10 +698,10 @@ impl CrateGraph {
fn find_path( fn find_path(
&self, &self,
visited: &mut FxHashSet<CrateId>, visited: &mut FxHashSet<CrateBuilderId>,
from: CrateId, from: CrateBuilderId,
to: CrateId, to: CrateBuilderId,
) -> Option<Vec<CrateId>> { ) -> Option<Vec<CrateBuilderId>> {
if !visited.insert(from) { if !visited.insert(from) {
return None; return None;
} }
@ -546,7 +710,7 @@ impl CrateGraph {
return Some(vec![to]); return Some(vec![to]);
} }
for dep in &self[from].dependencies { for dep in &self[from].basic.dependencies {
let crate_id = dep.crate_id; let crate_id = dep.crate_id;
if let Some(mut path) = self.find_path(visited, crate_id, to) { if let Some(mut path) = self.find_path(visited, crate_id, to) {
path.push(from); 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. /// 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. /// 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()]; let mut id_map = vec![None; self.arena.len()];
self.arena = std::mem::take(&mut self.arena) self.arena = std::mem::take(&mut self.arena)
.into_iter() .into_iter()
@ -567,12 +734,12 @@ impl CrateGraph {
.enumerate() .enumerate()
.map(|(new_id, (id, data))| { .map(|(new_id, (id, data))| {
id_map[id.into_raw().into_u32() as usize] = 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 data
}) })
.collect(); .collect();
for (_, data) in self.arena.iter_mut() { 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 = dep.crate_id =
id_map[dep.crate_id.into_raw().into_u32() as usize].expect("crate was filtered") 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 { pub(crate) fn transitive_rev_deps(db: &dyn RootQueryDb, of: Crate) -> FxHashSet<Crate> {
type Output = CrateData; let mut worklist = vec![of];
fn index(&self, crate_id: CrateId) -> &CrateData { let mut rev_deps = FxHashSet::default();
&self.arena[crate_id] 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));
}
} }
rev_deps
} }
impl CrateData { impl BuiltCrateData {
/// 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)
}
pub fn root_file_id(&self) -> EditionedFileId { pub fn root_file_id(&self) -> EditionedFileId {
EditionedFileId::new(self.root_file_id, self.edition) EditionedFileId::new(self.root_file_id, self.edition)
} }
@ -657,21 +838,21 @@ impl<'a> IntoIterator for &'a Env {
#[derive(Debug)] #[derive(Debug)]
pub struct CyclicDependenciesError { pub struct CyclicDependenciesError {
path: Vec<(CrateId, Option<CrateDisplayName>)>, path: Vec<(CrateBuilderId, Option<CrateDisplayName>)>,
} }
impl CyclicDependenciesError { impl CyclicDependenciesError {
fn from(&self) -> &(CrateId, Option<CrateDisplayName>) { fn from(&self) -> &(CrateBuilderId, Option<CrateDisplayName>) {
self.path.first().unwrap() self.path.first().unwrap()
} }
fn to(&self) -> &(CrateId, Option<CrateDisplayName>) { fn to(&self) -> &(CrateBuilderId, Option<CrateDisplayName>) {
self.path.last().unwrap() self.path.last().unwrap()
} }
} }
impl fmt::Display for CyclicDependenciesError { impl fmt::Display for CyclicDependenciesError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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:?})"), Some(it) => format!("{it}({id:?})"),
None => format!("{id:?}"), None => format!("{id:?}"),
}; };
@ -688,13 +869,19 @@ impl fmt::Display for CyclicDependenciesError {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::CrateOrigin; use triomphe::Arc;
use super::{CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId}; use crate::{CrateWorkspaceData, DependencyBuilder};
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] #[test]
fn detect_cyclic_dependency_indirect() { fn detect_cyclic_dependency_indirect() {
let mut graph = CrateGraph::default(); let mut graph = CrateGraphBuilder::default();
let crate1 = graph.add_crate_root( let crate1 = graph.add_crate_root(
FileId::from_raw(1u32), FileId::from_raw(1u32),
Edition2018, Edition2018,
@ -706,6 +893,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
let crate2 = graph.add_crate_root( let crate2 = graph.add_crate_root(
FileId::from_raw(2u32), FileId::from_raw(2u32),
@ -718,6 +906,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
let crate3 = graph.add_crate_root( let crate3 = graph.add_crate_root(
FileId::from_raw(3u32), FileId::from_raw(3u32),
@ -730,21 +919,22 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
assert!(graph assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,)) .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,))
.is_ok()); .is_ok());
assert!(graph assert!(graph
.add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,)) .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,))
.is_ok()); .is_ok());
assert!(graph assert!(graph
.add_dep(crate3, Dependency::new(CrateName::new("crate1").unwrap(), crate1,)) .add_dep(crate3, DependencyBuilder::new(CrateName::new("crate1").unwrap(), crate1,))
.is_err()); .is_err());
} }
#[test] #[test]
fn detect_cyclic_dependency_direct() { fn detect_cyclic_dependency_direct() {
let mut graph = CrateGraph::default(); let mut graph = CrateGraphBuilder::default();
let crate1 = graph.add_crate_root( let crate1 = graph.add_crate_root(
FileId::from_raw(1u32), FileId::from_raw(1u32),
Edition2018, Edition2018,
@ -756,6 +946,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
let crate2 = graph.add_crate_root( let crate2 = graph.add_crate_root(
FileId::from_raw(2u32), FileId::from_raw(2u32),
@ -768,18 +959,19 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
assert!(graph assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,)) .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,))
.is_ok()); .is_ok());
assert!(graph assert!(graph
.add_dep(crate2, Dependency::new(CrateName::new("crate2").unwrap(), crate2,)) .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,))
.is_err()); .is_err());
} }
#[test] #[test]
fn it_works() { fn it_works() {
let mut graph = CrateGraph::default(); let mut graph = CrateGraphBuilder::default();
let crate1 = graph.add_crate_root( let crate1 = graph.add_crate_root(
FileId::from_raw(1u32), FileId::from_raw(1u32),
Edition2018, Edition2018,
@ -791,6 +983,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
let crate2 = graph.add_crate_root( let crate2 = graph.add_crate_root(
FileId::from_raw(2u32), FileId::from_raw(2u32),
@ -803,6 +996,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
let crate3 = graph.add_crate_root( let crate3 = graph.add_crate_root(
FileId::from_raw(3u32), FileId::from_raw(3u32),
@ -815,18 +1009,19 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
assert!(graph assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2,)) .add_dep(crate1, DependencyBuilder::new(CrateName::new("crate2").unwrap(), crate2,))
.is_ok()); .is_ok());
assert!(graph assert!(graph
.add_dep(crate2, Dependency::new(CrateName::new("crate3").unwrap(), crate3,)) .add_dep(crate2, DependencyBuilder::new(CrateName::new("crate3").unwrap(), crate3,))
.is_ok()); .is_ok());
} }
#[test] #[test]
fn dashes_are_normalized() { fn dashes_are_normalized() {
let mut graph = CrateGraph::default(); let mut graph = CrateGraphBuilder::default();
let crate1 = graph.add_crate_root( let crate1 = graph.add_crate_root(
FileId::from_raw(1u32), FileId::from_raw(1u32),
Edition2018, Edition2018,
@ -838,6 +1033,7 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
let crate2 = graph.add_crate_root( let crate2 = graph.add_crate_root(
FileId::from_raw(2u32), FileId::from_raw(2u32),
@ -850,16 +1046,22 @@ mod tests {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
empty_ws_data(),
); );
assert!(graph assert!(graph
.add_dep( .add_dep(
crate1, crate1,
Dependency::new(CrateName::normalize_dashes("crate-name-with-dashes"), crate2,) DependencyBuilder::new(
CrateName::normalize_dashes("crate-name-with-dashes"),
crate2,
)
) )
.is_ok()); .is_ok());
assert_eq!( assert_eq!(
graph[crate1].dependencies, graph.arena[crate1].basic.dependencies,
vec![Dependency::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2,)] vec![
DependencyBuilder::new(CrateName::new("crate_name_with_dashes").unwrap(), crate2,)
]
); );
} }
} }

View file

@ -8,14 +8,15 @@ use std::hash::BuildHasherDefault;
pub use crate::{ pub use crate::{
change::FileChange, change::FileChange,
input::{ input::{
CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, BuiltCrateData, BuiltDependency, Crate, CrateBuilder, CrateBuilderId, CrateDataBuilder,
LangCrateOrigin, ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CratesIdMap, CratesMap,
TargetLayoutLoadResult, DependencyBuilder, Env, ExtraCrateData, LangCrateOrigin, ProcMacroPaths, ReleaseChannel,
SourceRoot, SourceRootId, TargetLayoutLoadResult, UniqueCrateData,
}, },
}; };
use dashmap::{mapref::entry::Entry, DashMap}; use dashmap::{mapref::entry::Entry, DashMap};
pub use query_group::{self}; pub use query_group::{self};
use rustc_hash::{FxHashMap, FxHasher}; use rustc_hash::{FxHashSet, FxHasher};
pub use salsa::{self}; pub use salsa::{self};
use salsa::{Durability, Setter}; use salsa::{Durability, Setter};
pub use semver::{BuildMetadata, Prerelease, Version, VersionReq}; 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. /// Returns the set of errors obtained from parsing the file including validation errors.
fn parse_errors(&self, file_id: EditionedFileId) -> Option<Arc<[SyntaxError]>>; fn parse_errors(&self, file_id: EditionedFileId) -> Option<Arc<[SyntaxError]>>;
/// The crate graph.
#[salsa::input]
fn crate_graph(&self) -> Arc<CrateGraph>;
#[salsa::input]
fn crate_workspace_data(&self) -> Arc<FxHashMap<CrateId, Arc<CrateWorkspaceData>>>;
#[salsa::transparent] #[salsa::transparent]
fn toolchain_channel(&self, krate: CrateId) -> Option<ReleaseChannel>; fn toolchain_channel(&self, krate: Crate) -> Option<ReleaseChannel>;
/// Crates whose root file is in `id`. /// Crates whose root file is in `id`.
fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>; fn source_root_crates(&self, id: SourceRootId) -> Arc<[Crate]>;
#[salsa::transparent] #[salsa::transparent]
fn relevant_crates(&self, file_id: FileId) -> Arc<[CrateId]>; fn relevant_crates(&self, file_id: FileId) -> Arc<[Crate]>;
/// 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 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] #[salsa::db]
@ -257,6 +290,9 @@ pub trait SourceDatabase: salsa::Database {
let source_root = self.source_root(source_root.source_root_id(self)); let source_root = self.source_root(source_root.source_root_id(self));
source_root.source_root(self).resolve_path(path) source_root.source_root(self).resolve_path(path)
} }
#[doc(hidden)]
fn crates_map(&self) -> Arc<CratesMap>;
} }
/// Crate related data shared by the whole workspace. /// Crate related data shared by the whole workspace.
@ -268,12 +304,8 @@ pub struct CrateWorkspaceData {
pub toolchain: Option<Version>, pub toolchain: Option<Version>,
} }
fn toolchain_channel(db: &dyn RootQueryDb, krate: CrateId) -> Option<ReleaseChannel> { fn toolchain_channel(db: &dyn RootQueryDb, krate: Crate) -> Option<ReleaseChannel> {
db.crate_workspace_data() krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
.get(&krate)?
.toolchain
.as_ref()
.and_then(|v| ReleaseChannel::from_str(&v.pre))
} }
fn parse(db: &dyn RootQueryDb, file_id: EditionedFileId) -> Parse<ast::SourceFile> { 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]> { fn source_root_crates(db: &dyn RootQueryDb, id: SourceRootId) -> Arc<[Crate]> {
let graph = db.crate_graph(); let crates = db.all_crates();
let mut crates = graph crates
.iter() .iter()
.copied()
.filter(|&krate| { .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 db.file_source_root(root_file).source_root_id(db) == id
}) })
.collect::<Vec<_>>(); .collect()
crates.sort();
crates.dedup();
crates.into_iter().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 _p = tracing::info_span!("relevant_crates").entered();
let source_root = db.file_source_root(file_id); let source_root = db.file_source_root(file_id);

View file

@ -104,6 +104,12 @@ impl CfgOptions {
_ => None, _ => 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 { impl Extend<CfgAtom> for CfgOptions {
@ -256,3 +262,9 @@ impl fmt::Display for InactiveReason {
Ok(()) 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]>,
}

View file

@ -2,7 +2,7 @@
use std::{borrow::Cow, hash::Hash, ops}; use std::{borrow::Cow, hash::Hash, ops};
use base_db::CrateId; use base_db::Crate;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{
@ -44,7 +44,7 @@ impl Attrs {
(**self).iter().find(|attr| attr.id == id) (**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)) 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 // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
let mut res = ArenaMap::default(); let mut res = ArenaMap::default();
let crate_graph = db.crate_graph();
let item_tree; let item_tree;
let (parent, fields, krate) = match v { let (parent, fields, krate) = match v {
VariantId::EnumVariantId(it) => { 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; let mut idx = 0;
for (id, _field) in fields.iter().enumerate() { for (id, _field) in fields.iter().enumerate() {

View file

@ -2,7 +2,7 @@
pub mod adt; pub mod adt;
use base_db::CrateId; use base_db::Crate;
use hir_expand::{ use hir_expand::{
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
}; };
@ -22,7 +22,7 @@ use crate::{
attr_resolution::ResolvedAttr, attr_resolution::ResolvedAttr,
diagnostics::{DefDiagnostic, DefDiagnostics}, diagnostics::{DefDiagnostic, DefDiagnostics},
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind}, proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
DefMap, MacroSubNs, DefMap, LocalDefMap, MacroSubNs,
}, },
path::ImportAlias, path::ImportAlias,
type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap}, type_ref::{TraitRef, TypeBound, TypeRefId, TypesMap},
@ -57,8 +57,7 @@ impl FunctionData {
item_tree[func.visibility].clone() item_tree[func.visibility].clone()
}; };
let crate_graph = db.crate_graph(); let cfg_options = krate.cfg_options(db);
let cfg_options = &crate_graph[krate].cfg_options;
let attr_owner = |idx| { let attr_owner = |idx| {
item_tree::AttrOwner::Param(loc.id.value, Idx::from_raw(RawIdx::from(idx as u32))) 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 name: Name,
pub alias: Option<ImportAlias>, pub alias: Option<ImportAlias>,
pub visibility: RawVisibility, pub visibility: RawVisibility,
pub crate_id: Option<CrateId>, pub crate_id: Option<Crate>,
} }
impl ExternCrateDeclData { impl ExternCrateDeclData {
@ -542,7 +541,7 @@ impl ExternCrateDeclData {
let crate_id = if name == sym::self_.clone() { let crate_id = if name == sym::self_.clone() {
Some(krate) Some(krate)
} else { } else {
db.crate_graph()[krate].dependencies.iter().find_map(|dep| { krate.data(db).dependencies.iter().find_map(|dep| {
if dep.name.symbol() == name.symbol() { if dep.name.symbol() == name.symbol() {
Some(dep.crate_id) Some(dep.crate_id)
} else { } else {
@ -633,6 +632,7 @@ struct AssocItemCollector<'a> {
db: &'a dyn DefDatabase, db: &'a dyn DefDatabase,
module_id: ModuleId, module_id: ModuleId,
def_map: Arc<DefMap>, def_map: Arc<DefMap>,
local_def_map: Arc<LocalDefMap>,
diagnostics: Vec<DefDiagnostic>, diagnostics: Vec<DefDiagnostic>,
container: ItemContainerId, container: ItemContainerId,
expander: Expander, expander: Expander,
@ -648,10 +648,12 @@ impl<'a> AssocItemCollector<'a> {
file_id: HirFileId, file_id: HirFileId,
container: ItemContainerId, container: ItemContainerId,
) -> Self { ) -> Self {
let (def_map, local_def_map) = module_id.local_def_map(db);
Self { Self {
db, db,
module_id, module_id,
def_map: module_id.def_map(db), def_map,
local_def_map,
container, container,
expander: Expander::new(db, file_id, module_id), expander: Expander::new(db, file_id, module_id),
items: Vec::new(), items: Vec::new(),
@ -697,6 +699,7 @@ impl<'a> AssocItemCollector<'a> {
let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id }; let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id };
match self.def_map.resolve_attr_macro( match self.def_map.resolve_attr_macro(
&self.local_def_map,
self.db, self.db,
self.module_id.local_id, self.module_id.local_id,
ast_id_with_path, ast_id_with_path,
@ -780,6 +783,7 @@ impl<'a> AssocItemCollector<'a> {
let resolver = |path: &_| { let resolver = |path: &_| {
self.def_map self.def_map
.resolve_path( .resolve_path(
&self.local_def_map,
self.db, self.db,
module, module,
path, path,

View file

@ -1,6 +1,6 @@
//! Defines hir-level representation of structs, enums and unions //! Defines hir-level representation of structs, enums and unions
use base_db::CrateId; use base_db::Crate;
use bitflags::bitflags; use bitflags::bitflags;
use cfg::CfgOptions; use cfg::CfgOptions;
use either::Either; use either::Either;
@ -90,7 +90,7 @@ pub struct FieldData {
fn repr_from_value( fn repr_from_value(
db: &dyn DefDatabase, db: &dyn DefDatabase,
krate: CrateId, krate: Crate,
item_tree: &ItemTree, item_tree: &ItemTree,
of: AttrOwner, of: AttrOwner,
) -> Option<ReprOptions> { ) -> Option<ReprOptions> {
@ -222,7 +222,7 @@ impl StructData {
loc.container.local_id, loc.container.local_id,
loc.id.tree_id(), loc.id.tree_id(),
&item_tree, &item_tree,
&db.crate_graph()[krate].cfg_options, krate.cfg_options(db),
FieldParent::Struct(loc.id.value), FieldParent::Struct(loc.id.value),
&strukt.fields, &strukt.fields,
None, None,
@ -274,7 +274,7 @@ impl StructData {
loc.container.local_id, loc.container.local_id,
loc.id.tree_id(), loc.id.tree_id(),
&item_tree, &item_tree,
&db.crate_graph()[krate].cfg_options, krate.cfg_options(db),
FieldParent::Union(loc.id.value), FieldParent::Union(loc.id.value),
&union.fields, &union.fields,
None, None,
@ -377,7 +377,7 @@ impl EnumVariantData {
container.local_id, container.local_id,
loc.id.tree_id(), loc.id.tree_id(),
&item_tree, &item_tree,
&db.crate_graph()[krate].cfg_options, krate.cfg_options(db),
FieldParent::Variant(loc.id.value), FieldParent::Variant(loc.id.value),
&variant.fields, &variant.fields,
Some(item_tree[loc.parent.lookup(db).id.value].visibility), Some(item_tree[loc.parent.lookup(db).id.value].visibility),
@ -448,7 +448,7 @@ pub enum StructKind {
fn lower_fields( fn lower_fields(
db: &dyn DefDatabase, db: &dyn DefDatabase,
krate: CrateId, krate: Crate,
container: LocalModuleId, container: LocalModuleId,
tree_id: TreeId, tree_id: TreeId,
item_tree: &ItemTree, item_tree: &ItemTree,

View file

@ -1,5 +1,5 @@
//! Defines database & queries for name resolution. //! Defines database & queries for name resolution.
use base_db::{CrateId, RootQueryDb, SourceDatabase, Upcast}; use base_db::{Crate, RootQueryDb, SourceDatabase, Upcast};
use either::Either; use either::Either;
use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId}; use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId};
use intern::sym; use intern::sym;
@ -20,7 +20,7 @@ use crate::{
import_map::ImportMap, import_map::ImportMap,
item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps}, item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps},
lang_item::{self, LangItem, LangItemTarget, LangItems}, lang_item::{self, LangItem, LangItemTarget, LangItems},
nameres::{diagnostics::DefDiagnostics, DefMap}, nameres::{diagnostics::DefDiagnostics, DefMap, LocalDefMap},
tt, tt,
type_ref::TypesSourceMap, type_ref::TypesSourceMap,
visibility::{self, Visibility}, visibility::{self, Visibility},
@ -130,8 +130,11 @@ pub trait DefDatabase:
block_id: BlockId, block_id: BlockId,
) -> (Arc<ItemTree>, Arc<ItemTreeSourceMaps>); ) -> (Arc<ItemTree>, Arc<ItemTreeSourceMaps>);
#[salsa::invoke(DefMap::crate_def_map_query)] #[salsa::invoke_actual(DefMap::crate_local_def_map_query)]
fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>; 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`. /// Computes the block-level `DefMap`.
#[salsa::invoke_actual(DefMap::block_def_map_query)] #[salsa::invoke_actual(DefMap::block_def_map_query)]
@ -258,10 +261,10 @@ pub trait DefDatabase:
// endregion:attrs // endregion:attrs
#[salsa::invoke(LangItems::lang_item_query)] #[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)] #[salsa::invoke_actual(ImportMap::import_map_query)]
fn import_map(&self, krate: CrateId) -> Arc<ImportMap>; fn import_map(&self, krate: Crate) -> Arc<ImportMap>;
// region:visibilities // region:visibilities
@ -277,23 +280,25 @@ pub trait DefDatabase:
// endregion:visibilities // endregion:visibilities
#[salsa::invoke(LangItems::crate_lang_items_query)] #[salsa::invoke_actual(LangItems::crate_lang_items_query)]
fn crate_lang_items(&self, krate: CrateId) -> Option<Arc<LangItems>>; fn crate_lang_items(&self, krate: Crate) -> Option<Arc<LangItems>>;
#[salsa::invoke(crate::lang_item::notable_traits_in_deps)] #[salsa::invoke_actual(crate::lang_item::notable_traits_in_deps)]
fn notable_traits_in_deps(&self, krate: CrateId) -> Arc<[Arc<[TraitId]>]>; fn notable_traits_in_deps(&self, krate: Crate) -> Arc<[Arc<[TraitId]>]>;
#[salsa::invoke(crate::lang_item::crate_notable_traits)] #[salsa::invoke_actual(crate::lang_item::crate_notable_traits)]
fn crate_notable_traits(&self, krate: CrateId) -> Option<Arc<[TraitId]>>; 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 // return: macro call id and include file id
fn include_macro_invoc( fn include_macro_invoc(
db: &dyn DefDatabase, db: &dyn DefDatabase,
krate: CrateId, krate: Crate,
) -> Arc<[(MacroCallId, EditionedFileId)]> { ) -> Arc<[(MacroCallId, EditionedFileId)]> {
db.crate_def_map(krate) db.crate_def_map(krate)
.modules .modules
@ -307,8 +312,8 @@ fn include_macro_invoc(
.collect() .collect()
} }
fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool { fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: Crate) -> bool {
let file = db.crate_graph()[crate_id].root_file_id(); let file = crate_id.data(db).root_file_id();
let item_tree = db.file_item_tree(file.into()); let item_tree = db.file_item_tree(file.into());
let attrs = item_tree.raw_attrs(AttrOwner::TopLevel); let attrs = item_tree.raw_attrs(AttrOwner::TopLevel);
for attr in &**attrs { for attr in &**attrs {

View file

@ -2,7 +2,7 @@
use std::cell::OnceCell; use std::cell::OnceCell;
use base_db::CrateId; use base_db::Crate;
use cfg::CfgOptions; use cfg::CfgOptions;
use drop_bomb::DropBomb; use drop_bomb::DropBomb;
use hir_expand::{ use hir_expand::{
@ -44,7 +44,7 @@ impl Expander {
module, module,
recursion_depth: 0, recursion_depth: 0,
recursion_limit, 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(), span_map: OnceCell::new(),
} }
} }
@ -53,7 +53,7 @@ impl Expander {
self.span_map.get_or_init(|| db.span_map(self.current_file_id)) 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 self.module.krate
} }

View file

@ -86,7 +86,6 @@ impl Body {
let item_tree = f.id.item_tree(db); let item_tree = f.id.item_tree(db);
let func = &item_tree[f.id.value]; let func = &item_tree[f.id.value];
let krate = f.container.module(db).krate; let krate = f.container.module(db).krate;
let crate_graph = db.crate_graph();
( (
param_list, param_list,
(0..func.params.len()).map(move |idx| { (0..func.params.len()).map(move |idx| {
@ -99,7 +98,7 @@ impl Body {
Idx::from_raw(RawIdx::from(idx as u32)), Idx::from_raw(RawIdx::from(idx as u32)),
), ),
) )
.is_cfg_enabled(&crate_graph[krate].cfg_options) .is_cfg_enabled(krate.cfg_options(db))
}), }),
) )
}); });

View file

@ -5,7 +5,7 @@ mod asm;
use std::mem; use std::mem;
use base_db::CrateId; use base_db::Crate;
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{
mod_path::tool_path, mod_path::tool_path,
@ -50,7 +50,7 @@ use crate::{
item_scope::BuiltinShadowMode, item_scope::BuiltinShadowMode,
lang_item::LangItem, lang_item::LangItem,
lower::LowerCtx, lower::LowerCtx,
nameres::{DefMap, MacroSubNs}, nameres::{DefMap, LocalDefMap, MacroSubNs},
path::{GenericArgs, Path}, path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef}, type_ref::{Mutability, Rawness, TypeRef},
AdtId, BlockId, BlockLoc, ConstBlockLoc, DefWithBodyId, MacroId, ModuleDefId, UnresolvedMacro, AdtId, BlockId, BlockLoc, ConstBlockLoc, DefWithBodyId, MacroId, ModuleDefId, UnresolvedMacro,
@ -64,7 +64,7 @@ pub(super) fn lower_body(
expander: Expander, expander: Expander,
parameters: Option<(ast::ParamList, impl Iterator<Item = bool>)>, parameters: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
body: Option<ast::Expr>, body: Option<ast::Expr>,
krate: CrateId, krate: Crate,
is_async_fn: bool, is_async_fn: bool,
) -> (Body, BodySourceMap) { ) -> (Body, BodySourceMap) {
// We cannot leave the root span map empty and let any identifier from it be treated as root, // 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, owner: ExprStoreOwnerId,
expander: Expander, expander: Expander,
body: Option<ast::Expr>, body: Option<ast::Expr>,
krate: CrateId, krate: Crate,
) -> (ExpressionStore, ExpressionStoreSourceMap) { ) -> (ExpressionStore, ExpressionStoreSourceMap) {
// We cannot leave the root span map empty and let any identifier from it be treated as root, // 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 // because when inside nested macros `SyntaxContextId`s from the outer macro will be interleaved
@ -214,8 +214,9 @@ struct ExprCollector<'a> {
expander: Expander, expander: Expander,
owner: ExprStoreOwnerId, owner: ExprStoreOwnerId,
def_map: Arc<DefMap>, def_map: Arc<DefMap>,
local_def_map: Arc<LocalDefMap>,
ast_id_map: Arc<AstIdMap>, ast_id_map: Arc<AstIdMap>,
krate: CrateId, krate: Crate,
store: ExpressionStoreBuilder, store: ExpressionStoreBuilder,
source_map: ExpressionStoreSourceMap, source_map: ExpressionStoreSourceMap,
@ -327,14 +328,16 @@ impl ExprCollector<'_> {
db: &dyn DefDatabase, db: &dyn DefDatabase,
owner: ExprStoreOwnerId, owner: ExprStoreOwnerId,
expander: Expander, expander: Expander,
krate: CrateId, krate: Crate,
span_map: Option<Arc<ExpansionSpanMap>>, span_map: Option<Arc<ExpansionSpanMap>>,
) -> ExprCollector<'_> { ) -> ExprCollector<'_> {
let (def_map, local_def_map) = expander.module.local_def_map(db);
ExprCollector { ExprCollector {
db, db,
owner, owner,
krate, krate,
def_map: expander.module.def_map(db), def_map,
local_def_map,
source_map: ExpressionStoreSourceMap::default(), source_map: ExpressionStoreSourceMap::default(),
ast_id_map: db.ast_id_map(expander.current_file_id()), ast_id_map: db.ast_id_map(expander.current_file_id()),
store: ExpressionStoreBuilder::default(), store: ExpressionStoreBuilder::default(),
@ -1306,6 +1309,7 @@ impl ExprCollector<'_> {
None => self.expander.enter_expand(self.db, mcall, |path| { None => self.expander.enter_expand(self.db, mcall, |path| {
self.def_map self.def_map
.resolve_path( .resolve_path(
&self.local_def_map,
self.db, self.db,
module, module,
path, path,
@ -1608,6 +1612,7 @@ impl ExprCollector<'_> {
// This could also be a single-segment path pattern. To // This could also be a single-segment path pattern. To
// decide that, we need to try resolving the name. // decide that, we need to try resolving the name.
let (resolved, _) = self.def_map.resolve_path( let (resolved, _) = self.def_map.resolve_path(
&self.local_def_map,
self.db, self.db,
self.expander.module.local_id, self.expander.module.local_id,
&name.clone().into(), &name.clone().into(),

View file

@ -293,7 +293,7 @@ impl SsrError {
assert_eq!(db.body_with_source_map(def).1.diagnostics(), &[]); assert_eq!(db.body_with_source_map(def).1.diagnostics(), &[]);
expect![[r#" expect![[r#"
fn main() -> () { fn main() -> () {
_ = $crate::error::SsrError::new( _ = ra_test_fixture::error::SsrError::new(
builtin#lang(Arguments::new_v1_formatted)( builtin#lang(Arguments::new_v1_formatted)(
&[ &[
"Failed to resolve path `", "`", "Failed to resolve path `", "`",
@ -353,7 +353,7 @@ fn f(a: i32, b: u32) -> String {
expect![[r#" expect![[r#"
fn f(a: i32, b: u32) -> String { fn f(a: i32, b: u32) -> String {
{ {
$crate::panicking::panic_fmt( core::panicking::panic_fmt(
builtin#lang(Arguments::new_v1_formatted)( builtin#lang(Arguments::new_v1_formatted)(
&[ &[
"cc", "cc",

View file

@ -2,7 +2,7 @@
use std::{cell::Cell, cmp::Ordering, iter}; use std::{cell::Cell, cmp::Ordering, iter};
use base_db::{CrateId, CrateOrigin, LangCrateOrigin}; use base_db::{Crate, CrateOrigin, LangCrateOrigin};
use hir_expand::{ use hir_expand::{
name::{AsName, Name}, name::{AsName, Name},
Lookup, Lookup,
@ -50,7 +50,7 @@ pub fn find_path(
prefix: prefix_kind, prefix: prefix_kind,
cfg, cfg,
ignore_local_imports, 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,
from_def_map: &from.def_map(db), from_def_map: &from.def_map(db),
fuel: Cell::new(FIND_PATH_FUEL), 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 // - 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 // 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 { if crate_root != def_id {
continue; 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 // 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. // 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) 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, max_len: usize,
best_choice: &mut Option<Choice>, best_choice: &mut Option<Choice>,
) { ) {
let crate_graph = ctx.db.crate_graph(); let dependencies = &ctx.from.krate.data(ctx.db).dependencies;
let dependencies = &crate_graph[ctx.from.krate].dependencies;
let mut search = |lang, best_choice: &mut _| { let mut search = |lang, best_choice: &mut _| {
if let Some(dep) = dependencies.iter().filter(|it| it.is_sysroot()).find(|dep| { 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, CrateOrigin::Lang(l) => l == lang,
_ => false, _ => false,
} }
@ -419,7 +418,7 @@ fn find_in_dep(
item: ItemInNs, item: ItemInNs,
max_len: usize, max_len: usize,
best_choice: &mut Option<Choice>, best_choice: &mut Option<Choice>,
dep: CrateId, dep: Crate,
) { ) {
let import_map = ctx.db.import_map(dep); let import_map = ctx.db.import_map(dep);
let Some(import_info_for) = import_map.import_info_for(item) else { let Some(import_info_for) = import_map.import_info_for(item) else {
@ -688,9 +687,10 @@ mod tests {
}) })
.unwrap(); .unwrap();
let def_map = module.def_map(&db); let (def_map, local_def_map) = module.local_def_map(&db);
let resolved = def_map let resolved = def_map
.resolve_path( .resolve_path(
&local_def_map,
&db, &db,
module.local_id, module.local_id,
&mod_path, &mod_path,

View file

@ -23,7 +23,7 @@ use crate::{
expander::Expander, expander::Expander,
item_tree::{AttrOwner, FileItemTreeId, GenericModItem, GenericsItemTreeNode, ItemTree}, item_tree::{AttrOwner, FileItemTreeId, GenericModItem, GenericsItemTreeNode, ItemTree},
lower::LowerCtx, lower::LowerCtx,
nameres::{DefMap, MacroSubNs}, nameres::{DefMap, LocalDefMap, MacroSubNs},
path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path}, path::{AssociatedTypeBinding, GenericArg, GenericArgs, NormalPath, Path},
type_ref::{ type_ref::{
ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId, ArrayType, ConstRef, FnType, LifetimeRef, PathId, RefType, TypeBound, TypeRef, TypeRefId,
@ -313,8 +313,7 @@ impl GenericParams {
let _p = tracing::info_span!("generic_params_query").entered(); let _p = tracing::info_span!("generic_params_query").entered();
let krate = def.krate(db); let krate = def.krate(db);
let cfg_options = db.crate_graph(); let cfg_options = &krate.cfg_options(db);
let cfg_options = &cfg_options[krate].cfg_options;
// Returns the generic parameters that are enabled under the current `#[cfg]` options // Returns the generic parameters that are enabled under the current `#[cfg]` options
let enabled_params = let enabled_params =
@ -413,7 +412,12 @@ impl GenericParams {
&mut types_source_maps, &mut types_source_maps,
&mut expander, &mut expander,
&mut || { &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, param,
&item.types_map, &item.types_map,
@ -626,8 +630,8 @@ impl GenericParamsCollector {
generics_types_map: &mut TypesMap, generics_types_map: &mut TypesMap,
generics_types_source_map: &mut TypesSourceMap, generics_types_source_map: &mut TypesSourceMap,
// FIXME: Change this back to `LazyCell` if https://github.com/rust-lang/libs-team/issues/429 is accepted. // 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: &mut Option<(Arc<DefMap>, Arc<LocalDefMap>, Expander)>,
exp_fill: &mut dyn FnMut() -> (Arc<DefMap>, Expander), exp_fill: &mut dyn FnMut() -> (Arc<DefMap>, Arc<LocalDefMap>, Expander),
type_ref: TypeRefId, type_ref: TypeRefId,
types_map: &TypesMap, types_map: &TypesMap,
types_source_map: &TypesSourceMap, types_source_map: &TypesSourceMap,
@ -657,12 +661,13 @@ impl GenericParamsCollector {
if let TypeRef::Macro(mc) = type_ref { if let TypeRef::Macro(mc) = type_ref {
let macro_call = mc.to_node(db.upcast()); 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 module = expander.module.local_id;
let resolver = |path: &_| { let resolver = |path: &_| {
def_map def_map
.resolve_path( .resolve_path(
local_def_map,
db, db,
module, module,
path, path,
@ -690,7 +695,7 @@ impl GenericParamsCollector {
&macro_types_map, &macro_types_map,
&macro_types_source_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);
} }
} }
}); });

View file

@ -2,7 +2,7 @@
use std::fmt; use std::fmt;
use base_db::CrateId; use base_db::Crate;
use fst::{raw::IndexedValue, Automaton, Streamer}; use fst::{raw::IndexedValue, Automaton, Streamer};
use hir_expand::name::Name; use hir_expand::name::Name;
use itertools::Itertools; use itertools::Itertools;
@ -78,7 +78,7 @@ impl ImportMap {
out 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 _p = tracing::info_span!("import_map_query").entered();
let map = Self::collect_import_map(db, krate); let map = Self::collect_import_map(db, krate);
@ -129,7 +129,7 @@ impl ImportMap {
self.item_to_info_map.get(&item).map(|(info, _)| &**info) 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 _p = tracing::info_span!("collect_import_map").entered();
let def_map = db.crate_def_map(krate); 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`. /// This returns a list of items that could be imported from dependencies of `krate`.
pub fn search_dependencies( pub fn search_dependencies(
db: &dyn DefDatabase, db: &dyn DefDatabase,
krate: CrateId, krate: Crate,
query: &Query, query: &Query,
) -> FxHashSet<ItemInNs> { ) -> FxHashSet<ItemInNs> {
let _p = tracing::info_span!("search_dependencies", ?query).entered(); let _p = tracing::info_span!("search_dependencies", ?query).entered();
let graph = db.crate_graph();
let import_maps: Vec<_> = 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(); let mut op = fst::map::OpBuilder::new();
@ -512,11 +510,13 @@ mod tests {
expect: Expect, expect: Expect,
) { ) {
let db = TestDB::with_files(ra_fixture); let db = TestDB::with_files(ra_fixture);
let crate_graph = db.crate_graph(); let all_crates = db.all_crates();
let krate = crate_graph let krate = all_crates
.iter() .iter()
.copied()
.find(|&krate| { .find(|&krate| {
crate_graph[krate] krate
.extra_data(&db)
.display_name .display_name
.as_ref() .as_ref()
.is_some_and(|it| it.crate_name().as_str() == crate_name) .is_some_and(|it| it.crate_name().as_str() == crate_name)
@ -545,7 +545,7 @@ mod tests {
Some(format!( Some(format!(
"{}::{} ({})\n", "{}::{} ({})\n",
crate_graph[dependency_krate].display_name.as_ref()?, dependency_krate.extra_data(&db).display_name.as_ref()?,
path, path,
mark mark
)) ))
@ -590,12 +590,13 @@ mod tests {
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
let db = TestDB::with_files(ra_fixture); 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() .iter()
.copied()
.filter_map(|krate| { .filter_map(|krate| {
let cdata = &crate_graph[krate]; let cdata = &krate.extra_data(&db);
let name = cdata.display_name.as_ref()?; let name = cdata.display_name.as_ref()?;
let map = db.import_map(krate); let map = db.import_map(krate);

View file

@ -3,7 +3,7 @@
use std::sync::LazyLock; use std::sync::LazyLock;
use base_db::CrateId; use base_db::Crate;
use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId}; use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId};
use indexmap::map::Entry; use indexmap::map::Entry;
use itertools::Itertools; use itertools::Itertools;
@ -916,7 +916,7 @@ impl ItemInNs {
} }
/// Returns the crate defining this item (or `None` if `self` is built-in). /// 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 { match self {
ItemInNs::Types(id) | ItemInNs::Values(id) => id.module(db).map(|m| m.krate), ItemInNs::Types(id) | ItemInNs::Values(id) => id.module(db).map(|m| m.krate),
ItemInNs::Macros(id) => Some(id.module(db).krate), ItemInNs::Macros(id) => Some(id.module(db).krate),

View file

@ -44,7 +44,7 @@ use std::{
}; };
use ast::{AstNode, StructKind}; use ast::{AstNode, StructKind};
use base_db::CrateId; use base_db::Crate;
use either::Either; use either::Either;
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
use intern::{Interned, Symbol}; use intern::{Interned, Symbol};
@ -202,7 +202,7 @@ impl ItemTree {
} }
/// Returns the inner attributes of the source file. /// 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( Attrs::filter(
db, db,
krate, krate,
@ -214,7 +214,7 @@ impl ItemTree {
self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY) 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()) Attrs::filter(db, krate, self.raw_attrs(of).clone())
} }

View file

@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
use triomphe::Arc; use triomphe::Arc;
use crate::{ 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, 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. /// Salsa query. This will look for lang items in a specific crate.
pub(crate) fn crate_lang_items_query( pub(crate) fn crate_lang_items_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
krate: CrateId, krate: Crate,
) -> Option<Arc<LangItems>> { ) -> Option<Arc<LangItems>> {
let _p = tracing::info_span!("crate_lang_items_query").entered(); let _p = tracing::info_span!("crate_lang_items_query").entered();
@ -175,7 +175,7 @@ impl LangItems {
/// traversing its dependencies. /// traversing its dependencies.
pub(crate) fn lang_item_query( pub(crate) fn lang_item_query(
db: &dyn DefDatabase, db: &dyn DefDatabase,
start_crate: CrateId, start_crate: Crate,
item: LangItem, item: LangItem,
) -> Option<LangItemTarget> { ) -> Option<LangItemTarget> {
let _p = tracing::info_span!("lang_item_query").entered(); let _p = tracing::info_span!("lang_item_query").entered();
@ -184,10 +184,7 @@ impl LangItems {
{ {
return Some(target); return Some(target);
} }
db.crate_graph()[start_crate] start_crate.data(db).dependencies.iter().find_map(|dep| db.lang_item(dep.crate_id, item))
.dependencies
.iter()
.find_map(|dep| db.lang_item(dep.crate_id, item))
} }
fn collect_lang_item<T>( 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() db.attrs(item).lang_item()
} }
pub(crate) fn notable_traits_in_deps( pub(crate) fn notable_traits_in_deps(db: &dyn DefDatabase, krate: Crate) -> Arc<[Arc<[TraitId]>]> {
db: &dyn DefDatabase,
krate: CrateId,
) -> Arc<[Arc<[TraitId]>]> {
let _p = tracing::info_span!("notable_traits_in_deps", ?krate).entered(); let _p = tracing::info_span!("notable_traits_in_deps", ?krate).entered();
let crate_graph = db.crate_graph();
Arc::from_iter( 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 _p = tracing::info_span!("crate_notable_traits", ?krate).entered();
let mut traits = Vec::new(); let mut traits = Vec::new();
@ -290,17 +282,12 @@ impl LangItem {
Self::from_symbol(name.symbol()) 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)?; let t = db.lang_item(start_crate, *self)?;
Some(Path::LangItem(t, None)) Some(Path::LangItem(t, None))
} }
pub fn ty_rel_path( pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option<Path> {
&self,
db: &dyn DefDatabase,
start_crate: CrateId,
seg: Name,
) -> Option<Path> {
let t = db.lang_item(start_crate, *self)?; let t = db.lang_item(start_crate, *self)?;
Some(Path::LangItem(t, Some(seg))) Some(Path::LangItem(t, Some(seg)))
} }

View file

@ -71,7 +71,7 @@ mod test_db;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use base_db::{impl_intern_key, CrateId}; use base_db::{impl_intern_key, Crate};
use hir_expand::{ use hir_expand::{
builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander}, builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
db::ExpandDatabase, db::ExpandDatabase,
@ -99,10 +99,10 @@ use crate::{
Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules, Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant, Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
}, },
nameres::LocalDefMap,
}; };
type FxIndexMap<K, V> = type FxIndexMap<K, V> = indexmap::IndexMap<K, V, rustc_hash::FxBuildHasher>;
indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
/// A wrapper around three booleans /// A wrapper around three booleans
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)] #[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub struct ImportPathConfig { pub struct ImportPathConfig {
@ -338,7 +338,7 @@ pub struct ConstBlockLoc {
/// A `ModuleId` that is always a crate's root module. /// A `ModuleId` that is always a crate's root module.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CrateRootModuleId { pub struct CrateRootModuleId {
krate: CrateId, krate: Crate,
} }
impl CrateRootModuleId { impl CrateRootModuleId {
@ -346,7 +346,11 @@ impl CrateRootModuleId {
db.crate_def_map(self.krate) 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 self.krate
} }
} }
@ -374,8 +378,8 @@ impl From<CrateRootModuleId> for ModuleDefId {
} }
} }
impl From<CrateId> for CrateRootModuleId { impl From<Crate> for CrateRootModuleId {
fn from(krate: CrateId) -> Self { fn from(krate: Crate) -> Self {
CrateRootModuleId { krate } CrateRootModuleId { krate }
} }
} }
@ -394,7 +398,7 @@ impl TryFrom<ModuleId> for CrateRootModuleId {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ModuleId { pub struct ModuleId {
krate: CrateId, krate: Crate,
/// If this `ModuleId` was derived from a `DefMap` for a block expression, this stores the /// 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 /// `BlockId` of that block expression. If `None`, this module is part of the crate-level
/// `DefMap` of `krate`. /// `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> { pub fn crate_def_map(self, db: &dyn DefDatabase) -> Arc<DefMap> {
db.crate_def_map(self.krate) db.crate_def_map(self.krate)
} }
pub fn krate(self) -> CrateId { pub fn krate(self) -> Crate {
self.krate self.krate
} }
@ -982,7 +997,7 @@ impl From<CallableDefId> for ModuleDefId {
} }
impl CallableDefId { impl CallableDefId {
pub fn krate(self, db: &dyn DefDatabase) -> CrateId { pub fn krate(self, db: &dyn DefDatabase) -> Crate {
match self { match self {
CallableDefId::FunctionId(f) => f.krate(db), CallableDefId::FunctionId(f) => f.krate(db),
CallableDefId::StructId(s) => s.krate(db), CallableDefId::StructId(s) => s.krate(db),
@ -1119,7 +1134,7 @@ pub trait HasModule {
/// Returns the crate this thing is defined within. /// Returns the crate this thing is defined within.
#[inline] #[inline]
#[doc(alias = "crate")] #[doc(alias = "crate")]
fn krate(&self, db: &dyn DefDatabase) -> CrateId { fn krate(&self, db: &dyn DefDatabase) -> Crate {
self.module(db).krate self.module(db).krate
} }
} }
@ -1367,7 +1382,7 @@ pub trait AsMacroCall {
fn as_call_id( fn as_call_id(
&self, &self,
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
krate: CrateId, krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy, resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Option<MacroCallId> { ) -> Option<MacroCallId> {
self.as_call_id_with_errors(db, krate, resolver).ok()?.value self.as_call_id_with_errors(db, krate, resolver).ok()?.value
@ -1376,7 +1391,7 @@ pub trait AsMacroCall {
fn as_call_id_with_errors( fn as_call_id_with_errors(
&self, &self,
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
krate: CrateId, krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy, resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>; ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>;
} }
@ -1385,7 +1400,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
fn as_call_id_with_errors( fn as_call_id_with_errors(
&self, &self,
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
krate: CrateId, krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy, resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> { ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
let expands_to = hir_expand::ExpandTo::from_call_site(self.value); 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: &AstIdWithPath<ast::MacroCall>,
call_site: SyntaxContextId, call_site: SyntaxContextId,
expand_to: ExpandTo, expand_to: ExpandTo,
krate: CrateId, krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy, resolver: impl Fn(&path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<Option<MacroCallId>, UnresolvedMacro> { ) -> Result<Option<MacroCallId>, UnresolvedMacro> {
macro_call_as_call_id_with_eager( macro_call_as_call_id_with_eager(
@ -1464,7 +1479,7 @@ fn macro_call_as_call_id_with_eager(
path: &path::ModPath, path: &path::ModPath,
call_site: SyntaxContextId, call_site: SyntaxContextId,
expand_to: ExpandTo, expand_to: ExpandTo,
krate: CrateId, krate: Crate,
resolver: impl FnOnce(&path::ModPath) -> Option<MacroDefId>, resolver: impl FnOnce(&path::ModPath) -> Option<MacroDefId>,
eager_resolver: impl Fn(&path::ModPath) -> Option<MacroDefId>, eager_resolver: impl Fn(&path::ModPath) -> Option<MacroDefId>,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> { ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {

View file

@ -376,4 +376,8 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
panic!("got invalid macro input: {:?}", parse.errors()); 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>()
}
} }

View file

@ -59,7 +59,7 @@ mod tests;
use std::ops::Deref; use std::ops::Deref;
use base_db::CrateId; use base_db::Crate;
use hir_expand::{ use hir_expand::{
name::Name, proc_macro::ProcMacroKind, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId, name::Name, proc_macro::ProcMacroKind, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId,
}; };
@ -69,7 +69,7 @@ use la_arena::Arena;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use span::{Edition, EditionedFileId, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID}; use span::{Edition, EditionedFileId, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID};
use stdx::format_to; use stdx::format_to;
use syntax::{ast, AstNode, SmolStr, SyntaxNode}; use syntax::{ast, AstNode, SmolStr, SyntaxNode, ToSmolStr};
use triomphe::Arc; use triomphe::Arc;
use tt::TextRange; use tt::TextRange;
@ -95,6 +95,39 @@ const PREDEFINED_TOOLS: &[SmolStr] = &[
SmolStr::new_static("rust_analyzer"), 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. /// Contains the results of (early) name resolution.
/// ///
/// A `DefMap` stores the module tree and the definitions that are in scope in every module after /// 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)] #[derive(Debug, PartialEq, Eq)]
pub struct DefMap { pub struct DefMap {
/// The crate this `DefMap` belongs to. /// 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 /// When this is a block def map, this will hold the block id of the block and module that
/// contains this block. /// contains this block.
block: Option<BlockInfo>, 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. /// 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)] #[derive(Clone, Debug, PartialEq, Eq)]
struct DefMapCrateData { 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. /// Side table for resolving derive helpers.
exported_derives: FxHashMap<MacroDefId, Box<[Name]>>, exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
fn_proc_macro_mapping: FxHashMap<FunctionId, ProcMacroId>, fn_proc_macro_mapping: FxHashMap<FunctionId, ProcMacroId>,
@ -166,7 +196,6 @@ struct DefMapCrateData {
impl DefMapCrateData { impl DefMapCrateData {
fn new(edition: Edition) -> Self { fn new(edition: Edition) -> Self {
Self { Self {
extern_prelude: FxIndexMap::default(),
exported_derives: FxHashMap::default(), exported_derives: FxHashMap::default(),
fn_proc_macro_mapping: FxHashMap::default(), fn_proc_macro_mapping: FxHashMap::default(),
registered_attrs: Vec::new(), registered_attrs: Vec::new(),
@ -182,7 +211,6 @@ impl DefMapCrateData {
fn shrink_to_fit(&mut self) { fn shrink_to_fit(&mut self) {
let Self { let Self {
extern_prelude,
exported_derives, exported_derives,
fn_proc_macro_mapping, fn_proc_macro_mapping,
registered_attrs, registered_attrs,
@ -194,7 +222,6 @@ impl DefMapCrateData {
edition: _, edition: _,
recursion_limit: _, recursion_limit: _,
} = self; } = self;
extern_prelude.shrink_to_fit();
exported_derives.shrink_to_fit(); exported_derives.shrink_to_fit();
fn_proc_macro_mapping.shrink_to_fit(); fn_proc_macro_mapping.shrink_to_fit();
registered_attrs.shrink_to_fit(); registered_attrs.shrink_to_fit();
@ -219,11 +246,11 @@ struct BlockRelativeModuleId {
} }
impl 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) 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 } ModuleId { krate, block: self.block, local_id: self.local_id }
} }
@ -337,11 +364,25 @@ impl DefMap {
self.data.edition self.data.edition
} }
pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc<DefMap> { pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: Crate) -> Arc<DefMap> {
let crate_graph = db.crate_graph(); db.crate_local_def_map(crate_id).0
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_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( let module_data = ModuleData::new(
ModuleOrigin::CrateRoot { definition: krate.root_file_id() }, ModuleOrigin::CrateRoot { definition: krate.root_file_id() },
@ -354,10 +395,14 @@ impl DefMap {
module_data, module_data,
None, None,
); );
let def_map = let (def_map, local_def_map) = collector::collect_defs(
collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id().into(), None)); 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> { pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
@ -370,10 +415,10 @@ impl DefMap {
let module_data = let module_data =
ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility); 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( let def_map = DefMap::empty(
module.krate, module.krate,
parent_map.data.clone(), crate_map.data.clone(),
module_data, module_data,
Some(BlockInfo { Some(BlockInfo {
block: block_id, block: block_id,
@ -381,13 +426,17 @@ impl DefMap {
}), }),
); );
let def_map = let (def_map, _) = collector::collect_defs(
collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id))); db,
def_map,
TreeId::new(ast_id.file_id, Some(block_id)),
Some(crate_local_map),
);
Arc::new(def_map) Arc::new(def_map)
} }
fn empty( fn empty(
krate: CrateId, krate: Crate,
crate_data: Arc<DefMapCrateData>, crate_data: Arc<DefMapCrateData>,
module_data: ModuleData, module_data: ModuleData,
block: Option<BlockInfo>, block: Option<BlockInfo>,
@ -479,7 +528,7 @@ impl DefMap {
self.data.fn_proc_macro_mapping.get(&id).copied() self.data.fn_proc_macro_mapping.get(&id).copied()
} }
pub fn krate(&self) -> CrateId { pub fn krate(&self) -> Crate {
self.krate self.krate
} }
@ -590,19 +639,13 @@ impl DefMap {
self.prelude 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>)> { pub(crate) fn macro_use_prelude(&self) -> &FxHashMap<Name, (MacroId, Option<ExternCrateId>)> {
&self.macro_use_prelude &self.macro_use_prelude
} }
pub(crate) fn resolve_path( pub(crate) fn resolve_path(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
original_module: LocalModuleId, original_module: LocalModuleId,
path: &ModPath, path: &ModPath,
@ -610,6 +653,7 @@ impl DefMap {
expected_macro_subns: Option<MacroSubNs>, expected_macro_subns: Option<MacroSubNs>,
) -> (PerNs, Option<usize>) { ) -> (PerNs, Option<usize>) {
let res = self.resolve_path_fp_with_macro( let res = self.resolve_path_fp_with_macro(
local_def_map,
db, db,
ResolveMode::Other, ResolveMode::Other,
original_module, original_module,
@ -624,12 +668,14 @@ impl DefMap {
/// points at the unresolved segments. /// points at the unresolved segments.
pub(crate) fn resolve_path_locally( pub(crate) fn resolve_path_locally(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
original_module: LocalModuleId, original_module: LocalModuleId,
path: &ModPath, path: &ModPath,
shadow: BuiltinShadowMode, shadow: BuiltinShadowMode,
) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) { ) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
let res = self.resolve_path_fp_with_macro_single( let res = self.resolve_path_fp_with_macro_single(
local_def_map,
db, db,
ResolveMode::Other, ResolveMode::Other,
original_module, original_module,

View file

@ -1,6 +1,6 @@
//! Post-nameres attribute resolution. //! Post-nameres attribute resolution.
use base_db::CrateId; use base_db::Crate;
use hir_expand::{ use hir_expand::{
attrs::{Attr, AttrId, AttrInput}, attrs::{Attr, AttrId, AttrInput},
inert_attr_macro::find_builtin_attr_idx, inert_attr_macro::find_builtin_attr_idx,
@ -13,7 +13,7 @@ use triomphe::Arc;
use crate::{ use crate::{
db::DefDatabase, db::DefDatabase,
item_scope::BuiltinShadowMode, item_scope::BuiltinShadowMode,
nameres::path_resolution::ResolveMode, nameres::{path_resolution::ResolveMode, LocalDefMap},
path::{self, ModPath, PathKind}, path::{self, ModPath, PathKind},
AstIdWithPath, LocalModuleId, MacroId, UnresolvedMacro, AstIdWithPath, LocalModuleId, MacroId, UnresolvedMacro,
}; };
@ -30,6 +30,7 @@ pub enum ResolvedAttr {
impl DefMap { impl DefMap {
pub(crate) fn resolve_attr_macro( pub(crate) fn resolve_attr_macro(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
original_module: LocalModuleId, original_module: LocalModuleId,
ast_id: AstIdWithPath<ast::Item>, ast_id: AstIdWithPath<ast::Item>,
@ -42,6 +43,7 @@ impl DefMap {
} }
let resolved_res = self.resolve_path_fp_with_macro( let resolved_res = self.resolve_path_fp_with_macro(
local_def_map,
db, db,
ResolveMode::Other, ResolveMode::Other,
original_module, original_module,
@ -105,7 +107,7 @@ pub(super) fn attr_macro_as_call_id(
db: &dyn DefDatabase, db: &dyn DefDatabase,
item_attr: &AstIdWithPath<ast::Item>, item_attr: &AstIdWithPath<ast::Item>,
macro_attr: &Attr, macro_attr: &Attr,
krate: CrateId, krate: Crate,
def: MacroDefId, def: MacroDefId,
) -> MacroCallId { ) -> MacroCallId {
let arg = match macro_attr.input.as_deref() { 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_attr_index: AttrId,
derive_pos: u32, derive_pos: u32,
call_site: SyntaxContextId, call_site: SyntaxContextId,
krate: CrateId, krate: Crate,
resolver: impl Fn(&path::ModPath) -> Option<(MacroId, MacroDefId)>, resolver: impl Fn(&path::ModPath) -> Option<(MacroId, MacroDefId)>,
derive_macro_id: MacroCallId, derive_macro_id: MacroCallId,
) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> { ) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> {

View file

@ -5,7 +5,7 @@
use std::{cmp::Ordering, iter, mem, ops::Not}; 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 cfg::{CfgAtom, CfgExpr, CfgOptions};
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{
@ -39,8 +39,8 @@ use crate::{
mod_resolution::ModDir, mod_resolution::ModDir,
path_resolution::ReachedFixedPoint, path_resolution::ReachedFixedPoint,
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind}, proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin, sub_namespace_match, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData,
ResolveMode, ModuleOrigin, ResolveMode,
}, },
path::{ImportAlias, ModPath, PathKind}, path::{ImportAlias, ModPath, PathKind},
per_ns::{Item, PerNs}, per_ns::{Item, PerNs},
@ -57,10 +57,14 @@ use crate::{
const GLOB_RECURSION_LIMIT: usize = 100; const GLOB_RECURSION_LIMIT: usize = 100;
const FIXED_POINT_LIMIT: usize = 8192; const FIXED_POINT_LIMIT: usize = 8192;
pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap { pub(super) fn collect_defs(
let crate_graph = db.crate_graph(); db: &dyn DefDatabase,
def_map: DefMap,
let krate = &crate_graph[def_map.krate]; 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 // populate external prelude and dependency list
let mut deps = 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 { let proc_macros = if krate.is_proc_macro {
db.proc_macros() db.proc_macros_for_crate(def_map.krate)
.for_crate(def_map.krate, db.syntax_context(tree_id.file_id(), krate.edition)) .and_then(|proc_macros| {
proc_macros.list(db.syntax_context(tree_id.file_id(), krate.edition))
})
.unwrap_or_default() .unwrap_or_default()
} else { } else {
Default::default() Default::default()
@ -82,13 +88,15 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
let mut collector = DefCollector { let mut collector = DefCollector {
db, db,
def_map, def_map,
local_def_map: LocalDefMap::default(),
crate_local_def_map,
deps, deps,
glob_imports: FxHashMap::default(), glob_imports: FxHashMap::default(),
unresolved_imports: Vec::new(), unresolved_imports: Vec::new(),
indeterminate_imports: Vec::new(), indeterminate_imports: Vec::new(),
unresolved_macros: Vec::new(), unresolved_macros: Vec::new(),
mod_dirs: FxHashMap::default(), mod_dirs: FxHashMap::default(),
cfg_options: &krate.cfg_options, cfg_options,
proc_macros, proc_macros,
from_glob_import: Default::default(), from_glob_import: Default::default(),
skip_attrs: 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.seed_with_top_level();
} }
collector.collect(); 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.shrink_to_fit();
def_map local_def_map.shrink_to_fit();
(def_map, local_def_map)
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -205,8 +214,11 @@ enum MacroDirectiveKind {
struct DefCollector<'a> { struct DefCollector<'a> {
db: &'a dyn DefDatabase, db: &'a dyn DefDatabase,
def_map: DefMap, 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`. // 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)>>, glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
unresolved_imports: Vec<ImportDirective>, unresolved_imports: Vec<ImportDirective>,
indeterminate_imports: Vec<(ImportDirective, PerNs)>, indeterminate_imports: Vec<(ImportDirective, PerNs)>,
@ -238,8 +250,7 @@ impl DefCollector<'_> {
fn seed_with_top_level(&mut self) { fn seed_with_top_level(&mut self) {
let _p = tracing::info_span!("seed_with_top_level").entered(); let _p = tracing::info_span!("seed_with_top_level").entered();
let crate_graph = self.db.crate_graph(); let file_id = self.def_map.krate.data(self.db).root_file_id();
let file_id = crate_graph[self.def_map.krate].root_file_id();
let item_tree = self.db.file_item_tree(file_id.into()); 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 attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap(); 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. // 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 // So here check if we are no_core / no_std and we are trying to add the
// corresponding dep from the sysroot // corresponding dep from the sysroot
let skip = match crate_graph[dep.crate_id].origin {
CrateOrigin::Lang(LangCrateOrigin::Core) => { // Depending on the crate data of a dependency seems bad for incrementality, but
crate_data.no_core && dep.is_sysroot() // 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
CrateOrigin::Lang(LangCrateOrigin::Std) => { // to have their crate ID invalidated, because they stay on the same root file and
crate_data.no_std && dep.is_sysroot() // they're dependencies of everything else, so if some collision miraculously occurs
} // we will resolve it by disambiguating the other crate.
_ => false, 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 { if skip {
continue; continue;
} }
crate_data self.local_def_map
.extern_prelude .extern_prelude
.insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None)); .insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None));
} }
@ -494,7 +509,7 @@ impl DefCollector<'_> {
let krate = if self.def_map.data.no_std { let krate = if self.def_map.data.no_std {
Name::new_symbol_root(sym::core.clone()) 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()) Name::new_symbol_root(sym::std.clone())
} else { } else {
// If `std` does not exist for some reason, fall back to core. This mostly helps // 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], [krate, Name::new_symbol_root(sym::prelude.clone()), edition],
); );
let (per_ns, _) = let (per_ns, _) = self.def_map.resolve_path(
self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None); 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 { match per_ns.types {
Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => { 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. /// Adds a definition of procedural macro `name` to the root module.
/// ///
/// # Notes on procedural macro resolution /// # Notes on procedural macro resolution
@ -660,7 +685,13 @@ impl DefCollector<'_> {
) { ) {
let vis = self let vis = self
.def_map .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); .unwrap_or(Visibility::Public);
self.def_map.modules[module_id].scope.declare(macro_.into()); self.def_map.modules[module_id].scope.declare(macro_.into());
self.update( self.update(
@ -694,7 +725,7 @@ impl DefCollector<'_> {
/// created by `use` in the root module, ignoring the visibility of `use`. /// created by `use` in the root module, ignoring the visibility of `use`.
fn import_macros_from_extern_crate( fn import_macros_from_extern_crate(
&mut self, &mut self,
krate: CrateId, krate: Crate,
names: Option<Vec<Name>>, names: Option<Vec<Name>>,
extern_crate: Option<ExternCrateId>, extern_crate: Option<ExternCrateId>,
) { ) {
@ -779,6 +810,7 @@ impl DefCollector<'_> {
.entered(); .entered();
tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition); tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
let res = self.def_map.resolve_path_fp_with_macro( 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, self.db,
ResolveMode::Import, ResolveMode::Import,
module_id, module_id,
@ -814,7 +846,13 @@ impl DefCollector<'_> {
let mut def = directive.status.namespaces(); let mut def = directive.status.namespaces();
let vis = self let vis = self
.def_map .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); .unwrap_or(Visibility::Public);
match import.source { match import.source {
@ -1210,6 +1248,7 @@ impl DefCollector<'_> {
}; };
let resolver = |path: &_| { let resolver = |path: &_| {
let resolved_res = self.def_map.resolve_path_fp_with_macro( 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, self.db,
ResolveMode::Other, ResolveMode::Other,
directive.module_id, directive.module_id,
@ -1495,7 +1534,7 @@ impl DefCollector<'_> {
.collect(item_tree.top_level_items(), container); .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. // Emit diagnostics for all remaining unexpanded macros.
let _p = tracing::info_span!("DefCollector::finish").entered(); let _p = tracing::info_span!("DefCollector::finish").entered();
@ -1511,6 +1550,7 @@ impl DefCollector<'_> {
self.def_map.krate, self.def_map.krate,
|path| { |path| {
let resolved_res = self.def_map.resolve_path_fp_with_macro( 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, self.db,
ResolveMode::Other, ResolveMode::Other,
directive.module_id, 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, None,
) )
}; };
let resolve_vis = |def_map: &DefMap, visibility| { let resolve_vis = |def_map: &DefMap, local_def_map: &LocalDefMap, visibility| {
def_map def_map
.resolve_visibility(db, module_id, visibility, false) .resolve_visibility(local_def_map, db, module_id, visibility, false)
.unwrap_or(Visibility::Public) .unwrap_or(Visibility::Public)
}; };
@ -1658,6 +1698,11 @@ impl ModCollector<'_, '_> {
let module = self.def_collector.def_map.module_id(module_id); let module = self.def_collector.def_map.module_id(module_id);
let def_map = &mut self.def_collector.def_map; 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 { match item {
ModItem::Mod(m) => self.collect_module(m, &attrs), ModItem::Mod(m) => self.collect_module(m, &attrs),
@ -1711,13 +1756,13 @@ impl ModCollector<'_, '_> {
}; };
if let Some(resolved) = resolved { 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 { if is_crate_root {
// extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 // 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 { if let Some(name) = name {
Arc::get_mut(&mut def_map.data) self.def_collector
.unwrap() .local_def_map
.extern_prelude .extern_prelude
.insert(name.clone(), (resolved, Some(id))); .insert(name.clone(), (resolved, Some(id)));
} }
@ -1784,7 +1829,7 @@ impl ModCollector<'_, '_> {
let fn_id = let fn_id =
FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); 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() if self.def_collector.def_map.block.is_none()
&& self.def_collector.is_proc_macro && self.def_collector.is_proc_macro
@ -1804,7 +1849,7 @@ impl ModCollector<'_, '_> {
ModItem::Struct(id) => { ModItem::Struct(id) => {
let it = &self.item_tree[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( update_def(
self.def_collector, self.def_collector,
StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@ -1818,7 +1863,7 @@ impl ModCollector<'_, '_> {
ModItem::Union(id) => { ModItem::Union(id) => {
let it = &self.item_tree[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( update_def(
self.def_collector, self.def_collector,
UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } 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) } EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
.intern(db); .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); update_def(self.def_collector, enum_.into(), &it.name, vis, false);
let mut index = 0; let mut index = 0;
@ -1878,7 +1923,8 @@ impl ModCollector<'_, '_> {
match &it.name { match &it.name {
Some(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); update_def(self.def_collector, const_id.into(), name, vis, false);
} }
None => { None => {
@ -1892,7 +1938,7 @@ impl ModCollector<'_, '_> {
ModItem::Static(id) => { ModItem::Static(id) => {
let it = &self.item_tree[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( update_def(
self.def_collector, self.def_collector,
StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) } StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
@ -1906,7 +1952,7 @@ impl ModCollector<'_, '_> {
ModItem::Trait(id) => { ModItem::Trait(id) => {
let it = &self.item_tree[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( update_def(
self.def_collector, self.def_collector,
TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@ -1920,7 +1966,7 @@ impl ModCollector<'_, '_> {
ModItem::TraitAlias(id) => { ModItem::TraitAlias(id) => {
let it = &self.item_tree[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( update_def(
self.def_collector, self.def_collector,
TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
@ -1934,7 +1980,7 @@ impl ModCollector<'_, '_> {
ModItem::TypeAlias(id) => { ModItem::TypeAlias(id) => {
let it = &self.item_tree[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( update_def(
self.def_collector, self.def_collector,
TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) } TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
@ -1971,7 +2017,7 @@ impl ModCollector<'_, '_> {
&mut self, &mut self,
extern_crate_id: ExternCrateId, extern_crate_id: ExternCrateId,
macro_use_attrs: impl Iterator<Item = &'a Attr>, 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); cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
let mut single_imports = Vec::new(); let mut single_imports = Vec::new();
@ -2115,7 +2161,16 @@ impl ModCollector<'_, '_> {
) -> LocalModuleId { ) -> LocalModuleId {
let def_map = &mut self.def_collector.def_map; let def_map = &mut self.def_collector.def_map;
let vis = 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); .unwrap_or(Visibility::Public);
let origin = match definition { let origin = match definition {
None => ModuleOrigin::Inline { None => ModuleOrigin::Inline {
@ -2417,6 +2472,10 @@ impl ModCollector<'_, '_> {
}, },
|path| { |path| {
let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro( 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, db,
ResolveMode::Other, ResolveMode::Other,
self.module_id, self.module_id,
@ -2517,7 +2576,6 @@ impl ModCollector<'_, '_> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use base_db::RootQueryDb;
use test_fixture::WithFixture; use test_fixture::WithFixture;
use crate::{nameres::DefMapCrateData, test_db::TestDB}; use crate::{nameres::DefMapCrateData, test_db::TestDB};
@ -2528,6 +2586,8 @@ mod tests {
let mut collector = DefCollector { let mut collector = DefCollector {
db, db,
def_map, def_map,
local_def_map: LocalDefMap::default(),
crate_local_def_map: None,
deps: FxHashMap::default(), deps: FxHashMap::default(),
glob_imports: FxHashMap::default(), glob_imports: FxHashMap::default(),
unresolved_imports: Vec::new(), unresolved_imports: Vec::new(),
@ -2550,7 +2610,7 @@ mod tests {
let (db, file_id) = TestDB::with_single_file(not_ra_fixture); let (db, file_id) = TestDB::with_single_file(not_ra_fixture);
let krate = db.test_crate(); 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 module_origin = ModuleOrigin::CrateRoot { definition: file_id };
let def_map = DefMap::empty( let def_map = DefMap::empty(
krate, krate,

View file

@ -19,7 +19,7 @@ use crate::{
db::DefDatabase, db::DefDatabase,
item_scope::{ImportOrExternCrate, BUILTIN_SCOPE}, item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
item_tree::FieldsShape, item_tree::FieldsShape,
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs},
path::{ModPath, PathKind}, path::{ModPath, PathKind},
per_ns::PerNs, per_ns::PerNs,
visibility::{RawVisibility, Visibility}, visibility::{RawVisibility, Visibility},
@ -91,6 +91,7 @@ impl PerNs {
impl DefMap { impl DefMap {
pub(crate) fn resolve_visibility( pub(crate) fn resolve_visibility(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
// module to import to // module to import to
original_module: LocalModuleId, original_module: LocalModuleId,
@ -101,8 +102,14 @@ impl DefMap {
) -> Option<Visibility> { ) -> Option<Visibility> {
let mut vis = match visibility { let mut vis = match visibility {
RawVisibility::Module(path, explicitness) => { RawVisibility::Module(path, explicitness) => {
let (result, remaining) = let (result, remaining) = self.resolve_path(
self.resolve_path(db, original_module, path, BuiltinShadowMode::Module, None); local_def_map,
db,
original_module,
path,
BuiltinShadowMode::Module,
None,
);
if remaining.is_some() { if remaining.is_some() {
return None; return None;
} }
@ -137,6 +144,7 @@ impl DefMap {
// the result. // the result.
pub(super) fn resolve_path_fp_with_macro( pub(super) fn resolve_path_fp_with_macro(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
mode: ResolveMode, mode: ResolveMode,
// module to import to // module to import to
@ -148,6 +156,7 @@ impl DefMap {
expected_macro_subns: Option<MacroSubNs>, expected_macro_subns: Option<MacroSubNs>,
) -> ResolvePathResult { ) -> ResolvePathResult {
let mut result = self.resolve_path_fp_with_macro_single( let mut result = self.resolve_path_fp_with_macro_single(
local_def_map,
db, db,
mode, mode,
original_module, original_module,
@ -196,6 +205,7 @@ impl DefMap {
current_map = &arc; current_map = &arc;
let new = current_map.resolve_path_fp_in_all_preludes( let new = current_map.resolve_path_fp_in_all_preludes(
local_def_map,
db, db,
mode, mode,
original_module, original_module,
@ -210,6 +220,7 @@ impl DefMap {
} }
let new = current_map.resolve_path_fp_with_macro_single( let new = current_map.resolve_path_fp_with_macro_single(
local_def_map,
db, db,
mode, mode,
original_module, original_module,
@ -224,6 +235,7 @@ impl DefMap {
pub(super) fn resolve_path_fp_with_macro_single( pub(super) fn resolve_path_fp_with_macro_single(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
mode: ResolveMode, mode: ResolveMode,
original_module: LocalModuleId, original_module: LocalModuleId,
@ -258,7 +270,12 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
}; };
tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 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 => { PathKind::Plain => {
let (_, segment) = match segments.next() { let (_, segment) = match segments.next() {
@ -276,6 +293,7 @@ impl DefMap {
tracing::debug!("resolving {:?} in module", segment); tracing::debug!("resolving {:?} in module", segment);
self.resolve_name_in_module( self.resolve_name_in_module(
local_def_map,
db, db,
original_module, original_module,
segment, segment,
@ -321,7 +339,9 @@ impl DefMap {
// with), resolve the remaining path segments in that `DefMap`. // with), resolve the remaining path segments in that `DefMap`.
let path = let path =
ModPath::from_segments(PathKind::SELF, path.segments().iter().cloned()); 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( return def_map.resolve_path_fp_with_macro(
local_def_map,
db, db,
mode, mode,
local_id, local_id,
@ -333,7 +353,7 @@ impl DefMap {
PerNs::types(module.into(), Visibility::Public, None) 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::Left(it) => it,
Either::Right(reached_fixed_point) => { Either::Right(reached_fixed_point) => {
return ResolvePathResult::empty(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. /// Resolves a path only in the preludes, without accounting for item scopes.
pub(super) fn resolve_path_fp_in_all_preludes( pub(super) fn resolve_path_fp_in_all_preludes(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
mode: ResolveMode, mode: ResolveMode,
original_module: LocalModuleId, original_module: LocalModuleId,
@ -368,7 +389,7 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
}; };
tracing::debug!("resolving {:?} in crate root (+ extern prelude)", segment); 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 => { PathKind::Plain => {
let (_, segment) = match segments.next() { let (_, segment) = match segments.next() {
@ -376,9 +397,9 @@ impl DefMap {
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
}; };
tracing::debug!("resolving {:?} in module", segment); 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::Left(it) => it,
Either::Right(reached_fixed_point) => { Either::Right(reached_fixed_point) => {
return ResolvePathResult::empty(reached_fixed_point) return ResolvePathResult::empty(reached_fixed_point)
@ -395,6 +416,7 @@ impl DefMap {
/// 2018-style absolute path -- only extern prelude /// 2018-style absolute path -- only extern prelude
fn resolve_path_abs<'a>( fn resolve_path_abs<'a>(
&self, &self,
local_def_map: &LocalDefMap,
segments: &mut impl Iterator<Item = (usize, &'a Name)>, segments: &mut impl Iterator<Item = (usize, &'a Name)>,
path: &ModPath, path: &ModPath,
) -> Either<PerNs, ReachedFixedPoint> { ) -> Either<PerNs, ReachedFixedPoint> {
@ -402,7 +424,7 @@ impl DefMap {
Some((_, segment)) => segment, Some((_, segment)) => segment,
None => return Either::Right(ReachedFixedPoint::Yes), 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); tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def);
Either::Left(PerNs::types( Either::Left(PerNs::types(
def.into(), def.into(),
@ -451,6 +473,7 @@ impl DefMap {
// this point, we know we're resolving a multi-segment path so macro kind // this point, we know we're resolving a multi-segment path so macro kind
// expectation is discarded. // expectation is discarded.
let resolution = defp_map.resolve_path_fp_with_macro( let resolution = defp_map.resolve_path_fp_with_macro(
LocalDefMap::EMPTY,
db, db,
ResolveMode::Other, ResolveMode::Other,
module.local_id, module.local_id,
@ -568,6 +591,7 @@ impl DefMap {
fn resolve_name_in_module( fn resolve_name_in_module(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
module: LocalModuleId, module: LocalModuleId,
name: &Name, name: &Name,
@ -611,7 +635,7 @@ impl DefMap {
// they might been shadowed by local names. // they might been shadowed by local names.
return PerNs::none(); 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 macro_use_prelude = || self.resolve_in_macro_use_prelude(name);
let prelude = || { let prelude = || {
@ -628,19 +652,24 @@ impl DefMap {
.or_else(prelude) .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: // Resolve in:
// - extern prelude / macro_use prelude // - extern prelude / macro_use prelude
// - std 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 macro_use_prelude = || self.resolve_in_macro_use_prelude(name);
let prelude = || self.resolve_in_prelude(db, name); let prelude = || self.resolve_in_prelude(db, name);
extern_prelude.or_else(macro_use_prelude).or_else(prelude) extern_prelude.or_else(macro_use_prelude).or_else(prelude)
} }
fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { fn resolve_name_in_extern_prelude(&self, local_def_map: &LocalDefMap, name: &Name) -> PerNs {
self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| { local_def_map.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
PerNs::types( PerNs::types(
it.into(), it.into(),
Visibility::Public, Visibility::Public,
@ -662,6 +691,7 @@ impl DefMap {
fn resolve_name_in_crate_root_or_extern_prelude( fn resolve_name_in_crate_root_or_extern_prelude(
&self, &self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase, db: &dyn DefDatabase,
module: LocalModuleId, module: LocalModuleId,
name: &Name, name: &Name,
@ -678,7 +708,7 @@ impl DefMap {
// Don't resolve extern prelude in pseudo-module of a block. // Don't resolve extern prelude in pseudo-module of a block.
return PerNs::none(); 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) from_crate_root.or_else(from_extern_prelude)

View file

@ -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 test_fixture::WithFixture;
use triomphe::Arc;
use crate::{db::DefDatabase, nameres::tests::TestDB, AdtId, ModuleDefId}; use crate::{db::DefDatabase, nameres::tests::TestDB, AdtId, ModuleDefId};
@ -22,6 +28,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] #[test]
fn typing_inside_a_function_should_not_invalidate_def_map() { fn typing_inside_a_function_should_not_invalidate_def_map() {
check_def_map_is_not_recomputed( check_def_map_is_not_recomputed(

View file

@ -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); let def_map = db.crate_def_map(krate);
assert_eq!(def_map.data.exported_derives.len(), 1); assert_eq!(def_map.data.exported_derives.len(), 1);
@ -1445,7 +1445,7 @@ struct TokenStream;
fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a } 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 def_map = db.crate_def_map(krate);
let root_module = &def_map[DefMap::ROOT].scope; let root_module = &def_map[DefMap::ROOT].scope;

View file

@ -80,7 +80,16 @@ pub(crate) fn print_path(
} }
PathKind::Crate => write!(buf, "crate")?, PathKind::Crate => write!(buf, "crate")?,
PathKind::Abs => {} 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")
)?,
}, },
} }

View file

@ -1,7 +1,7 @@
//! Name resolution façade. //! Name resolution façade.
use std::{fmt, iter, mem}; use std::{fmt, iter, mem};
use base_db::CrateId; use base_db::Crate;
use hir_expand::{name::Name, MacroDefId}; use hir_expand::{name::Name, MacroDefId};
use intern::{sym, Symbol}; use intern::{sym, Symbol};
use itertools::Itertools as _; use itertools::Itertools as _;
@ -22,7 +22,7 @@ use crate::{
hir::{BindingId, ExprId, LabelId}, hir::{BindingId, ExprId, LabelId},
item_scope::{BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, BUILTIN_SCOPE}, item_scope::{BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, BUILTIN_SCOPE},
lang_item::LangItemTarget, lang_item::LangItemTarget,
nameres::{DefMap, MacroSubNs, ResolvePathResultPrefixInfo}, nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo},
path::{ModPath, Path, PathKind}, path::{ModPath, Path, PathKind},
per_ns::PerNs, per_ns::PerNs,
type_ref::{LifetimeRef, TypesMap}, type_ref::{LifetimeRef, TypesMap},
@ -47,6 +47,7 @@ pub struct Resolver {
#[derive(Clone)] #[derive(Clone)]
struct ModuleItemMap { struct ModuleItemMap {
def_map: Arc<DefMap>, def_map: Arc<DefMap>,
local_def_map: Arc<LocalDefMap>,
module_id: LocalModuleId, module_id: LocalModuleId,
} }
@ -278,8 +279,8 @@ impl Resolver {
let within_impl = self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_))); let within_impl = self.scopes().any(|scope| matches!(scope, Scope::ImplDefScope(_)));
match visibility { match visibility {
RawVisibility::Module(_, _) => { RawVisibility::Module(_, _) => {
let (item_map, module) = self.item_scope(); let (item_map, item_local_map, module) = self.item_scope();
item_map.resolve_visibility(db, module, visibility, within_impl) item_map.resolve_visibility(item_local_map, db, module, visibility, within_impl)
} }
RawVisibility::Public => Some(Visibility::Public), RawVisibility::Public => Some(Visibility::Public),
} }
@ -474,9 +475,16 @@ impl Resolver {
path: &ModPath, path: &ModPath,
expected_macro_kind: Option<MacroSubNs>, expected_macro_kind: Option<MacroSubNs>,
) -> Option<(MacroId, Option<ImportOrGlob>)> { ) -> Option<(MacroId, Option<ImportOrGlob>)> {
let (item_map, module) = self.item_scope(); let (item_map, item_local_map, module) = self.item_scope();
item_map 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 .0
.take_macros_import() .take_macros_import()
} }
@ -550,7 +558,7 @@ impl Resolver {
for scope in self.scopes() { for scope in self.scopes() {
scope.process_names(&mut res, db); 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? // FIXME: should we provide `self` here?
// f( // f(
// Name::self_param(), // Name::self_param(),
@ -572,7 +580,7 @@ impl Resolver {
res.add(name, ScopeDef::ModuleDef(def.into())); 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()))); res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into())));
}); });
BUILTIN_SCOPE.iter().for_each(|(name, &def)| { 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)> + '_ { pub fn extern_crates_in_scope(&self) -> impl Iterator<Item = (Name, ModuleId)> + '_ {
self.module_scope self.module_scope
.def_map .local_def_map
.extern_prelude() .extern_prelude()
.map(|(name, module_id)| (name.clone(), module_id.0.into())) .map(|(name, module_id)| (name.clone(), module_id.0.into()))
} }
@ -647,11 +655,11 @@ impl Resolver {
} }
pub fn module(&self) -> ModuleId { 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) def_map.module_id(local_id)
} }
pub fn krate(&self) -> CrateId { pub fn krate(&self) -> Crate {
self.module_scope.def_map.krate() self.module_scope.def_map.krate()
} }
@ -844,9 +852,12 @@ impl Resolver {
})); }));
if let Some(block) = expr_scopes.block(scope_id) { if let Some(block) = expr_scopes.block(scope_id) {
let def_map = db.block_def_map(block); let def_map = db.block_def_map(block);
resolver let local_def_map = block.lookup(db).module.only_local_def_map(db);
.scopes resolver.scopes.push(Scope::BlockScope(ModuleItemMap {
.push(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT })); def_map,
local_def_map,
module_id: DefMap::ROOT,
}));
// FIXME: This adds as many module scopes as there are blocks, but resolving in each // 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 // already traverses all parents, so this is O(n²). I think we could only store the
// innermost module scope instead? // innermost module scope instead?
@ -933,9 +944,10 @@ impl Resolver {
path: &ModPath, path: &ModPath,
shadow: BuiltinShadowMode, shadow: BuiltinShadowMode,
) -> PerNs { ) -> 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. // 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() { if segment_index.is_some() {
return PerNs::none(); return PerNs::none();
} }
@ -943,13 +955,17 @@ impl Resolver {
} }
/// The innermost block scope that contains items or the module scope that contains this 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() self.scopes()
.find_map(|scope| match scope { .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, _ => 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() { for scope in scope_chain.into_iter().rev() {
if let Some(block) = scopes.block(scope) { if let Some(block) = scopes.block(scope) {
let def_map = db.block_def_map(block); 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 // 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 // already traverses all parents, so this is O(n²). I think we could only store the
// innermost module scope instead? // innermost module scope instead?
@ -1079,9 +1096,12 @@ impl Resolver {
self.push_scope(Scope::ImplDefScope(impl_def)) self.push_scope(Scope::ImplDefScope(impl_def))
} }
fn push_block_scope(self, def_map: Arc<DefMap>) -> Resolver { fn push_block_scope(self, def_map: Arc<DefMap>, local_def_map: Arc<LocalDefMap>) -> Resolver {
debug_assert!(def_map.block_id().is_some()); self.push_scope(Scope::BlockScope(ModuleItemMap {
self.push_scope(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT })) def_map,
local_def_map,
module_id: DefMap::ROOT,
}))
} }
fn push_expr_scope( fn push_expr_scope(
@ -1100,8 +1120,13 @@ impl ModuleItemMap {
db: &dyn DefDatabase, db: &dyn DefDatabase,
path: &ModPath, path: &ModPath,
) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> { ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> {
let (module_def, unresolved_idx, prefix_info) = let (module_def, unresolved_idx, prefix_info) = self.def_map.resolve_path_locally(
self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); &self.local_def_map,
db,
self.module_id,
path,
BuiltinShadowMode::Other,
);
match unresolved_idx { match unresolved_idx {
None => { None => {
let (value, import) = to_value_ns(module_def)?; let (value, import) = to_value_ns(module_def)?;
@ -1134,8 +1159,13 @@ impl ModuleItemMap {
path: &ModPath, path: &ModPath,
) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)> ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)>
{ {
let (module_def, idx, prefix_info) = let (module_def, idx, prefix_info) = self.def_map.resolve_path_locally(
self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); &self.local_def_map,
db,
self.module_id,
path,
BuiltinShadowMode::Other,
);
let (res, import) = to_type_ns(module_def)?; let (res, import) = to_type_ns(module_def)?;
Some((res, idx, import, prefix_info)) Some((res, idx, import, prefix_info))
} }
@ -1230,11 +1260,14 @@ pub trait HasResolver: Copy {
impl HasResolver for ModuleId { impl HasResolver for ModuleId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver { 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; let mut module_id = self.local_id;
if !self.is_block_module() { 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![]; let mut modules: SmallVec<[_; 1]> = smallvec![];
@ -1248,10 +1281,14 @@ impl HasResolver for ModuleId {
} }
let mut resolver = Resolver { let mut resolver = Resolver {
scopes: Vec::with_capacity(modules.len()), 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() { 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 resolver
} }
@ -1259,9 +1296,10 @@ impl HasResolver for ModuleId {
impl HasResolver for CrateRootModuleId { impl HasResolver for CrateRootModuleId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver { fn resolver(self, db: &dyn DefDatabase) -> Resolver {
let (def_map, local_def_map) = self.local_def_map(db);
Resolver { Resolver {
scopes: vec![], 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 },
} }
} }
} }

View file

@ -158,7 +158,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
let mut map = ArenaMap::new(); let mut map = ArenaMap::new();
match &src.value { match &src.value {
ast::StructKind::Tuple(fl) => { 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; let mut idx = 0;
for (i, fd) in fl.fields().enumerate() { for (i, fd) in fl.fields().enumerate() {
let attrs = item_tree.attrs( let attrs = item_tree.attrs(
@ -177,7 +177,7 @@ impl HasChildSource<LocalFieldId> for VariantId {
} }
} }
ast::StructKind::Record(fl) => { 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; let mut idx = 0;
for (i, fd) in fl.fields().enumerate() { for (i, fd) in fl.fields().enumerate() {
let attrs = item_tree.attrs( let attrs = item_tree.attrs(

View file

@ -3,8 +3,8 @@
use std::{fmt, panic, sync::Mutex}; use std::{fmt, panic, sync::Mutex};
use base_db::{ use base_db::{
CrateId, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, Crate, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb,
SourceRootInput, Upcast, SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast,
}; };
use hir_expand::{db::ExpandDatabase, files::FilePosition, InFile}; use hir_expand::{db::ExpandDatabase, files::FilePosition, InFile};
use salsa::{AsDynDatabase, Durability}; use salsa::{AsDynDatabase, Durability};
@ -24,6 +24,7 @@ use crate::{
pub(crate) struct TestDB { pub(crate) struct TestDB {
storage: salsa::Storage<Self>, storage: salsa::Storage<Self>,
files: Arc<base_db::Files>, files: Arc<base_db::Files>,
crates_map: Arc<CratesMap>,
events: Arc<Mutex<Option<Vec<salsa::Event>>>>, events: Arc<Mutex<Option<Vec<salsa::Event>>>>,
} }
@ -33,8 +34,12 @@ impl Default for TestDB {
storage: Default::default(), storage: Default::default(),
events: Default::default(), events: Default::default(),
files: Default::default(), files: Default::default(),
crates_map: Default::default(),
}; };
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); 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 this
} }
} }
@ -133,20 +138,23 @@ impl SourceDatabase for TestDB {
let files = Arc::clone(&self.files); let files = Arc::clone(&self.files);
files.set_file_source_root_with_durability(self, id, source_root_id, durability); 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 { impl TestDB {
pub(crate) fn fetch_test_crate(&self) -> CrateId { pub(crate) fn fetch_test_crate(&self) -> Crate {
let crate_graph = self.crate_graph(); let all_crates = self.all_crates();
let it = crate_graph all_crates
.iter() .iter()
.find(|&idx| { .copied()
crate_graph[idx].display_name.as_ref().map(|it| it.canonical_name().as_str()) .find(|&krate| {
krate.extra_data(self).display_name.as_ref().map(|it| it.canonical_name().as_str())
== Some("ra_test_fixture") == Some("ra_test_fixture")
}) })
.or_else(|| crate_graph.iter().next()) .unwrap_or(*all_crates.last().unwrap())
.unwrap();
it
} }
pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId {

View file

@ -1,7 +1,7 @@
//! A higher level attributes based on TokenTree, with also some shortcuts. //! A higher level attributes based on TokenTree, with also some shortcuts.
use std::{borrow::Cow, fmt, ops}; use std::{borrow::Cow, fmt, ops};
use base_db::CrateId; use base_db::Crate;
use cfg::CfgExpr; use cfg::CfgExpr;
use either::Either; use either::Either;
use intern::{sym, Interned, Symbol}; use intern::{sym, Interned, Symbol};
@ -119,7 +119,7 @@ impl RawAttrs {
/// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
// FIXME: This should return a different type, signaling it was filtered? // 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 let has_cfg_attrs = self
.iter() .iter()
.any(|attr| attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr.clone())); .any(|attr| attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr.clone()));
@ -127,7 +127,7 @@ impl RawAttrs {
return self; return self;
} }
let crate_graph = db.crate_graph(); let cfg_options = krate.cfg_options(db);
let new_attrs = let new_attrs =
self.iter() self.iter()
.flat_map(|attr| -> SmallVec<[_; 1]> { .flat_map(|attr| -> SmallVec<[_; 1]> {
@ -151,7 +151,6 @@ impl RawAttrs {
|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)), |(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 = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg);
let cfg = CfgExpr::parse(&cfg); let cfg = CfgExpr::parse(&cfg);
if cfg_options.check(&cfg) == Some(false) { if cfg_options.check(&cfg) == Some(false) {

View file

@ -231,7 +231,7 @@ fn assert_expand(
let cond = expect_fragment( let cond = expect_fragment(
&mut iter, &mut iter,
parser::PrefixEntryPoint::Expr, parser::PrefixEntryPoint::Expr,
db.crate_graph()[id.lookup(db).krate].edition, id.lookup(db).krate.data(db).edition,
tt.top_subtree().delimiter.delim_span(), tt.top_subtree().delimiter.delim_span(),
); );
_ = iter.expect_char(','); _ = iter.expect_char(',');
@ -333,7 +333,7 @@ fn cfg_expand(
) -> ExpandResult<tt::TopSubtree> { ) -> ExpandResult<tt::TopSubtree> {
let loc = db.lookup_intern_macro_call(id); let loc = db.lookup_intern_macro_call(id);
let expr = CfgExpr::parse(tt); 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) }; let expanded = if enabled { quote!(span=>true) } else { quote!(span=>false) };
ExpandResult::ok(expanded) ExpandResult::ok(expanded)
} }
@ -669,7 +669,7 @@ fn relative_file(
if res == call_site && !allow_recursion { if res == call_site && !allow_recursion {
Err(ExpandError::other(err_span, format!("recursive inclusion of `{path_str}`"))) Err(ExpandError::other(err_span, format!("recursive inclusion of `{path_str}`")))
} else { } 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> { fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &Symbol) -> Option<String> {
let krate = db.lookup_intern_macro_call(arg_id).krate; 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( fn env_expand(

View file

@ -1,7 +1,7 @@
//! Processes out #[cfg] and #[cfg_attr] attributes from the input for the derive macro //! Processes out #[cfg] and #[cfg_attr] attributes from the input for the derive macro
use std::iter::Peekable; use std::iter::Peekable;
use base_db::CrateId; use base_db::Crate;
use cfg::{CfgAtom, CfgExpr}; use cfg::{CfgAtom, CfgExpr};
use intern::{sym, Symbol}; use intern::{sym, Symbol};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
@ -13,16 +13,16 @@ use tracing::{debug, warn};
use crate::{db::ExpandDatabase, proc_macro::ProcMacroKind, MacroCallLoc, MacroDefKind}; 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")? { if !attr.simple_name().as_deref().map(|v| v == "cfg")? {
return None; return None;
} }
let cfg = parse_from_attr_token_tree(&attr.meta()?.token_tree()?)?; 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) 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")? { if !attr.simple_name().as_deref().map(|v| v == "cfg_attr")? {
return None; return None;
} }
@ -32,17 +32,17 @@ fn check_cfg_attr(db: &dyn ExpandDatabase, attr: &Attr, krate: CrateId) -> Optio
pub fn check_cfg_attr_value( pub fn check_cfg_attr_value(
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
attr: &TokenTree, attr: &TokenTree,
krate: CrateId, krate: Crate,
) -> Option<bool> { ) -> Option<bool> {
let cfg_expr = parse_from_attr_token_tree(attr)?; 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) Some(enabled)
} }
fn process_has_attrs_with_possible_comma<I: HasAttrs>( fn process_has_attrs_with_possible_comma<I: HasAttrs>(
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
items: impl Iterator<Item = I>, items: impl Iterator<Item = I>,
krate: CrateId, krate: Crate,
remove: &mut FxHashSet<SyntaxElement>, remove: &mut FxHashSet<SyntaxElement>,
) -> Option<()> { ) -> Option<()> {
for item in items { for item in items {
@ -144,7 +144,7 @@ fn remove_possible_comma(item: &impl AstNode, res: &mut FxHashSet<SyntaxElement>
fn process_enum( fn process_enum(
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
variants: VariantList, variants: VariantList,
krate: CrateId, krate: Crate,
remove: &mut FxHashSet<SyntaxElement>, remove: &mut FxHashSet<SyntaxElement>,
) -> Option<()> { ) -> Option<()> {
'variant: for variant in variants.variants() { 'variant: for variant in variants.variants() {

View file

@ -1,17 +1,16 @@
//! Defines a unit of change that can applied to the database to get the next //! Defines a unit of change that can applied to the database to get the next
//! state. Changes are transactional. //! state. Changes are transactional.
use base_db::{CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot}; use base_db::{CrateGraphBuilder, FileChange, SourceRoot};
use rustc_hash::FxHashMap;
use salsa::Durability; use salsa::Durability;
use span::FileId; use span::FileId;
use triomphe::Arc; use triomphe::Arc;
use crate::{db::ExpandDatabase, proc_macro::ProcMacros}; use crate::{db::ExpandDatabase, proc_macro::ProcMacrosBuilder};
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct ChangeWithProcMacros { pub struct ChangeWithProcMacros {
pub source_change: FileChange, pub source_change: FileChange,
pub proc_macros: Option<ProcMacros>, pub proc_macros: Option<ProcMacrosBuilder>,
} }
impl ChangeWithProcMacros { impl ChangeWithProcMacros {
@ -20,8 +19,13 @@ impl ChangeWithProcMacros {
} }
pub fn apply(self, db: &mut impl ExpandDatabase) { 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 { 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); 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) self.source_change.change_file(file_id, new_text)
} }
pub fn set_crate_graph( pub fn set_crate_graph(&mut self, graph: CrateGraphBuilder) {
&mut self,
graph: CrateGraph,
ws_data: FxHashMap<CrateId, Arc<CrateWorkspaceData>>,
) {
self.source_change.set_crate_graph(graph); 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); self.proc_macros = Some(proc_macros);
} }

View file

@ -1,6 +1,6 @@
//! Defines database & queries for macro expansion. //! Defines database & queries for macro expansion.
use base_db::{CrateId, RootQueryDb}; use base_db::{Crate, RootQueryDb};
use either::Either; use either::Either;
use mbe::MatchedArmIndex; use mbe::MatchedArmIndex;
use rustc_hash::FxHashSet; 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, span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt,
SyntaxContextExt as _, SyntaxContextExt as _,
}, },
proc_macro::{CustomProcMacroExpander, ProcMacros}, proc_macro::{CrateProcMacros, CustomProcMacroExpander, ProcMacros},
span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef},
tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo, tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo,
EagerExpander, ExpandError, ExpandResult, ExpandTo, MacroCallKind, MacroCallLoc, MacroDefId, EagerExpander, ExpandError, ExpandResult, ExpandTo, MacroCallKind, MacroCallLoc, MacroDefId,
@ -57,10 +57,13 @@ pub enum TokenExpander {
#[query_group::query_group] #[query_group::query_group]
pub trait ExpandDatabase: RootQueryDb { pub trait ExpandDatabase: RootQueryDb {
/// The proc macros. /// The proc macros. Do not use this! Use `proc_macros_for_crate()` instead.
#[salsa::input] #[salsa::input]
fn proc_macros(&self) -> Arc<ProcMacros>; 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>; fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
#[salsa::transparent] #[salsa::transparent]
@ -120,7 +123,7 @@ pub trait ExpandDatabase: RootQueryDb {
#[salsa::invoke(DeclarativeMacroExpander::expander)] #[salsa::invoke(DeclarativeMacroExpander::expander)]
fn decl_macro_expander( fn decl_macro_expander(
&self, &self,
def_crate: CrateId, def_crate: Crate,
id: AstId<ast::Macro>, id: AstId<ast::Macro>,
) -> Arc<DeclarativeMacroExpander>; ) -> Arc<DeclarativeMacroExpander>;

View file

@ -1,6 +1,6 @@
//! Compiled declarative macro expanders (`macro_rules!` and `macro`) //! Compiled declarative macro expanders (`macro_rules!` and `macro`)
use base_db::CrateId; use base_db::Crate;
use intern::sym; use intern::sym;
use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId}; use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId};
use stdx::TupleExt; use stdx::TupleExt;
@ -70,7 +70,7 @@ impl DeclarativeMacroExpander {
pub(crate) fn expander( pub(crate) fn expander(
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
def_crate: CrateId, def_crate: Crate,
id: AstId<ast::Macro>, id: AstId<ast::Macro>,
) -> Arc<DeclarativeMacroExpander> { ) -> Arc<DeclarativeMacroExpander> {
let (root, map) = crate::db::parse_with_map(db, id.file_id); let (root, map) = crate::db::parse_with_map(db, id.file_id);
@ -101,14 +101,12 @@ impl DeclarativeMacroExpander {
} }
}; };
let ctx_edition = |ctx: SyntaxContextId| { let ctx_edition = |ctx: SyntaxContextId| {
let crate_graph = db.crate_graph();
if ctx.is_root() { if ctx.is_root() {
crate_graph[def_crate].edition def_crate.data(db).edition
} else { } else {
// UNWRAP-SAFETY: Only the root context has no outer expansion // UNWRAP-SAFETY: Only the root context has no outer expansion
let krate = db.lookup_intern_macro_call(ctx.outer_expn(db).unwrap()).def.krate; 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) { let (mac, transparency) = match id.to_ptr(db).to_node(&root) {

View file

@ -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> //! 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 span::SyntaxContextId;
use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent}; use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent};
use syntax_bridge::DocCommentDesugarMode; use syntax_bridge::DocCommentDesugarMode;
@ -34,7 +34,7 @@ use crate::{
pub fn expand_eager_macro_input( pub fn expand_eager_macro_input(
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
krate: CrateId, krate: Crate,
macro_call: &ast::MacroCall, macro_call: &ast::MacroCall,
ast_id: AstId<ast::MacroCall>, ast_id: AstId<ast::MacroCall>,
def: MacroDefId, def: MacroDefId,
@ -115,7 +115,7 @@ fn lazy_expand(
def: &MacroDefId, def: &MacroDefId,
macro_call: &ast::MacroCall, macro_call: &ast::MacroCall,
ast_id: AstId<ast::MacroCall>, ast_id: AstId<ast::MacroCall>,
krate: CrateId, krate: Crate,
call_site: SyntaxContextId, call_site: SyntaxContextId,
) -> ExpandResult<(InFile<Parse<SyntaxNode>>, Arc<ExpansionSpanMap>)> { ) -> ExpandResult<(InFile<Parse<SyntaxNode>>, Arc<ExpansionSpanMap>)> {
let expand_to = ExpandTo::from_call_site(macro_call); let expand_to = ExpandTo::from_call_site(macro_call);
@ -137,7 +137,7 @@ fn eager_macro_recur(
expanded_map: &mut ExpansionSpanMap, expanded_map: &mut ExpansionSpanMap,
mut offset: TextSize, mut offset: TextSize,
curr: InFile<SyntaxNode>, curr: InFile<SyntaxNode>,
krate: CrateId, krate: Crate,
call_site: SyntaxContextId, call_site: SyntaxContextId,
macro_resolver: &dyn Fn(&ModPath) -> Option<MacroDefId>, macro_resolver: &dyn Fn(&ModPath) -> Option<MacroDefId>,
) -> ExpandResult<Option<(SyntaxNode, TextSize)>> { ) -> ExpandResult<Option<(SyntaxNode, TextSize)>> {
@ -176,7 +176,7 @@ fn eager_macro_recur(
Some(path) => match macro_resolver(&path) { Some(path) => match macro_resolver(&path) {
Some(def) => def, Some(def) => def,
None => { None => {
let edition = db.crate_graph()[krate].edition; let edition = krate.data(db).edition;
error = Some(ExpandError::other( error = Some(ExpandError::other(
span_map.span_at(call.syntax().text_range().start()), span_map.span_at(call.syntax().text_range().start()),
format!("unresolved macro {}", path.display(db, edition)), format!("unresolved macro {}", path.display(db, edition)),

View file

@ -33,7 +33,7 @@ use triomphe::Arc;
use core::fmt; use core::fmt;
use std::hash::Hash; use std::hash::Hash;
use base_db::CrateId; use base_db::Crate;
use either::Either; use either::Either;
use span::{ use span::{
Edition, EditionedFileId, ErasedFileAstId, FileAstId, HirFileIdRepr, Span, SpanAnchor, Edition, EditionedFileId, ErasedFileAstId, FileAstId, HirFileIdRepr, Span, SpanAnchor,
@ -157,7 +157,7 @@ impl ExpandError {
pub enum ExpandErrorKind { pub enum ExpandErrorKind {
/// Attribute macro expansion is disabled. /// Attribute macro expansion is disabled.
ProcMacroAttrExpansionDisabled, ProcMacroAttrExpansionDisabled,
MissingProcMacroExpander(CrateId), MissingProcMacroExpander(Crate),
/// The macro for this call is disabled. /// The macro for this call is disabled.
MacroDisabled, MacroDisabled,
/// The macro definition has errors. /// The macro definition has errors.
@ -200,7 +200,7 @@ impl ExpandErrorKind {
kind: RenderedExpandError::DISABLED, kind: RenderedExpandError::DISABLED,
}, },
&ExpandErrorKind::MissingProcMacroExpander(def_crate) => { &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 { Some((e, hard_err)) => RenderedExpandError {
message: e.to_owned(), message: e.to_owned(),
error: hard_err, error: hard_err,
@ -250,14 +250,14 @@ impl From<mbe::ExpandError> for ExpandError {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroCallLoc { pub struct MacroCallLoc {
pub def: MacroDefId, pub def: MacroDefId,
pub krate: CrateId, pub krate: Crate,
pub kind: MacroCallKind, pub kind: MacroCallKind,
pub ctxt: SyntaxContextId, pub ctxt: SyntaxContextId,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct MacroDefId { pub struct MacroDefId {
pub krate: CrateId, pub krate: Crate,
pub edition: Edition, pub edition: Edition,
pub kind: MacroDefKind, pub kind: MacroDefKind,
pub local_inner: bool, pub local_inner: bool,
@ -525,7 +525,7 @@ impl MacroDefId {
pub fn make_call( pub fn make_call(
self, self,
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
krate: CrateId, krate: Crate,
kind: MacroCallKind, kind: MacroCallKind,
ctxt: SyntaxContextId, ctxt: SyntaxContextId,
) -> MacroCallId { ) -> MacroCallId {

View file

@ -11,7 +11,7 @@ use crate::{
name::{AsName, Name}, name::{AsName, Name},
tt, tt,
}; };
use base_db::CrateId; use base_db::Crate;
use intern::sym; use intern::sym;
use smallvec::SmallVec; use smallvec::SmallVec;
use span::{Edition, SyntaxContextId}; use span::{Edition, SyntaxContextId};
@ -33,7 +33,7 @@ pub enum PathKind {
Abs, Abs,
// FIXME: Can we remove this somehow? // FIXME: Can we remove this somehow?
/// `$crate` from macro expansion /// `$crate` from macro expansion
DollarCrate(CrateId), DollarCrate(Crate),
} }
impl PathKind { impl PathKind {
@ -333,7 +333,7 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: tt::TokenTreesView<'_>) -> Optio
Some(ModPath { kind, segments }) 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`, // 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` // 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. // as described in `SyntaxContextId::apply_mark`, so we ignore prepended opaque marks.

View file

@ -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 { fn as_name(&self) -> Name {
Name::new_symbol_root((*self.name).clone()) Name::new_symbol_root((*self.name).clone())
} }

View file

@ -1,6 +1,6 @@
//! Pretty printing of macros output. //! Pretty printing of macros output.
use base_db::CrateId; use base_db::Crate;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use syntax::NodeOrToken; use syntax::NodeOrToken;
use syntax::{ast::make, SyntaxNode}; use syntax::{ast::make, SyntaxNode};
@ -13,13 +13,12 @@ pub fn prettify_macro_expansion(
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
syn: SyntaxNode, syn: SyntaxNode,
span_map: &ExpansionSpanMap, span_map: &ExpansionSpanMap,
target_crate_id: CrateId, target_crate_id: Crate,
) -> SyntaxNode { ) -> SyntaxNode {
// Because `syntax_bridge::prettify_macro_expansion::prettify_macro_expansion()` clones subtree for `syn`, // Because `syntax_bridge::prettify_macro_expansion::prettify_macro_expansion()` clones subtree for `syn`,
// that means it will be offsetted to the beginning. // that means it will be offsetted to the beginning.
let span_offset = syn.text_range().start(); let span_offset = syn.text_range().start();
let crate_graph = db.crate_graph(); let target_crate = target_crate_id.data(db);
let target_crate = &crate_graph[target_crate_id];
let mut syntax_ctx_id_to_dollar_crate_replacement = FxHashMap::default(); let mut syntax_ctx_id_to_dollar_crate_replacement = FxHashMap::default();
syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(syn, &mut |dollar_crate| { 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; 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) target_crate.dependencies.iter().find(|dep| dep.crate_id == macro_def_crate)
{ {
make::tokens::ident(dep.name.as_str()) 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()) make::tokens::ident(crate_name.crate_name().as_str())
} else { } else {
return dollar_crate.clone(); return dollar_crate.clone();

View file

@ -1,24 +1,36 @@
//! Proc Macro Expander stuff //! Proc Macro Expander stuff
use core::fmt; use core::fmt;
use std::any::Any;
use std::{panic::RefUnwindSafe, sync}; use std::{panic::RefUnwindSafe, sync};
use base_db::{CrateId, Env}; use base_db::{Crate, CrateBuilderId, CratesIdMap, Env};
use intern::Symbol; use intern::Symbol;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use span::Span; use span::Span;
use triomphe::Arc;
use crate::{db::ExpandDatabase, tt, ExpandError, ExpandErrorKind, ExpandResult}; 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 { pub enum ProcMacroKind {
CustomDerive, CustomDerive,
Bang, Bang,
Attr, 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. /// 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 /// Run the expander with the given input subtree, optional attribute input subtree (for
/// [`ProcMacroKind::Attr`]), environment variables, and span information. /// [`ProcMacroKind::Attr`]), environment variables, and span information.
fn expand( fn expand(
@ -31,8 +43,18 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
mixed_site: Span, mixed_site: Span,
current_dir: Option<String>, current_dir: Option<String>,
) -> Result<tt::TopSubtree, ProcMacroExpansionError>; ) -> 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)] #[derive(Debug)]
pub enum ProcMacroExpansionError { pub enum ProcMacroExpansionError {
/// The proc-macro panicked. /// The proc-macro panicked.
@ -45,41 +67,68 @@ pub type ProcMacroLoadResult = Result<Vec<ProcMacro>, (String, bool)>;
type StoredProcMacroLoadResult = Result<Box<[ProcMacro]>, (Box<str>, bool)>; type StoredProcMacroLoadResult = Result<Box<[ProcMacro]>, (Box<str>, bool)>;
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct ProcMacrosBuilder(FxHashMap<CrateId, StoredProcMacroLoadResult>); pub struct ProcMacrosBuilder(FxHashMap<CrateBuilderId, Arc<CrateProcMacros>>);
impl ProcMacrosBuilder { 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( self.0.insert(
proc_macros_crate, proc_macros_crate,
match proc_macro { match proc_macro {
Ok(it) => Ok(it.into_boxed_slice()), Ok(it) => Arc::new(CrateProcMacros(Ok(it.into_boxed_slice()))),
Err((e, hard_err)) => Err((e.into_boxed_str(), hard_err)), 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(); pub(crate) fn build(self, crates_id_map: &CratesIdMap) -> ProcMacros {
ProcMacros(self.0) 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)] impl FromIterator<(CrateBuilderId, ProcMacroLoadResult)> for ProcMacrosBuilder {
pub struct ProcMacros(FxHashMap<CrateId, StoredProcMacroLoadResult>); fn from_iter<T: IntoIterator<Item = (CrateBuilderId, ProcMacroLoadResult)>>(iter: T) -> Self {
impl FromIterator<(CrateId, ProcMacroLoadResult)> for ProcMacros {
fn from_iter<T: IntoIterator<Item = (CrateId, ProcMacroLoadResult)>>(iter: T) -> Self {
let mut builder = ProcMacrosBuilder::default(); let mut builder = ProcMacrosBuilder::default();
for (k, v) in iter { for (k, v) in iter {
builder.insert(k, v); 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 { impl ProcMacros {
fn get(&self, krate: CrateId, idx: u32, err_span: Span) -> Result<&ProcMacro, ExpandError> { fn get(&self, krate: Crate) -> Option<Arc<CrateProcMacros>> {
let proc_macros = match self.0.get(&krate) { self.0.get(&krate).cloned()
Some(Ok(proc_macros)) => proc_macros, }
Some(Err(_)) | None => { }
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( return Err(ExpandError::other(
err_span, err_span,
"internal error: no proc macros for crate", "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)> { pub fn get_error(&self) -> Option<(&str, bool)> {
self.0.get(&krate).and_then(|it| it.as_ref().err()).map(|(e, hard_err)| (&**e, *hard_err)) self.0.as_ref().err().map(|(e, hard_err)| (&**e, *hard_err))
} }
/// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate. /// Fetch the [`CustomProcMacroExpander`]s and their corresponding names for the given crate.
pub fn for_crate( pub fn list(
&self, &self,
krate: CrateId,
def_site_ctx: span::SyntaxContextId, def_site_ctx: span::SyntaxContextId,
) -> Option<Box<[(crate::name::Name, CustomProcMacroExpander, bool)]>> { ) -> Option<Box<[(crate::name::Name, CustomProcMacroExpander, bool)]>> {
match self.0.get(&krate) { match &self.0 {
Some(Ok(proc_macros)) => Some({ Ok(proc_macros) => Some(
proc_macros proc_macros
.iter() .iter()
.enumerate() .enumerate()
@ -117,15 +165,15 @@ impl ProcMacros {
let name = crate::name::Name::new_symbol(it.name.clone(), def_site_ctx); let name = crate::name::Name::new_symbol(it.name.clone(), def_site_ctx);
(name, CustomProcMacroExpander::new(idx as u32), it.disabled) (name, CustomProcMacroExpander::new(idx as u32), it.disabled)
}) })
.collect() .collect(),
}), ),
_ => None, _ => None,
} }
} }
} }
/// A loaded proc-macro. /// A loaded proc-macro.
#[derive(Debug, Clone)] #[derive(Debug, Clone, Eq)]
pub struct ProcMacro { pub struct ProcMacro {
/// The name of the proc macro. /// The name of the proc macro.
pub name: Symbol, pub name: Symbol,
@ -137,6 +185,23 @@ pub struct ProcMacro {
pub disabled: bool, 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`] /// A custom proc-macro expander handle. This handle together with its crate resolves to a [`ProcMacro`]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct CustomProcMacroExpander { pub struct CustomProcMacroExpander {
@ -187,7 +252,7 @@ impl CustomProcMacroExpander {
} }
/// The macro is explicitly disabled due to proc-macro attribute expansion being disabled. /// 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 { match self.proc_macro_id {
Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandErrorKind::ProcMacroAttrExpansionDisabled), Self::PROC_MACRO_ATTR_DISABLED => Some(ExpandErrorKind::ProcMacroAttrExpansionDisabled),
Self::DISABLED_ID => Some(ExpandErrorKind::MacroDisabled), Self::DISABLED_ID => Some(ExpandErrorKind::MacroDisabled),
@ -199,8 +264,8 @@ impl CustomProcMacroExpander {
pub fn expand( pub fn expand(
self, self,
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
def_crate: CrateId, def_crate: Crate,
calling_crate: CrateId, calling_crate: Crate,
tt: &tt::TopSubtree, tt: &tt::TopSubtree,
attr_arg: Option<&tt::TopSubtree>, attr_arg: Option<&tt::TopSubtree>,
def_site: Span, def_site: Span,
@ -221,8 +286,22 @@ impl CustomProcMacroExpander {
ExpandError::new(call_site, ExpandErrorKind::MacroDisabled), ExpandError::new(call_site, ExpandErrorKind::MacroDisabled),
), ),
id => { id => {
let proc_macros = db.proc_macros(); let proc_macros = match db.proc_macros_for_crate(def_crate) {
let proc_macro = match proc_macros.get(def_crate, id, call_site) { 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, Ok(proc_macro) => proc_macro,
Err(e) => { Err(e) => {
return ExpandResult::new( 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. // 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 = 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( match proc_macro.expander.expand(
tt, 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)
}

View file

@ -11,7 +11,7 @@ use tracing::debug;
use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds}; use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds};
use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
use base_db::CrateId; use base_db::Crate;
use hir_def::{ use hir_def::{
data::{adt::StructFlags, TraitFlags}, data::{adt::StructFlags, TraitFlags},
hir::Movability, hir::Movability,
@ -523,7 +523,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
impl ChalkContext<'_> { impl ChalkContext<'_> {
fn edition(&self) -> Edition { fn edition(&self) -> Edition {
self.db.crate_graph()[self.krate].edition self.krate.data(self.db).edition
} }
fn for_trait_impls( 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( pub(crate) fn program_clauses_for_chalk_env_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
block: Option<BlockId>, block: Option<BlockId>,
environment: chalk_ir::Environment<Interner>, environment: chalk_ir::Environment<Interner>,
) -> chalk_ir::ProgramClauses<Interner> { ) -> chalk_ir::ProgramClauses<Interner> {
@ -665,7 +665,7 @@ pub(crate) fn associated_ty_data_query(
pub(crate) fn trait_datum_query( pub(crate) fn trait_datum_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
trait_id: TraitId, trait_id: TraitId,
) -> Arc<TraitDatum> { ) -> Arc<TraitDatum> {
debug!("trait_datum {:?}", trait_id); 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( pub(crate) fn adt_datum_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
chalk_ir::AdtId(adt_id): AdtId, chalk_ir::AdtId(adt_id): AdtId,
) -> Arc<AdtDatum> { ) -> Arc<AdtDatum> {
debug!("adt_datum {:?}", adt_id); debug!("adt_datum {:?}", adt_id);
@ -824,7 +824,7 @@ pub(crate) fn adt_datum_query(
pub(crate) fn impl_datum_query( pub(crate) fn impl_datum_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
impl_id: ImplId, impl_id: ImplId,
) -> Arc<ImplDatum> { ) -> Arc<ImplDatum> {
let _p = tracing::info_span!("impl_datum_query").entered(); 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_) impl_def_datum(db, krate, impl_)
} }
fn impl_def_datum( fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId) -> Arc<ImplDatum> {
db: &dyn HirDatabase,
krate: CrateId,
impl_id: hir_def::ImplId,
) -> Arc<ImplDatum> {
let trait_ref = db let trait_ref = db
.impl_trait(impl_id) .impl_trait(impl_id)
// ImplIds for impls where the trait ref can't be resolved should never reach Chalk // 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( pub(crate) fn associated_ty_value_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
id: AssociatedTyValueId, id: AssociatedTyValueId,
) -> Arc<AssociatedTyValue> { ) -> Arc<AssociatedTyValue> {
let type_alias: TypeAliasAsValue = from_chalk(db, id); 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( fn type_alias_associated_ty_value(
db: &dyn HirDatabase, db: &dyn HirDatabase,
_krate: CrateId, _krate: Crate,
type_alias: TypeAliasId, type_alias: TypeAliasId,
) -> Arc<AssociatedTyValue> { ) -> Arc<AssociatedTyValue> {
let type_alias_data = db.type_alias_data(type_alias); let type_alias_data = db.type_alias_data(type_alias);

View file

@ -1,6 +1,6 @@
//! Constant evaluation details //! Constant evaluation details
use base_db::CrateId; use base_db::Crate;
use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex}; use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex};
use hir_def::{ use hir_def::{
expr_store::{Body, HygieneId}, expr_store::{Body, HygieneId},
@ -162,7 +162,7 @@ pub fn intern_const_ref(
db: &dyn HirDatabase, db: &dyn HirDatabase,
value: &LiteralConstRef, value: &LiteralConstRef,
ty: Ty, ty: Ty,
krate: CrateId, krate: Crate,
) -> Const { ) -> Const {
let layout = db.layout_of_ty(ty.clone(), TraitEnvironment::empty(krate)); let layout = db.layout_of_ty(ty.clone(), TraitEnvironment::empty(krate));
let bytes = match value { let bytes = match value {
@ -185,7 +185,7 @@ pub fn intern_const_ref(
} }
/// Interns a possibly-unknown target usize /// 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( intern_const_ref(
db, db,
&value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt), &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt),

View file

@ -101,10 +101,7 @@ fn check_answer(
fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String { fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
let mut err = String::new(); let mut err = String::new();
let span_formatter = |file, range| format!("{file:?} {range:?}"); let span_formatter = |file, range| format!("{file:?} {range:?}");
let display_target = DisplayTarget::from_crate( let display_target = DisplayTarget::from_crate(&db, *db.all_crates().last().unwrap());
&db,
*db.crate_graph().crates_in_topological_order().last().unwrap(),
);
match e { match e {
ConstEvalError::MirLowerError(e) => { ConstEvalError::MirLowerError(e) => {
e.pretty_print(&mut err, &db, span_formatter, display_target) e.pretty_print(&mut err, &db, span_formatter, display_target)

View file

@ -3,7 +3,7 @@
use std::sync; use std::sync;
use base_db::{impl_intern_key, CrateId, Upcast}; use base_db::{impl_intern_key, Crate, Upcast};
use hir_def::{ use hir_def::{
db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, CallableDefId, db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, CallableDefId,
ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId, 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)] #[salsa::cycle(crate::layout::layout_of_ty_recover)]
fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>; fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
#[salsa::invoke(crate::layout::target_data_layout_query)] #[salsa::invoke_actual(crate::layout::target_data_layout_query)]
fn target_data_layout(&self, krate: CrateId) -> Result<Arc<TargetDataLayout>, Arc<str>>; fn target_data_layout(&self, krate: Crate) -> Result<Arc<TargetDataLayout>, Arc<str>>;
#[salsa::invoke_actual(crate::dyn_compatibility::dyn_compatibility_of_trait_query)] #[salsa::invoke_actual(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>; 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)] #[salsa::invoke_actual(crate::lower::generic_defaults_query)]
fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults; fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults;
#[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] #[salsa::invoke_actual(InherentImpls::inherent_impls_in_crate_query)]
fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>; fn inherent_impls_in_crate(&self, krate: Crate) -> Arc<InherentImpls>;
#[salsa::invoke_actual(InherentImpls::inherent_impls_in_block_query)] #[salsa::invoke_actual(InherentImpls::inherent_impls_in_block_query)]
fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>; 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)] #[salsa::invoke(crate::method_resolution::incoherent_inherent_impl_crates)]
fn incoherent_inherent_impl_crates( fn incoherent_inherent_impl_crates(
&self, &self,
krate: CrateId, krate: Crate,
fp: TyFingerprint, fp: TyFingerprint,
) -> SmallVec<[CrateId; 2]>; ) -> SmallVec<[Crate; 2]>;
#[salsa::invoke(TraitImpls::trait_impls_in_crate_query)] #[salsa::invoke_actual(TraitImpls::trait_impls_in_crate_query)]
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>; fn trait_impls_in_crate(&self, krate: Crate) -> Arc<TraitImpls>;
#[salsa::invoke_actual(TraitImpls::trait_impls_in_block_query)] #[salsa::invoke_actual(TraitImpls::trait_impls_in_block_query)]
fn trait_impls_in_block(&self, block: BlockId) -> Option<Arc<TraitImpls>>; fn trait_impls_in_block(&self, block: BlockId) -> Option<Arc<TraitImpls>>;
#[salsa::invoke(TraitImpls::trait_impls_in_deps_query)] #[salsa::invoke_actual(TraitImpls::trait_impls_in_deps_query)]
fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<[Arc<TraitImpls>]>; fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc<TraitImpls>]>;
// Interned IDs for Chalk integration // Interned IDs for Chalk integration
#[salsa::interned] #[salsa::interned]
@ -253,23 +253,16 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> + std::fmt::Debug {
#[salsa::invoke(chalk_db::trait_datum_query)] #[salsa::invoke(chalk_db::trait_datum_query)]
fn trait_datum( fn trait_datum(
&self, &self,
krate: CrateId, krate: Crate,
trait_id: chalk_db::TraitId, trait_id: chalk_db::TraitId,
) -> sync::Arc<chalk_db::TraitDatum>; ) -> sync::Arc<chalk_db::TraitDatum>;
#[salsa::invoke(chalk_db::adt_datum_query)] #[salsa::invoke(chalk_db::adt_datum_query)]
fn adt_datum( fn adt_datum(&self, krate: Crate, struct_id: chalk_db::AdtId) -> sync::Arc<chalk_db::AdtDatum>;
&self,
krate: CrateId,
struct_id: chalk_db::AdtId,
) -> sync::Arc<chalk_db::AdtDatum>;
#[salsa::invoke(chalk_db::impl_datum_query)] #[salsa::invoke(chalk_db::impl_datum_query)]
fn impl_datum( fn impl_datum(&self, krate: Crate, impl_id: chalk_db::ImplId)
&self, -> sync::Arc<chalk_db::ImplDatum>;
krate: CrateId,
impl_id: chalk_db::ImplId,
) -> sync::Arc<chalk_db::ImplDatum>;
#[salsa::invoke(chalk_db::fn_def_datum_query)] #[salsa::invoke(chalk_db::fn_def_datum_query)]
fn fn_def_datum(&self, fn_def_id: FnDefId) -> sync::Arc<chalk_db::FnDefDatum>; 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)] #[salsa::invoke(chalk_db::associated_ty_value_query)]
fn associated_ty_value( fn associated_ty_value(
&self, &self,
krate: CrateId, krate: Crate,
id: chalk_db::AssociatedTyValueId, id: chalk_db::AssociatedTyValueId,
) -> sync::Arc<chalk_db::AssociatedTyValue>; ) -> 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)] #[salsa::invoke(crate::traits::trait_solve_query)]
fn trait_solve( fn trait_solve(
&self, &self,
krate: CrateId, krate: Crate,
block: Option<BlockId>, block: Option<BlockId>,
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>, goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
) -> Option<crate::Solution>; ) -> 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)] #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
fn program_clauses_for_chalk_env( fn program_clauses_for_chalk_env(
&self, &self,
krate: CrateId, krate: Crate,
block: Option<BlockId>, block: Option<BlockId>,
env: chalk_ir::Environment<Interner>, env: chalk_ir::Environment<Interner>,
) -> chalk_ir::ProgramClauses<Interner>; ) -> chalk_ir::ProgramClauses<Interner>;

View file

@ -288,7 +288,7 @@ impl<'a> DeclValidator<'a> {
fn edition(&self, id: impl HasModule) -> span::Edition { fn edition(&self, id: impl HasModule) -> span::Edition {
let krate = id.krate(self.db.upcast()); 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) { fn validate_struct(&mut self, struct_id: StructId) {

View file

@ -4,7 +4,7 @@
use std::fmt; use std::fmt;
use base_db::CrateId; use base_db::Crate;
use chalk_solve::rust_ir::AdtKind; use chalk_solve::rust_ir::AdtKind;
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
@ -630,7 +630,7 @@ fn missing_match_arms<'p>(
scrut_ty: &Ty, scrut_ty: &Ty,
witnesses: Vec<WitnessPat<'p>>, witnesses: Vec<WitnessPat<'p>>,
arms_is_empty: bool, arms_is_empty: bool,
krate: CrateId, krate: Crate,
) -> String { ) -> String {
struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, DisplayTarget); struct DisplayWitness<'a, 'p>(&'a WitnessPat<'p>, &'a MatchCheckCtx<'p>, DisplayTarget);
impl fmt::Display for DisplayWitness<'_, '_> { impl fmt::Display for DisplayWitness<'_, '_> {

View file

@ -160,7 +160,7 @@ impl<'a> UnsafeVisitor<'a> {
DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())), DefWithBodyId::FunctionId(func) => TargetFeatures::from_attrs(&db.attrs(func.into())),
_ => TargetFeatures::default(), _ => TargetFeatures::default(),
}; };
let edition = db.crate_graph()[resolver.module().krate()].edition; let edition = resolver.module().krate().data(db).edition;
Self { Self {
db, db,
infer, infer,

View file

@ -7,7 +7,7 @@ use std::{
mem, mem,
}; };
use base_db::CrateId; use base_db::Crate;
use chalk_ir::{BoundVar, Safety, TyKind}; use chalk_ir::{BoundVar, Safety, TyKind};
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
@ -339,7 +339,7 @@ pub trait HirDisplay {
} }
impl HirFormatter<'_> { impl HirFormatter<'_> {
pub fn krate(&self) -> CrateId { pub fn krate(&self) -> Crate {
self.display_target.krate self.display_target.krate
} }
@ -408,13 +408,13 @@ impl HirFormatter<'_> {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct DisplayTarget { pub struct DisplayTarget {
krate: CrateId, krate: Crate,
pub edition: Edition, pub edition: Edition,
} }
impl DisplayTarget { impl DisplayTarget {
pub fn from_crate(db: &dyn HirDatabase, krate: CrateId) -> Self { pub fn from_crate(db: &dyn HirDatabase, krate: Crate) -> Self {
let edition = db.crate_graph()[krate].edition; let edition = krate.data(db).edition;
Self { krate, 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)] #[derive(Clone, Copy, PartialEq, Eq)]
pub enum SizedByDefault { pub enum SizedByDefault {
NotSized, NotSized,
Sized { anchor: CrateId }, Sized { anchor: Crate },
} }
impl SizedByDefault { impl SizedByDefault {
@ -2266,8 +2266,8 @@ impl HirDisplayWithTypesMap for Path {
// Resolve `$crate` to the crate's display name. // Resolve `$crate` to the crate's display name.
// FIXME: should use the dependency name instead if available, but that depends on // FIXME: should use the dependency name instead if available, but that depends on
// the crate invoking `HirDisplay` // the crate invoking `HirDisplay`
let crate_graph = f.db.crate_graph(); let crate_data = id.extra_data(f.db);
let name = crate_graph[*id] let name = crate_data
.display_name .display_name
.as_ref() .as_ref()
.map(|name| name.canonical_name()) .map(|name| name.canonical_name())

View file

@ -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.insert_str(0, "r#");
} }
result result
@ -316,7 +316,7 @@ impl CapturedItem {
pub fn display_place_source_code(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String { pub fn display_place_source_code(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
let body = db.body(owner); let body = db.body(owner);
let krate = owner.krate(db.upcast()); 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 result = body[self.place.local].name.display(db.upcast(), edition).to_string();
for proj in &self.place.projections { for proj in &self.place.projections {
match proj { match proj {
@ -368,7 +368,7 @@ impl CapturedItem {
pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String { pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> String {
let body = db.body(owner); let body = db.body(owner);
let krate = owner.krate(db.upcast()); 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 result = body[self.place.local].name.display(db.upcast(), edition).to_string();
let mut field_need_paren = false; let mut field_need_paren = false;
for proj in &self.place.projections { for proj in &self.place.projections {

View file

@ -1,6 +1,6 @@
//! Target dependent parameters needed for layouts //! Target dependent parameters needed for layouts
use base_db::CrateId; use base_db::Crate;
use hir_def::layout::TargetDataLayout; use hir_def::layout::TargetDataLayout;
use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors}; use rustc_abi::{AlignFromBytesError, TargetDataLayoutErrors};
use triomphe::Arc; use triomphe::Arc;
@ -9,9 +9,9 @@ use crate::db::HirDatabase;
pub fn target_data_layout_query( pub fn target_data_layout_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
) -> Result<Arc<TargetDataLayout>, Arc<str>> { ) -> 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) => match TargetDataLayout::parse_from_llvm_datalayout_string(it) {
Ok(it) => Ok(Arc::new(it)), Ok(it) => Ok(Arc::new(it)),
Err(e) => { Err(e) => {

View file

@ -14,7 +14,7 @@ use std::{
ops::{self, Not as _}, ops::{self, Not as _},
}; };
use base_db::CrateId; use base_db::Crate;
use chalk_ir::{ use chalk_ir::{
cast::Cast, cast::Cast,
fold::{Shift, TypeFoldable}, 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); cov_mark::hit!(lower_rpit);
let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner); let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { 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)) .unwrap_or_else(|| unknown_const(expected_ty))
} }
&ConstRef::Complex(it) => { &ConstRef::Complex(it) => {
let crate_data = &db.crate_graph()[resolver.krate()]; let krate = resolver.krate();
if crate_data.env.get("__ra_is_test_fixture").is_none() && crate_data.origin.is_local() // 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 // FIXME: current `InTypeConstId` is very unstable, so we only use it in non local crate
// that are unlikely to be edited. // that are unlikely to be edited.

View file

@ -5,7 +5,7 @@
use std::ops::ControlFlow; use std::ops::ControlFlow;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use base_db::CrateId; use base_db::Crate;
use chalk_ir::{cast::Cast, UniverseIndex, WithKind}; use chalk_ir::{cast::Cast, UniverseIndex, WithKind};
use hir_def::{ use hir_def::{
data::{adt::StructFlags, ImplData, TraitFlags}, data::{adt::StructFlags, ImplData, TraitFlags},
@ -148,7 +148,7 @@ pub struct TraitImpls {
} }
impl 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 _p = tracing::info_span!("trait_impls_in_crate_query", ?krate).entered();
let mut impls = FxHashMap::default(); let mut impls = FxHashMap::default();
@ -175,13 +175,11 @@ impl TraitImpls {
pub(crate) fn trait_impls_in_deps_query( pub(crate) fn trait_impls_in_deps_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
) -> Arc<[Arc<Self>]> { ) -> Arc<[Arc<Self>]> {
let _p = tracing::info_span!("trait_impls_in_deps_query", ?krate).entered(); let _p = tracing::info_span!("trait_impls_in_deps_query", ?krate).entered();
let crate_graph = db.crate_graph();
Arc::from_iter( 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 { 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 _p = tracing::info_span!("inherent_impls_in_crate_query", ?krate).entered();
let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() }; let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
@ -367,16 +365,15 @@ impl InherentImpls {
pub(crate) fn incoherent_inherent_impl_crates( pub(crate) fn incoherent_inherent_impl_crates(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
fp: TyFingerprint, fp: TyFingerprint,
) -> SmallVec<[CrateId; 2]> { ) -> SmallVec<[Crate; 2]> {
let _p = tracing::info_span!("incoherent_inherent_impl_crates").entered(); let _p = tracing::info_span!("incoherent_inherent_impl_crates").entered();
let mut res = SmallVec::new(); let mut res = SmallVec::new();
let crate_graph = db.crate_graph();
// should pass crate for finger print and do reverse deps // 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); let impls = db.inherent_impls_in_crate(krate);
if impls.map.get(&fp).is_some_and(|v| !v.is_empty()) { if impls.map.get(&fp).is_some_and(|v| !v.is_empty()) {
res.push(krate); res.push(krate);
@ -386,11 +383,7 @@ pub(crate) fn incoherent_inherent_impl_crates(
res res
} }
pub fn def_crates( pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<SmallVec<[Crate; 2]>> {
db: &dyn HirDatabase,
ty: &Ty,
cur_crate: CrateId,
) -> Option<SmallVec<[CrateId; 2]>> {
match ty.kind(Interner) { match ty.kind(Interner) {
&TyKind::Adt(AdtId(def_id), _) => { &TyKind::Adt(AdtId(def_id), _) => {
let rustc_has_incoherent_inherent_impls = match 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 // FIXME: this should really be using the edition of the method name's span, in case it
// comes from a macro // comes from a macro
if !db.crate_graph()[krate].edition.at_least_2021() { if !krate.data(db).edition.at_least_2021() {
continue; 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 // FIXME: this should really be using the edition of the method name's span, in case it
// comes from a macro // comes from a macro
if !db.crate_graph()[krate].edition.at_least_2024() { if !krate.data(db).edition.at_least_2024() {
continue; continue;
} }
} }

View file

@ -12,7 +12,7 @@ use crate::{
CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap, CallableDefId, ClosureId, Const, ConstScalar, InferenceResult, Interner, MemoryMap,
Substitution, TraitEnvironment, Ty, TyExt, TyKind, Substitution, TraitEnvironment, Ty, TyExt, TyKind,
}; };
use base_db::CrateId; use base_db::Crate;
use chalk_ir::Mutability; use chalk_ir::Mutability;
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
@ -143,7 +143,7 @@ impl<V, T> ProjectionElem<V, T> {
mut base: Ty, mut base: Ty,
db: &dyn HirDatabase, db: &dyn HirDatabase,
closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty, closure_field: impl FnOnce(ClosureId, &Substitution, usize) -> Ty,
krate: CrateId, krate: Crate,
) -> Ty { ) -> Ty {
// we only bail on mir building when there are type mismatches // 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 // but error types may pop up resulting in us still attempting to build the mir

View file

@ -2,7 +2,7 @@
use std::{borrow::Cow, cell::RefCell, fmt::Write, iter, mem, ops::Range}; 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 chalk_ir::{cast::Cast, Mutability};
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
@ -186,7 +186,7 @@ pub struct Evaluator<'a> {
cached_fn_trait_func: Option<FunctionId>, cached_fn_trait_func: Option<FunctionId>,
cached_fn_mut_trait_func: Option<FunctionId>, cached_fn_mut_trait_func: Option<FunctionId>,
cached_fn_once_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` // FIXME: This is a workaround, see the comment on `interpret_mir`
assert_placeholder_ty_is_unused: bool, assert_placeholder_ty_is_unused: bool,
/// A general limit on execution, to prevent non terminating programs from breaking r-a main process /// 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 db = self.db.upcast();
let loc = variant.lookup(db); let loc = variant.lookup(db);
let enum_loc = loc.parent.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!( let name = format!(
"{}::{}", "{}::{}",
enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast(), edition), enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db.upcast(), edition),

View file

@ -569,7 +569,7 @@ impl Evaluator<'_> {
} }
String::from_utf8_lossy(&name_buf) 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 { match value {
None => { None => {
// Write null as fail // Write null as fail

View file

@ -2,7 +2,7 @@
use std::{fmt::Write, iter, mem}; 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 chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind};
use hir_def::{ use hir_def::{
data::adt::{StructKind, VariantData}, data::adt::{StructKind, VariantData},
@ -1920,10 +1920,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
} }
fn edition(&self) -> Edition { 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()) 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>> { pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<MirBody>> {
let krate = def.krate(db.upcast()); let krate = def.krate(db.upcast());
let edition = db.crate_graph()[krate].edition; let edition = krate.data(db).edition;
let detail = match def { let detail = match def {
DefWithBodyId::FunctionId(it) => { DefWithBodyId::FunctionId(it) => {
db.function_data(it).name.display(db.upcast(), edition).to_string() db.function_data(it).name.display(db.upcast(), edition).to_string()

View file

@ -3,8 +3,8 @@
use std::{fmt, panic, sync::Mutex}; use std::{fmt, panic, sync::Mutex};
use base_db::{ use base_db::{
FileSourceRootInput, FileText, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, RootQueryDb, SourceDatabase,
SourceRootInput, Upcast, SourceRoot, SourceRootId, SourceRootInput, Upcast,
}; };
use hir_def::{db::DefDatabase, ModuleId}; use hir_def::{db::DefDatabase, ModuleId};
@ -21,6 +21,7 @@ use triomphe::Arc;
pub(crate) struct TestDB { pub(crate) struct TestDB {
storage: salsa::Storage<Self>, storage: salsa::Storage<Self>,
files: Arc<base_db::Files>, files: Arc<base_db::Files>,
crates_map: Arc<CratesMap>,
events: Arc<Mutex<Option<Vec<salsa::Event>>>>, events: Arc<Mutex<Option<Vec<salsa::Event>>>>,
} }
@ -30,8 +31,12 @@ impl Default for TestDB {
storage: Default::default(), storage: Default::default(),
events: Default::default(), events: Default::default(),
files: Default::default(), files: Default::default(),
crates_map: Default::default(),
}; };
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH); 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 this
} }
} }
@ -115,6 +120,10 @@ impl SourceDatabase for TestDB {
let files = Arc::clone(&self.files); let files = Arc::clone(&self.files);
files.set_file_source_root_with_durability(self, id, source_root_id, durability); 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] #[salsa::db]
@ -151,8 +160,7 @@ impl TestDB {
&self, &self,
) -> FxHashMap<EditionedFileId, Vec<(TextRange, String)>> { ) -> FxHashMap<EditionedFileId, Vec<(TextRange, String)>> {
let mut files = Vec::new(); let mut files = Vec::new();
let crate_graph = self.crate_graph(); for &krate in self.all_crates().iter() {
for krate in crate_graph.iter() {
let crate_def_map = self.crate_def_map(krate); let crate_def_map = self.crate_def_map(krate);
for (module_id, _) in crate_def_map.modules() { for (module_id, _) in crate_def_map.modules() {
let file_id = crate_def_map[module_id].origin.file_id(); let file_id = crate_def_map[module_id].origin.file_id();

View file

@ -15,7 +15,7 @@ mod type_alias_impl_traits;
use std::env; use std::env;
use std::sync::LazyLock; use std::sync::LazyLock;
use base_db::{CrateId, SourceDatabase}; use base_db::{Crate, SourceDatabase};
use expect_test::Expect; use expect_test::Expect;
use hir_def::{ use hir_def::{
db::DefDatabase, db::DefDatabase,
@ -124,7 +124,7 @@ fn check_impl(
} }
assert!(had_annotations || allow_none, "no `//^` annotations found"); 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 { for file_id in files {
let module = db.module_for_file_opt(file_id); let module = db.module_for_file_opt(file_id);
let module = match module { 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>, let mut infer_def = |inference_result: Arc<InferenceResult>,
body: Arc<Body>, body: Arc<Body>,
body_source_map: Arc<BodySourceMap>, body_source_map: Arc<BodySourceMap>,
krate: CrateId| { krate: Crate| {
let display_target = DisplayTarget::from_crate(&db, krate); let display_target = DisplayTarget::from_crate(&db, krate);
let mut types: Vec<(InFile<SyntaxNode>, &Ty)> = Vec::new(); let mut types: Vec<(InFile<SyntaxNode>, &Ty)> = Vec::new();
let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch)> = 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 module = db.module_for_file(file_id);
let def_map = module.def_map(&db); 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| { visit_module(&db, &def_map, module.local_id, &mut |it| {
let def = match it { let def = match it {
ModuleDefId::FunctionId(it) => it.into(), ModuleDefId::FunctionId(it) => it.into(),

View file

@ -7,7 +7,7 @@ use chalk_ir::{fold::TypeFoldable, DebruijnIndex, GoalData};
use chalk_recursive::Cache; use chalk_recursive::Cache;
use chalk_solve::{logging_db::LoggingRustIrDatabase, rust_ir, Solver}; use chalk_solve::{logging_db::LoggingRustIrDatabase, rust_ir, Solver};
use base_db::CrateId; use base_db::Crate;
use hir_def::{ use hir_def::{
lang_item::{LangItem, LangItemTarget}, lang_item::{LangItem, LangItemTarget},
BlockId, TraitId, BlockId, TraitId,
@ -30,7 +30,7 @@ const CHALK_SOLVER_FUEL: i32 = 1000;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub(crate) struct ChalkContext<'a> { pub(crate) struct ChalkContext<'a> {
pub(crate) db: &'a dyn HirDatabase, pub(crate) db: &'a dyn HirDatabase,
pub(crate) krate: CrateId, pub(crate) krate: Crate,
pub(crate) block: Option<BlockId>, pub(crate) block: Option<BlockId>,
} }
@ -48,7 +48,7 @@ fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
/// we assume that `T: Default`. /// we assume that `T: Default`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TraitEnvironment { pub struct TraitEnvironment {
pub krate: CrateId, pub krate: Crate,
pub block: Option<BlockId>, pub block: Option<BlockId>,
// FIXME make this a BTreeMap // FIXME make this a BTreeMap
traits_from_clauses: Box<[(Ty, TraitId)]>, traits_from_clauses: Box<[(Ty, TraitId)]>,
@ -56,7 +56,7 @@ pub struct TraitEnvironment {
} }
impl TraitEnvironment { impl TraitEnvironment {
pub fn empty(krate: CrateId) -> Arc<Self> { pub fn empty(krate: Crate) -> Arc<Self> {
Arc::new(TraitEnvironment { Arc::new(TraitEnvironment {
krate, krate,
block: None, block: None,
@ -66,7 +66,7 @@ impl TraitEnvironment {
} }
pub fn new( pub fn new(
krate: CrateId, krate: Crate,
block: Option<BlockId>, block: Option<BlockId>,
traits_from_clauses: Box<[(Ty, TraitId)]>, traits_from_clauses: Box<[(Ty, TraitId)]>,
env: chalk_ir::Environment<Interner>, env: chalk_ir::Environment<Interner>,
@ -109,7 +109,7 @@ pub(crate) fn normalize_projection_query(
/// Solve a trait goal using Chalk. /// Solve a trait goal using Chalk.
pub(crate) fn trait_solve_query( pub(crate) fn trait_solve_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
block: Option<BlockId>, block: Option<BlockId>,
goal: Canonical<InEnvironment<Goal>>, goal: Canonical<InEnvironment<Goal>>,
) -> Option<Solution> { ) -> Option<Solution> {
@ -148,7 +148,7 @@ pub(crate) fn trait_solve_query(
fn solve( fn solve(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: Crate,
block: Option<BlockId>, block: Option<BlockId>,
goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>>, goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>>,
) -> Option<chalk_solve::Solution<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())?; let target = db.lang_item(krate, self.lang_item())?;
match target { match target {
LangItemTarget::Trait(t) => Some(t), LangItemTarget::Trait(t) => Some(t),

View file

@ -3,7 +3,7 @@
use std::{hash::Hash, iter}; use std::{hash::Hash, iter};
use base_db::CrateId; use base_db::Crate;
use chalk_ir::{ use chalk_ir::{
fold::{FallibleTypeFolder, Shift}, fold::{FallibleTypeFolder, Shift},
DebruijnIndex, DebruijnIndex,
@ -34,10 +34,7 @@ use crate::{
TraitRefExt, Ty, WhereClause, TraitRefExt, Ty, WhereClause,
}; };
pub(crate) fn fn_traits( pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator<Item = TraitId> + '_ {
db: &dyn DefDatabase,
krate: CrateId,
) -> impl Iterator<Item = TraitId> + '_ {
[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce] [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]
.into_iter() .into_iter()
.filter_map(move |lang| db.lang_item(krate, lang)) .filter_map(move |lang| db.lang_item(krate, lang))

View file

@ -30,7 +30,7 @@ macro_rules! from_id {
} }
from_id![ from_id![
(base_db::CrateId, crate::Crate), (base_db::Crate, crate::Crate),
(hir_def::ModuleId, crate::Module), (hir_def::ModuleId, crate::Module),
(hir_def::StructId, crate::Struct), (hir_def::StructId, crate::Struct),
(hir_def::UnionId, crate::Union), (hir_def::UnionId, crate::Union),

View file

@ -39,7 +39,7 @@ use std::{
}; };
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, CrateOrigin, LangCrateOrigin}; use base_db::{CrateDisplayName, CrateOrigin, LangCrateOrigin};
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
data::{adt::VariantData, TraitFlags}, data::{adt::VariantData, TraitFlags},
@ -176,7 +176,7 @@ use {
/// root module. /// root module.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Crate { pub struct Crate {
pub(crate) id: CrateId, pub(crate) id: base_db::Crate,
} }
#[derive(Debug)] #[derive(Debug)]
@ -187,7 +187,7 @@ pub struct CrateDependency {
impl Crate { impl Crate {
pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin { 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 { pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
@ -195,7 +195,8 @@ impl Crate {
} }
pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> { pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
db.crate_graph()[self.id] self.id
.data(db)
.dependencies .dependencies
.iter() .iter()
.map(|dep| { .map(|dep| {
@ -207,12 +208,11 @@ impl Crate {
} }
pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> { pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
let crate_graph = db.crate_graph(); let all_crates = db.all_crates();
crate_graph all_crates
.iter() .iter()
.filter(|&krate| { .copied()
crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id) .filter(|&krate| krate.data(db).dependencies.iter().any(|it| it.crate_id == self.id))
})
.map(|id| Crate { id }) .map(|id| Crate { id })
.collect() .collect()
} }
@ -221,7 +221,7 @@ impl Crate {
self, self,
db: &dyn HirDatabase, db: &dyn HirDatabase,
) -> impl Iterator<Item = Crate> { ) -> 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 { pub fn root_module(self) -> Module {
@ -234,19 +234,19 @@ impl Crate {
} }
pub fn root_file(self, db: &dyn HirDatabase) -> FileId { 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 { 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> { 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> { 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( pub fn query_external_importables(
@ -264,7 +264,7 @@ impl Crate {
} }
pub fn all(db: &dyn HirDatabase) -> Vec<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. /// 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> { 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> { pub fn potential_cfg<'db>(&self, db: &'db dyn HirDatabase) -> &'db CfgOptions {
let data = &db.crate_graph()[self.id]; let data = self.id.extra_data(db);
data.potential_cfg_options.clone().unwrap_or_else(|| data.cfg_options.clone()) data.potential_cfg_options.as_ref().unwrap_or_else(|| self.id.cfg_options(db))
} }
pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget { pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget {
@ -289,11 +289,12 @@ impl Crate {
} }
fn core(db: &dyn HirDatabase) -> Option<Crate> { fn core(db: &dyn HirDatabase) -> Option<Crate> {
let crate_graph = db.crate_graph(); let result = db
let result = crate_graph .all_crates()
.iter() .iter()
.copied()
.find(|&krate| { .find(|&krate| {
matches!(crate_graph[krate].origin, CrateOrigin::Lang(LangCrateOrigin::Core)) matches!(krate.data(db).origin, CrateOrigin::Lang(LangCrateOrigin::Core))
}) })
.map(Crate::from); .map(Crate::from);
result result
@ -490,9 +491,7 @@ impl HasCrate for ModuleDef {
fn krate(&self, db: &dyn HirDatabase) -> Crate { fn krate(&self, db: &dyn HirDatabase) -> Crate {
match self.module(db) { match self.module(db) {
Some(module) => module.krate(), Some(module) => module.krate(),
None => Crate::core(db).unwrap_or_else(|| { None => Crate::core(db).unwrap_or_else(|| db.all_crates()[0].into()),
(*db.crate_graph().crates_in_topological_order().last().unwrap()).into()
}),
} }
} }
} }
@ -611,7 +610,7 @@ impl Module {
style_lints: bool, style_lints: bool,
) { ) {
let _p = tracing::info_span!("diagnostics", name = ?self.name(db)).entered(); 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()); let def_map = self.id.def_map(db.upcast());
for diag in def_map.diagnostics() { for diag in def_map.diagnostics() {
if diag.in_module != self.id.local_id { 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; return;
}; };
let krate = HasModule::krate(&m.id, db.upcast()); let krate = HasModule::krate(&m.id, db.upcast());
let edition = db.crate_graph()[krate].edition; let edition = krate.data(db).edition;
emit_def_diagnostic_( emit_def_diagnostic_(
db, db,
acc, acc,
@ -3027,7 +3026,8 @@ impl BuiltinType {
} }
pub fn ty(self, db: &dyn HirDatabase) -> Type { 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 { pub fn name(self) -> Name {
@ -3968,7 +3968,7 @@ impl DeriveHelper {
// FIXME: Wrong name? This is could also be a registered attribute // FIXME: Wrong name? This is could also be a registered attribute
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct BuiltinAttr { pub struct BuiltinAttr {
krate: Option<CrateId>, krate: Option<base_db::Crate>,
idx: u32, idx: u32,
} }
@ -4014,7 +4014,7 @@ impl BuiltinAttr {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ToolModule { pub struct ToolModule {
krate: CrateId, krate: base_db::Crate,
idx: u32, idx: u32,
} }
@ -4732,7 +4732,7 @@ impl Type {
Type { env: environment, ty } 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 } Type { env: TraitEnvironment::empty(krate), ty }
} }
@ -4794,7 +4794,7 @@ impl Type {
Type { env: ty.env, ty: TyBuilder::slice(ty.ty) } 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()); let tys = tys.iter().map(|it| it.ty.clone());
Type { env: TraitEnvironment::empty(krate), ty: TyBuilder::tuple_with(tys) } 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 { pub fn contains_reference(&self, db: &dyn HirDatabase) -> bool {
return go(db, self.env.krate, &self.ty); 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) { match ty.kind(Interner) {
// Reference itself // Reference itself
TyKind::Ref(_, _, _) => true, TyKind::Ref(_, _, _) => true,
@ -6209,7 +6209,7 @@ impl HasContainer for Module {
let def_map = self.id.def_map(db.upcast()); let def_map = self.id.def_map(db.upcast());
match def_map[self.id.local_id].parent { match def_map[self.id.local_id].parent {
Some(parent_id) => ItemContainer::Module(Module { id: def_map.module_id(parent_id) }), 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), Impl(Impl),
Module(Module), Module(Module),
ExternBlock(ExternBlock), ExternBlock(ExternBlock),
Crate(CrateId), Crate(Crate),
} }
/// Subset of `ide_db::Definition` that doc links can resolve to. /// Subset of `ide_db::Definition` that doc links can resolve to.

View file

@ -318,7 +318,7 @@ impl<'db> SemanticsImpl<'db> {
pub fn first_crate_or_default(&self, file: FileId) -> Crate { pub fn first_crate_or_default(&self, file: FileId) -> Crate {
match self.file_to_module_defs(file).next() { match self.file_to_module_defs(file).next() {
Some(module) => module.krate(), Some(module) => module.krate(),
None => (*self.db.crate_graph().crates_in_topological_order().last().unwrap()).into(), None => (*self.db.all_crates().last().unwrap()).into(),
} }
} }

View file

@ -77,10 +77,7 @@ impl<'a> SymbolCollector<'a> {
symbols: Default::default(), symbols: Default::default(),
work: Default::default(), work: Default::default(),
current_container_name: None, current_container_name: None,
display_target: DisplayTarget::from_crate( display_target: DisplayTarget::from_crate(db, *db.all_crates().last().unwrap()),
db,
*db.crate_graph().crates_in_topological_order().last().unwrap(),
),
} }
} }

View file

@ -7,7 +7,7 @@ use hir::{
sym, FileRange, PathResolution, Semantics, TypeInfo, sym, FileRange, PathResolution, Semantics, TypeInfo,
}; };
use ide_db::{ use ide_db::{
base_db::CrateId, base_db::Crate,
defs::Definition, defs::Definition,
imports::insert_use::remove_path_if_in_use_stmt, imports::insert_use::remove_path_if_in_use_stmt,
path_transform::PathTransform, path_transform::PathTransform,
@ -251,11 +251,11 @@ struct CallInfo {
node: ast::CallableExpr, node: ast::CallableExpr,
arguments: Vec<ast::Expr>, arguments: Vec<ast::Expr>,
generic_arg_list: Option<ast::GenericArgList>, generic_arg_list: Option<ast::GenericArgList>,
krate: CrateId, krate: Crate,
} }
impl CallInfo { 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()?; let parent = name_ref.syntax().parent()?;
if let Some(call) = ast::MethodCallExpr::cast(parent.clone()) { if let Some(call) = ast::MethodCallExpr::cast(parent.clone()) {
let receiver = call.receiver()?; let receiver = call.receiver()?;

View file

@ -233,7 +233,13 @@ impl RootDatabase {
// // SourceDatabase // // SourceDatabase
// base_db::ParseQuery // base_db::ParseQuery
// base_db::ParseErrorsQuery // 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 // base_db::CrateWorkspaceDataQuery
// // SourceDatabaseExt // // SourceDatabaseExt

View file

@ -1,6 +1,6 @@
//! See [`FamousDefs`]. //! 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 hir::{Crate, Enum, Function, Macro, Module, ScopeDef, Semantics, Trait};
use crate::RootDatabase; use crate::RootDatabase;
@ -198,11 +198,10 @@ impl FamousDefs<'_, '_> {
fn find_lang_crate(&self, origin: LangCrateOrigin) -> Option<Crate> { fn find_lang_crate(&self, origin: LangCrateOrigin) -> Option<Crate> {
let krate = self.1; let krate = self.1;
let db = self.0.db; let db = self.0.db;
let crate_graph = self.0.db.crate_graph();
let res = krate let res = krate
.dependencies(db) .dependencies(db)
.into_iter() .into_iter()
.find(|dep| crate_graph[dep.krate.into()].origin == CrateOrigin::Lang(origin))? .find(|dep| dep.krate.origin(db) == CrateOrigin::Lang(origin))?
.krate; .krate;
Some(res) Some(res)
} }

View file

@ -51,9 +51,8 @@ use salsa::Durability;
use std::{fmt, mem::ManuallyDrop}; use std::{fmt, mem::ManuallyDrop};
use base_db::{ use base_db::{
query_group::{self}, query_group, CrateGraphBuilder, CratesMap, FileSourceRootInput, FileText, Files, RootQueryDb,
FileSourceRootInput, FileText, Files, RootQueryDb, SourceDatabase, SourceRoot, SourceRootId, SourceDatabase, SourceRoot, SourceRootId, SourceRootInput, Upcast,
SourceRootInput, Upcast,
}; };
use hir::{ use hir::{
db::{DefDatabase, ExpandDatabase, HirDatabase}, db::{DefDatabase, ExpandDatabase, HirDatabase},
@ -85,6 +84,7 @@ pub struct RootDatabase {
// compile times of all `ide_*` and downstream crates suffer greatly. // compile times of all `ide_*` and downstream crates suffer greatly.
storage: ManuallyDrop<salsa::Storage<Self>>, storage: ManuallyDrop<salsa::Storage<Self>>,
files: Arc<Files>, files: Arc<Files>,
crates_map: Arc<CratesMap>,
} }
impl std::panic::RefUnwindSafe for RootDatabase {} impl std::panic::RefUnwindSafe for RootDatabase {}
@ -102,7 +102,11 @@ impl Drop for RootDatabase {
impl Clone for RootDatabase { impl Clone for RootDatabase {
fn clone(&self) -> Self { 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); let files = Arc::clone(&self.files);
files.set_file_source_root_with_durability(self, id, source_root_id, durability); 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 { impl Default for RootDatabase {
@ -207,8 +215,11 @@ impl RootDatabase {
let mut db = RootDatabase { let mut db = RootDatabase {
storage: ManuallyDrop::new(salsa::Storage::default()), storage: ManuallyDrop::new(salsa::Storage::default()),
files: Default::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_proc_macros_with_durability(Default::default(), Durability::HIGH);
db.set_local_roots_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); db.set_library_roots_with_durability(Default::default(), Durability::HIGH);
@ -258,7 +269,11 @@ impl RootDatabase {
} }
pub fn snapshot(&self) -> Self { 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(),
}
} }
} }

View file

@ -11,7 +11,7 @@ use itertools::Itertools;
use salsa::{Cancelled, Database}; use salsa::{Cancelled, Database};
use crate::{ use crate::{
base_db::{CrateId, RootQueryDb}, base_db::{Crate, RootQueryDb},
symbol_index::SymbolsDatabase, symbol_index::SymbolsDatabase,
FxIndexMap, RootDatabase, FxIndexMap, RootDatabase,
}; };
@ -35,20 +35,22 @@ pub fn parallel_prime_caches(
) { ) {
let _p = tracing::info_span!("parallel_prime_caches").entered(); let _p = tracing::info_span!("parallel_prime_caches").entered();
let graph = db.crate_graph();
let mut crates_to_prime = { 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(); let mut builder = topologic_sort::TopologicalSortIter::builder();
for crate_id in graph.iter() { for &crate_id in db.all_crates().iter() {
builder.add(crate_id, graph[crate_id].dependencies.iter().map(|d| d.crate_id)); builder.add(crate_id, crate_id.data(db).dependencies.iter().map(|d| d.crate_id));
} }
builder.build() builder.build()
}; };
enum ParallelPrimeCacheWorkerProgress { enum ParallelPrimeCacheWorkerProgress {
BeginCrate { crate_id: CrateId, crate_name: Symbol }, BeginCrate { crate_id: Crate, crate_name: Symbol },
EndCrate { crate_id: CrateId }, EndCrate { crate_id: Crate },
} }
// We split off def map computation from other work, // We split off def map computation from other work,
@ -108,16 +110,14 @@ pub fn parallel_prime_caches(
while crates_done < crates_total { while crates_done < crates_total {
db.unwind_if_revision_cancelled(); db.unwind_if_revision_cancelled();
for crate_id in &mut crates_to_prime { for krate in &mut crates_to_prime {
let krate = &graph[crate_id]; let name = krate.extra_data(db).display_name.as_deref().cloned().unwrap_or_else(|| {
let name = krate Symbol::integer(salsa::plumbing::AsId::as_id(&krate).as_u32() as usize)
.display_name });
.as_deref() let origin = &krate.data(db).origin;
.cloned() if origin.is_lang() {
.unwrap_or_else(|| Symbol::integer(crate_id.into_raw().into_u32() as usize)); additional_phases.push((krate, name.clone(), PrimingPhase::ImportMap));
if krate.origin.is_lang() { } else if origin.is_local() {
additional_phases.push((crate_id, name.clone(), PrimingPhase::ImportMap));
} else if krate.origin.is_local() {
// Compute the symbol search index. // Compute the symbol search index.
// This primes the cache for `ide_db::symbol_index::world_symbols()`. // 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 // FIXME: We should do it unconditionally if the configuration is set to default to
// searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we // searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we
// would need to pipe that configuration information down here. // 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 // recv_timeout is somewhat a hack, we need a way to from this thread check to see if the current salsa revision

View file

@ -162,13 +162,13 @@ impl SearchScope {
fn crate_graph(db: &RootDatabase) -> SearchScope { fn crate_graph(db: &RootDatabase) -> SearchScope {
let mut entries = FxHashMap::default(); let mut entries = FxHashMap::default();
let graph = db.crate_graph(); let all_crates = db.all_crates();
for krate in graph.iter() { for &krate in all_crates.iter() {
let root_file = graph[krate].root_file_id; let crate_data = krate.data(db);
let source_root = db.file_source_root(root_file).source_root_id(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); let source_root = db.source_root(source_root).source_root(db);
entries.extend( 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 } SearchScope { entries }

View file

@ -2,7 +2,9 @@
( (
Module { Module {
id: ModuleId { id: ModuleId {
krate: Idx::<CrateData>(0), krate: Crate {
[salsa id]: Id(2c00),
},
block: None, block: None,
local_id: Idx::<ModuleData>(0), local_id: Idx::<ModuleData>(0),
}, },

View file

@ -2,7 +2,9 @@
( (
Module { Module {
id: ModuleId { id: ModuleId {
krate: Idx::<CrateData>(0), krate: Crate {
[salsa id]: Id(2c00),
},
block: None, block: None,
local_id: Idx::<ModuleData>(0), local_id: Idx::<ModuleData>(0),
}, },
@ -532,7 +534,9 @@
def: Module( def: Module(
Module { Module {
id: ModuleId { id: ModuleId {
krate: Idx::<CrateData>(0), krate: Crate {
[salsa id]: Id(2c00),
},
block: None, block: None,
local_id: Idx::<ModuleData>(1), local_id: Idx::<ModuleData>(1),
}, },
@ -565,7 +569,9 @@
def: Module( def: Module(
Module { Module {
id: ModuleId { id: ModuleId {
krate: Idx::<CrateData>(0), krate: Crate {
[salsa id]: Id(2c00),
},
block: None, block: None,
local_id: Idx::<ModuleData>(2), local_id: Idx::<ModuleData>(2),
}, },
@ -827,7 +833,9 @@
( (
Module { Module {
id: ModuleId { id: ModuleId {
krate: Idx::<CrateData>(0), krate: Crate {
[salsa id]: Id(2c00),
},
block: None, block: None,
local_id: Idx::<ModuleData>(1), local_id: Idx::<ModuleData>(1),
}, },
@ -871,7 +879,9 @@
( (
Module { Module {
id: ModuleId { id: ModuleId {
krate: Idx::<CrateData>(0), krate: Crate {
[salsa id]: Id(2c00),
},
block: None, block: None,
local_id: Idx::<ModuleData>(2), local_id: Idx::<ModuleData>(2),
}, },

View file

@ -389,9 +389,9 @@ pub fn semantic_diagnostics(
module.and_then(|m| db.toolchain_channel(m.krate().into())), module.and_then(|m| db.toolchain_channel(m.krate().into())),
Some(ReleaseChannel::Nightly) | None Some(ReleaseChannel::Nightly) | None
); );
let krate = module.map(|module| module.krate()).unwrap_or_else(|| { let krate = module
(*db.crate_graph().crates_in_topological_order().last().unwrap()).into() .map(|module| module.krate())
}); .unwrap_or_else(|| (*db.all_crates().last().unwrap()).into());
let display_target = krate.to_display_target(db); let display_target = krate.to_display_target(db);
let ctx = DiagnosticsContext { config, sema, resolve, edition, is_nightly, display_target }; let ctx = DiagnosticsContext { config, sema, resolve, edition, is_nightly, display_target };

View file

@ -626,11 +626,11 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
match_error!("Failed to get receiver type for `{}`", expr.syntax().text()) match_error!("Failed to get receiver type for `{}`", expr.syntax().text())
})? })?
.original; .original;
let krate = self.sema.scope(expr.syntax()).map(|it| it.krate()).unwrap_or_else(|| { let krate = self
hir::Crate::from( .sema
*self.sema.db.crate_graph().crates_in_topological_order().last().unwrap(), .scope(expr.syntax())
) .map(|it| it.krate())
}); .unwrap_or_else(|| hir::Crate::from(*self.sema.db.all_crates().last().unwrap()));
let res = code_type let res = code_type
.autoderef(self.sema.db) .autoderef(self.sema.db)
.enumerate() .enumerate()

View file

@ -504,9 +504,7 @@ fn get_doc_base_urls(
let Some(krate) = krate else { return Default::default() }; let Some(krate) = krate else { return Default::default() };
let Some(display_name) = krate.display_name(db) 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 krate.origin(db) {
let (web_base, local_base) = match &crate_data.origin {
// std and co do not specify `html_root_url` any longer so we gotta handwrite this ourself. // 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 // FIXME: Use the toolchains channel instead of nightly
CrateOrigin::Lang( CrateOrigin::Lang(

View file

@ -1,8 +1,8 @@
use hir::db::ExpandDatabase; use hir::db::ExpandDatabase;
use hir::{ExpandResult, InFile, MacroFileIdExt, Semantics}; use hir::{ExpandResult, InFile, MacroFileIdExt, Semantics};
use ide_db::base_db::CrateId;
use ide_db::{ 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 span::{Edition, SpanMap, SyntaxContextId, TextRange, TextSize};
use stdx::format_to; use stdx::format_to;
@ -208,7 +208,7 @@ fn format(
file_id: FileId, file_id: FileId,
expanded: SyntaxNode, expanded: SyntaxNode,
span_map: &SpanMap<SyntaxContextId>, span_map: &SpanMap<SyntaxContextId>,
krate: CrateId, krate: Crate,
) -> String { ) -> String {
let expansion = prettify_macro_expansion(db, expanded, span_map, krate).to_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 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 &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)] #[allow(clippy::disallowed_methods)]
let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path()); let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path());

View file

@ -20,21 +20,24 @@ pub struct CrateInfo {
// //
// ![Show Dependency Tree](https://user-images.githubusercontent.com/5748995/229394139-2625beab-f4c9-484b-84ed-ad5dee0b1e1a.png) // ![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> { pub(crate) fn fetch_crates(db: &RootDatabase) -> FxIndexSet<CrateInfo> {
let crate_graph = db.crate_graph(); db.all_crates()
crate_graph
.iter() .iter()
.map(|crate_id| &crate_graph[crate_id]) .copied()
.filter(|&data| !matches!(data.origin, CrateOrigin::Local { .. })) .map(|crate_id| (crate_id.data(db), crate_id.extra_data(db)))
.map(crate_info) .filter(|(data, _)| !matches!(data.origin, CrateOrigin::Local { .. }))
.map(|(data, extra_data)| crate_info(data, extra_data))
.collect() .collect()
} }
fn crate_info(data: &ide_db::base_db::CrateData) -> CrateInfo { fn crate_info(
let crate_name = crate_name(data); data: &ide_db::base_db::BuiltCrateData,
let version = data.version.clone(); 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 } 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()) data.display_name.as_ref().map(|it| it.canonical_name().as_str().to_owned())
} }

View file

@ -8,7 +8,6 @@ use hir::{
MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef, MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef,
}; };
use ide_db::{ use ide_db::{
base_db::RootQueryDb,
defs::Definition, defs::Definition,
documentation::HasDocs, documentation::HasDocs,
famous_defs::FamousDefs, famous_defs::FamousDefs,
@ -466,8 +465,7 @@ pub(super) fn path(
item_name: Option<String>, item_name: Option<String>,
edition: Edition, edition: Edition,
) -> String { ) -> String {
let crate_name = let crate_name = module.krate().display_name(db).as_ref().map(|it| it.to_string());
db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
let module_path = module let module_path = module
.path_to_root(db) .path_to_root(db)
.into_iter() .into_iter()

View file

@ -9252,7 +9252,7 @@ fn main() {
S S
``` ```
___ ___
Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S>"#]], Implements notable traits: Future<Output = u32>, Iterator<Item = S>, Notable"#]],
); );
} }

View file

@ -868,15 +868,15 @@ fn main() {
//- minicore: fn //- minicore: fn
fn main() { fn main() {
let x = || 2; let x = || 2;
//^ {closure#26624} //^ {closure#25600}
let y = |t: i32| x() + t; let y = |t: i32| x() + t;
//^ {closure#26625} //^ {closure#25601}
let mut t = 5; let mut t = 5;
//^ i32 //^ i32
let z = |k: i32| { t += k; }; let z = |k: i32| { t += k; };
//^ {closure#26626} //^ {closure#25602}
let p = (y, z); let p = (y, z);
//^ ({closure#26625}, {closure#26626}) //^ ({closure#25601}, {closure#25602})
} }
"#, "#,
); );

View file

@ -57,7 +57,7 @@ mod view_memory_layout;
mod view_mir; mod view_mir;
mod view_syntax_tree; mod view_syntax_tree;
use std::{iter, panic::UnwindSafe}; use std::panic::UnwindSafe;
use cfg::CfgOptions; use cfg::CfgOptions;
use fetch_crates::CrateInfo; use fetch_crates::CrateInfo;
@ -125,7 +125,7 @@ pub use ide_completion::{
}; };
pub use ide_db::text_edit::{Indel, TextEdit}; pub use ide_db::text_edit::{Indel, TextEdit};
pub use ide_db::{ pub use ide_db::{
base_db::{CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId}, base_db::{Crate, CrateGraphBuilder, FileChange, SourceRoot, SourceRootId},
documentation::Documentation, documentation::Documentation,
label::Label, label::Label,
line_index::{LineCol, LineIndex}, line_index::{LineCol, LineIndex},
@ -239,7 +239,7 @@ impl Analysis {
let mut change = ChangeWithProcMacros::new(); let mut change = ChangeWithProcMacros::new();
change.set_roots(vec![source_root]); change.set_roots(vec![source_root]);
let mut crate_graph = CrateGraph::default(); let mut crate_graph = CrateGraphBuilder::default();
// FIXME: cfg options // FIXME: cfg options
// Default to enable test for single file. // Default to enable test for single file.
let mut cfg_options = CfgOptions::default(); let mut cfg_options = CfgOptions::default();
@ -255,16 +255,13 @@ impl Analysis {
CrateOrigin::Local { repo: None, name: None }, CrateOrigin::Local { repo: None, name: None },
false, false,
None, None,
); Arc::new(CrateWorkspaceData {
change.change_file(file_id, Some(text));
let ws_data = crate_graph
.iter()
.zip(iter::repeat(Arc::new(CrateWorkspaceData {
data_layout: Err("fixture has no layout".into()), data_layout: Err("fixture has no layout".into()),
toolchain: None, 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.apply_change(change);
(host.analysis(), file_id) (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)) 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)) 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. /// 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)) self.with_db(|db| parent_module::crates_for(db, file_id))
} }
/// Returns crates that this file belongs to. /// Returns crates that this file belongs to.
pub fn transitive_rev_deps(&self, crate_id: CrateId) -> Cancellable<Vec<CrateId>> { pub fn transitive_rev_deps(&self, crate_id: Crate) -> Cancellable<Vec<Crate>> {
self.with_db(|db| db.crate_graph().transitive_rev_deps(crate_id).collect()) self.with_db(|db| Vec::from_iter(db.transitive_rev_deps(crate_id)))
} }
/// Returns crates that this file *might* belong to. /// 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| { self.with_db(|db| {
let db = Upcast::<dyn RootQueryDb>::upcast(db); let db = Upcast::<dyn RootQueryDb>::upcast(db);
db.relevant_crates(file_id).iter().copied().collect() db.relevant_crates(file_id).iter().copied().collect()
@ -620,18 +617,23 @@ impl Analysis {
} }
/// Returns the edition of the given crate. /// Returns the edition of the given crate.
pub fn crate_edition(&self, crate_id: CrateId) -> Cancellable<Edition> { pub fn crate_edition(&self, crate_id: Crate) -> Cancellable<Edition> {
self.with_db(|db| db.crate_graph()[crate_id].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. /// 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()) self.with_db(|db| hir::db::DefDatabase::crate_def_map(db, crate_id).is_no_std())
} }
/// Returns the root file of the given crate. /// Returns the root file of the given crate.
pub fn crate_root(&self, crate_id: CrateId) -> Cancellable<FileId> { pub fn crate_root(&self, crate_id: Crate) -> Cancellable<FileId> {
self.with_db(|db| db.crate_graph()[crate_id].root_file_id) self.with_db(|db| crate_id.data(db).root_file_id)
} }
/// Returns the set of possible targets to run for the current file. /// Returns the set of possible targets to run for the current file.

View file

@ -1,6 +1,6 @@
use hir::{db::DefDatabase, Semantics}; use hir::{db::DefDatabase, Semantics};
use ide_db::{ use ide_db::{
base_db::{CrateId, RootQueryDb, Upcast}, base_db::{Crate, RootQueryDb, Upcast},
FileId, FilePosition, RootDatabase, FileId, FilePosition, RootDatabase,
}; };
use itertools::Itertools; 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. /// 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); let root_db = Upcast::<dyn RootQueryDb>::upcast(db);
root_db root_db
.relevant_crates(file_id) .relevant_crates(file_id)

View file

@ -498,9 +498,8 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
}; };
let krate = def.krate(db); let krate = def.krate(db);
let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT); let edition = krate.map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
let display_target = krate let display_target =
.unwrap_or_else(|| (*db.crate_graph().crates_in_topological_order().last().unwrap()).into()) krate.unwrap_or_else(|| (*db.all_crates().last().unwrap()).into()).to_display_target(db);
.to_display_target(db);
if !has_runnable_doc_test(&attrs) { if !has_runnable_doc_test(&attrs) {
return None; return None;
} }

View file

@ -119,9 +119,7 @@ fn documentation_for_definition(
sema.db, sema.db,
famous_defs.as_ref(), famous_defs.as_ref(),
def.krate(sema.db) def.krate(sema.db)
.unwrap_or_else(|| { .unwrap_or_else(|| (*sema.db.all_crates().last().unwrap()).into())
(*sema.db.crate_graph().crates_in_topological_order().last().unwrap()).into()
})
.to_display_target(sema.db), .to_display_target(sema.db),
) )
} }

View file

@ -1,4 +1,4 @@
use ide_db::base_db::{CrateData, RootQueryDb, Upcast}; use ide_db::base_db::{BuiltCrateData, ExtraCrateData};
use ide_db::RootDatabase; use ide_db::RootDatabase;
use itertools::Itertools; use itertools::Itertools;
use span::FileId; use span::FileId;
@ -34,28 +34,25 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
if crates.is_empty() { if crates.is_empty() {
format_to!(buf, "Does not belong to any crate"); format_to!(buf, "Does not belong to any crate");
} }
let crate_graph = Upcast::<dyn RootQueryDb>::upcast(db).crate_graph();
for crate_id in crates { for crate_id in crates {
let CrateData { let BuiltCrateData {
root_file_id, root_file_id,
edition, edition,
version,
display_name,
cfg_options,
potential_cfg_options,
env,
dependencies, dependencies,
origin, origin,
is_proc_macro, is_proc_macro,
proc_macro_cwd, 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!( format_to!(
buf, buf,
"Crate: {}\n", "Crate: {}\n",
match display_name { match display_name {
Some(it) => format!("{it}({})", crate_id.into_raw()), Some(it) => format!("{it}({:?})", crate_id),
None => format!("{}", crate_id.into_raw()), None => format!("{:?}", crate_id),
} }
); );
format_to!(buf, " Root module file id: {}\n", root_file_id.index()); 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); format_to!(buf, " Proc macro cwd: {:?}\n", proc_macro_cwd);
let deps = dependencies let deps = dependencies
.iter() .iter()
.map(|dep| format!("{}={}", dep.name, dep.crate_id.into_raw())) .map(|dep| format!("{}={:?}", dep.name, dep.crate_id))
.format(", "); .format(", ");
format_to!(buf, " Dependencies: {}\n", deps); format_to!(buf, " Dependencies: {}\n", deps);
} }

View file

@ -1,17 +1,15 @@
//! Discovers tests //! Discovers tests
use hir::{Crate, Module, ModuleDef, Semantics}; use hir::{Crate, Module, ModuleDef, Semantics};
use ide_db::{ use ide_db::base_db;
base_db::{CrateGraph, CrateId, RootQueryDb}, use ide_db::{base_db::RootQueryDb, FileId, RootDatabase};
FileId, RootDatabase,
};
use syntax::TextRange; use syntax::TextRange;
use crate::{runnables::runnable_fn, NavigationTarget, Runnable, TryToNav}; use crate::{runnables::runnable_fn, NavigationTarget, Runnable, TryToNav};
#[derive(Debug)] #[derive(Debug)]
pub enum TestItemKind { pub enum TestItemKind {
Crate(CrateId), Crate(base_db::Crate),
Module, Module,
Function, Function,
} }
@ -28,12 +26,12 @@ pub struct TestItem {
} }
pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> { pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> {
let crate_graph = db.crate_graph(); db.all_crates()
crate_graph
.iter() .iter()
.filter(|&id| crate_graph[id].origin.is_local()) .copied()
.filter(|&id| id.data(db).origin.is_local())
.filter_map(|id| { .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 { Some(TestItem {
kind: TestItemKind::Crate(id), kind: TestItemKind::Crate(id),
label: test_id.clone(), label: test_id.clone(),
@ -47,12 +45,12 @@ pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> {
.collect() .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 // 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. // only show tests for the local crates.
crate_graph.iter().find(|&id| { db.all_crates().iter().copied().find(|&id| {
crate_graph[id].origin.is_local() id.data(db).origin.is_local()
&& crate_graph[id].display_name.as_ref().is_some_and(|x| x.to_string() == crate_id) && 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, db: &RootDatabase,
crate_test_id: &str, crate_test_id: &str,
) -> Vec<TestItem> { ) -> Vec<TestItem> {
let crate_graph = db.crate_graph(); let Some(crate_id) = find_crate_by_id(db, crate_test_id) else {
let Some(crate_id) = find_crate_by_id(&crate_graph, crate_test_id) else {
return vec![]; return vec![];
}; };
discover_tests_in_crate(db, crate_id) discover_tests_in_crate(db, crate_id)
@ -171,12 +168,14 @@ fn find_module_id_and_test_parents(
Some((r, id)) Some((r, id))
} }
pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec<TestItem> { pub(crate) fn discover_tests_in_crate(
let crate_graph = db.crate_graph(); db: &RootDatabase,
if !crate_graph[crate_id].origin.is_local() { crate_id: base_db::Crate,
) -> Vec<TestItem> {
if !crate_id.data(db).origin.is_local() {
return vec![]; 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![]; return vec![];
}; };
let kind = TestItemKind::Crate(crate_id); let kind = TestItemKind::Crate(crate_id);

View file

@ -1,9 +1,10 @@
use dot::{Id, LabelText}; use dot::{Id, LabelText};
use ide_db::{ use ide_db::{
base_db::{CrateGraph, CrateId, Dependency, RootQueryDb, SourceDatabase, Upcast}, base_db::{
FxHashSet, RootDatabase, BuiltCrateData, BuiltDependency, Crate, ExtraCrateData, RootQueryDb, SourceDatabase,
},
FxHashMap, RootDatabase,
}; };
use triomphe::Arc;
// Feature: View Crate Graph // Feature: View Crate Graph
// //
@ -16,77 +17,80 @@ use triomphe::Arc;
// |---------|-------------| // |---------|-------------|
// | VS Code | **rust-analyzer: View Crate Graph** | // | VS Code | **rust-analyzer: View Crate Graph** |
pub(crate) fn view_crate_graph(db: &RootDatabase, full: bool) -> Result<String, String> { pub(crate) fn view_crate_graph(db: &RootDatabase, full: bool) -> Result<String, String> {
let crate_graph = Upcast::<dyn RootQueryDb>::upcast(db).crate_graph(); let all_crates = db.all_crates();
let crates_to_render = crate_graph let crates_to_render = all_crates
.iter() .iter()
.filter(|krate| { .copied()
.map(|krate| (krate, (krate.data(db), krate.extra_data(db))))
.filter(|(_, (crate_data, _))| {
if full { if full {
true true
} else { } else {
// Only render workspace crates // Only render workspace crates
let root_id = let root_id = db.file_source_root(crate_data.root_file_id).source_root_id(db);
db.file_source_root(crate_graph[*krate].root_file_id).source_root_id(db);
!db.source_root(root_id).source_root(db).is_library !db.source_root(root_id).source_root(db).is_library
} }
}) })
.collect(); .collect();
let graph = DotCrateGraph { graph: crate_graph, crates_to_render }; let graph = DotCrateGraph { crates_to_render };
let mut dot = Vec::new(); let mut dot = Vec::new();
dot::render(&graph, &mut dot).unwrap(); dot::render(&graph, &mut dot).unwrap();
Ok(String::from_utf8(dot).unwrap()) Ok(String::from_utf8(dot).unwrap())
} }
struct DotCrateGraph { struct DotCrateGraph<'db> {
graph: Arc<CrateGraph>, crates_to_render: FxHashMap<Crate, (&'db BuiltCrateData, &'db ExtraCrateData)>,
crates_to_render: FxHashSet<CrateId>,
} }
type Edge<'a> = (CrateId, &'a Dependency); type Edge<'a> = (Crate, &'a BuiltDependency);
impl<'a> dot::GraphWalk<'a, CrateId, Edge<'a>> for DotCrateGraph { impl<'a> dot::GraphWalk<'a, Crate, Edge<'a>> for DotCrateGraph<'_> {
fn nodes(&'a self) -> dot::Nodes<'a, CrateId> { fn nodes(&'a self) -> dot::Nodes<'a, Crate> {
self.crates_to_render.iter().copied().collect() self.crates_to_render.keys().copied().collect()
} }
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
self.crates_to_render self.crates_to_render
.iter() .iter()
.flat_map(|krate| { .flat_map(|(krate, (crate_data, _))| {
self.graph[*krate] crate_data
.dependencies .dependencies
.iter() .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)) .map(move |dep| (*krate, dep))
}) })
.collect() .collect()
} }
fn source(&'a self, edge: &Edge<'a>) -> CrateId { fn source(&'a self, edge: &Edge<'a>) -> Crate {
edge.0 edge.0
} }
fn target(&'a self, edge: &Edge<'a>) -> CrateId { fn target(&'a self, edge: &Edge<'a>) -> Crate {
edge.1.crate_id 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> { fn graph_id(&'a self) -> Id<'a> {
Id::new("rust_analyzer_crate_graph").unwrap() Id::new("rust_analyzer_crate_graph").unwrap()
} }
fn node_id(&'a self, n: &CrateId) -> Id<'a> { fn node_id(&'a self, n: &Crate) -> Id<'a> {
Id::new(format!("_{}", u32::from(n.into_raw()))).unwrap() 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())) Some(LabelText::LabelStr("box".into()))
} }
fn node_label(&'a self, n: &CrateId) -> LabelText<'a> { fn node_label(&'a self, n: &Crate) -> LabelText<'a> {
let name = let name = self.crates_to_render[n]
self.graph[*n].display_name.as_ref().map_or("(unnamed crate)", |name| name.as_str()); .1
.display_name
.as_ref()
.map_or("(unnamed crate)", |name| name.as_str());
LabelText::LabelStr(name.into()) LabelText::LabelStr(name.into())
} }
} }

View file

@ -42,6 +42,18 @@ struct TaggedArcPtr {
unsafe impl Send for TaggedArcPtr {} unsafe impl Send for TaggedArcPtr {}
unsafe impl Sync 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 { impl TaggedArcPtr {
const BOOL_BITS: usize = true as usize; 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 { pub struct Symbol {
repr: TaggedArcPtr, repr: TaggedArcPtr,
} }

View file

@ -2,15 +2,15 @@
//! for incorporating changes. //! for incorporating changes.
// Note, don't remove any public api from this. This API is consumed by external tools // Note, don't remove any public api from this. This API is consumed by external tools
// to run rust-analyzer as a library. // 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 crossbeam_channel::{unbounded, Receiver};
use hir_expand::proc_macro::{ use hir_expand::proc_macro::{
ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacroLoadResult, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacroLoadResult,
ProcMacros, ProcMacrosBuilder,
}; };
use ide_db::{ use ide_db::{
base_db::{CrateGraph, CrateWorkspaceData, Env, SourceRoot, SourceRootId}, base_db::{CrateGraphBuilder, Env, SourceRoot, SourceRootId},
prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase, prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase,
}; };
use itertools::Itertools; use itertools::Itertools;
@ -139,7 +139,6 @@ pub fn load_workspace(
}); });
let db = load_crate_graph( let db = load_crate_graph(
&ws,
crate_graph, crate_graph,
proc_macros, proc_macros,
project_folders.source_root_config, project_folders.source_root_config,
@ -418,15 +417,12 @@ pub fn load_proc_macro(
} }
fn load_crate_graph( fn load_crate_graph(
ws: &ProjectWorkspace, crate_graph: CrateGraphBuilder,
crate_graph: CrateGraph, proc_macros: ProcMacrosBuilder,
proc_macros: ProcMacros,
source_root_config: SourceRootConfig, source_root_config: SourceRootConfig,
vfs: &mut vfs::Vfs, vfs: &mut vfs::Vfs,
receiver: &Receiver<vfs::loader::Message>, receiver: &Receiver<vfs::loader::Message>,
) -> RootDatabase { ) -> 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 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 db = RootDatabase::new(lru_cap);
let mut analysis_change = ChangeWithProcMacros::new(); let mut analysis_change = ChangeWithProcMacros::new();
@ -461,14 +457,7 @@ fn load_crate_graph(
let source_roots = source_root_config.partition(vfs); let source_roots = source_root_config.partition(vfs);
analysis_change.set_roots(source_roots); analysis_change.set_roots(source_roots);
let ws_data = crate_graph analysis_change.set_crate_graph(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_proc_macros(proc_macros); analysis_change.set_proc_macros(proc_macros);
db.apply_change(analysis_change); 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); struct Expander(proc_macro_api::ProcMacro);
impl ProcMacroExpander for Expander { impl ProcMacroExpander for Expander {
@ -522,6 +511,10 @@ impl ProcMacroExpander for Expander {
Err(err) => Err(ProcMacroExpansionError::System(err.to_string())), 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)] #[cfg(test)]
@ -543,7 +536,7 @@ mod tests {
let (db, _vfs, _proc_macro) = let (db, _vfs, _proc_macro) =
load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {}).unwrap(); 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 // RA has quite a few crates, but the exact count doesn't matter
assert!(n_crates > 20); assert!(n_crates > 20);
} }

View file

@ -13,7 +13,7 @@ mod process;
use paths::{AbsPath, AbsPathBuf}; use paths::{AbsPath, AbsPathBuf};
use span::Span; use span::Span;
use std::{fmt, io, sync::Arc}; use std::{fmt, io, sync::Arc, time::SystemTime};
use crate::{ use crate::{
legacy_protocol::msg::{ legacy_protocol::msg::{
@ -66,6 +66,7 @@ pub struct ProcMacro {
dylib_path: Arc<AbsPathBuf>, dylib_path: Arc<AbsPathBuf>,
name: Box<str>, name: Box<str>,
kind: ProcMacroKind, kind: ProcMacroKind,
dylib_last_modified: Option<SystemTime>,
} }
impl Eq for ProcMacro {} impl Eq for ProcMacro {}
@ -73,7 +74,8 @@ impl PartialEq for ProcMacro {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.name == other.name self.name == other.name
&& self.kind == other.kind && 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) && Arc::ptr_eq(&self.process, &other.process)
} }
} }
@ -116,6 +118,9 @@ impl ProcMacroClient {
let macros = self.process.find_proc_macros(&dylib.path)?; let macros = self.process.find_proc_macros(&dylib.path)?;
let dylib_path = Arc::new(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 { match macros {
Ok(macros) => Ok(macros Ok(macros) => Ok(macros
.into_iter() .into_iter()
@ -124,6 +129,7 @@ impl ProcMacroClient {
name: name.into(), name: name.into(),
kind, kind,
dylib_path: dylib_path.clone(), dylib_path: dylib_path.clone(),
dylib_last_modified,
}) })
.collect()), .collect()),
Err(message) => Err(ServerError { message, io: None }), Err(message) => Err(ServerError { message, io: None }),

View file

@ -12,7 +12,7 @@ fn test_derive_empty() {
"DeriveEmpty", "DeriveEmpty",
r#"struct S;"#, r#"struct S;"#,
expect!["SUBTREE $$ 1 1"], expect!["SUBTREE $$ 1 1"],
expect!["SUBTREE $$ 42:2@0..100#2 42:2@0..100#2"], expect!["SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037"],
); );
} }
@ -29,12 +29,12 @@ fn test_derive_error() {
LITERAL Str #[derive(DeriveError)] struct S ; 1 LITERAL Str #[derive(DeriveError)] struct S ; 1
PUNCH ; [alone] 1"#]], PUNCH ; [alone] 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
IDENT compile_error 42:2@0..100#2 IDENT compile_error 42:2@0..100#4294967037
PUNCH ! [alone] 42:2@0..100#2 PUNCH ! [alone] 42:2@0..100#4294967037
SUBTREE () 42:2@0..100#2 42:2@0..100#2 SUBTREE () 42:2@0..100#4294967037 42:2@0..100#4294967037
LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#2 LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#4294967037
PUNCH ; [alone] 42:2@0..100#2"#]], PUNCH ; [alone] 42:2@0..100#4294967037"#]],
); );
} }
@ -53,14 +53,14 @@ fn test_fn_like_macro_noop() {
PUNCH , [alone] 1 PUNCH , [alone] 1
SUBTREE [] 1 1"#]], SUBTREE [] 1 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
IDENT ident 42:2@0..5#2 IDENT ident 42:2@0..5#4294967037
PUNCH , [alone] 42:2@5..6#2 PUNCH , [alone] 42:2@5..6#4294967037
LITERAL Integer 0 42:2@7..8#2 LITERAL Integer 0 42:2@7..8#4294967037
PUNCH , [alone] 42:2@8..9#2 PUNCH , [alone] 42:2@8..9#4294967037
LITERAL Integer 1 42:2@10..11#2 LITERAL Integer 1 42:2@10..11#4294967037
PUNCH , [alone] 42:2@11..12#2 PUNCH , [alone] 42:2@11..12#4294967037
SUBTREE [] 42:2@13..14#2 42:2@14..15#2"#]], SUBTREE [] 42:2@13..14#4294967037 42:2@14..15#4294967037"#]],
); );
} }
@ -75,10 +75,10 @@ fn test_fn_like_macro_clone_ident_subtree() {
PUNCH , [alone] 1 PUNCH , [alone] 1
SUBTREE [] 1 1"#]], SUBTREE [] 1 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
IDENT ident 42:2@0..5#2 IDENT ident 42:2@0..5#4294967037
PUNCH , [alone] 42:2@5..6#2 PUNCH , [alone] 42:2@5..6#4294967037
SUBTREE [] 42:2@7..8#2 42:2@7..8#2"#]], SUBTREE [] 42:2@7..8#4294967037 42:2@7..8#4294967037"#]],
); );
} }
@ -91,8 +91,8 @@ fn test_fn_like_macro_clone_raw_ident() {
SUBTREE $$ 1 1 SUBTREE $$ 1 1
IDENT r#async 1"#]], IDENT r#async 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
IDENT r#async 42:2@0..7#2"#]], IDENT r#async 42:2@0..7#4294967037"#]],
); );
} }
@ -105,8 +105,8 @@ fn test_fn_like_fn_like_span_join() {
SUBTREE $$ 1 1 SUBTREE $$ 1 1
IDENT r#joined 1"#]], IDENT r#joined 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
IDENT r#joined 42:2@0..11#2"#]], IDENT r#joined 42:2@0..11#4294967037"#]],
); );
} }
@ -121,10 +121,10 @@ fn test_fn_like_fn_like_span_ops() {
IDENT resolved_at_def_site 1 IDENT resolved_at_def_site 1
IDENT start_span 1"#]], IDENT start_span 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
IDENT set_def_site 41:1@0..150#2 IDENT set_def_site 41:1@0..150#4294967037
IDENT resolved_at_def_site 42:2@13..33#2 IDENT resolved_at_def_site 42:2@13..33#4294967037
IDENT start_span 42:2@34..34#2"#]], IDENT start_span 42:2@34..34#4294967037"#]],
); );
} }
@ -143,14 +143,14 @@ fn test_fn_like_mk_literals() {
LITERAL Integer 123i64 1 LITERAL Integer 123i64 1
LITERAL Integer 123 1"#]], LITERAL Integer 123 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
LITERAL ByteStr byte_string 42:2@0..100#2 LITERAL ByteStr byte_string 42:2@0..100#4294967037
LITERAL Char c 42:2@0..100#2 LITERAL Char c 42:2@0..100#4294967037
LITERAL Str string 42:2@0..100#2 LITERAL Str string 42:2@0..100#4294967037
LITERAL Float 3.14f64 42:2@0..100#2 LITERAL Float 3.14f64 42:2@0..100#4294967037
LITERAL Float 3.14 42:2@0..100#2 LITERAL Float 3.14 42:2@0..100#4294967037
LITERAL Integer 123i64 42:2@0..100#2 LITERAL Integer 123i64 42:2@0..100#4294967037
LITERAL Integer 123 42:2@0..100#2"#]], LITERAL Integer 123 42:2@0..100#4294967037"#]],
); );
} }
@ -164,9 +164,9 @@ fn test_fn_like_mk_idents() {
IDENT standard 1 IDENT standard 1
IDENT r#raw 1"#]], IDENT r#raw 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
IDENT standard 42:2@0..100#2 IDENT standard 42:2@0..100#4294967037
IDENT r#raw 42:2@0..100#2"#]], IDENT r#raw 42:2@0..100#4294967037"#]],
); );
} }
@ -198,27 +198,27 @@ fn test_fn_like_macro_clone_literals() {
PUNCH , [alone] 1 PUNCH , [alone] 1
LITERAL CStr null 1"#]], LITERAL CStr null 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
LITERAL Integer 1u16 42:2@0..4#2 LITERAL Integer 1u16 42:2@0..4#4294967037
PUNCH , [alone] 42:2@4..5#2 PUNCH , [alone] 42:2@4..5#4294967037
LITERAL Integer 2_u32 42:2@6..11#2 LITERAL Integer 2_u32 42:2@6..11#4294967037
PUNCH , [alone] 42:2@11..12#2 PUNCH , [alone] 42:2@11..12#4294967037
PUNCH - [alone] 42:2@13..14#2 PUNCH - [alone] 42:2@13..14#4294967037
LITERAL Integer 4i64 42:2@14..18#2 LITERAL Integer 4i64 42:2@14..18#4294967037
PUNCH , [alone] 42:2@18..19#2 PUNCH , [alone] 42:2@18..19#4294967037
LITERAL Float 3.14f32 42:2@20..27#2 LITERAL Float 3.14f32 42:2@20..27#4294967037
PUNCH , [alone] 42:2@27..28#2 PUNCH , [alone] 42:2@27..28#4294967037
LITERAL Str hello bridge 42:2@29..43#2 LITERAL Str hello bridge 42:2@29..43#4294967037
PUNCH , [alone] 42:2@43..44#2 PUNCH , [alone] 42:2@43..44#4294967037
LITERAL Str suffixedsuffix 42:2@45..61#2 LITERAL Str suffixedsuffix 42:2@45..61#4294967037
PUNCH , [alone] 42:2@61..62#2 PUNCH , [alone] 42:2@61..62#4294967037
LITERAL StrRaw(2) raw 42:2@63..73#2 LITERAL StrRaw(2) raw 42:2@63..73#4294967037
PUNCH , [alone] 42:2@73..74#2 PUNCH , [alone] 42:2@73..74#4294967037
LITERAL Char a 42:2@75..78#2 LITERAL Char a 42:2@75..78#4294967037
PUNCH , [alone] 42:2@78..79#2 PUNCH , [alone] 42:2@78..79#4294967037
LITERAL Byte b 42:2@80..84#2 LITERAL Byte b 42:2@80..84#4294967037
PUNCH , [alone] 42:2@84..85#2 PUNCH , [alone] 42:2@84..85#4294967037
LITERAL CStr null 42:2@86..93#2"#]], LITERAL CStr null 42:2@86..93#4294967037"#]],
); );
} }
@ -239,12 +239,12 @@ fn test_attr_macro() {
LITERAL Str #[attr_error(some arguments)] mod m {} 1 LITERAL Str #[attr_error(some arguments)] mod m {} 1
PUNCH ; [alone] 1"#]], PUNCH ; [alone] 1"#]],
expect![[r#" expect![[r#"
SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 SUBTREE $$ 42:2@0..100#4294967037 42:2@0..100#4294967037
IDENT compile_error 42:2@0..100#2 IDENT compile_error 42:2@0..100#4294967037
PUNCH ! [alone] 42:2@0..100#2 PUNCH ! [alone] 42:2@0..100#4294967037
SUBTREE () 42:2@0..100#2 42:2@0..100#2 SUBTREE () 42:2@0..100#4294967037 42:2@0..100#4294967037
LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#2 LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#4294967037
PUNCH ; [alone] 42:2@0..100#2"#]], PUNCH ; [alone] 42:2@0..100#4294967037"#]],
); );
} }

View file

@ -452,7 +452,7 @@ pub enum TargetKindData {
} }
/// Identifies a crate by position in the crates array. /// 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. /// workspaces are loaded.
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)]
#[serde(transparent)] #[serde(transparent)]

View file

@ -1,4 +1,4 @@
use base_db::{CrateGraph, ProcMacroPaths}; use base_db::{CrateGraphBuilder, ProcMacroPaths};
use cargo_metadata::Metadata; use cargo_metadata::Metadata;
use cfg::{CfgAtom, CfgDiff}; use cfg::{CfgAtom, CfgDiff};
use expect_test::{expect_file, ExpectFile}; use expect_test::{expect_file, ExpectFile};
@ -15,7 +15,7 @@ use crate::{
Sysroot, WorkspaceBuildScripts, Sysroot, WorkspaceBuildScripts,
}; };
fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) { fn load_cargo(file: &str) -> (CrateGraphBuilder, ProcMacroPaths) {
let project_workspace = load_workspace_from_metadata(file); let project_workspace = load_workspace_from_metadata(file);
to_crate_graph(project_workspace, &mut Default::default()) to_crate_graph(project_workspace, &mut Default::default())
} }
@ -23,7 +23,7 @@ fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
fn load_cargo_with_overrides( fn load_cargo_with_overrides(
file: &str, file: &str,
cfg_overrides: CfgOverrides, cfg_overrides: CfgOverrides,
) -> (CrateGraph, ProcMacroPaths) { ) -> (CrateGraphBuilder, ProcMacroPaths) {
let project_workspace = let project_workspace =
ProjectWorkspace { cfg_overrides, ..load_workspace_from_metadata(file) }; ProjectWorkspace { cfg_overrides, ..load_workspace_from_metadata(file) };
to_crate_graph(project_workspace, &mut Default::default()) 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 data = get_test_json_file(file);
let project = rooted_project_json(data); let project = rooted_project_json(data);
let sysroot = get_fake_sysroot(); let sysroot = get_fake_sysroot();
@ -142,7 +142,7 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
fn to_crate_graph( fn to_crate_graph(
project_workspace: ProjectWorkspace, project_workspace: ProjectWorkspace,
file_map: &mut FxHashMap<AbsPathBuf, FileId>, file_map: &mut FxHashMap<AbsPathBuf, FileId>,
) -> (CrateGraph, ProcMacroPaths) { ) -> (CrateGraphBuilder, ProcMacroPaths) {
project_workspace.to_crate_graph( project_workspace.to_crate_graph(
&mut { &mut {
|path| { |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:#?}"); let mut crate_graph = format!("{crate_graph:#?}");
replace_root(&mut crate_graph, false); replace_root(&mut crate_graph, false);

View file

@ -6,8 +6,9 @@ use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync, thread};
use anyhow::Context; use anyhow::Context;
use base_db::{ use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, CrateBuilderId, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin,
LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult, CrateWorkspaceData, DependencyBuilder, Env, LangCrateOrigin, ProcMacroPaths,
TargetLayoutLoadResult,
}; };
use cfg::{CfgAtom, CfgDiff, CfgOptions}; use cfg::{CfgAtom, CfgDiff, CfgOptions};
use intern::{sym, Symbol}; use intern::{sym, Symbol};
@ -848,10 +849,14 @@ impl ProjectWorkspace {
&self, &self,
load: FileLoader<'_>, load: FileLoader<'_>,
extra_env: &FxHashMap<String, String>, extra_env: &FxHashMap<String, String>,
) -> (CrateGraph, ProcMacroPaths) { ) -> (CrateGraphBuilder, ProcMacroPaths) {
let _p = tracing::info_span!("ProjectWorkspace::to_crate_graph").entered(); let _p = tracing::info_span!("ProjectWorkspace::to_crate_graph").entered();
let Self { kind, sysroot, cfg_overrides, rustc_cfg, .. } = self; 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 { let (crate_graph, proc_macros) = match kind {
ProjectWorkspaceKind::Json(project) => project_json_to_crate_graph( ProjectWorkspaceKind::Json(project) => project_json_to_crate_graph(
rustc_cfg.clone(), rustc_cfg.clone(),
@ -861,6 +866,7 @@ impl ProjectWorkspace {
extra_env, extra_env,
cfg_overrides, cfg_overrides,
self.set_test, self.set_test,
crate_ws_data,
), ),
ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _ } => { ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _ } => {
cargo_to_crate_graph( cargo_to_crate_graph(
@ -872,6 +878,7 @@ impl ProjectWorkspace {
cfg_overrides, cfg_overrides,
build_scripts, build_scripts,
self.set_test, self.set_test,
crate_ws_data,
) )
} }
ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => { ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => {
@ -885,6 +892,7 @@ impl ProjectWorkspace {
cfg_overrides, cfg_overrides,
build_scripts, build_scripts,
self.set_test, self.set_test,
crate_ws_data,
) )
} else { } else {
detached_file_to_crate_graph( detached_file_to_crate_graph(
@ -894,6 +902,7 @@ impl ProjectWorkspace {
sysroot, sysroot,
cfg_overrides, cfg_overrides,
self.set_test, self.set_test,
crate_ws_data,
) )
} }
} }
@ -959,15 +968,22 @@ fn project_json_to_crate_graph(
extra_env: &FxHashMap<String, String>, extra_env: &FxHashMap<String, String>,
override_cfg: &CfgOverrides, override_cfg: &CfgOverrides,
set_test: bool, set_test: bool,
) -> (CrateGraph, ProcMacroPaths) { crate_ws_data: Arc<CrateWorkspaceData>,
let mut res = (CrateGraph::default(), ProcMacroPaths::default()); ) -> (CrateGraphBuilder, ProcMacroPaths) {
let mut res = (CrateGraphBuilder::default(), ProcMacroPaths::default());
let (crate_graph, proc_macros) = &mut res; let (crate_graph, proc_macros) = &mut res;
let (public_deps, libproc_macro) = let (public_deps, libproc_macro) = sysroot_to_crate_graph(
sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); 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 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() .crates()
.filter_map(|(idx, krate)| Some((idx, krate, load(&krate.root_module)?))) .filter_map(|(idx, krate)| Some((idx, krate, load(&krate.root_module)?)))
.map( .map(
@ -1042,6 +1058,7 @@ fn project_json_to_crate_graph(
}, },
*is_proc_macro, *is_proc_macro,
proc_macro_cwd.clone(), proc_macro_cwd.clone(),
crate_ws_data.clone(),
); );
debug!( debug!(
?crate_graph_crate_id, ?crate_graph_crate_id,
@ -1092,12 +1109,19 @@ fn cargo_to_crate_graph(
override_cfg: &CfgOverrides, override_cfg: &CfgOverrides,
build_scripts: &WorkspaceBuildScripts, build_scripts: &WorkspaceBuildScripts,
set_test: bool, set_test: bool,
) -> (CrateGraph, ProcMacroPaths) { crate_ws_data: Arc<CrateWorkspaceData>,
) -> (CrateGraphBuilder, ProcMacroPaths) {
let _p = tracing::info_span!("cargo_to_crate_graph").entered(); 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 (crate_graph, proc_macros) = &mut res;
let (public_deps, libproc_macro) = let (public_deps, libproc_macro) = sysroot_to_crate_graph(
sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load); 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); let cfg_options = CfgOptions::from_iter(rustc_cfg);
@ -1163,6 +1187,7 @@ fn cargo_to_crate_graph(
name: Symbol::intern(&pkg_data.name), name: Symbol::intern(&pkg_data.name),
} }
}, },
crate_ws_data.clone(),
); );
if let TargetKind::Lib { .. } = kind { if let TargetKind::Lib { .. } = kind {
lib_tgt = Some((crate_id, name.clone())); lib_tgt = Some((crate_id, name.clone()));
@ -1267,6 +1292,8 @@ fn cargo_to_crate_graph(
} else { } else {
rustc_build_scripts 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, sysroot: &Sysroot,
override_cfg: &CfgOverrides, override_cfg: &CfgOverrides,
set_test: bool, set_test: bool,
) -> (CrateGraph, ProcMacroPaths) { crate_ws_data: Arc<CrateWorkspaceData>,
) -> (CrateGraphBuilder, ProcMacroPaths) {
let _p = tracing::info_span!("detached_file_to_crate_graph").entered(); let _p = tracing::info_span!("detached_file_to_crate_graph").entered();
let mut crate_graph = CrateGraph::default(); let mut crate_graph = CrateGraphBuilder::default();
let (public_deps, _libproc_macro) = let (public_deps, _libproc_macro) = sysroot_to_crate_graph(
sysroot_to_crate_graph(&mut crate_graph, sysroot, rustc_cfg.clone(), load); &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); let mut cfg_options = CfgOptions::from_iter(rustc_cfg);
if set_test { if set_test {
@ -1316,6 +1350,7 @@ fn detached_file_to_crate_graph(
}, },
false, false,
None, None,
crate_ws_data,
); );
public_deps.add_to_crate_graph(&mut crate_graph, detached_file_crate); 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( fn handle_rustc_crates(
crate_graph: &mut CrateGraph, crate_graph: &mut CrateGraphBuilder,
proc_macros: &mut ProcMacroPaths, proc_macros: &mut ProcMacroPaths,
pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>, pkg_to_lib_crate: &mut FxHashMap<Package, CrateBuilderId>,
load: FileLoader<'_>, load: FileLoader<'_>,
rustc_workspace: &CargoWorkspace, rustc_workspace: &CargoWorkspace,
cargo: &CargoWorkspace, cargo: &CargoWorkspace,
public_deps: &SysrootPublicDeps, public_deps: &SysrootPublicDeps,
libproc_macro: Option<CrateId>, libproc_macro: Option<CrateBuilderId>,
pkg_crates: &FxHashMap<Package, Vec<(CrateId, TargetKind)>>, pkg_crates: &FxHashMap<Package, Vec<(CrateBuilderId, TargetKind)>>,
cfg_options: &CfgOptions, cfg_options: &CfgOptions,
override_cfg: &CfgOverrides, override_cfg: &CfgOverrides,
build_scripts: &WorkspaceBuildScripts, build_scripts: &WorkspaceBuildScripts,
crate_ws_data: Arc<CrateWorkspaceData>,
) { ) {
let mut rustc_pkg_crates = FxHashMap::default(); let mut rustc_pkg_crates = FxHashMap::default();
// The root package of the rustc-dev component is rustc_driver, so we match that // 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, &rustc_workspace[tgt].name,
kind, kind,
CrateOrigin::Rustc { name: Symbol::intern(&rustc_workspace[pkg].name) }, CrateOrigin::Rustc { name: Symbol::intern(&rustc_workspace[pkg].name) },
crate_ws_data.clone(),
); );
pkg_to_lib_crate.insert(pkg, crate_id); pkg_to_lib_crate.insert(pkg, crate_id);
// Add dependencies on core / std / alloc for this crate // 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 // 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` // `rust_analyzer` thinks that it should use the one from the `rustc_source`
// instead of the one from `crates.io` // 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); add_dep(crate_graph, *from, name.clone(), to);
} }
} }
@ -1427,7 +1464,7 @@ fn handle_rustc_crates(
} }
fn add_target_crate_root( fn add_target_crate_root(
crate_graph: &mut CrateGraph, crate_graph: &mut CrateGraphBuilder,
proc_macros: &mut ProcMacroPaths, proc_macros: &mut ProcMacroPaths,
cargo: &CargoWorkspace, cargo: &CargoWorkspace,
pkg: &PackageData, pkg: &PackageData,
@ -1437,7 +1474,8 @@ fn add_target_crate_root(
cargo_name: &str, cargo_name: &str,
kind: TargetKind, kind: TargetKind,
origin: CrateOrigin, origin: CrateOrigin,
) -> CrateId { crate_ws_data: Arc<CrateWorkspaceData>,
) -> CrateBuilderId {
let edition = pkg.edition; let edition = pkg.edition;
let potential_cfg_options = if pkg.features.is_empty() { let potential_cfg_options = if pkg.features.is_empty() {
None None
@ -1474,7 +1512,7 @@ fn add_target_crate_root(
Some(CrateDisplayName::from_canonical_name(cargo_name)), Some(CrateDisplayName::from_canonical_name(cargo_name)),
Some(pkg.version.to_string()), Some(pkg.version.to_string()),
Arc::new(cfg_options), Arc::new(cfg_options),
potential_cfg_options.map(Arc::new), potential_cfg_options,
env, env,
origin, origin,
matches!(kind, TargetKind::Lib { is_proc_macro: true }), matches!(kind, TargetKind::Lib { is_proc_macro: true }),
@ -1483,6 +1521,7 @@ fn add_target_crate_root(
} else { } else {
pkg.manifest.parent().to_path_buf() pkg.manifest.parent().to_path_buf()
}), }),
crate_ws_data,
); );
if let TargetKind::Lib { is_proc_macro: true } = kind { if let TargetKind::Lib { is_proc_macro: true } = kind {
let proc_macro = match build_data { let proc_macro = match build_data {
@ -1503,12 +1542,12 @@ fn add_target_crate_root(
#[derive(Default, Debug)] #[derive(Default, Debug)]
struct SysrootPublicDeps { struct SysrootPublicDeps {
deps: Vec<(CrateName, CrateId, bool)>, deps: Vec<(CrateName, CrateBuilderId, bool)>,
} }
impl SysrootPublicDeps { impl SysrootPublicDeps {
/// Makes `from` depend on the public sysroot crates. /// 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 { for (name, krate, prelude) in &self.deps {
add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude, true); add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude, true);
} }
@ -1516,10 +1555,10 @@ impl SysrootPublicDeps {
} }
fn extend_crate_graph_with_sysroot( fn extend_crate_graph_with_sysroot(
crate_graph: &mut CrateGraph, crate_graph: &mut CrateGraphBuilder,
mut sysroot_crate_graph: CrateGraph, mut sysroot_crate_graph: CrateGraphBuilder,
mut sysroot_proc_macros: ProcMacroPaths, mut sysroot_proc_macros: ProcMacroPaths,
) -> (SysrootPublicDeps, Option<CrateId>) { ) -> (SysrootPublicDeps, Option<CrateBuilderId>) {
let mut pub_deps = vec![]; let mut pub_deps = vec![];
let mut libproc_macro = None; let mut libproc_macro = None;
let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]); 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. // uninject `test` flag so `core` keeps working.
Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone()); Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
// patch the origin // patch the origin
if c.origin.is_local() { if c.basic.origin.is_local() {
let lang_crate = LangCrateOrigin::from( 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 { match lang_crate {
LangCrateOrigin::Test LangCrateOrigin::Test
| LangCrateOrigin::Alloc | LangCrateOrigin::Alloc
@ -1579,11 +1618,12 @@ fn extend_crate_graph_with_sysroot(
} }
fn sysroot_to_crate_graph( fn sysroot_to_crate_graph(
crate_graph: &mut CrateGraph, crate_graph: &mut CrateGraphBuilder,
sysroot: &Sysroot, sysroot: &Sysroot,
rustc_cfg: Vec<CfgAtom>, rustc_cfg: Vec<CfgAtom>,
load: FileLoader<'_>, load: FileLoader<'_>,
) -> (SysrootPublicDeps, Option<CrateId>) { crate_ws_data: Arc<CrateWorkspaceData>,
) -> (SysrootPublicDeps, Option<CrateBuilderId>) {
let _p = tracing::info_span!("sysroot_to_crate_graph").entered(); let _p = tracing::info_span!("sysroot_to_crate_graph").entered();
match sysroot.workspace() { match sysroot.workspace() {
RustLibSrcWorkspace::Workspace(cargo) => { RustLibSrcWorkspace::Workspace(cargo) => {
@ -1605,6 +1645,7 @@ fn sysroot_to_crate_graph(
}, },
&WorkspaceBuildScripts::default(), &WorkspaceBuildScripts::default(),
false, false,
crate_ws_data,
); );
extend_crate_graph_with_sysroot(crate_graph, cg, pm) extend_crate_graph_with_sysroot(crate_graph, cg, pm)
@ -1627,6 +1668,7 @@ fn sysroot_to_crate_graph(
..Default::default() ..Default::default()
}, },
false, false,
crate_ws_data,
); );
extend_crate_graph_with_sysroot(crate_graph, cg, pm) 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.insert_atom(sym::miri.clone());
cfg_options cfg_options
}); });
let sysroot_crates: FxHashMap<crate::sysroot::stitched::RustLibSrcCrate, CrateId> = let sysroot_crates: FxHashMap<
stitched crate::sysroot::stitched::RustLibSrcCrate,
.crates() CrateBuilderId,
.filter_map(|krate| { > = stitched
let file_id = load(&stitched[krate].root)?; .crates()
.filter_map(|krate| {
let file_id = load(&stitched[krate].root)?;
let display_name = let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name);
CrateDisplayName::from_canonical_name(&stitched[krate].name); let crate_id = crate_graph.add_crate_root(
let crate_id = crate_graph.add_crate_root( file_id,
file_id, Edition::CURRENT_FIXME,
Edition::CURRENT_FIXME, Some(display_name),
Some(display_name), None,
None, cfg_options.clone(),
cfg_options.clone(), None,
None, Env::default(),
Env::default(), CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)), false,
false, None,
None, crate_ws_data.clone(),
); );
Some((krate, crate_id)) Some((krate, crate_id))
}) })
.collect(); .collect();
for from in stitched.crates() { for from in stitched.crates() {
for &to in stitched[from].deps.iter() { 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) { fn add_dep(
add_dep_inner(graph, from, Dependency::new(name, to)) graph: &mut CrateGraphBuilder,
from: CrateBuilderId,
name: CrateName,
to: CrateBuilderId,
) {
add_dep_inner(graph, from, DependencyBuilder::new(name, to))
} }
fn add_dep_with_prelude( fn add_dep_with_prelude(
graph: &mut CrateGraph, graph: &mut CrateGraphBuilder,
from: CrateId, from: CrateBuilderId,
name: CrateName, name: CrateName,
to: CrateId, to: CrateBuilderId,
prelude: bool, prelude: bool,
sysroot: 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( add_dep_with_prelude(
crate_graph, crate_graph,
from, 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) { if let Err(err) = graph.add_dep(from, dep) {
tracing::warn!("{}", err) tracing::warn!("{}", err)
} }

View file

@ -1,20 +1,47 @@
{ {
0: CrateData { 0: CrateBuilder {
root_file_id: FileId( basic: CrateData {
1, root_file_id: FileId(
), 1,
edition: Edition2018, ),
version: Some( edition: Edition2018,
"0.1.0", dependencies: [
), Dependency {
display_name: Some( crate_id: Idx::<CrateBuilder>(4),
CrateDisplayName { name: CrateName(
crate_name: CrateName( "libc",
"hello_world", ),
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( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
@ -22,7 +49,6 @@
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -44,45 +70,64 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(4), "target_data_layout not loaded",
name: CrateName( ),
"libc", toolchain: None,
},
},
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",
), ),
prelude: true,
sysroot: false,
}, },
], is_proc_macro: false,
origin: Local { proc_macro_cwd: Some(
repo: None, AbsPathBuf(
name: Some( "$ROOT$hello-world",
"hello-world", ),
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
1: CrateData { crate_name: CrateName(
root_file_id: FileId( "hello_world",
2, ),
), canonical_name: "hello-world",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"hello_world",
),
canonical_name: "hello-world",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
@ -90,7 +135,6 @@
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -112,53 +156,64 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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 { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$ROOT$hello-world",
), ),
prelude: true,
sysroot: false,
},
],
origin: Local {
repo: None,
name: Some(
"hello-world",
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
2: CrateData { crate_name: CrateName(
root_file_id: FileId( "an_example",
3, ),
), canonical_name: "an-example",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"an_example",
),
canonical_name: "an-example",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
@ -166,7 +221,6 @@
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -188,53 +242,64 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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 { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$ROOT$hello-world",
), ),
prelude: true,
sysroot: false,
},
],
origin: Local {
repo: None,
name: Some(
"hello-world",
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
3: CrateData { crate_name: CrateName(
root_file_id: FileId( "it",
4, ),
), canonical_name: "it",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"it",
),
canonical_name: "it",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
@ -242,7 +307,6 @@
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -264,53 +328,60 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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, name: "libc",
sysroot: false,
}, },
Dependency { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$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, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.2.98",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
4: CrateData { crate_name: CrateName(
root_file_id: FileId( "libc",
5, ),
), canonical_name: "libc",
edition: Edition2015, },
version: Some( ),
"0.2.98", potential_cfg_options: Some(
), CfgOptions(
display_name: Some( [
CrateDisplayName { "feature=align",
crate_name: CrateName( "feature=const-extern-fn",
"libc", "feature=default",
"feature=extra_traits",
"feature=rustc-dep-of-std",
"feature=std",
"feature=use_std",
"true",
],
), ),
canonical_name: "libc", ),
}, },
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"feature=default", "feature=default",
@ -318,20 +389,6 @@
"true", "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 { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -353,18 +410,11 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [], ws_data: CrateWorkspaceData {
origin: Library { data_layout: Err(
repo: Some( "target_data_layout not loaded",
"https://github.com/rust-lang/libc",
), ),
name: "libc", toolchain: None,
}, },
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
),
}, },
} }

View file

@ -1,20 +1,47 @@
{ {
0: CrateData { 0: CrateBuilder {
root_file_id: FileId( basic: CrateData {
1, root_file_id: FileId(
), 1,
edition: Edition2018, ),
version: Some( edition: Edition2018,
"0.1.0", dependencies: [
), Dependency {
display_name: Some( crate_id: Idx::<CrateBuilder>(4),
CrateDisplayName { name: CrateName(
crate_name: CrateName( "libc",
"hello_world", ),
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( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
@ -22,7 +49,6 @@
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -44,45 +70,64 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(4), "target_data_layout not loaded",
name: CrateName( ),
"libc", toolchain: None,
},
},
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",
), ),
prelude: true,
sysroot: false,
}, },
], is_proc_macro: false,
origin: Local { proc_macro_cwd: Some(
repo: None, AbsPathBuf(
name: Some( "$ROOT$hello-world",
"hello-world", ),
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
1: CrateData { crate_name: CrateName(
root_file_id: FileId( "hello_world",
2, ),
), canonical_name: "hello-world",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"hello_world",
),
canonical_name: "hello-world",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
@ -90,7 +135,6 @@
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -112,53 +156,64 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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 { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$ROOT$hello-world",
), ),
prelude: true,
sysroot: false,
},
],
origin: Local {
repo: None,
name: Some(
"hello-world",
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
2: CrateData { crate_name: CrateName(
root_file_id: FileId( "an_example",
3, ),
), canonical_name: "an-example",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"an_example",
),
canonical_name: "an-example",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
@ -166,7 +221,6 @@
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -188,53 +242,64 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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 { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$ROOT$hello-world",
), ),
prelude: true,
sysroot: false,
},
],
origin: Local {
repo: None,
name: Some(
"hello-world",
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
3: CrateData { crate_name: CrateName(
root_file_id: FileId( "it",
4, ),
), canonical_name: "it",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"it",
),
canonical_name: "it",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
@ -242,7 +307,6 @@
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -264,53 +328,60 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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, name: "libc",
sysroot: false,
}, },
Dependency { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$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, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.2.98",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
4: CrateData { crate_name: CrateName(
root_file_id: FileId( "libc",
5, ),
), canonical_name: "libc",
edition: Edition2015, },
version: Some( ),
"0.2.98", potential_cfg_options: Some(
), CfgOptions(
display_name: Some( [
CrateDisplayName { "feature=align",
crate_name: CrateName( "feature=const-extern-fn",
"libc", "feature=default",
"feature=extra_traits",
"feature=rustc-dep-of-std",
"feature=std",
"feature=use_std",
"true",
],
), ),
canonical_name: "libc", ),
}, },
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"feature=default", "feature=default",
@ -318,20 +389,6 @@
"true", "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 { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -353,18 +410,11 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [], ws_data: CrateWorkspaceData {
origin: Library { data_layout: Err(
repo: Some( "target_data_layout not loaded",
"https://github.com/rust-lang/libc",
), ),
name: "libc", toolchain: None,
}, },
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
),
}, },
} }

View file

@ -1,27 +1,53 @@
{ {
0: CrateData { 0: CrateBuilder {
root_file_id: FileId( basic: CrateData {
1, root_file_id: FileId(
), 1,
edition: Edition2018, ),
version: Some( edition: Edition2018,
"0.1.0", dependencies: [
), Dependency {
display_name: Some( crate_id: Idx::<CrateBuilder>(4),
CrateDisplayName { name: CrateName(
crate_name: CrateName( "libc",
"hello_world", ),
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( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -43,52 +69,70 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(4), "target_data_layout not loaded",
name: CrateName( ),
"libc", toolchain: None,
},
},
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",
), ),
prelude: true,
sysroot: false,
}, },
], is_proc_macro: false,
origin: Local { proc_macro_cwd: Some(
repo: None, AbsPathBuf(
name: Some( "$ROOT$hello-world",
"hello-world", ),
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
1: CrateData { crate_name: CrateName(
root_file_id: FileId( "hello_world",
2, ),
), canonical_name: "hello-world",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"hello_world",
),
canonical_name: "hello-world",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -110,60 +154,70 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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 { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$ROOT$hello-world",
), ),
prelude: true,
sysroot: false,
},
],
origin: Local {
repo: None,
name: Some(
"hello-world",
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
2: CrateData { crate_name: CrateName(
root_file_id: FileId( "an_example",
3, ),
), canonical_name: "an-example",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"an_example",
),
canonical_name: "an-example",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -185,60 +239,70 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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 { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$ROOT$hello-world",
), ),
prelude: true,
sysroot: false,
},
],
origin: Local {
repo: None,
name: Some(
"hello-world",
), ),
}, },
is_proc_macro: false, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.1.0",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
3: CrateData { crate_name: CrateName(
root_file_id: FileId( "it",
4, ),
), canonical_name: "it",
edition: Edition2018, },
version: Some( ),
"0.1.0", potential_cfg_options: None,
), },
display_name: Some(
CrateDisplayName {
crate_name: CrateName(
"it",
),
canonical_name: "it",
},
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"rust_analyzer", "rust_analyzer",
"true", "true",
], ],
), ),
potential_cfg_options: None,
env: Env { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -260,53 +324,60 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [ ws_data: CrateWorkspaceData {
Dependency { data_layout: Err(
crate_id: Idx::<CrateData>(0), "target_data_layout not loaded",
name: CrateName( ),
"hello_world", 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, name: "libc",
sysroot: false,
}, },
Dependency { is_proc_macro: false,
crate_id: Idx::<CrateData>(4), proc_macro_cwd: Some(
name: CrateName( AbsPathBuf(
"libc", "$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, extra: ExtraCrateData {
proc_macro_cwd: Some( version: Some(
AbsPathBuf( "0.2.98",
"$ROOT$hello-world",
), ),
), display_name: Some(
}, CrateDisplayName {
4: CrateData { crate_name: CrateName(
root_file_id: FileId( "libc",
5, ),
), canonical_name: "libc",
edition: Edition2015, },
version: Some( ),
"0.2.98", potential_cfg_options: Some(
), CfgOptions(
display_name: Some( [
CrateDisplayName { "feature=align",
crate_name: CrateName( "feature=const-extern-fn",
"libc", "feature=default",
"feature=extra_traits",
"feature=rustc-dep-of-std",
"feature=std",
"feature=use_std",
"true",
],
), ),
canonical_name: "libc", ),
}, },
),
cfg_options: CfgOptions( cfg_options: CfgOptions(
[ [
"feature=default", "feature=default",
@ -314,20 +385,6 @@
"true", "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 { env: Env {
entries: { entries: {
"CARGO": "$CARGO$", "CARGO": "$CARGO$",
@ -349,18 +406,11 @@
"CARGO_PKG_VERSION_PRE": "", "CARGO_PKG_VERSION_PRE": "",
}, },
}, },
dependencies: [], ws_data: CrateWorkspaceData {
origin: Library { data_layout: Err(
repo: Some( "target_data_layout not loaded",
"https://github.com/rust-lang/libc",
), ),
name: "libc", toolchain: None,
}, },
is_proc_macro: false,
proc_macro_cwd: Some(
AbsPathBuf(
"$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
),
),
}, },
} }

Some files were not shown because too many files have changed in this diff Show more