diff --git a/src/cargo/core/resolver/context.rs b/src/cargo/core/resolver/context.rs index 08c289d9f8b..d1bae02f8fa 100644 --- a/src/cargo/core/resolver/context.rs +++ b/src/cargo/core/resolver/context.rs @@ -1,13 +1,12 @@ use super::dep_cache::RegistryQueryer; use super::errors::ActivateResult; -use super::types::{ConflictMap, ConflictReason, FeaturesSet, ResolveOpts}; +use super::types::{ActivationsKey, ConflictMap, ConflictReason, FeaturesSet, ResolveOpts}; use super::RequestedFeatures; -use crate::core::{Dependency, PackageId, SourceId, Summary}; +use crate::core::{Dependency, PackageId, Summary}; use crate::util::interning::InternedString; use crate::util::Graph; use anyhow::format_err; use std::collections::HashMap; -use std::num::NonZeroU64; use tracing::debug; // A `Context` is basically a bunch of local resolution information which is @@ -39,39 +38,9 @@ pub type ContextAge = usize; /// By storing this in a hash map we ensure that there is only one /// semver compatible version of each crate. /// This all so stores the `ContextAge`. -pub type ActivationsKey = (InternedString, SourceId, SemverCompatibility); - pub type Activations = im_rc::HashMap; -/// A type that represents when cargo treats two Versions as compatible. -/// Versions `a` and `b` are compatible if their left-most nonzero digit is the -/// same. -#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)] -pub enum SemverCompatibility { - Major(NonZeroU64), - Minor(NonZeroU64), - Patch(u64), -} - -impl From<&semver::Version> for SemverCompatibility { - fn from(ver: &semver::Version) -> Self { - if let Some(m) = NonZeroU64::new(ver.major) { - return SemverCompatibility::Major(m); - } - if let Some(m) = NonZeroU64::new(ver.minor) { - return SemverCompatibility::Minor(m); - } - SemverCompatibility::Patch(ver.patch) - } -} - -impl PackageId { - pub fn as_activations_key(self) -> ActivationsKey { - (self.name(), self.source_id(), self.version().into()) - } -} - impl ResolverContext { pub fn new() -> ResolverContext { ResolverContext { @@ -137,7 +106,8 @@ impl ResolverContext { // versions came from a `[patch]` source. if let Some((_, dep)) = parent { if dep.source_id() != id.source_id() { - let key = (id.name(), dep.source_id(), id.version().into()); + let key = + ActivationsKey::new(id.name(), id.version().into(), dep.source_id()); let prev = self.activations.insert(key, (summary.clone(), age)); if let Some((previous_summary, _)) = prev { return Err( diff --git a/src/cargo/core/resolver/types.rs b/src/cargo/core/resolver/types.rs index 2dc5d44ca33..2248d79bbf3 100644 --- a/src/cargo/core/resolver/types.rs +++ b/src/cargo/core/resolver/types.rs @@ -1,10 +1,11 @@ use super::features::{CliFeatures, RequestedFeatures}; -use crate::core::{Dependency, PackageId, Summary}; +use crate::core::{Dependency, PackageId, SourceId, Summary}; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; use crate::util::GlobalContext; use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet}; +use std::num::NonZeroU64; use std::rc::Rc; use std::time::{Duration, Instant}; @@ -163,6 +164,58 @@ impl ResolveOpts { } } +/// A key that when stord in a hash map ensures that there is only one +/// semver compatible version of each crate. +/// Find the activated version of a crate based on the name, source, and semver compatibility. +#[derive(Clone, PartialEq, Eq, Debug, Ord, PartialOrd)] +pub struct ActivationsKey(InternedString, SemverCompatibility, SourceId); + +impl ActivationsKey { + pub fn new( + name: InternedString, + ver: SemverCompatibility, + source_id: SourceId, + ) -> ActivationsKey { + ActivationsKey(name, ver, source_id) + } +} + +impl std::hash::Hash for ActivationsKey { + fn hash(&self, state: &mut H) { + self.0.hash(state); + self.1.hash(state); + // self.2.hash(state); // Packages that only differ by SourceId are rare enough to not be worth hashing + } +} + +/// A type that represents when cargo treats two Versions as compatible. +/// Versions `a` and `b` are compatible if their left-most nonzero digit is the +/// same. +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, PartialOrd, Ord)] +pub enum SemverCompatibility { + Major(NonZeroU64), + Minor(NonZeroU64), + Patch(u64), +} + +impl From<&semver::Version> for SemverCompatibility { + fn from(ver: &semver::Version) -> Self { + if let Some(m) = NonZeroU64::new(ver.major) { + return SemverCompatibility::Major(m); + } + if let Some(m) = NonZeroU64::new(ver.minor) { + return SemverCompatibility::Minor(m); + } + SemverCompatibility::Patch(ver.patch) + } +} + +impl PackageId { + pub fn as_activations_key(self) -> ActivationsKey { + ActivationsKey(self.name(), self.version().into(), self.source_id()) + } +} + #[derive(Clone)] pub struct DepsFrame { pub parent: Summary,