diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index 19f745109..19cb4be6c 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -19,7 +19,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use tokio::sync::mpsc::{self, Receiver, Sender}; use tokio::sync::oneshot; use tokio_stream::wrappers::ReceiverStream; -use tracing::{debug, instrument, trace, warn, Level}; +use tracing::{debug, info, instrument, trace, warn, Level}; use distribution_types::{ BuiltDist, CompatibleDist, Dist, DistributionMetadata, IncompatibleDist, IncompatibleSource, @@ -388,6 +388,27 @@ impl ResolverState ResolverState 1 { + info!( + "Solved your requirements for {} environments", + resolutions.len() + ); + } for resolution in resolutions { + if let Some(markers) = resolution.markers.fork_markers() { + debug!( + "Distinct solution for ({markers}) with {} packages", + resolution.nodes.len() + ); + } combined.union(resolution); } Self::trace_resolution(&combined); @@ -2388,6 +2421,7 @@ impl ForkState { nodes: packages, edges: dependencies, pins: self.pins, + markers: self.markers, } } } @@ -2396,7 +2430,7 @@ impl ForkState { /// /// Each package can have multiple versions and each edge between two packages can have multiple /// version specifiers to support diverging versions and requirements in different forks. -#[derive(Debug, Default)] +#[derive(Debug)] pub(crate) struct Resolution { pub(crate) nodes: FxHashMap>, /// The directed connections between the nodes, where the marker is the node weight. We don't @@ -2404,6 +2438,8 @@ pub(crate) struct Resolution { pub(crate) edges: FxHashSet, /// Map each package name, version tuple from `packages` to a distribution. pub(crate) pins: FilePins, + /// The marker setting this resolution was found under. + pub(crate) markers: ResolverMarkers, } /// Package representation we used during resolution where each extra and also the dev-dependencies @@ -2436,6 +2472,30 @@ pub(crate) struct ResolutionDependencyEdge { } impl Resolution { + fn universal() -> Self { + Self { + nodes: FxHashMap::default(), + edges: FxHashSet::default(), + pins: FilePins::default(), + markers: ResolverMarkers::Universal, + } + } +} + +impl Resolution { + /// Whether we got two identical resolutions in two separate forks. + /// + /// Ignores pins since the which distribution we prioritized for each version doesn't matter. + fn same_graph(&self, other: &Self) -> bool { + // TODO(konsti): The edges being equal is not a requirement for the graph being equal. While + // an exact solution is too much here, we should ignore different in edges that point to + // nodes that are always installed. Example: root requires foo, root requires bar. bar + // forks, and one for the branches has bar -> foo while the other doesn't. The resolution + // is still the same graph since the presence or absence of the bar -> foo edge cannot + // change which packages and versions are installed. + self.nodes == other.nodes && self.edges == other.edges + } + fn union(&mut self, other: Resolution) { for (other_package, other_versions) in other.nodes { self.nodes diff --git a/crates/uv-resolver/src/resolver/resolver_markers.rs b/crates/uv-resolver/src/resolver/resolver_markers.rs index 5bbe5321e..5b3d213fd 100644 --- a/crates/uv-resolver/src/resolver/resolver_markers.rs +++ b/crates/uv-resolver/src/resolver/resolver_markers.rs @@ -28,13 +28,20 @@ impl ResolverMarkers { } } - /// If solving for a specific environment, return this environment + /// If solving for a specific environment, return this environment. pub fn marker_environment(&self) -> Option<&MarkerEnvironment> { match self { ResolverMarkers::Universal | ResolverMarkers::Fork(_) => None, ResolverMarkers::SpecificEnvironment(env) => Some(env), } } + /// If solving a fork, return that fork's markers. + pub fn fork_markers(&self) -> Option<&MarkerTree> { + match self { + ResolverMarkers::SpecificEnvironment(_) | ResolverMarkers::Universal => None, + ResolverMarkers::Fork(markers) => Some(markers), + } + } } impl Display for ResolverMarkers {