/// Trick to avoid stackoverflow on deep graphs:
/// We don't recuse at all, and if we would have wanted to to recurse we return `Err` instead.
/// This function then explicitly recuses using a heap-allocation stack by repeatedly calling `f`.
///
/// `f` _must_ be deterministic and have built-in caching.