From 0cd72d3d658cc5ca22b38c155e1927dbe21ce67e Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 29 Jun 2026 02:29:27 +0000 Subject: [PATCH 1/5] Adapt to IDs-only PubGrub dependencies --- Cargo.lock | 8 ++-- Cargo.toml | 4 +- crates/uv-pep440/src/version_specifier.rs | 12 ++--- crates/uv-pep508/src/marker/algebra.rs | 4 +- crates/uv-pep508/src/marker/tree.rs | 6 +-- crates/uv-resolver/src/error.rs | 4 +- crates/uv-resolver/src/pubgrub/report.rs | 8 ++-- crates/uv-resolver/src/resolver/derivation.rs | 26 +++++++++-- crates/uv-resolver/src/resolver/mod.rs | 45 ++++++++++++++----- 9 files changed, 78 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a1f95980820d..488d9176aaffb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,9 +217,8 @@ dependencies = [ [[package]] name = "astral-pubgrub" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6cb15b4f5096a3a1b41fdc2736a1c33d87c78f34d3c1ec2b669e766edadd559" +version = "0.4.3" +source = "git+https://github.com/astral-sh/pubgrub?rev=446afc9f756253b94df0f9b0f167ec8fba0b3693#446afc9f756253b94df0f9b0f167ec8fba0b3693" dependencies = [ "astral-version-ranges", "indexmap", @@ -293,8 +292,7 @@ dependencies = [ [[package]] name = "astral-version-ranges" version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31979bc305610246d78ac01d63467a12d8454c6e3b8b22b5811d343a1198dfbb" +source = "git+https://github.com/astral-sh/pubgrub?rev=446afc9f756253b94df0f9b0f167ec8fba0b3693#446afc9f756253b94df0f9b0f167ec8fba0b3693" dependencies = [ "smallvec", ] diff --git a/Cargo.toml b/Cargo.toml index 3fe444de5b805..fd3a82e853255 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,7 +189,7 @@ percent-encoding = { version = "2.3.1" } petgraph = { version = "0.8.0" } proc-macro2 = { version = "1.0.86" } procfs = { version = "0.18.0", default-features = false, features = ["flate2"] } -pubgrub = { version = "0.3.3", package = "astral-pubgrub" } +pubgrub = { git = "https://github.com/astral-sh/pubgrub", rev = "446afc9f756253b94df0f9b0f167ec8fba0b3693", package = "astral-pubgrub" } quote = { version = "1.0.37" } rand = { version = "0.9.4" } rayon = { version = "1.10.0" } @@ -289,7 +289,7 @@ unicode-width = { version = "0.2.0" } unscanny = { version = "0.1.0" } url = { version = "2.5.2", features = ["serde"] } uuid = { version = "1.16.0" } -version-ranges = { version = "0.1.3", package = "astral-version-ranges" } +version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "446afc9f756253b94df0f9b0f167ec8fba0b3693", package = "astral-version-ranges" } walkdir = { version = "2.5.0" } webpki-root-certs = { version = "1" } which = { version = "8.0.0", features = ["regex"] } diff --git a/crates/uv-pep440/src/version_specifier.rs b/crates/uv-pep440/src/version_specifier.rs index 02f83da9ccc58..8ea5baa07180e 100644 --- a/crates/uv-pep440/src/version_specifier.rs +++ b/crates/uv-pep440/src/version_specifier.rs @@ -83,7 +83,7 @@ impl VersionSpecifiers { /// /// This function is not applicable to ranges involving pre-release versions. pub fn from_release_only_bounds<'a>( - mut bounds: impl Iterator, &'a Bound)>, + mut bounds: impl Iterator, Bound<&'a Version>)>, ) -> Self { let mut specifiers = Vec::new(); @@ -552,7 +552,7 @@ impl VersionSpecifier { /// /// This function is not applicable to ranges involving pre-release versions. pub fn from_release_only_bounds( - bounds: (&Bound, &Bound), + bounds: (Bound<&Version>, Bound<&Version>), ) -> impl Iterator { let (b1, b2) = match bounds { (Bound::Included(v1), Bound::Included(v2)) if v1 == v2 => { @@ -572,8 +572,8 @@ impl VersionSpecifier { (Some(Self::equals_star_version(version)), None) } _ => ( - Self::from_lower_bound(&Bound::Included(v1.clone())), - Self::from_upper_bound(&Bound::Excluded(v2.clone())), + Self::from_lower_bound(Bound::Included(v1)), + Self::from_upper_bound(Bound::Excluded(v2)), ), } } @@ -584,7 +584,7 @@ impl VersionSpecifier { } /// Returns a version specifier representing the given lower bound. - fn from_lower_bound(bound: &Bound) -> Option { + fn from_lower_bound(bound: Bound<&Version>) -> Option { match bound { Bound::Included(version) => { Some(Self::from_version(Operator::GreaterThanEqual, version.clone()).unwrap()) @@ -597,7 +597,7 @@ impl VersionSpecifier { } /// Returns a version specifier representing the given upper bound. - fn from_upper_bound(bound: &Bound) -> Option { + fn from_upper_bound(bound: Bound<&Version>) -> Option { match bound { Bound::Included(version) => { Some(Self::from_version(Operator::LessThanEqual, version.clone()).unwrap()) diff --git a/crates/uv-pep508/src/marker/algebra.rs b/crates/uv-pep508/src/marker/algebra.rs index df467321292ce..700e9959015cb 100644 --- a/crates/uv-pep508/src/marker/algebra.rs +++ b/crates/uv-pep508/src/marker/algebra.rs @@ -1438,13 +1438,13 @@ impl Edges { // Add the `true` edges. for (start, end) in range.iter() { - let range = Ranges::from_range_bounds((start.clone(), end.clone())); + let range = Ranges::from_range_bounds((start.cloned(), end.cloned())); edges.push((range, NodeId::TRUE)); } // Add the `false` edges. for (start, end) in range.complement().iter() { - let range = Ranges::from_range_bounds((start.clone(), end.clone())); + let range = Ranges::from_range_bounds((start.cloned(), end.cloned())); edges.push((range, NodeId::FALSE)); } diff --git a/crates/uv-pep508/src/marker/tree.rs b/crates/uv-pep508/src/marker/tree.rs index 8da6fde444ce4..3ee4d7dc38472 100644 --- a/crates/uv-pep508/src/marker/tree.rs +++ b/crates/uv-pep508/src/marker/tree.rs @@ -305,7 +305,7 @@ impl MarkerOperator { /// Returns the marker operator and value whose union represents the given range. pub(crate) fn from_bounds( - bounds: (&Bound, &Bound), + bounds: (Bound<&ArcStr>, Bound<&ArcStr>), ) -> impl Iterator { let (b1, b2) = match bounds { (Bound::Included(v1), Bound::Included(v2)) if v1 == v2 => { @@ -321,7 +321,7 @@ impl MarkerOperator { } /// Returns a value specifier representing the given lower bound. - fn from_lower_bound(bound: &Bound) -> Option<(Self, ArcStr)> { + fn from_lower_bound(bound: Bound<&ArcStr>) -> Option<(Self, ArcStr)> { match bound { Bound::Included(value) => Some((Self::GreaterEqual, value.clone())), Bound::Excluded(value) => Some((Self::GreaterThan, value.clone())), @@ -330,7 +330,7 @@ impl MarkerOperator { } /// Returns a value specifier representing the given upper bound. - fn from_upper_bound(bound: &Bound) -> Option<(Self, ArcStr)> { + fn from_upper_bound(bound: Bound<&ArcStr>) -> Option<(Self, ArcStr)> { match bound { Bound::Included(value) => Some((Self::LessEqual, value.clone())), Bound::Excluded(value) => Some((Self::LessThan, value.clone())), diff --git a/crates/uv-resolver/src/error.rs b/crates/uv-resolver/src/error.rs index eee9f5650db33..1bcbfe86acf9d 100644 --- a/crates/uv-resolver/src/error.rs +++ b/crates/uv-resolver/src/error.rs @@ -1315,7 +1315,7 @@ impl SentinelRange<'_> { pub fn strip(&self) -> Ranges { self.0 .iter() - .map(|(lower, upper)| Self::strip_sentinel(lower.clone(), upper.clone())) + .map(|(lower, upper)| Self::strip_sentinel(lower.cloned(), upper.cloned())) .collect() } @@ -1406,7 +1406,7 @@ impl<'a> PrefixMatch<'a> { /// /// Prefix matches are desugared to (e.g.) `>=2.4.dev0,<2.5.dev0`, but we want to render them /// as `==2.4.*` in error messages. - pub(crate) fn from_range(lower: &'a Bound, upper: &'a Bound) -> Option { + pub(crate) fn from_range(lower: Bound<&'a Version>, upper: Bound<&'a Version>) -> Option { let Bound::Included(lower) = lower else { return None; }; diff --git a/crates/uv-resolver/src/pubgrub/report.rs b/crates/uv-resolver/src/pubgrub/report.rs index e824b3d435dc8..2950b0546596f 100644 --- a/crates/uv-resolver/src/pubgrub/report.rs +++ b/crates/uv-resolver/src/pubgrub/report.rs @@ -2380,7 +2380,7 @@ fn update_availability_range( range .iter() .filter_map(|(lower, upper)| { - let segment_range = Range::from_range_bounds((lower.clone(), upper.clone())); + let segment_range = Range::from_range_bounds((lower.cloned(), upper.cloned())); // Drop the segment if it's disjoint with the available range, e.g., if the segment is // `foo>999`, and the available versions are all `<10` it's useless to show. @@ -2412,13 +2412,13 @@ fn update_availability_range( Bound::Included(version) if !version_contained_in(version, available_versions) => { Bound::Excluded(version.clone()) } - _ => (*lower).clone(), + _ => lower.cloned(), }; let upper = match upper { Bound::Included(version) if !version_contained_in(version, available_versions) => { Bound::Excluded(version.clone()) } - _ => (*upper).clone(), + _ => upper.cloned(), }; Some((lower, upper)) @@ -2477,7 +2477,7 @@ impl std::fmt::Display for PackageRange<'_> { } } (Bound::Included(v), Bound::Excluded(b)) => { - if let Some(prefix) = PrefixMatch::from_range(lower, upper) { + if let Some(prefix) = PrefixMatch::from_range(*lower, *upper) { write!(f, "{package}{prefix}")?; } else { write!(f, "{package}>={v},<{b}")?; diff --git a/crates/uv-resolver/src/resolver/derivation.rs b/crates/uv-resolver/src/resolver/derivation.rs index 0ecd081f13f57..09617cdee95a1 100644 --- a/crates/uv-resolver/src/resolver/derivation.rs +++ b/crates/uv-resolver/src/resolver/derivation.rs @@ -1,4 +1,4 @@ -use pubgrub::{Id, Kind, State}; +use pubgrub::{Id, Kind, Ranges, State, Term}; use rustc_hash::FxHashMap; use uv_distribution_types::{DerivationChain, DerivationStep}; @@ -37,7 +37,27 @@ impl DerivationChainBuilder { let incompat = &state.incompatibility_store[*index]; // Find a dependency from a package to the current package. - if let Kind::FromDependencyOf(id1, _, id2, v2) = &incompat.kind { + if let Kind::FromDependencyOf(id1, id2) = &incompat.kind { + let mut terms = incompat.iter(); + let Some((term_id1, Term::Positive(_))) = terms.next() else { + unreachable!( + "dependency incompatibility must start with its positive term" + ); + }; + if term_id1 != *id1 { + unreachable!("dependency incompatibility has a mismatched dependent term"); + } + let v2 = match terms.next() { + None => Ranges::empty(), + Some((term_id2, Term::Negative(v2))) if term_id2 == *id2 => v2.clone(), + _ => unreachable!( + "dependency incompatibility must end with its negative term" + ), + }; + assert!( + terms.next().is_none(), + "dependency incompatibility must contain at most two terms" + ); if id == *id2 && v2.contains(version) { if let Some(version) = solution.get(id1) { let p1 = &state.package_store[*id1]; @@ -55,7 +75,7 @@ impl DerivationChainBuilder { p1.extra().cloned(), p1.group().cloned(), Some(version.clone()), - v2.clone(), + v2, )); // Recursively search the next package. diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index 873db40376c4c..f68497f106e40 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -13,7 +13,7 @@ use either::Either; use futures::{FutureExt, StreamExt}; use itertools::Itertools; use papaya::{HashMap, ResizeMode}; -use pubgrub::{Id, IncompId, Incompatibility, Kind, Range, Ranges, State}; +use pubgrub::{Id, IncompId, Incompatibility, Kind, Range, Ranges, State, Term}; use rustc_hash::{FxHashMap, FxHashSet}; use tokio::sync::mpsc::{self, Receiver, Sender}; use tokio::sync::oneshot; @@ -2666,7 +2666,7 @@ impl ResolverState = Vec::with_capacity(edge_count); for (package, self_version) in &solution { for id in &self.pubgrub.incompatibilities[package] { - let pubgrub::Kind::FromDependencyOf( - self_package, - ref self_range, - dependency_package, - ref dependency_range, - ) = self.pubgrub.incompatibility_store[*id].kind + let incompatibility = &self.pubgrub.incompatibility_store[*id]; + let pubgrub::Kind::FromDependencyOf(self_package, dependency_package) = + &incompatibility.kind else { continue; }; + let (self_package, dependency_package) = (*self_package, *dependency_package); + let mut terms = incompatibility.iter(); + let Some((term_package, Term::Positive(self_range))) = terms.next() else { + unreachable!("dependency incompatibility must start with its positive term"); + }; + if term_package != self_package { + unreachable!("dependency incompatibility has a mismatched dependent term"); + } + let dependency_range = match terms.next() { + None => Cow::Owned(Ranges::empty()), + Some((term_package, Term::Negative(range))) + if term_package == dependency_package => + { + Cow::Borrowed(range) + } + _ => unreachable!("dependency incompatibility must end with its negative term"), + }; + assert!( + terms.next().is_none(), + "dependency incompatibility must contain at most two terms" + ); if *package != self_package { continue; } @@ -4257,7 +4278,7 @@ fn find_environments(id: Id, state: &State for index in incompatibilities { let incompat = &state.incompatibility_store[*index]; - if let Kind::FromDependencyOf(parent, _, child, _) = &incompat.kind { + if let Kind::FromDependencyOf(parent, child) = &incompat.kind { if current != *child { continue; } @@ -4291,7 +4312,7 @@ fn find_environments(id: Id, state: &State for index in incompatibilities { let incompat = &state.incompatibility_store[*index]; - let Kind::FromDependencyOf(parent, _, child, _) = &incompat.kind else { + let Kind::FromDependencyOf(parent, child) = &incompat.kind else { continue; }; if current != *parent || !ancestors.contains(child) { From 06fcfb0f94f327d4c6b6619515e6cbfee032db14 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 29 Jun 2026 03:02:55 +0000 Subject: [PATCH 2/5] Update PubGrub draft pin --- Cargo.lock | 6 +++--- Cargo.toml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 488d9176aaffb..5333444c63236 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,7 +218,7 @@ dependencies = [ [[package]] name = "astral-pubgrub" version = "0.4.3" -source = "git+https://github.com/astral-sh/pubgrub?rev=446afc9f756253b94df0f9b0f167ec8fba0b3693#446afc9f756253b94df0f9b0f167ec8fba0b3693" +source = "git+https://github.com/astral-sh/pubgrub?rev=8f31b20e3def5dbd1f68a6911f19190c87adf53d#8f31b20e3def5dbd1f68a6911f19190c87adf53d" dependencies = [ "astral-version-ranges", "indexmap", @@ -291,8 +291,8 @@ dependencies = [ [[package]] name = "astral-version-ranges" -version = "0.1.4" -source = "git+https://github.com/astral-sh/pubgrub?rev=446afc9f756253b94df0f9b0f167ec8fba0b3693#446afc9f756253b94df0f9b0f167ec8fba0b3693" +version = "0.1.5" +source = "git+https://github.com/astral-sh/pubgrub?rev=8f31b20e3def5dbd1f68a6911f19190c87adf53d#8f31b20e3def5dbd1f68a6911f19190c87adf53d" dependencies = [ "smallvec", ] diff --git a/Cargo.toml b/Cargo.toml index fd3a82e853255..be185202b740c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,7 +189,7 @@ percent-encoding = { version = "2.3.1" } petgraph = { version = "0.8.0" } proc-macro2 = { version = "1.0.86" } procfs = { version = "0.18.0", default-features = false, features = ["flate2"] } -pubgrub = { git = "https://github.com/astral-sh/pubgrub", rev = "446afc9f756253b94df0f9b0f167ec8fba0b3693", package = "astral-pubgrub" } +pubgrub = { git = "https://github.com/astral-sh/pubgrub", rev = "8f31b20e3def5dbd1f68a6911f19190c87adf53d", package = "astral-pubgrub" } quote = { version = "1.0.37" } rand = { version = "0.9.4" } rayon = { version = "1.10.0" } @@ -289,7 +289,7 @@ unicode-width = { version = "0.2.0" } unscanny = { version = "0.1.0" } url = { version = "2.5.2", features = ["serde"] } uuid = { version = "1.16.0" } -version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "446afc9f756253b94df0f9b0f167ec8fba0b3693", package = "astral-version-ranges" } +version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "8f31b20e3def5dbd1f68a6911f19190c87adf53d", package = "astral-version-ranges" } walkdir = { version = "2.5.0" } webpki-root-certs = { version = "1" } which = { version = "8.0.0", features = ["regex"] } From 5a52b49550239bbb2f8f1d2e53a4a0571eb15e7a Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 29 Jun 2026 09:20:18 -0400 Subject: [PATCH 3/5] Use PubGrub dependency version-set accessor --- Cargo.lock | 4 +-- Cargo.toml | 4 +-- crates/uv-resolver/src/resolver/derivation.rs | 29 +++++-------------- crates/uv-resolver/src/resolver/mod.rs | 27 +++++------------ 4 files changed, 18 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5333444c63236..bedb0a9a4533a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,7 +218,7 @@ dependencies = [ [[package]] name = "astral-pubgrub" version = "0.4.3" -source = "git+https://github.com/astral-sh/pubgrub?rev=8f31b20e3def5dbd1f68a6911f19190c87adf53d#8f31b20e3def5dbd1f68a6911f19190c87adf53d" +source = "git+https://github.com/astral-sh/pubgrub?rev=b8dd822dee1f94499787d2245dfe51e963bb411f#b8dd822dee1f94499787d2245dfe51e963bb411f" dependencies = [ "astral-version-ranges", "indexmap", @@ -292,7 +292,7 @@ dependencies = [ [[package]] name = "astral-version-ranges" version = "0.1.5" -source = "git+https://github.com/astral-sh/pubgrub?rev=8f31b20e3def5dbd1f68a6911f19190c87adf53d#8f31b20e3def5dbd1f68a6911f19190c87adf53d" +source = "git+https://github.com/astral-sh/pubgrub?rev=b8dd822dee1f94499787d2245dfe51e963bb411f#b8dd822dee1f94499787d2245dfe51e963bb411f" dependencies = [ "smallvec", ] diff --git a/Cargo.toml b/Cargo.toml index be185202b740c..b241e3b5890dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,7 +189,7 @@ percent-encoding = { version = "2.3.1" } petgraph = { version = "0.8.0" } proc-macro2 = { version = "1.0.86" } procfs = { version = "0.18.0", default-features = false, features = ["flate2"] } -pubgrub = { git = "https://github.com/astral-sh/pubgrub", rev = "8f31b20e3def5dbd1f68a6911f19190c87adf53d", package = "astral-pubgrub" } +pubgrub = { git = "https://github.com/astral-sh/pubgrub", rev = "b8dd822dee1f94499787d2245dfe51e963bb411f", package = "astral-pubgrub" } quote = { version = "1.0.37" } rand = { version = "0.9.4" } rayon = { version = "1.10.0" } @@ -289,7 +289,7 @@ unicode-width = { version = "0.2.0" } unscanny = { version = "0.1.0" } url = { version = "2.5.2", features = ["serde"] } uuid = { version = "1.16.0" } -version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "8f31b20e3def5dbd1f68a6911f19190c87adf53d", package = "astral-version-ranges" } +version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "b8dd822dee1f94499787d2245dfe51e963bb411f", package = "astral-version-ranges" } walkdir = { version = "2.5.0" } webpki-root-certs = { version = "1" } which = { version = "8.0.0", features = ["regex"] } diff --git a/crates/uv-resolver/src/resolver/derivation.rs b/crates/uv-resolver/src/resolver/derivation.rs index 09617cdee95a1..47911d5a38b05 100644 --- a/crates/uv-resolver/src/resolver/derivation.rs +++ b/crates/uv-resolver/src/resolver/derivation.rs @@ -1,4 +1,4 @@ -use pubgrub::{Id, Kind, Ranges, State, Term}; +use pubgrub::{Id, Kind, Ranges, State}; use rustc_hash::FxHashMap; use uv_distribution_types::{DerivationChain, DerivationStep}; @@ -38,27 +38,12 @@ impl DerivationChainBuilder { // Find a dependency from a package to the current package. if let Kind::FromDependencyOf(id1, id2) = &incompat.kind { - let mut terms = incompat.iter(); - let Some((term_id1, Term::Positive(_))) = terms.next() else { - unreachable!( - "dependency incompatibility must start with its positive term" - ); + let Some((_, dependency_versions)) = incompat.dependency_version_sets() else { + continue; }; - if term_id1 != *id1 { - unreachable!("dependency incompatibility has a mismatched dependent term"); - } - let v2 = match terms.next() { - None => Ranges::empty(), - Some((term_id2, Term::Negative(v2))) if term_id2 == *id2 => v2.clone(), - _ => unreachable!( - "dependency incompatibility must end with its negative term" - ), - }; - assert!( - terms.next().is_none(), - "dependency incompatibility must contain at most two terms" - ); - if id == *id2 && v2.contains(version) { + let dependency_versions = + dependency_versions.cloned().unwrap_or_else(Ranges::empty); + if id == *id2 && dependency_versions.contains(version) { if let Some(version) = solution.get(id1) { let p1 = &state.package_store[*id1]; let p2 = &state.package_store[*id2]; @@ -75,7 +60,7 @@ impl DerivationChainBuilder { p1.extra().cloned(), p1.group().cloned(), Some(version.clone()), - v2, + dependency_versions, )); // Recursively search the next package. diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index f68497f106e40..94e2b52144ff1 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -13,7 +13,7 @@ use either::Either; use futures::{FutureExt, StreamExt}; use itertools::Itertools; use papaya::{HashMap, ResizeMode}; -use pubgrub::{Id, IncompId, Incompatibility, Kind, Range, Ranges, State, Term}; +use pubgrub::{Id, IncompId, Incompatibility, Kind, Range, Ranges, State}; use rustc_hash::{FxHashMap, FxHashSet}; use tokio::sync::mpsc::{self, Receiver, Sender}; use tokio::sync::oneshot; @@ -3333,26 +3333,13 @@ impl ForkState { continue; }; let (self_package, dependency_package) = (*self_package, *dependency_package); - let mut terms = incompatibility.iter(); - let Some((term_package, Term::Positive(self_range))) = terms.next() else { - unreachable!("dependency incompatibility must start with its positive term"); - }; - if term_package != self_package { - unreachable!("dependency incompatibility has a mismatched dependent term"); - } - let dependency_range = match terms.next() { - None => Cow::Owned(Ranges::empty()), - Some((term_package, Term::Negative(range))) - if term_package == dependency_package => - { - Cow::Borrowed(range) - } - _ => unreachable!("dependency incompatibility must end with its negative term"), + let Some((self_range, dependency_range)) = + incompatibility.dependency_version_sets() + else { + continue; }; - assert!( - terms.next().is_none(), - "dependency incompatibility must contain at most two terms" - ); + let dependency_range = + dependency_range.map_or_else(|| Cow::Owned(Ranges::empty()), Cow::Borrowed); if *package != self_package { continue; } From 7ff5a2025512b9fb8af498851a34415489dfd043 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 29 Jun 2026 09:27:31 -0400 Subject: [PATCH 4/5] Update PubGrub draft pin --- Cargo.lock | 4 ++-- Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bedb0a9a4533a..4165592703ef7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,7 +218,7 @@ dependencies = [ [[package]] name = "astral-pubgrub" version = "0.4.3" -source = "git+https://github.com/astral-sh/pubgrub?rev=b8dd822dee1f94499787d2245dfe51e963bb411f#b8dd822dee1f94499787d2245dfe51e963bb411f" +source = "git+https://github.com/astral-sh/pubgrub?rev=8fd9709ea671b1b3ead53e6ec847da5fcad7c03d#8fd9709ea671b1b3ead53e6ec847da5fcad7c03d" dependencies = [ "astral-version-ranges", "indexmap", @@ -292,7 +292,7 @@ dependencies = [ [[package]] name = "astral-version-ranges" version = "0.1.5" -source = "git+https://github.com/astral-sh/pubgrub?rev=b8dd822dee1f94499787d2245dfe51e963bb411f#b8dd822dee1f94499787d2245dfe51e963bb411f" +source = "git+https://github.com/astral-sh/pubgrub?rev=8fd9709ea671b1b3ead53e6ec847da5fcad7c03d#8fd9709ea671b1b3ead53e6ec847da5fcad7c03d" dependencies = [ "smallvec", ] diff --git a/Cargo.toml b/Cargo.toml index b241e3b5890dd..93798f06fe238 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,7 +189,7 @@ percent-encoding = { version = "2.3.1" } petgraph = { version = "0.8.0" } proc-macro2 = { version = "1.0.86" } procfs = { version = "0.18.0", default-features = false, features = ["flate2"] } -pubgrub = { git = "https://github.com/astral-sh/pubgrub", rev = "b8dd822dee1f94499787d2245dfe51e963bb411f", package = "astral-pubgrub" } +pubgrub = { git = "https://github.com/astral-sh/pubgrub", rev = "8fd9709ea671b1b3ead53e6ec847da5fcad7c03d", package = "astral-pubgrub" } quote = { version = "1.0.37" } rand = { version = "0.9.4" } rayon = { version = "1.10.0" } @@ -289,7 +289,7 @@ unicode-width = { version = "0.2.0" } unscanny = { version = "0.1.0" } url = { version = "2.5.2", features = ["serde"] } uuid = { version = "1.16.0" } -version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "b8dd822dee1f94499787d2245dfe51e963bb411f", package = "astral-version-ranges" } +version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "8fd9709ea671b1b3ead53e6ec847da5fcad7c03d", package = "astral-version-ranges" } walkdir = { version = "2.5.0" } webpki-root-certs = { version = "1" } which = { version = "8.0.0", features = ["regex"] } From e63c818850636d89858b9df6554670af8ef20cab Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 29 Jun 2026 10:14:30 -0400 Subject: [PATCH 5/5] Use published PubGrub releases --- Cargo.lock | 10 ++++++---- Cargo.toml | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4165592703ef7..ee14ea69138a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,8 +217,9 @@ dependencies = [ [[package]] name = "astral-pubgrub" -version = "0.4.3" -source = "git+https://github.com/astral-sh/pubgrub?rev=8fd9709ea671b1b3ead53e6ec847da5fcad7c03d#8fd9709ea671b1b3ead53e6ec847da5fcad7c03d" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c79d771681f6c21ebe25dda598774b6e6badca8b720ce2168df7788b2821c46d" dependencies = [ "astral-version-ranges", "indexmap", @@ -291,8 +292,9 @@ dependencies = [ [[package]] name = "astral-version-ranges" -version = "0.1.5" -source = "git+https://github.com/astral-sh/pubgrub?rev=8fd9709ea671b1b3ead53e6ec847da5fcad7c03d#8fd9709ea671b1b3ead53e6ec847da5fcad7c03d" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086f936efdefab117f5a72367fb3d68c4fded8ba5a7008e3c63365eecf723822" dependencies = [ "smallvec", ] diff --git a/Cargo.toml b/Cargo.toml index 93798f06fe238..89f31f3bf4a32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -189,7 +189,7 @@ percent-encoding = { version = "2.3.1" } petgraph = { version = "0.8.0" } proc-macro2 = { version = "1.0.86" } procfs = { version = "0.18.0", default-features = false, features = ["flate2"] } -pubgrub = { git = "https://github.com/astral-sh/pubgrub", rev = "8fd9709ea671b1b3ead53e6ec847da5fcad7c03d", package = "astral-pubgrub" } +pubgrub = { version = "0.5.0", package = "astral-pubgrub" } quote = { version = "1.0.37" } rand = { version = "0.9.4" } rayon = { version = "1.10.0" } @@ -289,7 +289,7 @@ unicode-width = { version = "0.2.0" } unscanny = { version = "0.1.0" } url = { version = "2.5.2", features = ["serde"] } uuid = { version = "1.16.0" } -version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "8fd9709ea671b1b3ead53e6ec847da5fcad7c03d", package = "astral-version-ranges" } +version-ranges = { version = "0.2.0", package = "astral-version-ranges" } walkdir = { version = "2.5.0" } webpki-root-certs = { version = "1" } which = { version = "8.0.0", features = ["regex"] }