fix template depth explosion with large FSMs sharing dep types (issue #639)#668
Merged
kris-jusiak merged 2 commits intoMay 23, 2026
Merged
Conversation
…ext#659) Actions that take a submachine struct by reference (e.g. `[](MySubSM &s, ...)`) were receiving the copy in deps_ rather than the live state in sub_sms_. sm_impl<sm_policy<T>> inherits from T and is the authoritative state; deps_ holds only a separate, unused copy. Fix: add 6-parameter get_arg overloads (int/... priority) that look in sub_sms_ first via sub_sm<sm_impl<sm_policy<T>>>::get when T is a sub-SM type. The current SM's own type (Tsm::sm_t) is excluded to preserve existing behaviour for top-level SM member-function callbacks. call::execute (no-policy and logger variants) now pass subs to get_arg; the logger path also threads subs through execute_impl. Test: submachine_state_data_persistence in test/ft/composite.cpp
…oost-ext#639) get_mapping<event<E>, event<E>, T, R> was calling unique_mappings_t on all k+1 state_mappings even though R's k entries were already unique, causing O(k) nested recursion inside O(N) outer recursion → total depth O(2N). Add a more-specific partial specialization that uses is_base_of (O(1)) to check membership and extend_mapping_t (O(1) pack expansion) to merge, reducing total instantiation depth from O(2N) to O(N). A 450-transition FSM sharing the same event type now compiles at default template depth. Regression test: issue_639_repro.cpp compiled with -ftemplate-depth=100 (50 same-event transitions; unfixed code hits depth ~100 and fails there).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
get_mapping<event<E>, event<E>, T, R>was callingunique_mappings_ton all k+1state_mappingseven thoughR's k entries were already unique. This caused O(k) nested recursion inside the O(N) outerunique_mappings_implrecursion, for a total instantiation depth of O(2N) when N transitions share the same event type.With GCC's default
-ftemplate-depth=900, an FSM with ~450 transitions on a single event type would hit the limit and fail to compile.Root cause
R::typesalready contains k uniquestate_mappings. Re-runningunique_mappings_ton all k+1 items recurses k levels deep — unnecessarily, since only the single new entry fromTneeds to be merged.Fix
Add a more-specific partial specialization after
extend_mapping_tthat:is_base_of(O(1)) to check if the newstate_mapping's source state is already inRextend_mapping_t(O(1) pack expansion)state_mappingdirectlyThe original general specialization remains as a fallback for any edge cases.
Result
A 450-transition FSM with all transitions sharing the same event type now compiles at default template depth. The original would fail at ~450 transitions.
Test
test/ft/issue_639_repro.cpp— 50 same-event transitions compiled with-ftemplate-depth=100:Fixes #639