It’s not. I’m not saying that’s inherently bad. It’s just what it is. Consider the following code:
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var list = try std.ArrayList(u8).initCapacity(allocator, 4);
try list.appendSlice("Hell");
const c = &list.items[0];
try list.append('o');
try list.append(c.*);
It compiles just fine but triggers a segfault due to a Use-After-Free bug in the last line:
$ zig run main.zig
Segmentation fault at address 0x104b00000
aborting due to recursive panic
zsh: abort zig run main.zig
If you have a use case where you don’t care about that - you do you!
We can analyze what safety even is (or what memory even is), or say that other tools can help (ASan, etc.) but this code isn’t safer than similar code written in C, C++, and other unsafe languages.