It crashes when you dereference the pointer (val.*).
The problem is that you are casting to get the pointer.
If you use foo.ptr you get:
error: expected type '*i32', found '[*]i32'
const val: *i32 = foo.ptr;
~~~^~~~
note: a many pointer cannot cast into a single pointer
Zig compiler complains because [*]i32 can have zero elements.
Zig compiler cannot complain when calling @ptrCast because this is a no-operation to signal the compiler that you know what you are doing (e.g. you just checked that foo.len > 0).
Zig compiler cannot complain when calling @ptrCast
I understand that. The question is, why don’t we get a runtime safety check in debug build mode? I suppose that performing such cast is undefined behavior (analogous to casting a null pointer to *i32 which is undefined behaviour and causes cast causes pointer to be null at runtime)?