i’d like to revisit this approach, with a slightly more generalized solution:
const std = @import("std");
pub const NIL = ~@as(u16, 0);
const Elem = struct {
data: u32,
next: u16 = NIL,
};
pub fn getElem(idx: u16) ?*Elem {
return if (idx == NIL) null else &elem_tab[idx];
}
var elem_tab = [_]Elem{
Elem{ .data = 10, .next = 1 },
Elem{ .data = 20, .next = 2 },
Elem{ .data = 30, .next = 0 },
};
var head = getElem(0);
pub fn main() void {
var e = head.?;
while (true) {
std.log.debug("data = {d}", .{e.data});
if (getElem(e.next) == null) break;
e = getElem(e.next).?;
if (e == head) break;
}
}
as before, elem_tab effectively contains cycles… but since the next field is represented as an index into elem_tab, i avoid the compiler dependency loop error…
something else quite remarkable about this approach (which i’ve verified in a more memory-constrained target) is the overhead of getElem is virtually equivalent to using pointers directly… this approach is also smaller than any of the approaches using run-time initialization of elem_tab…
equally remarkable, the compiler in the example above will “downgrade” var elem_tab to constant status – since it sees none of its values being mutated… the space shows up in the image’s .const rather than .data section…
the challenge, of course, is that using getElem with some index value is inherently error-prone and dangerous… unlike a typed pointer, the vanilla u16 used for my indicies don’t say anything about the type of the referenced object let alone the name of the array to be used as a base…
seems simple enough to create some generic types to wrap these relationships… but the problem is (as i’ve discovered after painfully trying) is that any value of a generic type that somehow references elem_tab cannot be placed inside elem_tab itself!!!
even moving the getElem function inside some generic Index type leads to a dependency loop… the compiler has so far seen through all of my attempts to mask what i’m really trying to do here 
any thoughts on how i can improve the safety of my index-based solution, without creating an actually dependency loop within elem_tab ???