3
3
//! Core model and functions
4
4
//! to write a functional PubGrub algorithm.
5
5
6
- use std:: error :: Error ;
6
+ use std:: collections :: HashSet as Set ;
7
7
use std:: sync:: Arc ;
8
8
9
9
use crate :: error:: PubGrubError ;
10
10
use crate :: internal:: arena:: Arena ;
11
- use crate :: internal:: incompatibility:: { IncompId , Incompatibility , Relation } ;
11
+ use crate :: internal:: incompatibility:: { Incompatibility , Relation } ;
12
12
use crate :: internal:: partial_solution:: SatisfierSearch :: {
13
13
DifferentDecisionLevels , SameDecisionLevels ,
14
14
} ;
15
15
use crate :: internal:: partial_solution:: { DecisionLevel , PartialSolution } ;
16
16
use crate :: internal:: small_vec:: SmallVec ;
17
- use crate :: package:: Package ;
18
17
use crate :: report:: DerivationTree ;
19
- use crate :: type_aliases:: { DependencyConstraints , Map , Set } ;
18
+ use crate :: solver:: DependencyProvider ;
19
+ use crate :: type_aliases:: { DependencyConstraints , IncompDpId , Map } ;
20
20
use crate :: version_set:: VersionSet ;
21
21
22
22
/// Current state of the PubGrub algorithm.
23
23
#[ derive( Clone ) ]
24
- pub struct State < P : Package , VS : VersionSet , Priority : Ord + Clone > {
25
- root_package : P ,
26
- root_version : VS :: V ,
24
+ pub struct State < DP : DependencyProvider > {
25
+ root_package : DP :: P ,
26
+ root_version : DP :: V ,
27
27
28
- incompatibilities : Map < P , Vec < IncompId < P , VS > > > ,
28
+ #[ allow( clippy:: type_complexity) ]
29
+ incompatibilities : Map < DP :: P , Vec < IncompDpId < DP > > > ,
29
30
30
31
/// Store the ids of incompatibilities that are already contradicted.
31
32
/// For each one keep track of the decision level when it was found to be contradicted.
32
33
/// These will stay contradicted until we have backtracked beyond its associated decision level.
33
- contradicted_incompatibilities : Map < IncompId < P , VS > , DecisionLevel > ,
34
+ contradicted_incompatibilities : Map < IncompDpId < DP > , DecisionLevel > ,
34
35
35
36
/// All incompatibilities expressing dependencies,
36
37
/// with common dependents merged.
37
- merged_dependencies : Map < ( P , P ) , SmallVec < IncompId < P , VS > > > ,
38
+ #[ allow( clippy:: type_complexity) ]
39
+ merged_dependencies : Map < ( DP :: P , DP :: P ) , SmallVec < IncompDpId < DP > > > ,
38
40
39
41
/// Partial solution.
40
42
/// TODO: remove pub.
41
- pub partial_solution : PartialSolution < P , VS , Priority > ,
43
+ pub partial_solution : PartialSolution < DP > ,
42
44
43
45
/// The store is the reference storage for all incompatibilities.
44
- pub incompatibility_store : Arena < Incompatibility < P , VS > > ,
46
+ pub incompatibility_store : Arena < Incompatibility < DP :: P , DP :: VS > > ,
45
47
46
48
/// This is a stack of work to be done in `unit_propagation`.
47
49
/// It can definitely be a local variable to that method, but
48
50
/// this way we can reuse the same allocation for better performance.
49
- unit_propagation_buffer : SmallVec < P > ,
51
+ unit_propagation_buffer : SmallVec < DP :: P > ,
50
52
}
51
53
52
- impl < P : Package , VS : VersionSet , Priority : Ord + Clone > State < P , VS , Priority > {
54
+ impl < DP : DependencyProvider > State < DP > {
53
55
/// Initialization of PubGrub state.
54
- pub fn init ( root_package : P , root_version : VS :: V ) -> Self {
56
+ pub fn init ( root_package : DP :: P , root_version : DP :: V ) -> Self {
55
57
let mut incompatibility_store = Arena :: new ( ) ;
56
58
let not_root_id = incompatibility_store. alloc ( Incompatibility :: not_root (
57
59
root_package. clone ( ) ,
@@ -72,38 +74,38 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
72
74
}
73
75
74
76
/// Add an incompatibility to the state.
75
- pub fn add_incompatibility ( & mut self , incompat : Incompatibility < P , VS > ) {
77
+ pub fn add_incompatibility ( & mut self , incompat : Incompatibility < DP :: P , DP :: VS > ) {
76
78
let id = self . incompatibility_store . alloc ( incompat) ;
77
79
self . merge_incompatibility ( id) ;
78
80
}
79
81
80
82
/// Add an incompatibility to the state.
81
83
pub fn add_incompatibility_from_dependencies (
82
84
& mut self ,
83
- package : P ,
84
- version : VS :: V ,
85
- deps : & DependencyConstraints < P , VS > ,
86
- ) -> std:: ops:: Range < IncompId < P , VS > > {
85
+ package : DP :: P ,
86
+ version : DP :: V ,
87
+ deps : & DependencyConstraints < DP :: P , DP :: VS > ,
88
+ ) -> std:: ops:: Range < IncompDpId < DP > > {
87
89
// Create incompatibilities and allocate them in the store.
88
90
let new_incompats_id_range =
89
91
self . incompatibility_store
90
92
. alloc_iter ( deps. iter ( ) . map ( |dep| {
91
93
Incompatibility :: from_dependency (
92
94
package. clone ( ) ,
93
- VS :: singleton ( version. clone ( ) ) ,
95
+ < DP :: VS as VersionSet > :: singleton ( version. clone ( ) ) ,
94
96
dep,
95
97
)
96
98
} ) ) ;
97
99
// Merge the newly created incompatibilities with the older ones.
98
- for id in IncompId :: range_to_iter ( new_incompats_id_range. clone ( ) ) {
100
+ for id in IncompDpId :: < DP > :: range_to_iter ( new_incompats_id_range. clone ( ) ) {
99
101
self . merge_incompatibility ( id) ;
100
102
}
101
103
new_incompats_id_range
102
104
}
103
105
104
106
/// Unit propagation is the core mechanism of the solving algorithm.
105
107
/// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
106
- pub fn unit_propagation < E : Error > ( & mut self , package : P ) -> Result < ( ) , PubGrubError < P , VS , E > > {
108
+ pub fn unit_propagation ( & mut self , package : DP :: P ) -> Result < ( ) , PubGrubError < DP > > {
107
109
self . unit_propagation_buffer . clear ( ) ;
108
110
self . unit_propagation_buffer . push ( package) ;
109
111
while let Some ( current_package) = self . unit_propagation_buffer . pop ( ) {
@@ -179,10 +181,10 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
179
181
/// Return the root cause and the backtracked model.
180
182
/// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
181
183
#[ allow( clippy:: type_complexity) ]
182
- fn conflict_resolution < E : Error > (
184
+ fn conflict_resolution (
183
185
& mut self ,
184
- incompatibility : IncompId < P , VS > ,
185
- ) -> Result < ( P , IncompId < P , VS > ) , PubGrubError < P , VS , E > > {
186
+ incompatibility : IncompDpId < DP > ,
187
+ ) -> Result < ( DP :: P , IncompDpId < DP > ) , PubGrubError < DP > > {
186
188
let mut current_incompat_id = incompatibility;
187
189
let mut current_incompat_changed = false ;
188
190
loop {
@@ -229,7 +231,7 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
229
231
/// Backtracking.
230
232
fn backtrack (
231
233
& mut self ,
232
- incompat : IncompId < P , VS > ,
234
+ incompat : IncompDpId < DP > ,
233
235
incompat_changed : bool ,
234
236
decision_level : DecisionLevel ,
235
237
) {
@@ -257,7 +259,7 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
257
259
/// (provided that no other version of foo exists between 1.0.0 and 2.0.0).
258
260
/// We could collapse them into { foo (1.0.0 ∪ 1.1.0), not bar ^1.0.0 }
259
261
/// without having to check the existence of other versions though.
260
- fn merge_incompatibility ( & mut self , mut id : IncompId < P , VS > ) {
262
+ fn merge_incompatibility ( & mut self , mut id : IncompDpId < DP > ) {
261
263
if let Some ( ( p1, p2) ) = self . incompatibility_store [ id] . as_dependency ( ) {
262
264
// If we are a dependency, there's a good chance we can be merged with a previous dependency
263
265
let deps_lookup = self
@@ -295,8 +297,8 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> State<P, VS, Priority> {
295
297
296
298
// Error reporting #########################################################
297
299
298
- fn build_derivation_tree ( & self , incompat : IncompId < P , VS > ) -> DerivationTree < P , VS > {
299
- let mut all_ids = Set :: default ( ) ;
300
+ fn build_derivation_tree ( & self , incompat : IncompDpId < DP > ) -> DerivationTree < DP :: P , DP :: VS > {
301
+ let mut all_ids: Set < IncompDpId < DP > > = Set :: default ( ) ;
300
302
let mut shared_ids = Set :: default ( ) ;
301
303
let mut stack = vec ! [ incompat] ;
302
304
while let Some ( i) = stack. pop ( ) {
0 commit comments