Skip to content

Commit fa8c4ee

Browse files
committed
improve some documentation
1 parent 451f76d commit fa8c4ee

File tree

1 file changed

+38
-15
lines changed

1 file changed

+38
-15
lines changed

src/cargo/util/graph.rs

+38-15
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,35 @@
4141
//! Ok(finalize(dependency_graph_so_far))
4242
//! }
4343
//! }
44+
//!
45+
//! fn activate(&mut dependency_graph: _, &mut unresolved_dependencies: _, candidate:_) -> Result<(), Problem> {
46+
//! // check that we can use candidate given the other selected packages
47+
//! if semver conflict { return Err(Problem::Semver); };
48+
//! if links conflict { return Err(Problem::Links); };
49+
//! ...
50+
//! // update other state
51+
//! if used a [replace] section { update that lookup table };
52+
//! if used a [patch] section { update that lookup table };
53+
//! update activated features
54+
//! ...
55+
//! // add candidate to dependency_graph
56+
//! dependency_graph.add_edge(candidate.parent, candidate.id, candidate.dependency);
57+
//! // add candidate's dependencies to the list to be resolved
58+
//! unresolved_dependencies.extend(candidate.dependencies);
59+
//! Ok(())
60+
//! }
4461
//! ```
4562
//!
46-
//! The real resolver is not recursive to avoid blowing the stack, and has lots of other state to
47-
//! maintain. The most expensive (non recursive) call in this algorithm is the
48-
//! `dependency_graph_so_far.clone();`. To make this more annoying the first thing we try will
49-
//! probably work, and any work we do to prepare for the next iteration is wasted. If we had a
50-
//! `undo_activate` we could be much more efficient, completely remove the `.clone()` and just
51-
//! `undo_activate` if things tern out to not work. Unfortunately, making sure `undo_activate`
52-
//! handles all the corner cases correctly is not practical for the resolver. However, this is
53-
//! possible for a graph like thing, a `clone` means record the size of the graph. a `&mut self`
54-
//! method means undo everything newer and do the mutation, a `&self` method means only look at the
55-
//! older part. This module provides a `StackGraph` type to encapsulate this pattern.
63+
//! The real resolver is not recursive to avoid blowing the stack. The most expensive
64+
//! (non recursive) call in this algorithm is the `dependency_graph_so_far.clone();`.
65+
//! To make this more annoying the first thing we try will probably work, and any work we do to
66+
//! prepare for the next iteration is wasted. If we had a `undo_activate` we could be much more efficient,
67+
//! completely remove the `.clone()` and just `undo_activate` if things tern out to not work.
68+
//! Unfortunately, making sure `undo_activate` handles all the corner cases correctly is not
69+
//! practical for the resolver. However, this is possible for a graph like thing, a `clone` means
70+
//! record the size of the graph. a `&mut self` method means undo everything newer and do the
71+
//! mutation, a `&self` method means only look at the older part. This module provides a
72+
//! `StackGraph` type to encapsulate this pattern.
5673
5774
use indexmap::IndexMap;
5875
use std::borrow::Borrow;
@@ -64,6 +81,10 @@ use std::rc::Rc;
6481

6582
type EdgeIndex = usize;
6683

84+
/// This stores one Edge or Link element. If the two Nodes have data to connect them then we say it
85+
/// is an Edge and the `value` is `Some(E)`, if the two Nodes did not have data then we say it is a
86+
/// Link and the `value` is `None`. If there are other `EdgeLink`s associated with the same two Nodes,
87+
/// then we make a index based doubly linked list using the `next` and `previous` fields.
6788
#[derive(Clone, Debug)]
6889
struct EdgeLink<E: Clone> {
6990
value: Option<E>,
@@ -79,11 +100,13 @@ struct EdgeLink<E: Clone> {
79100
/// that efficiently undoes the most reason modifications.
80101
#[derive(Clone)]
81102
pub struct Graph<N: Clone, E: Clone> {
82-
/// an index based linked list of the edge data for links. This maintains insertion order.
103+
/// An index based linked list of the edge data. This maintains insertion order.
104+
/// If the connection has data associated with it then that Edge is stored here.
105+
/// If the connection has no data associated with it then that Link is represented with a dummy here.
83106
edges: Vec<EdgeLink<E>>,
84-
/// a hashmap that stores the set of nodes. This is an `IndexMap` so it maintains insertion order.
85-
/// For each node it stores all the other nodes that it links to.
86-
/// For each link it stores the first index into `edges`.
107+
/// A map from a "from" node to (a map of "to" node to the starting index in the `edges`).
108+
/// The inner map may be empty to represent a Node that was `add` but not connected to anything.
109+
/// The maps are `IndexMap`s so they maintains insertion order.
87110
nodes: indexmap::IndexMap<N, indexmap::IndexMap<N, EdgeIndex>>,
88111
}
89112

@@ -402,7 +425,7 @@ impl<N: Eq + Hash + Clone, E: Eq + Clone> Eq for Graph<N, E> {}
402425
/// - the clone has no overhead to read the `Graph` as it was
403426
/// - no overhead over using the `Graph` directly when modifying the biggest clone
404427
/// Is this too good to be true?
405-
/// - If a modification (`&mut` method) is done to a smaller older clone then a full `O(N)`
428+
/// - If a modification (`&mut` method) is done to a clone that is not the largest then a full `O(N)`
406429
/// deep clone will happen internally.
407430
pub struct StackGraph<N: Clone, E: Clone> {
408431
/// The `Graph` shared by all clones, this `StackGraph` refers to only the prefix of size `age`

0 commit comments

Comments
 (0)