]> git.proxmox.com Git - cargo.git/commitdiff
Merge remote-tracking branch 'origin/master' into PeekAtRemainingCandidates
authorEh2406 <YeomanYaacov@gmail.com>
Sun, 25 Feb 2018 01:23:49 +0000 (20:23 -0500)
committerEh2406 <YeomanYaacov@gmail.com>
Sun, 25 Feb 2018 01:28:54 +0000 (20:28 -0500)
# Conflicts:
# src/cargo/core/resolver/mod.rs

1  2 
src/cargo/core/resolver/mod.rs

index 8c80f5cf2a076001c9f9b77458cddbc7fa07d2ee,2345a59da42570c6ff998f015d10f5d11eaa046f..e4913268f53df9c6f00dc5e5fc5a367bf5d23fd5
@@@ -528,7 -532,21 +532,22 @@@ impl Ord for DepsFrame 
      }
  }
  
+ #[derive(Clone, PartialOrd, Ord, PartialEq, Eq)]
+ enum ConflictReason {
+     Semver,
+     Links(String),
+ }
+ impl ConflictReason {
+     fn is_links(&self) -> bool {
+         match self {
+             &ConflictReason::Semver => false,
+             &ConflictReason::Links(_) => true,
+         }
+     }
+ }
 +#[derive(Clone)]
  struct BacktrackFrame<'a> {
      cur: usize,
      context_backup: Context<'a>,
  struct RemainingCandidates {
      remaining: RcVecIter<Candidate>,
      // note: change to RcList or something if clone is to expensive
-     conflicting_prev_active: HashSet<PackageId>,
+     conflicting_prev_active: HashMap<PackageId, ConflictReason>,
 +    // This is a inlined peekable generator
 +    has_another: Option<Candidate>,
  }
  
  impl RemainingCandidates {
 -    fn next(&mut self, prev_active: &[Summary], links: &HashMap<String, PackageId>) -> Result<Candidate, HashMap<PackageId, ConflictReason>> {
 +    fn new(candidates: &Rc<Vec<Candidate>>) -> RemainingCandidates {
 +        RemainingCandidates {
 +            remaining: RcVecIter::new(Rc::clone(candidates)),
-             conflicting_prev_active: HashSet::new(),
++            conflicting_prev_active: HashMap::new(),
 +            has_another: None,
 +        }
 +    }
 +
-     fn next(&mut self, prev_active: &[Summary]) -> Result<(Candidate, bool), HashSet<PackageId>> {
++    fn next(&mut self, prev_active: &[Summary], links: &HashMap<String, PackageId>) -> Result<(Candidate, bool), HashMap<PackageId, ConflictReason>> {
          // Filter the set of candidates based on the previously activated
          // versions for this dependency. We can actually use a version if it
          // precisely matches an activated version or if it is otherwise
          // When we are done we return the set of previously activated
          // that conflicted with the ones we tried. If any of these change
          // then we would have considered different candidates.
 +        use std::mem::replace;
          for (_, b) in self.remaining.by_ref() {
 -            if let Some(a) = prev_active.iter().find(|a| compatible(a.version(), b.summary.version())) {
+             if let Some(link) = b.summary.links() {
+                 if let Some(a) = links.get(link) {
+                     if a != b.summary.package_id() {
+                         self.conflicting_prev_active.insert(a.clone(), ConflictReason::Links(link.to_owned()));
+                         continue
+                     }
+                 }
+             }
 +            if let Some(a) = prev_active
 +                .iter()
 +                .find(|a| compatible(a.version(), b.summary.version()))
 +            {
                  if *a != b.summary {
-                     self.conflicting_prev_active.insert(a.package_id().clone());
+                     self.conflicting_prev_active.insert(a.package_id().clone(), ConflictReason::Semver);
 -                    continue
 +                    continue;
                  }
              }
 -            return Ok(b);
 +            if let Some(r) = replace(&mut self.has_another, Some(b)) {
 +                return Ok((r, true));
 +            }
          }
 -        Err(self.conflicting_prev_active.clone())
 +        replace(&mut self.has_another, None)
 +            .map(|r| (r, false))
 +            .ok_or_else(|| self.conflicting_prev_active.clone())
      }
  }
  
@@@ -672,10 -680,20 +700,10 @@@ fn activate_deps_loop<'a>
          let (mut parent, (mut cur, (mut dep, candidates, mut features))) = frame;
          assert!(!remaining_deps.is_empty());
  
 -        let (next, has_another, remaining_candidates) = {
 -            let prev_active = cx.prev_active(&dep);
 -            trace!("{}[{}]>{} {} candidates", parent.name(), cur, dep.name(),
 -                   candidates.len());
 -            trace!("{}[{}]>{} {} prev activations", parent.name(), cur,
 -                   dep.name(), prev_active.len());
 -            let mut candidates = RemainingCandidates {
 -                remaining: RcVecIter::new(Rc::clone(&candidates)),
 -                conflicting_prev_active: HashMap::new(),
 -            };
 -            (candidates.next(prev_active, &cx.links),
 -             candidates.clone().next(prev_active, &cx.links).is_ok(),
 -             candidates)
 -        };
 +        trace!("{}[{}]>{} {} candidates", parent.name(), cur, dep.name(), candidates.len());
 +        trace!("{}[{}]>{} {} prev activations", parent.name(), cur, dep.name(), cx.prev_active(&dep).len());
 +        let mut remaining_candidates = RemainingCandidates::new(&candidates);
-         let next = remaining_candidates.next(cx.prev_active(&dep));
++        let next = remaining_candidates.next(cx.prev_active(&dep), &cx.links);
  
          // Alright, for each candidate that's gotten this far, it meets the
          // following requirements:
@@@ -767,11 -784,16 +795,11 @@@ fn find_candidate<'a>
      cur: &mut usize,
      dep: &mut Dependency,
      features: &mut Rc<Vec<String>>,
-     conflicting_activations: &mut HashSet<PackageId>,
 +    remaining_candidates: &mut RemainingCandidates,
 -) -> Option<Candidate> {
+     conflicting_activations: &mut HashMap<PackageId, ConflictReason>,
 +) -> Option<(Candidate, bool)> {
      while let Some(mut frame) = backtrack_stack.pop() {
-         let next= frame.remaining_candidates.next(frame.context_backup.prev_active(&frame.dep));
 -        let (next, has_another) = {
 -            let prev_active = frame.context_backup.prev_active(&frame.dep);
 -            (
 -                frame.remaining_candidates.next(prev_active, &frame.context_backup.links),
 -                frame.remaining_candidates.clone().next(prev_active, &frame.context_backup.links).is_ok(),
 -            )
 -        };
++        let next= frame.remaining_candidates.next(frame.context_backup.prev_active(&frame.dep), &frame.context_backup.links);
          if frame.context_backup.is_active(parent.package_id())
             && conflicting_activations
             .iter()