@@ -19,14 +19,16 @@ use crate::solver::DependencyProvider;
1919use crate :: type_aliases:: { IncompDpId , Map } ;
2020use crate :: version_set:: VersionSet ;
2121
22+ use super :: arena:: { HashArena , Id } ;
23+
2224/// Current state of the PubGrub algorithm.
2325#[ derive( Clone ) ]
2426pub struct State < DP : DependencyProvider > {
25- root_package : DP :: P ,
27+ pub root_package : Id < DP :: P > ,
2628 root_version : DP :: V ,
2729
2830 #[ allow( clippy:: type_complexity) ]
29- incompatibilities : Map < DP :: P , Vec < IncompDpId < DP > > > ,
31+ incompatibilities : Map < Id < DP :: P > , Vec < IncompDpId < DP > > > ,
3032
3133 /// Store the ids of incompatibilities that are already contradicted.
3234 /// For each one keep track of the decision level when it was found to be contradicted.
@@ -36,7 +38,7 @@ pub struct State<DP: DependencyProvider> {
3638 /// All incompatibilities expressing dependencies,
3739 /// with common dependents merged.
3840 #[ allow( clippy:: type_complexity) ]
39- merged_dependencies : Map < ( DP :: P , DP :: P ) , SmallVec < IncompDpId < DP > > > ,
41+ merged_dependencies : Map < ( Id < DP :: P > , Id < DP :: P > ) , SmallVec < IncompDpId < DP > > > ,
4042
4143 /// Partial solution.
4244 /// TODO: remove pub.
@@ -45,29 +47,35 @@ pub struct State<DP: DependencyProvider> {
4547 /// The store is the reference storage for all incompatibilities.
4648 pub incompatibility_store : Arena < Incompatibility < DP :: P , DP :: VS , DP :: M > > ,
4749
50+ /// The store is the reference storage for all incompatibilities.
51+ pub package_store : HashArena < DP :: P > ,
52+
4853 /// This is a stack of work to be done in `unit_propagation`.
4954 /// It can definitely be a local variable to that method, but
5055 /// this way we can reuse the same allocation for better performance.
51- unit_propagation_buffer : SmallVec < DP :: P > ,
56+ unit_propagation_buffer : SmallVec < Id < DP :: P > > ,
5257}
5358
5459impl < DP : DependencyProvider > State < DP > {
5560 /// Initialization of PubGrub state.
5661 pub fn init ( root_package : DP :: P , root_version : DP :: V ) -> Self {
5762 let mut incompatibility_store = Arena :: new ( ) ;
63+ let mut package_store = HashArena :: new ( ) ;
64+ let root_package = package_store. alloc ( root_package) ;
5865 let not_root_id = incompatibility_store. alloc ( Incompatibility :: not_root (
59- root_package. clone ( ) ,
66+ root_package,
6067 root_version. clone ( ) ,
6168 ) ) ;
6269 let mut incompatibilities = Map :: default ( ) ;
63- incompatibilities. insert ( root_package. clone ( ) , vec ! [ not_root_id] ) ;
70+ incompatibilities. insert ( root_package, vec ! [ not_root_id] ) ;
6471 Self {
6572 root_package,
6673 root_version,
6774 incompatibilities,
6875 contradicted_incompatibilities : Map :: default ( ) ,
6976 partial_solution : PartialSolution :: empty ( ) ,
7077 incompatibility_store,
78+ package_store,
7179 unit_propagation_buffer : SmallVec :: Empty ,
7280 merged_dependencies : Map :: default ( ) ,
7381 }
@@ -82,18 +90,19 @@ impl<DP: DependencyProvider> State<DP> {
8290 /// Add an incompatibility to the state.
8391 pub fn add_incompatibility_from_dependencies (
8492 & mut self ,
85- package : DP :: P ,
93+ package : Id < DP :: P > ,
8694 version : DP :: V ,
8795 deps : impl IntoIterator < Item = ( DP :: P , DP :: VS ) > ,
8896 ) -> std:: ops:: Range < IncompDpId < DP > > {
8997 // Create incompatibilities and allocate them in the store.
9098 let new_incompats_id_range =
9199 self . incompatibility_store
92- . alloc_iter ( deps. into_iter ( ) . map ( |dep| {
100+ . alloc_iter ( deps. into_iter ( ) . map ( |( dep_p, dep_vs) | {
101+ let dep_pid = self . package_store . alloc ( dep_p) ;
93102 Incompatibility :: from_dependency (
94- package. clone ( ) ,
103+ package,
95104 <DP :: VS as VersionSet >:: singleton ( version. clone ( ) ) ,
96- dep ,
105+ ( dep_pid , dep_vs ) ,
97106 )
98107 } ) ) ;
99108 // Merge the newly created incompatibilities with the older ones.
@@ -105,7 +114,7 @@ impl<DP: DependencyProvider> State<DP> {
105114
106115 /// Unit propagation is the core mechanism of the solving algorithm.
107116 /// CF <https://github.com/dart-lang/pub/blob/master/doc/solver.md#unit-propagation>
108- pub fn unit_propagation ( & mut self , package : DP :: P ) -> Result < ( ) , NoSolutionError < DP > > {
117+ pub fn unit_propagation ( & mut self , package : Id < DP :: P > ) -> Result < ( ) , NoSolutionError < DP > > {
109118 self . unit_propagation_buffer . clear ( ) ;
110119 self . unit_propagation_buffer . push ( package) ;
111120 while let Some ( current_package) = self . unit_propagation_buffer . pop ( ) {
@@ -126,7 +135,7 @@ impl<DP: DependencyProvider> State<DP> {
126135 // we must perform conflict resolution.
127136 Relation :: Satisfied => {
128137 log:: info!(
129- "Start conflict resolution because incompat satisfied:\n {}" ,
138+ "Start conflict resolution because incompat satisfied:\n {:? }" ,
130139 current_incompat
131140 ) ;
132141 conflict_id = Some ( incompat_id) ;
@@ -139,7 +148,7 @@ impl<DP: DependencyProvider> State<DP> {
139148 // In practice the most common pathology is adding the same package repeatedly.
140149 // So we only check if it is duplicated with the last item.
141150 if self . unit_propagation_buffer . last ( ) != Some ( & package_almost) {
142- self . unit_propagation_buffer . push ( package_almost. clone ( ) ) ;
151+ self . unit_propagation_buffer . push ( package_almost) ;
143152 }
144153 // Add (not term) to the partial solution with incompat as cause.
145154 self . partial_solution . add_derivation (
@@ -165,7 +174,7 @@ impl<DP: DependencyProvider> State<DP> {
165174 self . build_derivation_tree ( terminal_incompat_id)
166175 } ) ?;
167176 self . unit_propagation_buffer . clear ( ) ;
168- self . unit_propagation_buffer . push ( package_almost. clone ( ) ) ;
177+ self . unit_propagation_buffer . push ( package_almost) ;
169178 // Add to the partial solution with incompat as cause.
170179 self . partial_solution . add_derivation (
171180 package_almost,
@@ -188,12 +197,12 @@ impl<DP: DependencyProvider> State<DP> {
188197 fn conflict_resolution (
189198 & mut self ,
190199 incompatibility : IncompDpId < DP > ,
191- ) -> Result < ( DP :: P , IncompDpId < DP > ) , IncompDpId < DP > > {
200+ ) -> Result < ( Id < DP :: P > , IncompDpId < DP > ) , IncompDpId < DP > > {
192201 let mut current_incompat_id = incompatibility;
193202 let mut current_incompat_changed = false ;
194203 loop {
195204 if self . incompatibility_store [ current_incompat_id]
196- . is_terminal ( & self . root_package , & self . root_version )
205+ . is_terminal ( self . root_package , & self . root_version )
197206 {
198207 return Err ( current_incompat_id) ;
199208 } else {
@@ -205,7 +214,6 @@ impl<DP: DependencyProvider> State<DP> {
205214 DifferentDecisionLevels {
206215 previous_satisfier_level,
207216 } => {
208- let package = package. clone ( ) ;
209217 self . backtrack (
210218 current_incompat_id,
211219 current_incompat_changed,
@@ -221,7 +229,7 @@ impl<DP: DependencyProvider> State<DP> {
221229 package,
222230 & self . incompatibility_store ,
223231 ) ;
224- log:: info!( "prior cause: {}" , prior_cause) ;
232+ log:: info!( "prior cause: {:? }" , prior_cause) ;
225233 current_incompat_id = self . incompatibility_store . alloc ( prior_cause) ;
226234 current_incompat_changed = true ;
227235 }
@@ -264,19 +272,16 @@ impl<DP: DependencyProvider> State<DP> {
264272 fn merge_incompatibility ( & mut self , mut id : IncompDpId < DP > ) {
265273 if let Some ( ( p1, p2) ) = self . incompatibility_store [ id] . as_dependency ( ) {
266274 // If we are a dependency, there's a good chance we can be merged with a previous dependency
267- let deps_lookup = self
268- . merged_dependencies
269- . entry ( ( p1. clone ( ) , p2. clone ( ) ) )
270- . or_default ( ) ;
275+ let deps_lookup = self . merged_dependencies . entry ( ( p1, p2) ) . or_default ( ) ;
271276 if let Some ( ( past, merged) ) = deps_lookup. as_mut_slice ( ) . iter_mut ( ) . find_map ( |past| {
272277 self . incompatibility_store [ id]
273278 . merge_dependents ( & self . incompatibility_store [ * past] )
274279 . map ( |m| ( past, m) )
275280 } ) {
276281 let new = self . incompatibility_store . alloc ( merged) ;
277- for ( pkg, _) in self . incompatibility_store [ new] . iter ( ) {
282+ for ( & pkg, _) in self . incompatibility_store [ new] . iter ( ) {
278283 self . incompatibilities
279- . entry ( pkg. clone ( ) )
284+ . entry ( pkg)
280285 . or_default ( )
281286 . retain ( |id| id != past) ;
282287 }
@@ -286,14 +291,11 @@ impl<DP: DependencyProvider> State<DP> {
286291 deps_lookup. push ( id) ;
287292 }
288293 }
289- for ( pkg, term) in self . incompatibility_store [ id] . iter ( ) {
294+ for ( & pkg, term) in self . incompatibility_store [ id] . iter ( ) {
290295 if cfg ! ( debug_assertions) {
291296 assert_ne ! ( term, & crate :: term:: Term :: any( ) ) ;
292297 }
293- self . incompatibilities
294- . entry ( pkg. clone ( ) )
295- . or_default ( )
296- . push ( id) ;
298+ self . incompatibilities . entry ( pkg) . or_default ( ) . push ( id) ;
297299 }
298300 }
299301
@@ -328,6 +330,7 @@ impl<DP: DependencyProvider> State<DP> {
328330 id,
329331 & shared_ids,
330332 & self . incompatibility_store ,
333+ & self . package_store ,
331334 & precomputed,
332335 ) ;
333336 precomputed. insert ( id, Arc :: new ( tree) ) ;
0 commit comments