Skip to content

Commit 2d29734

Browse files
committed
Some cleanups
1 parent 1d43c19 commit 2d29734

File tree

2 files changed

+41
-33
lines changed

2 files changed

+41
-33
lines changed

src/cargo/core/resolver/context.rs

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,17 @@ impl Context {
240240
}
241241
}
242242

243+
impl Graph<PackageId, Rc<Vec<Dependency>>> {
244+
pub fn parents_of(&self, p: PackageId) -> impl Iterator<Item = (PackageId, bool)> + '_ {
245+
self.edges(&p)
246+
.map(|(grand, d)| (*grand, d.iter().any(|x| x.is_public())))
247+
}
248+
}
249+
243250
#[derive(Clone, Debug, Default)]
244251
pub struct PublicDependency {
252+
/// For each active package the set of all the names it can see,
253+
/// for each name the exact package that name resolves to and whether it exports that visibility.
245254
inner: im_rc::HashMap<PackageId, im_rc::HashMap<InternedString, (PackageId, bool)>>,
246255
}
247256

@@ -251,29 +260,30 @@ impl PublicDependency {
251260
inner: im_rc::HashMap::new(),
252261
}
253262
}
263+
fn publicly_exports(&self, candidate_pid: PackageId) -> Vec<PackageId> {
264+
self.inner
265+
.get(&candidate_pid) // if we have seen it before
266+
.iter()
267+
.flat_map(|x| x.values()) // all the things we have stored
268+
.filter(|x| x.1) // as publicly exported
269+
.map(|x| x.0)
270+
.chain(Some(candidate_pid)) // but even if not we know that everything exports itself
271+
.collect()
272+
}
254273
pub fn add_edge(
255274
&mut self,
256275
candidate_pid: PackageId,
257276
parent_pid: PackageId,
258-
dep: &Dependency,
277+
is_public: bool,
259278
parents: &Graph<PackageId, Rc<Vec<Dependency>>>,
260279
) {
261280
// one tricky part is that `candidate_pid` may already be active and
262281
// have public dependencies of its own. So we not only need to mark
263282
// `candidate_pid` as visible to its parents but also all of its existing
264-
// public dependencies.
265-
let existing_public_deps: Vec<PackageId> = self
266-
.inner
267-
.get(&candidate_pid)
268-
.iter()
269-
.flat_map(|x| x.values())
270-
.filter_map(|x| if x.1 { Some(&x.0) } else { None })
271-
.chain(&Some(candidate_pid))
272-
.cloned()
273-
.collect();
274-
for c in existing_public_deps {
283+
// publicly exported dependencies.
284+
for c in self.publicly_exports(candidate_pid) {
275285
// for each (transitive) parent that can newly see `t`
276-
let mut stack = vec![(parent_pid, dep.is_public())];
286+
let mut stack = vec![(parent_pid, is_public)];
277287
while let Some((p, public)) = stack.pop() {
278288
match self.inner.entry(p).or_default().entry(c.name()) {
279289
im_rc::hashmap::Entry::Occupied(mut o) => {
@@ -299,9 +309,7 @@ impl PublicDependency {
299309
// if `candidate_pid` was a private dependency of `p` then `p` parents can't see `c` thru `p`
300310
if public {
301311
// if it was public, then we add all of `p`s parents to be checked
302-
for &(grand, ref d) in parents.edges(&p) {
303-
stack.push((grand, d.iter().any(|x| x.is_public())));
304-
}
312+
stack.extend(parents.parents_of(p));
305313
}
306314
}
307315
}
@@ -310,21 +318,16 @@ impl PublicDependency {
310318
&self,
311319
b_id: PackageId,
312320
parent: PackageId,
313-
dep: &Dependency,
321+
is_public: bool,
314322
parents: &Graph<PackageId, Rc<Vec<Dependency>>>,
315323
) -> Result<(), (PackageId, ConflictReason)> {
316-
let existing_public_deps: Vec<PackageId> = self
317-
.inner
318-
.get(&b_id)
319-
.iter()
320-
.flat_map(|x| x.values())
321-
.filter_map(|x| if x.1 { Some(&x.0) } else { None })
322-
.chain(&Some(b_id))
323-
.cloned()
324-
.collect();
325-
for t in existing_public_deps {
324+
// one tricky part is that `candidate_pid` may already be active and
325+
// have public dependencies of its own. So we not only need to check
326+
// `b_id` as visible to its parents but also all of its existing
327+
// publicly exported dependencies.
328+
for t in self.publicly_exports(b_id) {
326329
// for each (transitive) parent that can newly see `t`
327-
let mut stack = vec![(parent, dep.is_public())];
330+
let mut stack = vec![(parent, is_public)];
328331
while let Some((p, public)) = stack.pop() {
329332
// TODO: dont look at the same thing more then once
330333
if let Some(o) = self.inner.get(&p).and_then(|x| x.get(&t.name())) {
@@ -333,13 +336,17 @@ impl PublicDependency {
333336
// So, adding `b` will cause `p` to have a public dependency conflict on `t`.
334337
return Err((p, ConflictReason::PublicDependency));
335338
}
339+
if o.1 {
340+
// The previous time the parent saw `t`, it was a public dependency.
341+
// So all of its parents already know about `t`
342+
// and we can save some time by stopping now.
343+
continue;
344+
}
336345
}
337346
// if `b` was a private dependency of `p` then `p` parents can't see `t` thru `p`
338347
if public {
339348
// if it was public, then we add all of `p`s parents to be checked
340-
for &(grand, ref d) in parents.edges(&p) {
341-
stack.push((grand, d.iter().any(|x| x.is_public())));
342-
}
349+
stack.extend(parents.parents_of(p));
343350
}
344351
}
345352
}

src/cargo/core/resolver/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ fn activate(
603603
// and associate dep with that edge
604604
.push(dep.clone());
605605
if let Some(public_dependency) = cx.public_dependency.as_mut() {
606-
public_dependency.add_edge(candidate_pid, parent_pid, dep, &cx.parents);
606+
public_dependency.add_edge(candidate_pid, parent_pid, dep.is_public(), &cx.parents);
607607
}
608608
}
609609

@@ -756,7 +756,8 @@ impl RemainingCandidates {
756756
// activated and have public dependants of its own,
757757
// all of witch also need to be checked the same way.
758758
if let Some(public_dependency) = cx.public_dependency.as_ref() {
759-
if let Err((p, c)) = public_dependency.can_add_edge(b_id, parent, dep, &cx.parents)
759+
if let Err((p, c)) =
760+
public_dependency.can_add_edge(b_id, parent, dep.is_public(), &cx.parents)
760761
{
761762
conflicting_prev_active.insert(p, c);
762763
continue;

0 commit comments

Comments
 (0)