Split out of #582 — same root cause (equation()'s O(n²) string-building cost, per #582's own measurement table), but a different, narrower fix site and more urgent: this is breaking master's CI right now, independent of whatever #582 decides about a depth cap.
Verification status: reproduced
tests/test_quantity.cpp:736, TEST_CASE("equation() walks a 70000-node provenance chain without overflowing the stack", ...) (added by #581/morph574). Its only assertions (lines 743-747) check output correctness, not performance — 70,000 was chosen solely to safely exceed the old recursive crash threshold (60,000 under clang -O2, per docs/spec/util/quantity_type.md's table). It has no performance budget of its own; it inherits the blanket TIMEOUT 120 every test gets from catch_discover_tests(... PROPERTIES TIMEOUT 120) (tests/CMakeLists.txt:214).
Reproduced on master's own CI, independent of any PR, at commit 3e8f59f2 (the commit that merged #581):
1076/1739 Test #1076: equation() walks a 70000-node provenance chain without
overflowing the stack ...... ***Timeout 120.07 sec
https://github.com/LASTRADA-Software/morph/actions/runs/35431457068/job/105872791321
Also independently reproduced on two unrelated draft PRs (#585, #586) via the pull_request merge-ref — neither PR's own changes touch this code; that's how it was first noticed.
#582 measured 70,000 nodes at 32.3s under ASan+UBSan; TSan's per-access instrumentation is evidently heavier here and pushes the same case past 120s.
Proposed fix (mechanical, does not touch equation())
Give this test (and the sibling destruction test at test_quantity.cpp:723, which is presumably cheaper but shares the same node count and is worth checking) an explicit, longer TIMEOUT via CTest's per-test PROPERTIES, at least under the sanitizer configurations. This is a test-calibration fix, not a design change — it does not require or preempt #582's depth-cap decision, and does not weaken what the test verifies (it still must not crash).
Why this is filed separately from #582
Different fix site: this is tests/CMakeLists.txt's test properties (or the test's own node count); #582 is EquationRenderer::combine in include/morph/util/. Per this repo's own guidance on consolidating issues, two problems sharing a root cause but not a fix site stay separate tickets. This one is also considerably more urgent — master's CI is red on clang-tsan right now.
🤖 Generated with Claude Code
Split out of #582 — same root cause (equation()'s O(n²) string-building cost, per #582's own measurement table), but a different, narrower fix site and more urgent: this is breaking master's CI right now, independent of whatever #582 decides about a depth cap.
Verification status: reproduced
tests/test_quantity.cpp:736,TEST_CASE("equation() walks a 70000-node provenance chain without overflowing the stack", ...)(added by #581/morph574). Its only assertions (lines 743-747) check output correctness, not performance — 70,000 was chosen solely to safely exceed the old recursive crash threshold (60,000 under clang-O2, perdocs/spec/util/quantity_type.md's table). It has no performance budget of its own; it inherits the blanketTIMEOUT 120every test gets fromcatch_discover_tests(... PROPERTIES TIMEOUT 120)(tests/CMakeLists.txt:214).Reproduced on master's own CI, independent of any PR, at commit
3e8f59f2(the commit that merged #581):https://github.com/LASTRADA-Software/morph/actions/runs/35431457068/job/105872791321
Also independently reproduced on two unrelated draft PRs (#585, #586) via the
pull_requestmerge-ref — neither PR's own changes touch this code; that's how it was first noticed.#582 measured 70,000 nodes at 32.3s under ASan+UBSan; TSan's per-access instrumentation is evidently heavier here and pushes the same case past 120s.
Proposed fix (mechanical, does not touch
equation())Give this test (and the sibling destruction test at
test_quantity.cpp:723, which is presumably cheaper but shares the same node count and is worth checking) an explicit, longerTIMEOUTvia CTest's per-testPROPERTIES, at least under the sanitizer configurations. This is a test-calibration fix, not a design change — it does not require or preempt #582's depth-cap decision, and does not weaken what the test verifies (it still must not crash).Why this is filed separately from #582
Different fix site: this is
tests/CMakeLists.txt's test properties (or the test's own node count); #582 isEquationRenderer::combineininclude/morph/util/. Per this repo's own guidance on consolidating issues, two problems sharing a root cause but not a fix site stay separate tickets. This one is also considerably more urgent — master's CI is red onclang-tsanright now.🤖 Generated with Claude Code