pub const MAX_PLACEMENT_DEPTH: usize = 100;Expand description
Maximum IfcLocalPlacement.PlacementRelTo chain any walk in this workspace
will follow. A chain longer than this composes only its first
MAX_PLACEMENT_DEPTH + 1 placements and the rest is dropped — silently, on
every site that uses it.
Shared because two walks follow the SAME attribute of the SAME entity and
their bounds must agree: ifc_lite_geometry::router::transforms (the mesh
path) and ifc_lite_geometry::profile_extractor (the 2D drawing path).
They disagreed — 32 against 100 — and because both exceed-branches return
the IDENTITY rather than an error, an element on a 33-to-101-link chain was
drawn in two different places by the two paths with nothing reported. #2873
§Why 100 and not 32
The 32 carried the rationale “keep low for WASM — each frame uses ~2KB+ of
stack”. The wasm bundles are linked with -zstack-size=8388608
(.cargo/config.toml and both extra bundles in scripts/build-wasm.sh), so
the budget is 8 MiB and the cap’s own worst case is ~0.1% of it; native
hosts give the geometry pool 256 MiB (rust/ffi, rust/python). Measured
rather than assumed: see the frame figures in #2873. PlacementRelTo is a
single reference, so this walk has fan-out 1 and costs O(depth) — the
breadth blow-up that makes a depth cap the wrong instrument elsewhere (see
AGENTS.md) does not apply here.
The two candidates are not symmetric. Equalising UP lets the mesh path
compose chains it currently flattens; equalising DOWN would make the 2D path
start flattening chains it composes correctly today, silently. Across the
111 fixtures in tests/models that contain placements the deepest chain is
7 links, so neither value binds on any file in the corpus and the choice is
decided entirely by which failure is worse on a file that does exceed it.
This bounds one path’s LENGTH only. A walk over a chain that can revisit also needs a cycle guard; see the module docs above.