@@ -133,19 +133,41 @@ impl<M: Eq + Clone + Debug + Display> Display for DatedDerivation<M> {
133133 }
134134}
135135
136- #[ derive( Clone , Debug ) ]
137- enum AssignmentsIntersection {
138- Decision ( ( u32 , VersionIndex , Term ) ) ,
139- Derivations ( Term ) ,
136+ #[ derive( Clone , Debug , Default ) ]
137+ struct AssignmentsIntersection {
138+ term : Term ,
139+ is_decision : bool ,
140+ decision_global_index : u32 ,
141+ decision_version_index : VersionIndex ,
142+ }
143+
144+ impl AssignmentsIntersection {
145+ fn decision ( global_index : u32 , version_index : VersionIndex ) -> Self {
146+ Self {
147+ term : Term :: exact ( version_index) ,
148+ is_decision : true ,
149+ decision_global_index : global_index,
150+ decision_version_index : version_index,
151+ }
152+ }
153+
154+ fn derivations ( term : Term ) -> Self {
155+ Self {
156+ term,
157+ ..Default :: default ( )
158+ }
159+ }
140160}
141161
142162impl Display for AssignmentsIntersection {
143163 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
144- match self {
145- Self :: Decision ( ( lvl, version_index, _) ) => {
146- write ! ( f, "Decision: level {}, v = {}" , lvl, version_index. get( ) )
147- }
148- Self :: Derivations ( term) => write ! ( f, "Derivations term: {}" , term) ,
164+ if self . is_decision {
165+ let lvl = self . decision_global_index ;
166+ let version = self . decision_version_index . get ( ) ;
167+ write ! ( f, "Decision: level {lvl}, v = {version}" )
168+ } else {
169+ let term = self . term ;
170+ write ! ( f, "Derivations term: {term}" )
149171 }
150172 }
151173}
@@ -192,25 +214,26 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
192214 pub ( crate ) fn add_decision ( & mut self , package_id : PackageId , version_index : VersionIndex ) {
193215 // Check that add_decision is never used in the wrong context.
194216 if cfg ! ( debug_assertions) {
195- match self . package_assignments . get_mut ( & package_id) {
196- None => panic ! ( "Derivations must already exist" ) ,
197- Some ( pa) => match & pa. assignments_intersection {
198- // Cannot be called when a decision has already been taken.
199- AssignmentsIntersection :: Decision ( _) => panic ! ( "Already existing decision" ) ,
200- // Cannot be called if the versions is not contained in the terms' intersection.
201- AssignmentsIntersection :: Derivations ( term) => {
202- debug_assert ! (
203- term. contains( version_index) ,
204- "{} was expected to be contained in {}" ,
205- version_index. get( ) ,
206- term,
207- )
208- }
209- } ,
210- }
217+ let pa = self
218+ . package_assignments
219+ . get_mut ( & package_id)
220+ . expect ( "Derivations must already exist" ) ;
221+ // Cannot be called when a decision has already been taken.
222+ assert ! (
223+ !pa. assignments_intersection. is_decision,
224+ "Already existing decision" ,
225+ ) ;
226+ // Cannot be called if the versions is not contained in the terms' intersection.
227+ let term = pa. assignments_intersection . term ;
228+ assert ! (
229+ term. contains( version_index) ,
230+ "{} was expected to be contained in {}" ,
231+ version_index. get( ) ,
232+ term,
233+ ) ;
211234 assert_eq ! (
212235 self . changed_this_decision_level,
213- self . package_assignments. len( )
236+ self . package_assignments. len( ) ,
214237 ) ;
215238 }
216239 let new_idx = self . current_decision_level . 0 as usize ;
@@ -220,11 +243,8 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
220243 . get_full_mut ( & package_id)
221244 . expect ( "Derivations must already exist" ) ;
222245 pa. highest_decision_level = self . current_decision_level ;
223- pa. assignments_intersection = AssignmentsIntersection :: Decision ( (
224- self . next_global_index ,
225- version_index,
226- Term :: exact ( version_index) ,
227- ) ) ;
246+ pa. assignments_intersection =
247+ AssignmentsIntersection :: decision ( self . next_global_index , version_index) ;
228248 // Maintain that the beginning of the `package_assignments` Have all decisions in sorted order.
229249 if new_idx != old_idx {
230250 self . package_assignments . swap_indices ( new_idx, old_idx) ;
@@ -253,21 +273,19 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
253273 let idx = occupied. index ( ) ;
254274 let pa = occupied. get_mut ( ) ;
255275 pa. highest_decision_level = self . current_decision_level ;
256- match & mut pa. assignments_intersection {
257- // Check that add_derivation is never called in the wrong context.
258- AssignmentsIntersection :: Decision ( _) => {
259- panic ! ( "add_derivation should not be called after a decision" )
260- }
261- AssignmentsIntersection :: Derivations ( t) => {
262- * t = t. intersection ( dated_derivation. accumulated_intersection ) ;
263- dated_derivation. accumulated_intersection = * t;
264- if t. is_positive ( ) {
265- // we can use `swap_indices` to make `changed_this_decision_level` only go down by 1
266- // but the copying is slower then the larger search
267- self . changed_this_decision_level =
268- std:: cmp:: min ( self . changed_this_decision_level , idx) ;
269- }
270- }
276+ // Check that add_derivation is never called in the wrong context.
277+ assert ! (
278+ !pa. assignments_intersection. is_decision,
279+ "add_derivation should not be called after a decision" ,
280+ ) ;
281+ let t = & mut pa. assignments_intersection . term ;
282+ * t = t. intersection ( dated_derivation. accumulated_intersection ) ;
283+ dated_derivation. accumulated_intersection = * t;
284+ if t. is_positive ( ) {
285+ // we can use `swap_indices` to make `changed_this_decision_level` only go down by 1
286+ // but the copying is slower then the larger search
287+ self . changed_this_decision_level =
288+ std:: cmp:: min ( self . changed_this_decision_level , idx) ;
271289 }
272290 pa. dated_derivations . push ( dated_derivation) ;
273291 }
@@ -281,7 +299,7 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
281299 smallest_decision_level : self . current_decision_level ,
282300 highest_decision_level : self . current_decision_level ,
283301 dated_derivations : SmallVec :: One ( [ dated_derivation] ) ,
284- assignments_intersection : AssignmentsIntersection :: Derivations ( term) ,
302+ assignments_intersection : AssignmentsIntersection :: derivations ( term) ,
285303 } ) ;
286304 }
287305 }
@@ -327,11 +345,12 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
327345 . package_assignments
328346 . iter ( )
329347 . take ( self . current_decision_level . 0 as usize )
330- . map ( |( & pid, pa) | match pa. assignments_intersection {
331- AssignmentsIntersection :: Decision ( ( _, version_index, _) ) => ( pid, version_index) ,
332- AssignmentsIntersection :: Derivations ( _) => {
333- panic ! ( "Derivations in the Decision part" )
334- }
348+ . map ( |( & pid, pa) | {
349+ assert ! (
350+ pa. assignments_intersection. is_decision,
351+ "Derivations in the Decision part" ,
352+ ) ;
353+ ( pid, pa. assignments_intersection . decision_version_index )
335354 } )
336355 . collect :: < Map < _ , _ > > ( ) ;
337356
@@ -374,7 +393,7 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
374393
375394 // Reset the assignments intersection.
376395 pa. assignments_intersection =
377- AssignmentsIntersection :: Derivations ( last. accumulated_intersection ) ;
396+ AssignmentsIntersection :: derivations ( last. accumulated_intersection ) ;
378397 true
379398 }
380399 } ) ;
@@ -462,7 +481,7 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
462481 pub ( crate ) fn term_intersection_for_package ( & self , package_id : PackageId ) -> Option < Term > {
463482 self . package_assignments
464483 . get ( & package_id)
465- . map ( |pa| pa. assignments_intersection . term ( ) )
484+ . map ( |pa| pa. assignments_intersection . term )
466485 }
467486
468487 /// Figure out if the satisfier and previous satisfier are of different decision levels.
@@ -544,10 +563,11 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
544563 let accum_term = if let & Some ( cause) = satisfier_cause {
545564 store[ cause] . get ( satisfier_package_id) . unwrap ( ) . negate ( )
546565 } else {
547- match satisfier_pa. assignments_intersection {
548- AssignmentsIntersection :: Derivations ( _) => panic ! ( "must be a decision" ) ,
549- AssignmentsIntersection :: Decision ( ( _, _, term) ) => term,
550- }
566+ assert ! (
567+ satisfier_pa. assignments_intersection. is_decision,
568+ "must be a decision" ,
569+ ) ;
570+ satisfier_pa. assignments_intersection . term
551571 } ;
552572
553573 let incompat_term = incompat
@@ -589,49 +609,37 @@ impl<M: Eq + Clone + Debug + Display> PackageAssignments<M> {
589609 debug_assert_eq ! ( dd. accumulated_intersection. intersection( start_term) , empty) ;
590610 return ( Some ( dd. cause ) , dd. global_index , dd. decision_level ) ;
591611 }
592- // If it wasn't found in the derivations,
593- // it must be the decision which is last (if called in the right context).
594- match & self . assignments_intersection {
595- AssignmentsIntersection :: Decision ( ( global_index , _ , _ ) ) => {
596- ( None , * global_index , self . highest_decision_level )
597- }
598- AssignmentsIntersection :: Derivations ( accumulated_intersection ) => {
599- let p = package_store . pkg ( package_id ) . unwrap ( ) ;
600- unreachable ! (
601- "while processing package {p}: \
602- accum_term = {accumulated_intersection} has overlap with incompat_term = {start_term}, \
603- which means the last assignment should have been a decision , \
604- but instead it was a derivation. This shouldn't be possible! \
605- (Maybe your Version ordering is broken?)"
606- )
607- }
612+ // If it wasn't found in the derivations, it must be the decision which is last (if called in the right context).
613+ let AssignmentsIntersection {
614+ term ,
615+ is_decision ,
616+ decision_global_index ,
617+ ..
618+ } = self . assignments_intersection ;
619+ if !is_decision {
620+ let p = package_store . pkg ( package_id ) . unwrap ( ) ;
621+ unreachable ! (
622+ "while processing package {p}: \
623+ accum_term = {term} has overlap with incompat_term = {start_term} , \
624+ which means the last assignment should have been a decision, \
625+ but instead it was a derivation. This shouldn't be possible! \
626+ (Maybe your Version ordering is broken?)"
627+ )
608628 }
629+ ( None , decision_global_index, self . highest_decision_level )
609630 }
610631}
611632
612633impl AssignmentsIntersection {
613- /// Returns the term intersection of all assignments (decision included).
614- fn term ( & self ) -> Term {
615- match * self {
616- Self :: Decision ( ( _, _, term) ) => term,
617- Self :: Derivations ( term) => term,
618- }
619- }
620-
621634 /// A package is a potential pick if there isn't an already
622635 /// selected version (no "decision")
623636 /// and if it contains at least one positive derivation term
624637 /// in the partial solution.
625638 fn potential_package_filter ( & self , package_id : PackageId ) -> Option < ( PackageId , VersionSet ) > {
626- match self {
627- Self :: Decision ( _) => None ,
628- Self :: Derivations ( term_intersection) => {
629- if term_intersection. is_positive ( ) {
630- Some ( ( package_id, term_intersection. unwrap_positive ( ) ) )
631- } else {
632- None
633- }
634- }
639+ if !self . is_decision && self . term . is_positive ( ) {
640+ Some ( ( package_id, self . term . unwrap_positive ( ) ) )
641+ } else {
642+ None
635643 }
636644 }
637645}
0 commit comments