in shed/facet/proc_macros/factory_impl.rs [630:669]
fn check_no_cycles(
top_ident: &Ident,
ident_map: &BTreeMap<&Ident, &Vec<FactoryParam>>,
) -> Result<(), Error> {
// A map from seen idents to a vector of the route to them from top_ident.
let mut seen = BTreeMap::new();
// A queue of idents to expand and the routes to them so far.
let mut queue = VecDeque::new();
queue.push_back((top_ident, vec![]));
while let Some((ident, route)) = queue.pop_front() {
if let Some(params) = ident_map.get(&ident) {
for param in *params {
if let FactoryParam::Facet(param_ident) = param {
seen.entry(param_ident).or_insert_with(|| {
let mut param_route = route.clone();
param_route.push(param_ident);
queue.push_back((param_ident, param_route));
route.clone()
});
}
}
}
}
if let Some(route) = seen.get(&top_ident) {
let via = if route.is_empty() {
String::from("directly")
} else {
let route = route.iter().map(ToString::to_string).collect::<Vec<_>>();
format!("via {}", route.join(" -> "))
};
return Err(Error::new(
top_ident.span(),
format!(
"cyclic facet dependency: {} depends on itself {}",
top_ident, via
),
));
}
Ok(())
}