in guppy/src/graph/feature/build.rs [365:455]
fn add_edges(
&mut self,
from_node: FeatureNode,
to_nodes_edges: impl IntoIterator<Item = (FeatureNode, FeatureEdge)>,
) {
// The from node should always be present because it is a known node.
let from_ix = self.lookup_node(&from_node).unwrap_or_else(|| {
panic!(
"while adding feature edges, missing 'from': {:?}",
from_node
);
});
to_nodes_edges.into_iter().for_each(|(to_node, edge)| {
let to_ix = self.lookup_node(&to_node).unwrap_or_else(|| {
panic!("while adding feature edges, missing 'to': {:?}", to_node)
});
match self.graph.find_edge(from_ix, to_ix) {
Some(edge_ix) => {
// The edge already exists. This could be an upgrade from a cross link to a
// feature dependency, for example:
//
// [package]
// name = "main"
//
// [dependencies]
// dep = { ..., optional = true }
//
// [features]
// "feat" = ["dep/feat", "dep"]
//
// "dep/feat" causes a cross link to be created from "main/feat" to "main/dep".
// However, the "dep" encountered later upgrades this link to a feature
// dependency.
//
// This could also be an upgrade from a weak to a non-weak dependency:
//
// [features]
// feat = ["dep?/feat", "dep/feat2"]
let old_edge = self
.graph
.edge_weight_mut(edge_ix)
.expect("this edge was just found");
#[allow(clippy::single_match)]
match (old_edge, edge) {
(
FeatureEdge::NamedFeatureWithSlash {
weak_index: old_weak_index,
..
},
FeatureEdge::NamedFeatureWithSlash { weak_index, .. },
) => {
if old_weak_index.is_some() && weak_index.is_some() {
debug_assert_eq!(
*old_weak_index, weak_index,
"weak indexes should match if some"
);
}
// Upgrade this edge from weak to non-weak.
if weak_index.is_none() {
*old_weak_index = None;
}
}
(
old_edge @ FeatureEdge::NamedFeatureWithSlash { .. },
edge @ FeatureEdge::NamedFeature
| edge @ FeatureEdge::NamedFeatureDepColon(_),
) => {
// Upgrade this edge from / conditional to dep: conditional or unconditional.
*old_edge = edge;
}
(
old_edge @ FeatureEdge::NamedFeatureDepColon(_),
edge @ FeatureEdge::NamedFeature,
) => {
// Upgrade this edge from dep: conditional to unconditional.
// XXX: can this ever happen?
*old_edge = edge;
}
_ => {
// In all other cases, leave the old edge alone.
}
}
}
None => {
self.graph.add_edge(from_ix, to_ix, edge);
}
}
})
}