Skip to content

Commit 1ced3f3

Browse files
committed
refactor: change to lib range_trait
1 parent 072f60b commit 1ced3f3

File tree

9 files changed

+209
-193
lines changed

9 files changed

+209
-193
lines changed

src/error.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ use thiserror::Error;
66

77
use crate::package::Package;
88
use crate::report::DerivationTree;
9-
use crate::version::Version;
9+
use crate::version_trait::{Interval, Version};
10+
use std::fmt::Debug;
1011

1112
/// Errors that may occur while solving dependencies.
1213
#[derive(Error, Debug)]
13-
pub enum PubGrubError<P: Package, V: Version> {
14+
pub enum PubGrubError<P: Package, I: Interval<V> + Debug, V: Version> {
1415
/// There is no solution for this set of dependencies.
1516
#[error("No solution")]
16-
NoSolution(DerivationTree<P, V>),
17+
NoSolution(DerivationTree<P, I, V>),
1718

1819
/// Error arising when the implementer of
1920
/// [DependencyProvider](crate::solver::DependencyProvider)

src/internal/core.rs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! to write a functional PubGrub algorithm.
55
66
use std::collections::HashSet as Set;
7+
use std::fmt::Debug;
78

89
use crate::error::PubGrubError;
910
use crate::internal::arena::Arena;
@@ -17,34 +18,34 @@ use crate::package::Package;
1718
use crate::report::DerivationTree;
1819
use crate::solver::DependencyConstraints;
1920
use crate::type_aliases::Map;
20-
use crate::version::Version;
21+
use crate::version_trait::{Interval, Version};
2122

2223
/// Current state of the PubGrub algorithm.
2324
#[derive(Clone)]
24-
pub struct State<P: Package, V: Version> {
25+
pub struct State<P: Package, I: Interval<V>, V: Version> {
2526
root_package: P,
2627
root_version: V,
2728

28-
incompatibilities: Map<P, Vec<IncompId<P, V>>>,
29+
incompatibilities: Map<P, Vec<IncompId<P, I, V>>>,
2930

3031
/// Store the ids of incompatibilities that are already contradicted
3132
/// and will stay that way until the next conflict and backtrack is operated.
32-
contradicted_incompatibilities: rustc_hash::FxHashSet<IncompId<P, V>>,
33+
contradicted_incompatibilities: rustc_hash::FxHashSet<IncompId<P, I, V>>,
3334

3435
/// Partial solution.
3536
/// TODO: remove pub.
36-
pub partial_solution: PartialSolution<P, V>,
37+
pub partial_solution: PartialSolution<P, I, V>,
3738

3839
/// The store is the reference storage for all incompatibilities.
39-
pub incompatibility_store: Arena<Incompatibility<P, V>>,
40+
pub incompatibility_store: Arena<Incompatibility<P, I, V>>,
4041

4142
/// This is a stack of work to be done in `unit_propagation`.
4243
/// It can definitely be a local variable to that method, but
4344
/// this way we can reuse the same allocation for better performance.
4445
unit_propagation_buffer: SmallVec<P>,
4546
}
4647

47-
impl<P: Package, V: Version> State<P, V> {
48+
impl<P: Package, I: Interval<V> + Debug, V: Version> State<P, I, V> {
4849
/// Initialization of PubGrub state.
4950
pub fn init(root_package: P, root_version: V) -> Self {
5051
let mut incompatibility_store = Arena::new();
@@ -66,7 +67,7 @@ impl<P: Package, V: Version> State<P, V> {
6667
}
6768

6869
/// Add an incompatibility to the state.
69-
pub fn add_incompatibility(&mut self, incompat: Incompatibility<P, V>) {
70+
pub fn add_incompatibility(&mut self, incompat: Incompatibility<P, I, V>) {
7071
let id = self.incompatibility_store.alloc(incompat);
7172
self.merge_incompatibility(id);
7273
}
@@ -76,8 +77,8 @@ impl<P: Package, V: Version> State<P, V> {
7677
&mut self,
7778
package: P,
7879
version: V,
79-
deps: &DependencyConstraints<P, V>,
80-
) -> std::ops::Range<IncompId<P, V>> {
80+
deps: &DependencyConstraints<P, I, V>,
81+
) -> std::ops::Range<IncompId<P, I, V>> {
8182
// Create incompatibilities and allocate them in the store.
8283
let new_incompats_id_range = self
8384
.incompatibility_store
@@ -92,13 +93,13 @@ impl<P: Package, V: Version> State<P, V> {
9293
}
9394

9495
/// Check if an incompatibility is terminal.
95-
pub fn is_terminal(&self, incompatibility: &Incompatibility<P, V>) -> bool {
96+
pub fn is_terminal(&self, incompatibility: &Incompatibility<P, I, V>) -> bool {
9697
incompatibility.is_terminal(&self.root_package, &self.root_version)
9798
}
9899

99100
/// Unit propagation is the core mechanism of the solving algorithm.
100101
/// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
101-
pub fn unit_propagation(&mut self, package: P) -> Result<(), PubGrubError<P, V>> {
102+
pub fn unit_propagation(&mut self, package: P) -> Result<(), PubGrubError<P, I, V>> {
102103
self.unit_propagation_buffer.clear();
103104
self.unit_propagation_buffer.push(package);
104105
while let Some(current_package) = self.unit_propagation_buffer.pop() {
@@ -158,8 +159,8 @@ impl<P: Package, V: Version> State<P, V> {
158159
/// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
159160
fn conflict_resolution(
160161
&mut self,
161-
incompatibility: IncompId<P, V>,
162-
) -> Result<(P, IncompId<P, V>), PubGrubError<P, V>> {
162+
incompatibility: IncompId<P, I, V>,
163+
) -> Result<(P, IncompId<P, I, V>), PubGrubError<P, I, V>> {
163164
let mut current_incompat_id = incompatibility;
164165
let mut current_incompat_changed = false;
165166
loop {
@@ -203,7 +204,7 @@ impl<P: Package, V: Version> State<P, V> {
203204
/// Backtracking.
204205
fn backtrack(
205206
&mut self,
206-
incompat: IncompId<P, V>,
207+
incompat: IncompId<P, I, V>,
207208
incompat_changed: bool,
208209
decision_level: DecisionLevel,
209210
) {
@@ -234,7 +235,7 @@ impl<P: Package, V: Version> State<P, V> {
234235
/// Here we do the simple stupid thing of just growing the Vec.
235236
/// It may not be trivial since those incompatibilities
236237
/// may already have derived others.
237-
fn merge_incompatibility(&mut self, id: IncompId<P, V>) {
238+
fn merge_incompatibility(&mut self, id: IncompId<P, I, V>) {
238239
for (pkg, _term) in self.incompatibility_store[id].iter() {
239240
self.incompatibilities
240241
.entry(pkg.clone())
@@ -245,12 +246,12 @@ impl<P: Package, V: Version> State<P, V> {
245246

246247
// Error reporting #########################################################
247248

248-
fn build_derivation_tree(&self, incompat: IncompId<P, V>) -> DerivationTree<P, V> {
249+
fn build_derivation_tree(&self, incompat: IncompId<P, I, V>) -> DerivationTree<P, I, V> {
249250
let shared_ids = self.find_shared_ids(incompat);
250251
Incompatibility::build_derivation_tree(incompat, &shared_ids, &self.incompatibility_store)
251252
}
252253

253-
fn find_shared_ids(&self, incompat: IncompId<P, V>) -> Set<IncompId<P, V>> {
254+
fn find_shared_ids(&self, incompat: IncompId<P, I, V>) -> Set<IncompId<P, I, V>> {
254255
let mut all_ids = Set::new();
255256
let mut shared_ids = Set::new();
256257
let mut stack = vec![incompat];

src/internal/incompatibility.rs

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ use std::fmt;
99
use crate::internal::arena::{Arena, Id};
1010
use crate::internal::small_map::SmallMap;
1111
use crate::package::Package;
12-
use crate::range::Range;
12+
use crate::range_trait::Range;
1313
use crate::report::{DefaultStringReporter, DerivationTree, Derived, External};
1414
use crate::term::{self, Term};
15-
use crate::version::Version;
15+
use crate::version_trait::{Interval, Version};
1616

1717
/// An incompatibility is a set of terms for different packages
1818
/// that should never be satisfied all together.
@@ -30,26 +30,26 @@ use crate::version::Version;
3030
/// during conflict resolution. More about all this in
3131
/// [PubGrub documentation](https://github.com/dart-lang/pub/blob/master/doc/solver.md#incompatibility).
3232
#[derive(Debug, Clone)]
33-
pub struct Incompatibility<P: Package, V: Version> {
34-
package_terms: SmallMap<P, Term<V>>,
35-
kind: Kind<P, V>,
33+
pub struct Incompatibility<P: Package, I: Interval<V>, V: Version> {
34+
package_terms: SmallMap<P, Term<I, V>>,
35+
kind: Kind<P, I, V>,
3636
}
3737

3838
/// Type alias of unique identifiers for incompatibilities.
39-
pub type IncompId<P, V> = Id<Incompatibility<P, V>>;
39+
pub type IncompId<P, I, V> = Id<Incompatibility<P, I, V>>;
4040

4141
#[derive(Debug, Clone)]
42-
enum Kind<P: Package, V: Version> {
42+
enum Kind<P: Package, I: Interval<V>, V: Version> {
4343
/// Initial incompatibility aiming at picking the root package for the first decision.
4444
NotRoot(P, V),
4545
/// There are no versions in the given range for this package.
46-
NoVersions(P, Range<V>),
46+
NoVersions(P, Range<I, V>),
4747
/// Dependencies of the package are unavailable for versions in that range.
48-
UnavailableDependencies(P, Range<V>),
48+
UnavailableDependencies(P, Range<I, V>),
4949
/// Incompatibility coming from the dependencies of a given package.
50-
FromDependencyOf(P, Range<V>, P, Range<V>),
50+
FromDependencyOf(P, Range<I, V>, P, Range<I, V>),
5151
/// Derived from two causes. Stores cause ids.
52-
DerivedFrom(IncompId<P, V>, IncompId<P, V>),
52+
DerivedFrom(IncompId<P, I, V>, IncompId<P, I, V>),
5353
}
5454

5555
/// A Relation describes how a set of terms can be compared to an incompatibility.
@@ -69,21 +69,21 @@ pub enum Relation<P: Package> {
6969
Inconclusive,
7070
}
7171

72-
impl<P: Package, V: Version> Incompatibility<P, V> {
72+
impl<P: Package, I: Interval<V>, V: Version> Incompatibility<P, I, V> {
7373
/// Create the initial "not Root" incompatibility.
7474
pub fn not_root(package: P, version: V) -> Self {
7575
Self {
7676
package_terms: SmallMap::One([(
7777
package.clone(),
78-
Term::Negative(Range::exact(version.clone())),
78+
Term::Negative(Range::singleton(version.clone())),
7979
)]),
8080
kind: Kind::NotRoot(package, version),
8181
}
8282
}
8383

8484
/// Create an incompatibility to remember
8585
/// that a given range does not contain any version.
86-
pub fn no_versions(package: P, term: Term<V>) -> Self {
86+
pub fn no_versions(package: P, term: Term<I, V>) -> Self {
8787
let range = match &term {
8888
Term::Positive(r) => r.clone(),
8989
Term::Negative(_) => panic!("No version should have a positive term"),
@@ -98,16 +98,16 @@ impl<P: Package, V: Version> Incompatibility<P, V> {
9898
/// that a package version is not selectable
9999
/// because its list of dependencies is unavailable.
100100
pub fn unavailable_dependencies(package: P, version: V) -> Self {
101-
let range = Range::exact(version);
101+
let range = Range::singleton(version);
102102
Self {
103103
package_terms: SmallMap::One([(package.clone(), Term::Positive(range.clone()))]),
104104
kind: Kind::UnavailableDependencies(package, range),
105105
}
106106
}
107107

108108
/// Build an incompatibility from a given dependency.
109-
pub fn from_dependency(package: P, version: V, dep: (&P, &Range<V>)) -> Self {
110-
let range1 = Range::exact(version);
109+
pub fn from_dependency(package: P, version: V, dep: (&P, &Range<I, V>)) -> Self {
110+
let range1 = Range::singleton(version);
111111
let (p2, range2) = dep;
112112
Self {
113113
package_terms: SmallMap::Two([
@@ -157,12 +157,12 @@ impl<P: Package, V: Version> Incompatibility<P, V> {
157157
}
158158

159159
/// Get the term related to a given package (if it exists).
160-
pub fn get(&self, package: &P) -> Option<&Term<V>> {
160+
pub fn get(&self, package: &P) -> Option<&Term<I, V>> {
161161
self.package_terms.get(package)
162162
}
163163

164164
/// Iterate over packages.
165-
pub fn iter(&self) -> impl Iterator<Item = (&P, &Term<V>)> {
165+
pub fn iter(&self) -> impl Iterator<Item = (&P, &Term<I, V>)> {
166166
self.package_terms.iter()
167167
}
168168

@@ -181,7 +181,7 @@ impl<P: Package, V: Version> Incompatibility<P, V> {
181181
self_id: Id<Self>,
182182
shared_ids: &Set<Id<Self>>,
183183
store: &Arena<Self>,
184-
) -> DerivationTree<P, V> {
184+
) -> DerivationTree<P, I, V> {
185185
match &store[self_id].kind {
186186
Kind::DerivedFrom(id1, id2) => {
187187
let cause1 = Self::build_derivation_tree(*id1, shared_ids, store);
@@ -215,9 +215,9 @@ impl<P: Package, V: Version> Incompatibility<P, V> {
215215
}
216216
}
217217

218-
impl<'a, P: Package, V: Version + 'a> Incompatibility<P, V> {
218+
impl<'a, P: Package, I: Interval<V> + 'a, V: Version + 'a> Incompatibility<P, I, V> {
219219
/// CF definition of Relation enum.
220-
pub fn relation(&self, terms: impl Fn(&P) -> Option<&'a Term<V>>) -> Relation<P> {
220+
pub fn relation(&self, terms: impl Fn(&P) -> Option<&'a Term<I, V>>) -> Relation<P> {
221221
let mut relation = Relation::Satisfied;
222222
for (package, incompat_term) in self.package_terms.iter() {
223223
match terms(package).map(|term| incompat_term.relation_with(&term)) {
@@ -243,7 +243,7 @@ impl<'a, P: Package, V: Version + 'a> Incompatibility<P, V> {
243243
}
244244
}
245245

246-
impl<P: Package, V: Version> fmt::Display for Incompatibility<P, V> {
246+
impl<P: Package, I: Interval<V>, V: Version> fmt::Display for Incompatibility<P, I, V> {
247247
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248248
write!(
249249
f,
@@ -276,12 +276,12 @@ pub mod tests {
276276
let mut store = Arena::new();
277277
let i1 = store.alloc(Incompatibility {
278278
package_terms: SmallMap::Two([("p1", t1.clone()), ("p2", t2.negate())]),
279-
kind: Kind::UnavailableDependencies("0", Range::any())
279+
kind: Kind::UnavailableDependencies("0", Range::full())
280280
});
281281

282282
let i2 = store.alloc(Incompatibility {
283283
package_terms: SmallMap::Two([("p2", t2), ("p3", t3.clone())]),
284-
kind: Kind::UnavailableDependencies("0", Range::any())
284+
kind: Kind::UnavailableDependencies("0", Range::full())
285285
});
286286

287287
let mut i3 = Map::default();

0 commit comments

Comments
 (0)