@@ -260,16 +260,8 @@ fn activate_deps_loop(
260260                . conflicting ( & resolver_ctx,  & dep) 
261261                . is_some ( ) ; 
262262
263-         let  mut  remaining_candidates = RemainingCandidates :: new ( & candidates) ; 
264- 
265-         // `conflicting_activations` stores all the reasons we were unable to 
266-         // activate candidates. One of these reasons will have to go away for 
267-         // backtracking to find a place to restart. It is also the list of 
268-         // things to explain in the error message if we fail to resolve. 
269-         // 
270-         // This is a map of package ID to a reason why that packaged caused a 
271-         // conflict for us. 
272-         let  mut  conflicting_activations = ConflictMap :: new ( ) ; 
263+         let  ( mut  remaining_candidates,  mut  conflicting_activations)  =
264+             RemainingCandidates :: new ( & candidates,  & resolver_ctx) ; 
273265
274266        // When backtracking we don't fully update `conflicting_activations` 
275267        // especially for the cases that we didn't make a backtrack frame in the 
@@ -279,7 +271,7 @@ fn activate_deps_loop(
279271        let  mut  backtracked = false ; 
280272
281273        loop  { 
282-             let  next = remaining_candidates. next ( & mut  conflicting_activations ,   & resolver_ctx ) ; 
274+             let  next = remaining_candidates. next ( ) ; 
283275
284276            let  ( candidate,  has_another)  = next. ok_or ( ( ) ) . or_else ( |_| { 
285277                // If we get here then our `remaining_candidates` was just 
@@ -712,47 +704,38 @@ struct BacktrackFrame {
712704/// more inputs) but in general acts like one. Each `RemainingCandidates` is 
713705/// created with a list of candidates to choose from. When attempting to iterate 
714706/// over the list of candidates only *valid* candidates are returned. Validity 
715- /// is defined within a `Context`. 
707+ /// is defined within a `Context`. In addition, the iterator will return 
708+ /// candidates that already have been activated first. 
716709/// 
717710/// Candidates passed to `new` may not be returned from `next` as they could be 
718- /// filtered out, and as they are filtered  the causes will be added to `conflicting_prev_active `. 
711+ /// filtered out. The filtered candidates and  the causes will be returned by `new `. 
719712#[ derive( Clone ) ]  
720713struct  RemainingCandidates  { 
721-     remaining :  RcVecIter < Summary > , 
714+     prioritized_candidates :  RcVecIter < Summary > , 
722715    // This is an inlined peekable generator 
723716    has_another :  Option < Summary > , 
724717} 
725718
726719impl  RemainingCandidates  { 
727-     fn  new ( candidates :  & Rc < Vec < Summary > > )  -> RemainingCandidates  { 
728-         RemainingCandidates  { 
729-             remaining :  RcVecIter :: new ( Rc :: clone ( candidates) ) , 
730-             has_another :  None , 
731-         } 
732-     } 
733- 
734-     /// Attempts to find another candidate to check from this list. 
735- /// 
736- /// This method will attempt to move this iterator forward, returning a 
737- /// candidate that's possible to activate. The `cx` argument is the current 
738- /// context which determines validity for candidates returned, and the `dep` 
739- /// is the dependency listing that we're activating for. 
740- /// 
741- /// If successful a `(Candidate, bool)` pair will be returned. The 
742- /// `Candidate` is the candidate to attempt to activate, and the `bool` is 
743- /// an indicator of whether there are remaining candidates to try of if 
744- /// we've reached the end of iteration. 
745- /// 
746- /// If we've reached the end of the iterator here then `Err` will be 
747- /// returned. The error will contain a map of package ID to conflict reason, 
748- /// where each package ID caused a candidate to be filtered out from the 
749- /// original list for the reason listed. 
750- fn  next ( 
751-         & mut  self , 
752-         conflicting_prev_active :  & mut  ConflictMap , 
720+     /// Prefilters and sorts the list of candidates to determine which ones are 
721+ /// valid to activate, and which ones should be prioritized. 
722+ fn  new ( 
723+         candidates :  & Rc < Vec < Summary > > , 
753724        cx :  & ResolverContext , 
754-     )  -> Option < ( Summary ,  bool ) >  { 
755-         for  b in  self . remaining . by_ref ( )  { 
725+     )  -> ( RemainingCandidates ,  ConflictMap )  { 
726+         // `conflicting_activations` stores all the reasons we were unable to 
727+         // activate candidates. One of these reasons will have to go away for 
728+         // backtracking to find a place to restart. It is also the list of 
729+         // things to explain in the error message if we fail to resolve. 
730+         // 
731+         // This is a map of package ID to a reason why that packaged caused a 
732+         // conflict for us. 
733+         let  mut  conflicting_activations = ConflictMap :: new ( ) ; 
734+ 
735+         let  mut  activated_candidates:  Vec < Summary >  = Vec :: with_capacity ( candidates. len ( ) ) ; 
736+         let  mut  non_activated_candidates:  Vec < Summary >  = Vec :: with_capacity ( candidates. len ( ) ) ; 
737+ 
738+         for  b in  candidates. as_ref ( )  { 
756739            let  b_id = b. package_id ( ) ; 
757740            // The `links` key in the manifest dictates that there's only one 
758741            // package in a dependency graph, globally, with that particular 
@@ -761,7 +744,7 @@ impl RemainingCandidates {
761744            if  let  Some ( link)  = b. links ( )  { 
762745                if  let  Some ( & a)  = cx. links . get ( & link)  { 
763746                    if  a != b_id { 
764-                         conflicting_prev_active 
747+                         conflicting_activations 
765748                            . entry ( a) 
766749                            . or_insert_with ( || ConflictReason :: Links ( link) ) ; 
767750                        continue ; 
@@ -774,18 +757,50 @@ impl RemainingCandidates {
774757            // semver-compatible versions of a crate. For example we can't 
775758            // simultaneously activate `foo 1.0.2` and `foo 1.2.0`. We can, 
776759            // however, activate `1.0.2` and `2.0.0`. 
777-             // 
778-             // Here we throw out our candidate if it's *compatible*, yet not 
779-             // equal, to all previously activated versions. 
780760            if  let  Some ( ( a,  _) )  = cx. activations . get ( & b_id. as_activations_key ( ) )  { 
781-                 if  * a != b { 
782-                     conflicting_prev_active
761+                 // If this candidate is already activated, then we want to put 
762+                 // it in our prioritized list to try first. 
763+                 if  a == b { 
764+                     activated_candidates. push ( b. clone ( ) ) ; 
765+                     continue ; 
766+                 } 
767+                 // Here we throw out our candidate if it's *compatible*, yet not 
768+                 // equal, to all previously activated versions. 
769+                 else  { 
770+                     conflicting_activations
783771                        . entry ( a. package_id ( ) ) 
784772                        . or_insert ( ConflictReason :: Semver ) ; 
785773                    continue ; 
786774                } 
775+             }  else  { 
776+                 non_activated_candidates. push ( b. clone ( ) ) ; 
787777            } 
778+         } 
788779
780+         // Combine the prioritized and non-prioritized candidates into one list 
781+         // such that the prioritized candidates are tried first. 
782+         activated_candidates. append ( & mut  non_activated_candidates) ; 
783+ 
784+         ( 
785+             RemainingCandidates  { 
786+                 prioritized_candidates :  RcVecIter :: new ( Rc :: new ( activated_candidates) ) , 
787+                 has_another :  None , 
788+             } , 
789+             conflicting_activations, 
790+         ) 
791+     } 
792+ 
793+     /// Attempts to find another candidate to check from this list. 
794+ /// 
795+ /// This method will attempt to move this iterator forward, returning a 
796+ /// candidate that's possible to activate. 
797+ /// 
798+ /// If successful a `(Candidate, bool)` pair will be returned. The 
799+ /// `Candidate` is the candidate to attempt to activate, and the `bool` is 
800+ /// an indicator of whether there are remaining candidates to try of if 
801+ /// we've reached the end of iteration. 
802+ fn  next ( & mut  self )  -> Option < ( Summary ,  bool ) >  { 
803+         for  b in  self . prioritized_candidates . by_ref ( )  { 
789804            // Well if we made it this far then we've got a valid dependency. We 
790805            // want this iterator to be inherently "peekable" so we don't 
791806            // necessarily return the item just yet. Instead we stash it away to 
@@ -961,9 +976,7 @@ fn find_candidate(
961976    } ; 
962977
963978    while  let  Some ( mut  frame)  = backtrack_stack. pop ( )  { 
964-         let  next = frame
965-             . remaining_candidates 
966-             . next ( & mut  frame. conflicting_activations ,  & frame. context ) ; 
979+         let  next = frame. remaining_candidates . next ( ) ; 
967980        let  Some ( ( candidate,  has_another) )  = next else  { 
968981            continue ; 
969982        } ; 
0 commit comments