Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SeedNode<N> — the seed-rooted row type

#![allow(unused)]
fn main() {
/// Opaque row type in a seed-closed chain's treeish. Values are
/// either the synthetic `EntryRoot` row (seed fan-out) or a resolved
/// `Node(N)`. User code inspects via [`is_entry_root`](Self::is_entry_root),
/// [`as_node`](Self::as_node), [`into_node`](Self::into_node), and
/// [`map_node`](Self::map_node); the variants are sealed.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct SeedNode<N> {
    // Exposed `pub` (not `pub(crate)`) so the doc-hidden
    // `seed_node_internal` module can re-export it for
    // `hylic-pipeline`'s dispatch. User code should treat this field
    // as opaque and use `is_entry_root` / `as_node` / `map_node`.
    #[doc(hidden)]
    pub inner: SeedNodeInner<N>,
}

/// Library-internal variant carrier for `SeedNode<N>`. Exposed
/// `pub` only to make crate-external re-export through the
/// `seed_node_internal` doc-hidden module possible. User code
/// should never name this directly.
#[doc(hidden)]
#[derive(Clone, PartialEq, Eq, Hash)]
pub enum SeedNodeInner<N> {
    EntryRoot,
    Node(N),
}
}

SeedNode<N> is the chain’s input node type once SeedLift has fired in a seed-rooted Stage2Pipeline. Two inhabitants:

  • Node(N) — a real grown node from the user’s seed graph.
  • EntryRoot — the synthetic forest root above the entry seeds.

Variants are sealed; pattern-matching is not exposed to user code. Inspection is through accessor methods:

methodreturns
sn.is_entry_root()bool
sn.as_node()Option<&N>
sn.into_node()Option<N>
sn.map_node(f: FnOnce(&N) -> M)SeedNode<M> — Node mapped, EntryRoot preserved

Inside Stage-2 sugar bodies, SeedNode<N> never appears; user closures type at &N and the row is peeled (or routed past) by Wrap dispatch.

Where the row surfaces

A lift whose output type mentions the chain’s N can carry SeedNode<N> to the chain tip. The explainer is the canonical case:

let raw: ExplainerResult<SeedNode<N>, H, R> = pipeline
    .lift()
    .explain()
    .run_from_slice(&exec, &seeds, h0);

ExplainerResult’s first parameter is the per-node heap.node, which on a seed-rooted chain is SeedNode<N>.

For walks over the trace (formatting, post-fact analysis), project to an N-typed view via SeedExplainerResult::from:

let sealed: SeedExplainerResult<N, H, R> = raw.into();
// sealed.entry_initial_heap, sealed.entry_working_heap, sealed.orig_result
//   — the EntryRoot row, promoted out of the tree as fields.
// sealed.roots: Vec<ExplainerResult<N, H, R>>
//   — per-seed subtrees, every node now plain N.

The conversion is total: every node below the EntryRoot row is unwrapped, and SeedNode<N> no longer appears in the user-visible shape.

Tree shape

        EntryRoot
        ├── Node(grow(seed_0))
        ├── Node(grow(seed_1))
        └── …

SeedLift produces this tree at run time from the entry seeds and the user’s grow. Each Node(n) below has the user’s seeds_from_node + grow as its own children-producing function.