1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! 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
//! *equivalent* — `lookup_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.
//!
//! # Flag-gated on purpose
//!
//! `SUI_NORMALIZE=1` opts in. Off, every consume site takes today's exact
//! unchanged path, so landing this cannot move a single byte for anyone until
//! the flag is proven and the default flipped.
use RefCell;
use OnceLock;
use ;
/// One-time read of `SUI_NORMALIZE`. `true` iff `SUI_NORMALIZE=1`.
static ENABLED: = new;
/// Whether plan-driven attrset construction is enabled (`SUI_NORMALIZE=1`).
///
/// Read once and cached — matches `resolve_env::enabled()`'s one-way latch.
thread_local!
/// Merge a freshly-computed [`NormalizeTable`] into the thread-local table.
/// No-op when the flag is off.
/// 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.
/// Drop every recorded plan. Wired into the same lifecycle point as
/// `resolve_env::clear`.