Expand description
The aggregates of a type graph that sit on a cycle.
A dump emitter inlines a member’s statements into its owner’s, and a
type graph with a cycle has no finite inline expansion: the CORBA
C++ emitter followed recursive-mutual’s
A → sequence<B> → B → sequence<A> until the Rust stack ran out,
and the C and Fast DDS emitters shared the walk and the crash. The
types this module names are emitted as functions instead, and the
expansion calls them where it would have unrolled them.
§Which walks ask, and which two did not
Three emitters carry the answer: crate::dump, crate::dump_cpp
and crate::corba_cpp’s dump half, each of which emits one
function per aggregate named here and calls it in place of the
expansion.
Two ran past it and followed the cycle instead, measured on
2026-08-31 over recursive-mutual — both reached
“has overflowed its stack” and SIGABRT:
corba_java::dump_at. The C++ half of that same file was given the machinery; the Java half was not.dump_ros::emit. Its comment namedros_idlas the gate, andros_idldoes refuse a recursive type — butwireprobe-dump --rosis a separate process invocation and no gate on this function.
Neither has a shape to emit a function into — a Java method body and
a C block inside the ROS decode template — and neither column takes a
recursive type at all, so both now refuse one by name, in the words
corba_idl and ros_idl already use for it. A refusal is a cell
that says why; a stack overflow is a cell that measured nothing.
The fill emitters do not ask, and do not need to: a fill walk follows the sample, and a recursive type has finite samples because the sequence that closes its cycle is eventually empty. That is a termination argument rather than a bound, and it is the sample’s nesting that bounds them.
Functions§
- recursive_
aggregates - The aggregates reachable from
rootthat sit on a cycle, in first-visit order.