What this changes
Zig 0.17.0-dev.1963 appends pointer_stability: debug.SafetyLock to ArrayList, and two idioms here assumed the old shape. 27 struct literals of the form .{ .items = &buf, .capacity = buf.len } name every field, so one more field stops them compiling — all are test fixtures wrapping a fixed array, and .fromOwnedSlice(&buf) says the same thing without enumerating fields. The other is a layout assertion in the JIT, which is the part worth reading.
emitDirectDenseArrayGuards mirrors the list as DenseListLayout and asserted it @sizeOf-equal to std.ArrayListUnmanaged(Value). Measured, @sizeOf(ArrayListUnmanaged(u64)) on aarch64-macos:
| toolchain | Debug | ReleaseSafe | ReleaseFast |
|---|---|---|---|
dev.1818 | 24 | 24 | 24 |
dev.1963 | 32 | 32 | 24 |
SafetyLock is zero-sized when runtime safety is off, so on 1963 that assertion fails in Debug and ReleaseSafe and passes in ReleaseFast — a compile error that depends on -O.
The mirror was never wrong about the part the JIT uses. @offsetOf(items) is 0 and @offsetOf(capacity) is 16 in all six combinations above, and the emitted loads only ever touch those two words plus the slice length. It was the equality that was wrong: it asserted a fact about a tail nothing reads. So the offsets now come from the real type via denseListWordOffset, and DenseListLayout is documented as a description of the prefix rather than a mirror.
Impact
Flips 0 test262 cases. No behaviour change on the current toolchain — same offsets, same emitted loads; @offsetOf resolves to the identical constants the literal did. What changes is that a future std reordering these fields moves the loads with it, instead of silently reading the wrong word — which the old assertion would not have caught either, since it only compared sizes.
Unblocks a downstream consumer (craft) that had to move off 0.17.0-dev.1509 because ziglang.org prunes dev builds: every 1509 tarball now 404s, so the pin could only be satisfied from cache.
Verification
zig build teston0.17.0-dev.1963+e00c6c439: 2285 passed, 1 skipped, 0 failed, 0 leaked, exit 0.zig buildon0.17.0-dev.1818+7051f8e73(this repo'sZIG_VERSION): clean, with siblings at upstreammain.- Size/offset table above measured directly on both toolchains across all three optimize modes, not inferred.
The 1963 figure is from a completed run whose log I later clobbered, and two attempts to regenerate it were killed by SIGTERM before finishing (error: process terminated with signal TERM) rather than failing — so treat it as reported, not attached. CI on this PR is the authoritative measurement and covers the 1818 leg the repo actually pins.