pub fn visit_unbounded(
fields: &'static [Field],
visit: &mut dyn FnMut(UnboundedField) -> ControlFlow<()>,
) -> ControlFlow<()>Expand description
Report EVERY member that makes fields unbounded, in declaration order.
first_unbounded answers “which member costs the bound” one member at a
time, and that is the wrong shape for the caller that actually asks.
phase-403 W0 made an unbounded type a BUILD ERROR, and a stock ROS type is
routinely unbounded in several places at once — nav_msgs/Odometry has
header.frame_id and child_frame_id, and sensor_msgs/PointCloud2 has
four. Naming only the first turns “bound your types” into cap, rebuild,
discover the next one, repeat, once per member, with a whole codegen run
between each step. One build should name everything that needs a bound.
THE walk. first_unbounded is expressed on top of this rather than beside
it: two walks of one schema is the shape the sizes-header mirror defect keeps
taking (issues 0088 -> 0268), and “the first thing this reports” is exactly
what “the first unbounded member” means, so there is nothing left for a
second implementation to say.
visit returns ControlFlow so a caller that wants only the first can
stop the walk rather than let it enumerate a whole type and discard all but
one answer. The return value is Break iff the visitor broke.
&mut dyn FnMut rather than impl FnMut: the walk recurses, and a recursive
generic function cannot name the closure type it would instantiate itself
with. no_std and allocation-free either way — nothing is collected here,
which is what lets an all-members form exist at all on a target with no
allocator. The COLLECTING is the caller’s, and only codegen (std) does it.