Repository navigation
t27b: array literals the reference prints as @constCast(&[_]E{ ... }) -- slice fields and constants returned as mutable slices #7680
Description
Part of #6063 (t27b coverage), which is item C10 of #6488.
What blocks
The t27b lab run of master 0fbb0a0 (https://t27b-lab-production.up.railway.app/latest.json) has three specs that the reference passes and that t27b blocks first on this family:
| spec | first blocker | the literal | next blocker |
|---|---|---|---|
specs/tri/graph/graph.t27 |
ExprArrayLiteral(to slice field) |
.nodes = []usize |
ExprCall (void fn used as a value) |
specs/tri/graph/topological_sort.t27 |
ExprArrayLiteral(to slice field) |
.order = []usize{0, 1, 2, 3}, .adjacency_list = []usize |
type mismatch |
specs/tri/graph/bellman_ford.t27 |
ExprArrayLiteral(constant to mutable slice) |
return []Edge{ ... } from -> []Edge |
ExprCall (void fn used as a value) |
specs/automation/wrapup-auto.t27 carries ExprArrayLiteral(to slice field) as its second blocker (its first is StmtAssign, #7404). 32 specs the reference blocks carry one of the two as well.
What the reference does
t27c gen prints every one of them as @constCast(&[_]E{ ... }), with E the element type of the destination (the field or the return type). The literal's own type text is not printed, so .nodes = []usize is @constCast(&[_]usize{ }), an empty slice.
Measured with zig 0.16.0 on the t27c lab, on a Zig file shaped like these:
- With the default x86_64 Debug backend, which
t27c test-reportbuilds with, a write through the slice succeeds. The same literal evaluated again reads the written value. So does another site with an equal literal, a[]constone included, because Zig interns comptime values: one object per type and value. A literal of another value or another element type is another object. - With
-fllvmthe same write faults (read-only memory). With ReleaseSafe the read is folded away. Neither is the reference. t27c test-reportruns each test in its own process, so every test starts from the constants.
What the refusals guarded
ExprArrayLiteral(to slice field)(4f14eda, t27b: array literals typed by their use (str args, tuple locals, empty slice fields) #6369): "A non-empty one points at a constant in the reference, which outlives any frame t27b could build it in." t27b had no storage with that lifetime that it could write.ExprArrayLiteral(constant to mutable slice)(6600bd3, feat(t27b): array literals returned as constant slices and literal locals passed by address (Closes #6866) #6938): "The reference faults on a write through that slice." t27b keeps constants in read-only data, where its interpreter faults on a store (an IR defect) and its JIT segfaults. The claim about the reference is not true of the backend the lab uses.
The step
Lower compile-time elements into one writable static object per element type and value: a t27b global, which both the JIT and the interpreter reset on every host entry, as they do for a module-level var. The decisions go into a t27 plan, specs/tri/t27b/slice_lit_plan.t27, through t27c gen-rust, and a conformance spec comes first. These stay refused:
- run-time elements, because the reference builds them in the frame and a return hands that address out (t27b: JIT and interpreter disagree on gen_canvas.t27 since #7425 (lab mismatch 1 on master) #7550);
- a field of an anonymous struct literal, a slice of arrays, a repeat, and a typed literal with a dimension and no elements.
Not the same mechanism
ExprArrayLiteralinspecs/isa/ternary_gates.t27andspecs/port/scripts/ultra_engine_v70_ultimate.t27. The reference prints these as an untyped tuple local (const vals = .{ ... };) that a test indexes, not as@constCast(&[_]E{ ... }).ExprArrayLiteral(reference empty typed)inspecs/port/fpga/verilog/ternary_mac_synth.t27. This is the reference's own printing defect ([0,1]u8prints its dimension as its element), and t27b lane 5: three specs whose tests do not test (layernorm, wrapup-auto, ternary_mac_synth) #7404 fixes the spec.
Activity
t27b conformance: equal bytes of another element type are another sta…
t27b slice_lit_plan: a one-element literal is static, after PARSE too (…
t27b slice_lit_plan: elements that hold a str are refused by name (Cl…
t27b ledger: the two new specs pass; AGENTS.md remainder line (Closes #…
Merge origin/master 3d71306 into t27b-arraylit-slice (Closes #7680)
Merge t27b-lane5-module-vars into master 927b1ef (from master's side)