The generated GetChildNodes materialized a List<AstNode> (plus a boxed
List.Enumerator at every foreach) for each node, so AstNode.Children and
the visitor's per-node child walk allocated three objects per traversal.
Decompiling System.Private.CoreLib that came to ~1.7 GB of extra garbage,
roughly +7% over the linked-list model the slot tree replaced. A yield
iterator removes the List but trades it for an equally costly per-node
state machine, so it is not enough on its own.
Enumerate children through a by-value struct enumerator over the existing
FirstChild/NextSibling primitives, capturing each child's successor before
it is yielded so a transform may still remove or replace the current child
mid-traversal. AstNodeCollection<T> gets the same struct treatment for a
direct foreach. Child enumeration now allocates nothing, bringing total
allocations back to the linked-list baseline at byte-identical output
(full Pretty suite green with CheckInvariant active).
Assisted-by: Claude:claude-opus-4-8:Claude Code