@@ -134,19 +134,41 @@ impl<M: Eq + Clone + Debug + Display> Display for DatedDerivation<M> {
134134 }
135135}
136136
137- #[ derive( Clone , Debug ) ]
138- enum AssignmentsIntersection {
139- Decision ( ( u32 , VersionIndex , Term ) ) ,
140- Derivations ( Term ) ,
137+ #[ derive( Clone , Debug , Default ) ]
138+ struct AssignmentsIntersection {
139+ term : Term ,
140+ is_decision : bool ,
141+ decision_global_index : u32 ,
142+ decision_version_index : VersionIndex ,
143+ }
144+
145+ impl AssignmentsIntersection {
146+ fn decision ( global_index : u32 , version_index : VersionIndex ) -> Self {
147+ Self {
148+ term : Term :: exact ( version_index) ,
149+ is_decision : true ,
150+ decision_global_index : global_index,
151+ decision_version_index : version_index,
152+ }
153+ }
154+
155+ fn derivations ( term : Term ) -> Self {
156+ Self {
157+ term,
158+ ..Default :: default ( )
159+ }
160+ }
141161}
142162
143163impl Display for AssignmentsIntersection {
144164 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
145- match self {
146- Self :: Decision ( ( lvl, version_index, _) ) => {
147- write ! ( f, "Decision: level {}, v = {}" , lvl, version_index. get( ) )
148- }
149- Self :: Derivations ( term) => write ! ( f, "Derivations term: {}" , term) ,
165+ if self . is_decision {
166+ let lvl = self . decision_global_index ;
167+ let version = self . decision_version_index . get ( ) ;
168+ write ! ( f, "Decision: level {lvl}, v = {version}" )
169+ } else {
170+ let term = self . term ;
171+ write ! ( f, "Derivations term: {term}" )
150172 }
151173 }
152174}
@@ -193,25 +215,26 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
193215 pub ( crate ) fn add_decision ( & mut self , package_id : PackageId , version_index : VersionIndex ) {
194216 // Check that add_decision is never used in the wrong context.
195217 if cfg ! ( debug_assertions) {
196- match self . package_assignments . get_mut ( & package_id) {
197- None => panic ! ( "Derivations must already exist" ) ,
198- Some ( pa) => match & pa. assignments_intersection {
199- // Cannot be called when a decision has already been taken.
200- AssignmentsIntersection :: Decision ( _) => panic ! ( "Already existing decision" ) ,
201- // Cannot be called if the versions is not contained in the terms' intersection.
202- AssignmentsIntersection :: Derivations ( term) => {
203- debug_assert ! (
204- term. contains( version_index) ,
205- "{} was expected to be contained in {}" ,
206- version_index. get( ) ,
207- term,
208- )
209- }
210- } ,
211- }
218+ let pa = self
219+ . package_assignments
220+ . get_mut ( & package_id)
221+ . expect ( "Derivations must already exist" ) ;
222+ // Cannot be called when a decision has already been taken.
223+ assert ! (
224+ !pa. assignments_intersection. is_decision,
225+ "Already existing decision" ,
226+ ) ;
227+ // Cannot be called if the versions is not contained in the terms' intersection.
228+ let term = pa. assignments_intersection . term ;
229+ assert ! (
230+ term. contains( version_index) ,
231+ "{} was expected to be contained in {}" ,
232+ version_index. get( ) ,
233+ term,
234+ ) ;
212235 assert_eq ! (
213236 self . changed_this_decision_level,
214- self . package_assignments. len( )
237+ self . package_assignments. len( ) ,
215238 ) ;
216239 }
217240 let new_idx = self . current_decision_level . 0 as usize ;
@@ -221,11 +244,8 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
221244 . get_full_mut ( & package_id)
222245 . expect ( "Derivations must already exist" ) ;
223246 pa. highest_decision_level = self . current_decision_level ;
224- pa. assignments_intersection = AssignmentsIntersection :: Decision ( (
225- self . next_global_index ,
226- version_index,
227- Term :: exact ( version_index) ,
228- ) ) ;
247+ pa. assignments_intersection =
248+ AssignmentsIntersection :: decision ( self . next_global_index , version_index) ;
229249 // Maintain that the beginning of the `package_assignments` Have all decisions in sorted order.
230250 if new_idx != old_idx {
231251 self . package_assignments . swap_indices ( new_idx, old_idx) ;
@@ -254,21 +274,19 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
254274 let idx = occupied. index ( ) ;
255275 let pa = occupied. get_mut ( ) ;
256276 pa. highest_decision_level = self . current_decision_level ;
257- match & mut pa. assignments_intersection {
258- // Check that add_derivation is never called in the wrong context.
259- AssignmentsIntersection :: Decision ( _) => {
260- panic ! ( "add_derivation should not be called after a decision" )
261- }
262- AssignmentsIntersection :: Derivations ( t) => {
263- * t = t. intersection ( dated_derivation. accumulated_intersection ) ;
264- dated_derivation. accumulated_intersection = * t;
265- if t. is_positive ( ) {
266- // we can use `swap_indices` to make `changed_this_decision_level` only go down by 1
267- // but the copying is slower then the larger search
268- self . changed_this_decision_level =
269- std:: cmp:: min ( self . changed_this_decision_level , idx) ;
270- }
271- }
277+ // Check that add_derivation is never called in the wrong context.
278+ assert ! (
279+ !pa. assignments_intersection. is_decision,
280+ "add_derivation should not be called after a decision" ,
281+ ) ;
282+ let t = & mut pa. assignments_intersection . term ;
283+ * t = t. intersection ( dated_derivation. accumulated_intersection ) ;
284+ dated_derivation. accumulated_intersection = * t;
285+ if t. is_positive ( ) {
286+ // we can use `swap_indices` to make `changed_this_decision_level` only go down by 1
287+ // but the copying is slower then the larger search
288+ self . changed_this_decision_level =
289+ std:: cmp:: min ( self . changed_this_decision_level , idx) ;
272290 }
273291 pa. dated_derivations . push ( dated_derivation) ;
274292 }
@@ -282,7 +300,7 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
282300 smallest_decision_level : self . current_decision_level ,
283301 highest_decision_level : self . current_decision_level ,
284302 dated_derivations : SmallVec :: One ( [ dated_derivation] ) ,
285- assignments_intersection : AssignmentsIntersection :: Derivations ( term) ,
303+ assignments_intersection : AssignmentsIntersection :: derivations ( term) ,
286304 } ) ;
287305 }
288306 }
@@ -328,11 +346,12 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
328346 . package_assignments
329347 . iter ( )
330348 . take ( self . current_decision_level . 0 as usize )
331- . map ( |( & pid, pa) | match pa. assignments_intersection {
332- AssignmentsIntersection :: Decision ( ( _, version_index, _) ) => ( pid, version_index) ,
333- AssignmentsIntersection :: Derivations ( _) => {
334- panic ! ( "Derivations in the Decision part" )
335- }
349+ . map ( |( & pid, pa) | {
350+ assert ! (
351+ pa. assignments_intersection. is_decision,
352+ "Derivations in the Decision part" ,
353+ ) ;
354+ ( pid, pa. assignments_intersection . decision_version_index )
336355 } )
337356 . collect :: < Map < _ , _ > > ( ) ;
338357
@@ -375,7 +394,7 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
375394
376395 // Reset the assignments intersection.
377396 pa. assignments_intersection =
378- AssignmentsIntersection :: Derivations ( last. accumulated_intersection ) ;
397+ AssignmentsIntersection :: derivations ( last. accumulated_intersection ) ;
379398 true
380399 }
381400 } ) ;
@@ -463,7 +482,7 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
463482 pub ( crate ) fn term_intersection_for_package ( & self , package_id : PackageId ) -> Option < Term > {
464483 self . package_assignments
465484 . get ( & package_id)
466- . map ( |pa| pa. assignments_intersection . term ( ) )
485+ . map ( |pa| pa. assignments_intersection . term )
467486 }
468487
469488 /// Figure out if the satisfier and previous satisfier are of different decision levels.
@@ -545,10 +564,11 @@ impl<DP: DependencyProvider> PartialSolution<DP> {
545564 let accum_term = if let Some ( cause) = satisfier_cause {
546565 store[ cause] . get ( satisfier_pid) . unwrap ( ) . negate ( )
547566 } else {
548- match satisfier_pa. assignments_intersection {
549- AssignmentsIntersection :: Derivations ( _) => panic ! ( "must be a decision" ) ,
550- AssignmentsIntersection :: Decision ( ( _, _, term) ) => term,
551- }
567+ assert ! (
568+ satisfier_pa. assignments_intersection. is_decision,
569+ "must be a decision" ,
570+ ) ;
571+ satisfier_pa. assignments_intersection . term
552572 } ;
553573
554574 let incompat_term = incompat
@@ -590,49 +610,37 @@ impl<M: Eq + Clone + Debug + Display> PackageAssignments<M> {
590610 debug_assert_eq ! ( dd. accumulated_intersection. intersection( start_term) , empty) ;
591611 return ( Some ( dd. cause ) , dd. global_index , dd. decision_level ) ;
592612 }
593- // If it wasn't found in the derivations,
594- // it must be the decision which is last (if called in the right context).
595- match & self . assignments_intersection {
596- AssignmentsIntersection :: Decision ( ( global_index , _ , _ ) ) => {
597- ( None , * global_index , self . highest_decision_level )
598- }
599- AssignmentsIntersection :: Derivations ( accumulated_intersection ) => {
600- let p = package_store . pkg ( package_id ) . unwrap ( ) ;
601- unreachable ! (
602- "while processing package {p}: \
603- accum_term = {accumulated_intersection} has overlap with incompat_term = {start_term}, \
604- which means the last assignment should have been a decision , \
605- but instead it was a derivation. This shouldn't be possible! \
606- (Maybe your Version ordering is broken?)"
607- )
608- }
613+ // If it wasn't found in the derivations, it must be the decision which is last (if called in the right context).
614+ let AssignmentsIntersection {
615+ term ,
616+ is_decision ,
617+ decision_global_index ,
618+ ..
619+ } = self . assignments_intersection ;
620+ if !is_decision {
621+ let p = package_store . pkg ( package_id ) . unwrap ( ) ;
622+ unreachable ! (
623+ "while processing package {p}: \
624+ accum_term = {term} has overlap with incompat_term = {start_term} , \
625+ which means the last assignment should have been a decision, \
626+ but instead it was a derivation. This shouldn't be possible! \
627+ (Maybe your Version ordering is broken?)"
628+ )
609629 }
630+ ( None , decision_global_index, self . highest_decision_level )
610631 }
611632}
612633
613634impl AssignmentsIntersection {
614- /// Returns the term intersection of all assignments (decision included).
615- fn term ( & self ) -> Term {
616- match * self {
617- Self :: Decision ( ( _, _, term) ) => term,
618- Self :: Derivations ( term) => term,
619- }
620- }
621-
622635 /// A package is a potential pick if there isn't an already
623636 /// selected version (no "decision")
624637 /// and if it contains at least one positive derivation term
625638 /// in the partial solution.
626639 fn potential_package_filter ( & self , package_id : PackageId ) -> Option < ( PackageId , VersionSet ) > {
627- match self {
628- Self :: Decision ( _) => None ,
629- Self :: Derivations ( term_intersection) => {
630- if term_intersection. is_positive ( ) {
631- Some ( ( package_id, term_intersection. unwrap_positive ( ) ) )
632- } else {
633- None
634- }
635- }
640+ if !self . is_decision && self . term . is_positive ( ) {
641+ Some ( ( package_id, self . term . unwrap_positive ( ) ) )
642+ } else {
643+ None
636644 }
637645 }
638646}
0 commit comments