deps.into_iter()
}
+ /// Returns an iterator over all transitive reverse dependencies of the given crate.
+ pub fn transitive_reverse_dependencies(
+ &self,
+ of: CrateId,
+ ) -> impl Iterator<Item = CrateId> + '_ {
+ let mut worklist = vec![of];
+ let mut rev_deps = FxHashSet::default();
+ let mut inverted_graph = FxHashMap::default();
+ self.arena.iter().for_each(|(&krate, data)| {
+ data.dependencies.iter().for_each(|dep| {
+ inverted_graph.entry(dep.crate_id).or_insert_with(Vec::default).push(krate)
+ })
+ });
+
+ while let Some(krate) = worklist.pop() {
+ if !rev_deps.insert(krate) {
+ continue;
+ }
+
+ if let Some(rev_deps) = inverted_graph.get(&krate) {
+ worklist.extend(rev_deps);
+ }
+ }
+
+ rev_deps.remove(&of);
+ rev_deps.into_iter()
+ }
+
/// Returns all crates in the graph, sorted in topological order (ie. dependencies of a crate
/// come before the crate itself).
pub fn crates_in_topological_order(&self) -> Vec<CrateId> {
InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, Ty,
TyDefId, TyKind, TyVariableKind,
};
+use itertools::Itertools;
use rustc_hash::FxHashSet;
use stdx::{format_to, impl_from};
use syntax::{
.collect()
}
- // FIXME: add `transitive_reverse_dependencies`.
pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
let crate_graph = db.crate_graph();
crate_graph
.collect()
}
+ pub fn transitive_reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
+ db.crate_graph()
+ .transitive_reverse_dependencies(self.id)
+ .into_iter()
+ .map(|id| Crate { id })
+ .collect()
+ }
+
pub fn root_module(self, db: &dyn HirDatabase) -> Module {
let def_map = db.crate_def_map(self.id);
Module { id: def_map.module_id(def_map.root()) }
};
let mut all = Vec::new();
- def_crates.into_iter().for_each(|id| {
+ def_crates.iter().for_each(|&id| {
all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter))
});
let fp = TyFingerprint::for_impl(&ty.value);
- for id in db.crate_graph().iter() {
+ for id in def_crates
+ .iter()
+ .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
+ .map(|Crate { id }| id)
+ .chain(def_crates.iter().copied())
+ .unique()
+ {
match fp {
Some(fp) => all.extend(
db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter),
pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
let krate = trait_.module(db).krate();
let mut all = Vec::new();
- for Crate { id } in krate.reverse_dependencies(db).into_iter().chain(Some(krate)) {
+ for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter().chain(Some(krate))
+ {
let impls = db.trait_impls_in_crate(id);
all.extend(impls.for_trait(trait_.id).map(Self::from))
}
let mut res = source_root.iter().map(|id| (id, None)).collect::<FxHashMap<_, _>>();
let krate = module.krate();
- for rev_dep in krate.reverse_dependencies(db) {
+ for rev_dep in krate.transitive_reverse_dependencies(db) {
let root_file = rev_dep.root_file(db);
let source_root_id = db.file_source_root(root_file);
let source_root = db.source_root(source_root_id);