// possible.
#[derive(Clone)]
struct Context<'a> {
- // TODO: Both this and the map below are super expensive to clone. We should
+ // TODO: Both this and the map two below are super expensive to clone. We should
// switch to persistent hash maps if we can at some point or otherwise
// make these much cheaper to clone in general.
activations: Activations,
resolve_features: HashMap<PackageId, HashSet<String>>,
+ links: HashSet<String>,
// These are two cheaply-cloneable lists (O(1) clone) which are effectively
// hash maps but are built up as "construction lists". We'll iterate these
let cx = Context {
resolve_graph: RcList::new(),
resolve_features: HashMap::new(),
+ links: HashSet::new(),
resolve_replacements: RcList::new(),
activations: HashMap::new(),
replacements,
}
impl RemainingCandidates {
- fn next(&mut self, prev_active: &[Summary], links: &HashSet<&str>) -> Option<Candidate> {
+ fn next(&mut self, prev_active: &[Summary], links: &HashSet<String>) -> Option<Candidate> {
// 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
let (next, has_another, remaining_candidates) = {
let prev_active = cx.prev_active(&dep);
- let prev_links = cx.prev_links();
trace!("{}[{}]>{} {} candidates", parent.name(), cur, dep.name(),
candidates.len());
trace!("{}[{}]>{} {} prev activations", parent.name(), cur,
let mut candidates = RemainingCandidates {
remaining: RcVecIter::new(Rc::clone(&candidates)),
};
- (candidates.next(prev_active, &prev_links),
- candidates.clone().next(prev_active, &prev_links).is_some(),
+ (candidates.next(prev_active, &cx.links),
+ candidates.clone().next(prev_active, &cx.links).is_some(),
candidates)
};
while let Some(mut frame) = backtrack_stack.pop() {
let (next, has_another) = {
let prev_active = frame.context_backup.prev_active(&frame.dep);
- let prev_links = frame.context_backup.prev_links();
- (frame.remaining_candidates.next(prev_active, &prev_links),
- frame.remaining_candidates.clone().next(prev_active, &prev_links).is_some())
+ (frame.remaining_candidates.next(prev_active, &frame.context_backup.links),
+ frame.remaining_candidates.clone().next(prev_active, &frame.context_backup.links).is_some())
};
if let Some(candidate) = next {
*cur = frame.cur;
.or_insert(Vec::new());
if !prev.iter().any(|c| c == summary) {
self.resolve_graph.push(GraphNode::Add(id.clone()));
+ if let Some(link) = summary.links() {
+ self.links.insert(link.to_owned());
+ }
prev.push(summary.clone());
return false
}
.unwrap_or(&[])
}
- fn prev_links(&self) -> HashSet<&str> {
- self.activations.iter()
- .flat_map(|(_, v)| v.iter())
- .flat_map(|(_, v)| v.iter())
- .filter_map(|s| s.links())
- .collect()
- }
-
/// Return all dependencies and the features we want from them.
fn resolve_features<'b>(&mut self,
s: &'b Summary,