@@ -107,6 +107,7 @@ pub struct DatedDerivation<P: Package, VS: VersionSet> {
107
107
global_index : u32 ,
108
108
decision_level : DecisionLevel ,
109
109
cause : IncompId < P , VS > ,
110
+ accumulated_intersection : Term < VS > ,
110
111
}
111
112
112
113
impl < P : Package , VS : VersionSet > Display for DatedDerivation < P , VS > {
@@ -207,11 +208,11 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
207
208
store : & Arena < Incompatibility < P , VS > > ,
208
209
) {
209
210
use indexmap:: map:: Entry ;
210
- let term = store[ cause] . get ( & package) . unwrap ( ) . negate ( ) ;
211
- let dated_derivation = DatedDerivation {
211
+ let mut dated_derivation = DatedDerivation {
212
212
global_index : self . next_global_index ,
213
213
decision_level : self . current_decision_level ,
214
214
cause,
215
+ accumulated_intersection : store[ cause] . get ( & package) . unwrap ( ) . negate ( ) ,
215
216
} ;
216
217
self . next_global_index += 1 ;
217
218
let pa_last_index = self . package_assignments . len ( ) . saturating_sub ( 1 ) ;
@@ -226,7 +227,8 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
226
227
panic ! ( "add_derivation should not be called after a decision" )
227
228
}
228
229
AssignmentsIntersection :: Derivations ( t) => {
229
- * t = t. intersection ( & term) ;
230
+ * t = t. intersection ( & dated_derivation. accumulated_intersection ) ;
231
+ dated_derivation. accumulated_intersection = t. clone ( ) ;
230
232
if t. is_positive ( ) {
231
233
// we can use `swap_indices` to make `changed_this_decision_level` only go down by 1
232
234
// but the copying is slower then the larger search
@@ -238,6 +240,7 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
238
240
pa. dated_derivations . push ( dated_derivation) ;
239
241
}
240
242
Entry :: Vacant ( v) => {
243
+ let term = dated_derivation. accumulated_intersection . clone ( ) ;
241
244
if term. is_positive ( ) {
242
245
self . changed_this_decision_level =
243
246
std:: cmp:: min ( self . changed_this_decision_level , pa_last_index) ;
@@ -297,13 +300,9 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
297
300
}
298
301
299
302
/// Backtrack the partial solution to a given decision level.
300
- pub fn backtrack (
301
- & mut self ,
302
- decision_level : DecisionLevel ,
303
- store : & Arena < Incompatibility < P , VS > > ,
304
- ) {
303
+ pub fn backtrack ( & mut self , decision_level : DecisionLevel ) {
305
304
self . current_decision_level = decision_level;
306
- self . package_assignments . retain ( |p , pa| {
305
+ self . package_assignments . retain ( |_p , pa| {
307
306
if pa. smallest_decision_level > decision_level {
308
307
// Remove all entries that have a smallest decision level higher than the backtrack target.
309
308
false
@@ -325,18 +324,14 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
325
324
}
326
325
debug_assert ! ( !pa. dated_derivations. is_empty( ) ) ;
327
326
327
+ let last = pa. dated_derivations . last ( ) . unwrap ( ) ;
328
+
328
329
// Update highest_decision_level.
329
- pa. highest_decision_level = pa. dated_derivations . last ( ) . unwrap ( ) . decision_level ;
330
-
331
- // Recompute the assignments intersection.
332
- pa. assignments_intersection = AssignmentsIntersection :: Derivations (
333
- pa. dated_derivations
334
- . iter ( )
335
- . fold ( Term :: any ( ) , |acc, dated_derivation| {
336
- let term = store[ dated_derivation. cause ] . get ( p) . unwrap ( ) . negate ( ) ;
337
- acc. intersection ( & term)
338
- } ) ,
339
- ) ;
330
+ pa. highest_decision_level = last. decision_level ;
331
+
332
+ // Reset the assignments intersection.
333
+ pa. assignments_intersection =
334
+ AssignmentsIntersection :: Derivations ( last. accumulated_intersection . clone ( ) ) ;
340
335
true
341
336
}
342
337
} ) ;
@@ -400,7 +395,7 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
400
395
incompat : & Incompatibility < P , VS > ,
401
396
store : & Arena < Incompatibility < P , VS > > ,
402
397
) -> ( P , SatisfierSearch < P , VS > ) {
403
- let satisfied_map = Self :: find_satisfier ( incompat, & self . package_assignments , store ) ;
398
+ let satisfied_map = Self :: find_satisfier ( incompat, & self . package_assignments ) ;
404
399
let ( satisfier_package, & ( satisfier_index, _, satisfier_decision_level) ) = satisfied_map
405
400
. iter ( )
406
401
. max_by_key ( |( _p, ( _, global_index, _) ) | global_index)
@@ -440,14 +435,13 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
440
435
fn find_satisfier (
441
436
incompat : & Incompatibility < P , VS > ,
442
437
package_assignments : & FnvIndexMap < P , PackageAssignments < P , VS > > ,
443
- store : & Arena < Incompatibility < P , VS > > ,
444
438
) -> SmallMap < P , ( usize , u32 , DecisionLevel ) > {
445
439
let mut satisfied = SmallMap :: Empty ;
446
440
for ( package, incompat_term) in incompat. iter ( ) {
447
441
let pa = package_assignments. get ( package) . expect ( "Must exist" ) ;
448
442
satisfied. insert (
449
443
package. clone ( ) ,
450
- pa. satisfier ( package, incompat_term, Term :: any ( ) , store ) ,
444
+ pa. satisfier ( package, incompat_term, & Term :: any ( ) ) ,
451
445
) ;
452
446
}
453
447
satisfied
@@ -483,7 +477,7 @@ impl<P: Package, VS: VersionSet, Priority: Ord + Clone> PartialSolution<P, VS, P
483
477
484
478
satisfied_map. insert (
485
479
satisfier_package. clone ( ) ,
486
- satisfier_pa. satisfier ( satisfier_package, incompat_term, accum_term, store ) ,
480
+ satisfier_pa. satisfier ( satisfier_package, incompat_term, & accum_term) ,
487
481
) ;
488
482
489
483
// Finally, let's identify the decision level of that previous satisfier.
@@ -504,16 +498,15 @@ impl<P: Package, VS: VersionSet> PackageAssignments<P, VS> {
504
498
& self ,
505
499
package : & P ,
506
500
incompat_term : & Term < VS > ,
507
- start_term : Term < VS > ,
508
- store : & Arena < Incompatibility < P , VS > > ,
501
+ start_term : & Term < VS > ,
509
502
) -> ( usize , u32 , DecisionLevel ) {
510
- // Term where we accumulate intersections until incompat_term is satisfied.
511
- let mut accum_term = start_term;
512
503
// Indicate if we found a satisfier in the list of derivations, otherwise it will be the decision.
513
504
for ( idx, dated_derivation) in self . dated_derivations . iter ( ) . enumerate ( ) {
514
- let this_term = store[ dated_derivation. cause ] . get ( package) . unwrap ( ) . negate ( ) ;
515
- accum_term = accum_term. intersection ( & this_term) ;
516
- if accum_term. subset_of ( incompat_term) {
505
+ if dated_derivation
506
+ . accumulated_intersection
507
+ . intersection ( start_term)
508
+ . subset_of ( incompat_term)
509
+ {
517
510
// We found the derivation causing satisfaction.
518
511
return (
519
512
idx,
@@ -524,13 +517,13 @@ impl<P: Package, VS: VersionSet> PackageAssignments<P, VS> {
524
517
}
525
518
// If it wasn't found in the derivations,
526
519
// it must be the decision which is last (if called in the right context).
527
- match self . assignments_intersection {
520
+ match & self . assignments_intersection {
528
521
AssignmentsIntersection :: Decision ( ( global_index, _, _) ) => (
529
522
self . dated_derivations . len ( ) ,
530
- global_index,
523
+ * global_index,
531
524
self . highest_decision_level ,
532
525
) ,
533
- AssignmentsIntersection :: Derivations ( _ ) => {
526
+ AssignmentsIntersection :: Derivations ( accumulated_intersection ) => {
534
527
unreachable ! (
535
528
concat!(
536
529
"while processing package {}: " ,
@@ -539,7 +532,9 @@ impl<P: Package, VS: VersionSet> PackageAssignments<P, VS> {
539
532
"but instead it was a derivation. This shouldn't be possible! " ,
540
533
"(Maybe your Version ordering is broken?)"
541
534
) ,
542
- package, accum_term, incompat_term
535
+ package,
536
+ accumulated_intersection. intersection( start_term) ,
537
+ incompat_term
543
538
)
544
539
}
545
540
}
0 commit comments