diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index 1a44a812d32..7924f8cb07f 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; use std::num::NonZeroU64; -use std::rc::Rc; use anyhow::format_err; use log::debug; @@ -35,7 +34,7 @@ pub struct Context { /// a way to look up for a package in activations what packages required it /// and all of the exact deps that it fulfilled. - pub parents: Graph>>, + pub parents: Graph>, } /// When backtracking it can be useful to know how far back to go. @@ -255,8 +254,8 @@ impl Context { .collect() } - pub fn graph(&self) -> Graph> { - let mut graph: Graph> = Graph::new(); + pub fn graph(&self) -> Graph> { + let mut graph: Graph> = Graph::new(); self.activations .values() .for_each(|(r, _)| graph.add(r.package_id())); @@ -265,14 +264,14 @@ impl Context { for (o, e) in self.parents.edges(i) { let old_link = graph.link(*o, *i); assert!(old_link.is_empty()); - *old_link = e.to_vec(); + *old_link = e.iter().cloned().collect(); } } graph } } -impl Graph>> { +impl Graph> { pub fn parents_of(&self, p: PackageId) -> impl Iterator + '_ { self.edges(&p) .map(|(grand, d)| (*grand, d.iter().any(|x| x.is_public()))) @@ -338,7 +337,7 @@ impl PublicDependency { parent_pid: PackageId, is_public: bool, age: ContextAge, - parents: &Graph>>, + parents: &Graph>, ) { // one tricky part is that `candidate_pid` may already be active and // have public dependencies of its own. So we not only need to mark @@ -383,7 +382,7 @@ impl PublicDependency { b_id: PackageId, parent: PackageId, is_public: bool, - parents: &Graph>>, + parents: &Graph>, ) -> Result< (), ( diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index cf6d3213fb3..22d3f33f6a2 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -609,12 +609,11 @@ fn activate( cx.age += 1; if let Some((parent, dep)) = parent { let parent_pid = parent.package_id(); - Rc::make_mut( - // add a edge from candidate to parent in the parents graph - cx.parents.link(candidate_pid, parent_pid), - ) - // and associate dep with that edge - .push(dep.clone()); + // add a edge from candidate to parent in the parents graph + cx.parents + .link(candidate_pid, parent_pid) + // and associate dep with that edge + .insert(dep.clone()); if let Some(public_dependency) = cx.public_dependency.as_mut() { public_dependency.add_edge( candidate_pid, diff --git a/src/cargo/core/resolver/resolve.rs b/src/cargo/core/resolver/resolve.rs index 91df17b2e18..1b823dc7b9f 100644 --- a/src/cargo/core/resolver/resolve.rs +++ b/src/cargo/core/resolver/resolve.rs @@ -18,7 +18,7 @@ pub struct Resolve { /// A graph, whose vertices are packages and edges are dependency specifications /// from `Cargo.toml`. We need a `Vec` here because the same package /// might be present in both `[dependencies]` and `[build-dependencies]`. - graph: Graph>, + graph: Graph>, /// Replacements from the `[replace]` table. replacements: HashMap, /// Inverted version of `replacements`. @@ -70,7 +70,7 @@ pub enum ResolveVersion { impl Resolve { pub fn new( - graph: Graph>, + graph: Graph>, replacements: HashMap, features: HashMap>, checksums: HashMap>, @@ -264,7 +264,7 @@ unable to verify that `{0}` is the same as when the lockfile was generated self.graph.iter().cloned() } - pub fn deps(&self, pkg: PackageId) -> impl Iterator { + pub fn deps(&self, pkg: PackageId) -> impl Iterator)> { self.deps_not_replaced(pkg) .map(move |(id, deps)| (self.replacement(id).unwrap_or(id), deps)) } @@ -272,10 +272,8 @@ unable to verify that `{0}` is the same as when the lockfile was generated pub fn deps_not_replaced( &self, pkg: PackageId, - ) -> impl Iterator { - self.graph - .edges(&pkg) - .map(|(id, deps)| (*id, deps.as_slice())) + ) -> impl Iterator)> { + self.graph.edges(&pkg).map(|(id, deps)| (*id, deps)) } pub fn replacement(&self, pkg: PackageId) -> Option { @@ -325,8 +323,9 @@ unable to verify that `{0}` is the same as when the lockfile was generated to: PackageId, to_target: &Target, ) -> CargoResult { + let empty_set: HashSet = HashSet::new(); let deps = if from == to { - &[] + &empty_set } else { self.dependencies_listed(from, to) }; @@ -349,7 +348,7 @@ unable to verify that `{0}` is the same as when the lockfile was generated Ok(name) } - fn dependencies_listed(&self, from: PackageId, to: PackageId) -> &[Dependency] { + fn dependencies_listed(&self, from: PackageId, to: PackageId) -> &HashSet { // We've got a dependency on `from` to `to`, but this dependency edge // may be affected by [replace]. If the `to` package is listed as the // target of a replacement (aka the key of a reverse replacement map) diff --git a/src/cargo/ops/cargo_output_metadata.rs b/src/cargo/ops/cargo_output_metadata.rs index 05b68fb7cdf..7892c2cc4ae 100644 --- a/src/cargo/ops/cargo_output_metadata.rs +++ b/src/cargo/ops/cargo_output_metadata.rs @@ -184,11 +184,7 @@ fn build_resolve_graph_r( CompileKind::Host => true, }) .filter_map(|(dep_id, deps)| { - let mut dep_kinds: Vec<_> = deps.iter().map(DepKindInfo::from).collect(); - // Duplicates may appear if the same package is used by different - // members of a workspace with different features selected. - dep_kinds.sort_unstable(); - dep_kinds.dedup(); + let dep_kinds: Vec<_> = deps.iter().map(DepKindInfo::from).collect(); package_map .get(&dep_id) .and_then(|pkg| pkg.targets().iter().find(|t| t.is_lib()))