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

View file

@ -1,10 +1,10 @@
//! A set of high-level utility fixture methods to use in tests.
use std::{iter, mem, str::FromStr, sync};
use std::{mem, str::FromStr, sync};
use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, CrateWorkspaceData, Dependency,
Env, FileChange, FileSet, LangCrateOrigin, RootQueryDb, SourceDatabase, SourceRoot, Version,
VfsPath,
Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData,
DependencyBuilder, Env, FileChange, FileSet, LangCrateOrigin, SourceDatabase, SourceRoot,
Version, VfsPath,
};
use cfg::CfgOptions;
use hir_expand::{
@ -26,6 +26,7 @@ use test_utils::{
extract_range_or_offset, Fixture, FixtureWithProjectMeta, RangeOrOffset, CURSOR_MARKER,
ESCAPED_CURSOR_MARKER,
};
use triomphe::Arc;
pub const WORKSPACE: base_db::SourceRootId = base_db::SourceRootId(0);
@ -101,14 +102,8 @@ pub trait WithFixture: Default + ExpandDatabase + SourceDatabase + 'static {
(db, file_id, range_or_offset)
}
fn test_crate(&self) -> CrateId {
let crate_graph = RootQueryDb::crate_graph(self);
let mut it = crate_graph.iter();
let mut res = it.next().unwrap();
while crate_graph[res].origin.is_lang() {
res = it.next().unwrap();
}
res
fn test_crate(&self) -> Crate {
self.all_crates().iter().copied().find(|&krate| !krate.data(self).origin.is_lang()).unwrap()
}
}
@ -146,7 +141,7 @@ impl ChangeFixture {
let mut source_change = FileChange::new();
let mut files = Vec::new();
let mut crate_graph = CrateGraph::default();
let mut crate_graph = CrateGraphBuilder::default();
let mut crates = FxHashMap::default();
let mut crate_deps = Vec::new();
let mut default_crate_root: Option<FileId> = None;
@ -163,6 +158,9 @@ impl ChangeFixture {
let mut file_position = None;
let crate_ws_data =
Arc::new(CrateWorkspaceData { data_layout: target_data_layout, toolchain });
for entry in fixture {
let mut range_or_offset = None;
let text = if entry.text.contains(CURSOR_MARKER) {
@ -210,11 +208,12 @@ impl ChangeFixture {
Some(crate_name.clone().into()),
version,
From::from(meta.cfg.clone()),
Some(From::from(meta.cfg)),
Some(meta.cfg),
meta.env,
origin,
false,
None,
crate_ws_data.clone(),
);
let prev = crates.insert(crate_name.clone(), crate_id);
assert!(prev.is_none(), "multiple crates with same name: {crate_name}");
@ -249,19 +248,23 @@ impl ChangeFixture {
Some(CrateName::new("ra_test_fixture").unwrap().into()),
None,
From::from(default_cfg.clone()),
Some(From::from(default_cfg)),
Some(default_cfg),
default_env,
CrateOrigin::Local { repo: None, name: None },
false,
None,
crate_ws_data.clone(),
);
} else {
for (from, to, prelude) in crate_deps {
let from_id = crates[&from];
let to_id = crates[&to];
let sysroot = crate_graph[to_id].origin.is_lang();
let sysroot = crate_graph[to_id].basic.origin.is_lang();
crate_graph
.add_dep(from_id, Dependency::with_prelude(to.clone(), to_id, prelude, sysroot))
.add_dep(
from_id,
DependencyBuilder::with_prelude(to.clone(), to_id, prelude, sysroot),
)
.unwrap();
}
}
@ -276,7 +279,7 @@ impl ChangeFixture {
source_change.change_file(core_file, Some(mini_core.source_code()));
let all_crates = crate_graph.crates_in_topological_order();
let all_crates = crate_graph.iter().collect::<Vec<_>>();
let core_crate = crate_graph.add_crate_root(
core_file,
@ -292,13 +295,14 @@ impl ChangeFixture {
CrateOrigin::Lang(LangCrateOrigin::Core),
false,
None,
crate_ws_data.clone(),
);
for krate in all_crates {
crate_graph
.add_dep(
krate,
Dependency::with_prelude(
DependencyBuilder::with_prelude(
CrateName::new("core").unwrap(),
core_crate,
true,
@ -324,7 +328,7 @@ impl ChangeFixture {
source_change.change_file(proc_lib_file, Some(source));
let all_crates = crate_graph.crates_in_topological_order();
let all_crates = crate_graph.iter().collect::<Vec<_>>();
let proc_macros_crate = crate_graph.add_crate_root(
proc_lib_file,
@ -340,6 +344,7 @@ impl ChangeFixture {
CrateOrigin::Local { repo: None, name: None },
true,
None,
crate_ws_data,
);
proc_macros.insert(proc_macros_crate, Ok(proc_macro));
@ -347,7 +352,10 @@ impl ChangeFixture {
crate_graph
.add_dep(
krate,
Dependency::new(CrateName::new("proc_macros").unwrap(), proc_macros_crate),
DependencyBuilder::new(
CrateName::new("proc_macros").unwrap(),
proc_macros_crate,
),
)
.unwrap();
}
@ -359,19 +367,9 @@ impl ChangeFixture {
};
roots.push(root);
let mut change =
ChangeWithProcMacros { source_change, proc_macros: Some(proc_macros.build()) };
let mut change = ChangeWithProcMacros { source_change, proc_macros: Some(proc_macros) };
change.source_change.set_roots(roots);
change.source_change.set_ws_data(
crate_graph
.iter()
.zip(iter::repeat(From::from(CrateWorkspaceData {
data_layout: target_data_layout,
toolchain,
})))
.collect(),
);
change.source_change.set_crate_graph(crate_graph);
ChangeFixture { file_position, files, change }
@ -654,6 +652,10 @@ impl ProcMacroExpander for IdentityProcMacroExpander {
) -> Result<TopSubtree, ProcMacroExpansionError> {
Ok(subtree.clone())
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}
// Expands to a macro_rules! macro, for issue #18089.
@ -685,6 +687,10 @@ impl ProcMacroExpander for Issue18089ProcMacroExpander {
#subtree
})
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}
// Pastes the attribute input as its output
@ -705,6 +711,10 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander {
.cloned()
.ok_or_else(|| ProcMacroExpansionError::Panic("Expected attribute input".into()))
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}
#[derive(Debug)]
@ -736,6 +746,10 @@ impl ProcMacroExpander for Issue18840ProcMacroExpander {
top_subtree_delimiter_mut.close = def_site;
Ok(result)
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}
#[derive(Debug)]
@ -767,6 +781,10 @@ impl ProcMacroExpander for MirrorProcMacroExpander {
traverse(&mut builder, input.iter());
Ok(builder.build())
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}
// Replaces every literal with an empty string literal and every identifier with its first letter,
@ -807,6 +825,10 @@ impl ProcMacroExpander for ShortenProcMacroExpander {
}
}
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}
// Reads ident type within string quotes, for issue #17479.
@ -832,6 +854,10 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander {
#symbol()
})
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}
// Reads ident type within string quotes, for issue #17479.
@ -883,6 +909,10 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander {
}
})
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}
// Reads ident type within string quotes, for issue #17479.
@ -910,4 +940,8 @@ impl ProcMacroExpander for DisallowCfgProcMacroExpander {
}
Ok(subtree.clone())
}
fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
other.as_any().type_id() == std::any::TypeId::of::<Self>()
}
}