perf(templateengine): memoise CollisionDetector's composed-module walk per check (review 2026-10-21 04/P8b)

This commit is contained in:
Joseph Doherty
2026-10-22 06:30:27 -04:00
parent 52aab37299
commit 0d4f7d33b9
3 changed files with 153 additions and 26 deletions
@@ -143,6 +143,8 @@ If any composed module introduces a name that already exists (from another compo
A derived template stores `IsInherited` placeholder rows that mirror the members it inherits from its parent chain. These placeholders are **excluded** from collision detection on the template's own member set and on the inherited-parent walk — the inheritance walk already re-adds those members under the parent's origin, so counting the placeholder copies as well would report a spurious self-collision against the very member they mirror. (Placeholders are only counted when a composed module is itself a derived template, because the composed-module walk does not climb that module's parent chain and the placeholders are then the sole representation of its inherited members.) Without this exclusion there is no supported way to add an attribute, alarm, script, or composition to a derived template — every add is blocked by false collisions on the pre-existing inherited rows.
A template composed into several slots — or reached through several parents (a diamond) — is checked under **every** slot, since each slot yields distinct canonical names. Its module-relative member list is computed once per collision check and memoised by template id; each further slot only re-prefixes it (review 2026-10-21 04/P8(b)). A genuine composition cycle still contributes nothing at the re-entered module, and a list cut short by a cycle is never memoised.
## Flattening Process
When an instance is deployed, the Template Engine resolves the full configuration: