Skip to main content

Module normalize_env

Module normalize_env 

Source
Expand description

The tree-walker’s consume side of the sui-normalize attrset-binding plan.

Mirrors crate::resolve_env’s three parts — a one-way env-flag latch, a thread-local table keyed by (source_id, text_offset), and populate/lookup/clear hooks wired into eval_with_file — because the keying hazard is identical: a plan recorded for a binder at offset o in one parse tree must never be read for a different (imported) tree that happens to have a binder at the same offset.

§★ The failure discipline here is the INVERSE of resolve_env’s

sui-resolve fails SAFE to Dynamic because its fallback is equivalentlookup_fast probes the same map with the same symbol, so falling back costs only speed.

This table’s fallback path is the divergence itself. Falling back means “walk set.entries() yourself”, which is precisely the code that produces the silent wrong answers sui-normalize exists to remove. So a miss must never be treated as “nothing to do” in a group that NEEDED a plan.

The shape that makes that safe: sui-normalize records a group only when it has a duplicate static key or a dotted path. A miss therefore means “this group has neither”, which is exactly when the existing path is already correct. The absence is a positive statement, not a fallback — and that is what bounds this change’s blast radius to the groups that are wrong today.

§Default ON since 2026-08-18

SUI_NORMALIZE=0 opts OUT, restoring the pre-plan construction path. The latch survives the flip on purpose — a divergence suspected to come from this pass is then one command away from being confirmed or cleared, which is worth more than the tidiness of deleting it.

Functions§

clear
Drop every recorded plan. Wired into the same lifecycle point as resolve_env::clear.
enabled
Whether plan-driven attrset construction is enabled. Default: yes.
plan_for
The plan for the binder node at text_offset in source_id, if one was recorded. None means the group needs no normalization — see the module docs on why that is a positive statement rather than a fallback.
populate
Merge a freshly-computed NormalizeTable into the thread-local table. No-op when the flag is off.