ADR 0066 — Static tables of views
- Status: Accepted by the owner, 2026-11-04 ("fix the static view table finding in CeeSafe"). Implemented on the working tree; not released. Raised by the ClayWind cleanup on 0.11.0 (
~/dev/CeeSafeApps/CEESAFE-FINDINGS.md§G). - Scope: the checker (
src/check/statics.cee). Spec: type-system.md §10 and §39.2. No new diagnostic.
1. Context
ADR 0064 §2 allowed constant tables of views, such as const LEVELS: [StringView; 3] = ["Low", "Medium", "High"];.
- A constant is a value, not a place (§10). It can be indexed and iterated, but slicing it or taking its
.lengthis N0247 or N0216 until it is bound to a local. - The ClayWind port passes tables to the controls as
Slice<StringView>, so every such call needed an extra line:let prioItems = PRIO_ITEMS;and thenprioItems[..]. - A
staticis a place (§39.2), which is what such a table wants. Butstatic LEVELS: [StringView; 3]was N0337: "'[StringView; 3]' is not 'Share'". - The check makes an exception for a bare
StringView.static NAME: StringViewis accepted, as the spec's own example shows, because "a view of static string data … is safe to share". The exception did not extend to an array of the same views.
2. Decision
- What a
staticmay hold. In astatic(not astatic mut),Tmay also be[StringView; N]. This is the same set of types a constant view may have,isConstantView(src/check/declare.cee), so constants and statics agree. - Its initialiser is unchanged (§39.4): an array literal or repeat of string literals or constant views.
- What it allows. The table is a place, so it is sliced, measured and borrowed where it is named:
f(LEVELS[..])andLEVELS.length;borrow LEVELS, asborrow(static) [StringView; 3].
- What stays rejected:
- Changing the table: assigning an element (N0211) and borrowing it mutably (N0248), as for every static.
- Arrays of arrays of views (N0337), as for constants.
static muttables of views (N0337, unchanged). See §3.
3. Not taken: static mut tables
- Release 0.11.0 does not check the regions of values written to a
static mut. Writing a view of a localStringintostatic mut N: StringViewcompiles, and readingNafterwards reads freed memory. - This ADR does not extend
static mutto arrays of views, which would widen that hole. Only the immutable form is added, and it cannot be written at all. - The hole itself is a separate soundness bug, fixed by ADR 0067: a write to a static may carry no loan (N0272).
4. Evidence (macOS arm64)
- New corpus tests:
run-pass/static-view-tablescovers slicing,.length, iteration, aborrow(static)result, a repeat, and a constant view as an element. Its expected output comes from a Python model of the same tables. It passes compiled and with--interp.check-fail/static-view-tablescoversstatic mut, nesting, a non-@constantinitialiser, writing and a mutable borrow.- Both tests fail on 0.11.0, with N0337 on every immutable table: the run-pass test's tables, and the check-fail test's
LEVELS, which should be accepted.
- The full corpus, the fixed point and the contract suite are recorded in ROADMAP §10.
5. Consequences
- ClayWind's demo tables can be
static. Itslet x = TABLE;lines then go, once a release carries this. - A
consttable still cannot be sliced where it is named. A table that is passed as a slice should be declaredstatic.