diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs index ffd82d5043..f9e69a0326 100644 --- a/crates/base-db/src/input.rs +++ b/crates/base-db/src/input.rs @@ -460,6 +460,32 @@ pub struct Crate { pub env: Env, } +#[salsa::tracked] +impl Crate { + /// Returns an iterator over all transitive dependencies of the given crate, + /// including the crate itself. + /// + /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. + #[salsa::tracked(returns(deref))] + pub fn transitive_deps(self, db: &dyn salsa::Database) -> Box<[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![self]; + let mut deps_seen = FxHashSet::default(); + let mut deps = Vec::new(); + + while let Some(krate) = worklist.pop() { + if !deps_seen.insert(krate) { + continue; + } + deps.push(krate); + + worklist.extend(krate.data(db).dependencies.iter().map(|dep| dep.crate_id)); + } + deps.into_boxed_slice() + } +} + /// The mapping from [`UniqueCrateData`] to their [`Crate`] input. #[derive(Debug, Default)] pub struct CratesMap(DashMap>); diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 90e0aa9065..4d226f5cbf 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -257,13 +257,6 @@ pub trait RootQueryDb: SourceDatabase + salsa::Database { #[salsa::input] fn all_crates(&self) -> Arc>; - /// Returns an iterator over all transitive dependencies of the given crate, - /// including the crate itself. - /// - /// **Warning**: do not use this query in `hir-*` crates! It kills incrementality across crate metadata modifications. - #[salsa::transparent] - fn transitive_deps(&self, crate_id: Crate) -> FxHashSet; - /// Returns all transitive reverse dependencies of the given crate, /// including the crate itself. /// @@ -273,23 +266,6 @@ pub trait RootQueryDb: SourceDatabase + salsa::Database { fn transitive_rev_deps(&self, of: Crate) -> FxHashSet; } -fn transitive_deps(db: &dyn SourceDatabase, crate_id: Crate) -> FxHashSet { - // 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_macros::db] pub trait SourceDatabase: salsa::Database { /// Text of the file. diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index 4e1d598623..925a078e82 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -273,10 +273,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase { // endregion:visibilities - #[salsa::invoke(crate::lang_item::notable_traits_in_deps)] - fn notable_traits_in_deps(&self, krate: Crate) -> Arc<[Arc<[TraitId]>]>; #[salsa::invoke(crate::lang_item::crate_notable_traits)] - fn crate_notable_traits(&self, krate: Crate) -> Option>; + #[salsa::transparent] + fn crate_notable_traits(&self, krate: Crate) -> Option<&[TraitId]>; #[salsa::invoke(crate_supports_no_std)] fn crate_supports_no_std(&self, crate_id: Crate) -> bool; diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs index df0705bf90..91a90f6d84 100644 --- a/crates/hir-def/src/lang_item.rs +++ b/crates/hir-def/src/lang_item.rs @@ -5,7 +5,6 @@ use hir_expand::name::Name; use intern::{Symbol, sym}; use rustc_hash::FxHashMap; -use triomphe::Arc; use crate::{ AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId, @@ -223,16 +222,8 @@ pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option Arc<[Arc<[TraitId]>]> { - let _p = tracing::info_span!("notable_traits_in_deps", ?krate).entered(); - Arc::from_iter( - db.transitive_deps(krate).into_iter().filter_map(|krate| db.crate_notable_traits(krate)), - ) -} - -pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option> { - let _p = tracing::info_span!("crate_notable_traits", ?krate).entered(); - +#[salsa::tracked(returns(as_deref))] +pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option> { let mut traits = Vec::new(); let crate_def_map = crate_def_map(db, krate); diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs index 522d12d012..aebb6def93 100644 --- a/crates/hir-ty/src/drop.rs +++ b/crates/hir-ty/src/drop.rs @@ -28,10 +28,10 @@ fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool { }; let impls = match module.containing_block() { Some(block) => match TraitImpls::for_block(db, block) { - Some(it) => it, + Some(it) => &**it, None => return false, }, - None => &**TraitImpls::for_crate(db, module.krate()), + None => TraitImpls::for_crate(db, module.krate()), }; !impls.for_trait_and_self_ty(drop_trait, &SimplifiedType::Adt(adt.into())).is_empty() } diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 799bfb3b4d..59299f2c35 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -687,7 +687,7 @@ impl TraitImpls { #[salsa::tracked(returns(ref))] pub fn for_crate_and_deps(db: &dyn HirDatabase, krate: Crate) -> Box<[Arc]> { - db.transitive_deps(krate).iter().map(|&dep| Self::for_crate(db, dep).clone()).collect() + krate.transitive_deps(db).iter().map(|&dep| Self::for_crate(db, dep).clone()).collect() } } diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs index e98e5e4828..a381f929e8 100644 --- a/crates/hir-ty/src/tests/incremental.rs +++ b/crates/hir-ty/src/tests/incremental.rs @@ -613,6 +613,7 @@ fn main() { "impl_signature_with_source_map_shim", "callable_item_signature_shim", "TraitImpls::for_crate_and_deps_", + "Crate::transitive_deps_", "TraitImpls::for_crate_", "impl_trait_with_diagnostics_shim", "impl_self_ty_with_diagnostics_shim", diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 82c6cf7442..b2fa4b6b20 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -250,6 +250,14 @@ impl Crate { db.transitive_rev_deps(self.id).into_iter().map(|id| Crate { id }) } + pub fn notable_traits_in_deps(self, db: &dyn HirDatabase) -> impl Iterator { + self.id + .transitive_deps(db) + .into_iter() + .filter_map(|&krate| db.crate_notable_traits(krate)) + .flatten() + } + pub fn root_module(self) -> Module { Module { id: CrateRootModuleId::from(self.id).into() } } diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index e1d18b0c41..fa4b4b6d24 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -8,7 +8,6 @@ use std::{iter, ops::Not}; use either::Either; use hir::{ DisplayTarget, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics, - db::DefDatabase, }; use ide_db::{ FileRange, FxIndexSet, MiniCore, Ranker, RootDatabase, @@ -522,9 +521,8 @@ fn notable_traits<'db>( return Vec::new(); } - db.notable_traits_in_deps(ty.krate(db).into()) - .iter() - .flat_map(|it| &**it) + ty.krate(db) + .notable_traits_in_deps(db) .filter_map(move |&trait_| { let trait_ = trait_.into(); ty.impls_trait(db, trait_, &[]).then(|| {