@@ -811,10 +811,8 @@ impl RemainingCandidates {
811811 }
812812}
813813
814- /// Attempts to find a new conflict that allows a `find_candidate` feather then the input one.
814+ /// Attempts to find a new conflict that allows a `find_candidate` better then the input one.
815815/// It will add the new conflict to the cache if one is found.
816- ///
817- /// Panics if the input conflict is not all active in `cx`.
818816fn generalize_conflicting (
819817 cx : & Context ,
820818 registry : & mut RegistryQueryer < ' _ > ,
@@ -823,15 +821,12 @@ fn generalize_conflicting(
823821 dep : & Dependency ,
824822 conflicting_activations : & ConflictMap ,
825823) -> Option < ConflictMap > {
826- if conflicting_activations. is_empty ( ) {
827- return None ;
828- }
829824 // We need to determine the `ContextAge` that this `conflicting_activations` will jump to, and why.
830- let ( backtrack_critical_age, backtrack_critical_id) = conflicting_activations
831- . keys ( )
832- . map ( | & c| ( cx . is_active ( c ) . expect ( "not currently active!?" ) , c ) )
833- . max ( )
834- . unwrap ( ) ;
825+ let ( backtrack_critical_age, backtrack_critical_id) = shortcircuit_max (
826+ conflicting_activations
827+ . keys ( )
828+ . map ( | & c| cx . is_active ( c ) . map ( |a| ( a , c ) ) ) ,
829+ ) ? ;
835830 let backtrack_critical_reason: ConflictReason =
836831 conflicting_activations[ & backtrack_critical_id] . clone ( ) ;
837832
@@ -923,6 +918,19 @@ fn generalize_conflicting(
923918 None
924919}
925920
921+ /// Returns Some of the largest item in the iterator.
922+ /// Returns None if any of the items are None or the iterator is empty.
923+ fn shortcircuit_max < I : Ord > ( iter : impl Iterator < Item = Option < I > > ) -> Option < I > {
924+ let mut out = None ;
925+ for i in iter {
926+ if i. is_none ( ) {
927+ return None ;
928+ }
929+ out = std:: cmp:: max ( out, i) ;
930+ }
931+ out
932+ }
933+
926934/// Looks through the states in `backtrack_stack` for dependencies with
927935/// remaining candidates. For each one, also checks if rolling back
928936/// could change the outcome of the failed resolution that caused backtracking
@@ -949,12 +957,10 @@ fn find_candidate(
949957 // the cause of that backtrack, so we do not update it.
950958 let age = if !backtracked {
951959 // we don't have abnormal situations. So we can ask `cx` for how far back we need to go.
952- let a = cx. is_conflicting ( Some ( parent. package_id ( ) ) , conflicting_activations) ;
953- // If the `conflicting_activations` does not apply to `cx`, then something went very wrong
954- // in building it. But we will just fall back to laboriously trying all possibilities witch
955- // will give us the correct answer so only `assert` if there is a developer to debug it.
956- debug_assert ! ( a. is_some( ) ) ;
957- a
960+ // If the `conflicting_activations` does not apply to `cx`,
961+ // we will just fall back to laboriously trying all possibilities witch
962+ // will give us the correct answer.
963+ cx. is_conflicting ( Some ( parent. package_id ( ) ) , conflicting_activations)
958964 } else {
959965 None
960966 } ;
0 commit comments