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

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

View file

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

View file

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

View file

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