It's always going to be possible to do unsafe things in Zig, because we have inline assembly, @intToPtr, and ability to call extern functions with the wrong ABI.
But what if we could eliminate everything else? What if, after enumerating all kinds of undefined behavior (See #1966), we could make all of them safety-checked, with only some obvious exceptions such as inline assembly?
@intToPtr could look at the type it was casting to and make sure it is correct, somehow?This might turn out to be impossible or impractical, but it's worth investigating.
If we could reduce the unchecked undefined behavior surface to a minimum level, there could be auditing/linting tools to point out where unsafety lies in zig software. It would be possible to say something like, "Debug and ReleaseSafe builds of Zig code are safe (in that they crash rather than have undefined behavior), except for inline assembly and extern function ABI mismatch", or some short list of exceptions.
If the cost of these protections is high, that's what we have @setRuntimeSafety for (see #978).
It would be reasonable for these protections to depend on OS-specific behavior, and to be unavailable on some targets, such as freestanding.
Interestingly, this may be related to #130. One current area of unsafety is when you use struct embedding and @fieldParentPtr with an enum telling which kind of type something is with a @ptrCast. If you mismatch ids and types, boom. Potentially the interface/vtable/oop feature, if any, that ends up coming out of #130 could solve this safety issue. Or maybe there could be a more general solution.
any improvement?
IMHO the important thing to get right in regards to safety is memory safety. Existing publications on this topic often make a distinction between spatial and temporal memory safety, e.g. [1]:
Memory safety has two aspects. Temporal safety is ensured when memory is never used after it is freed. Spatial safety is ensured when any pointer dereference is always within the memory allocated to that pointer.
As it stands currently, I think Zig offers neither spatial nor temporal memory safety. Haven't really used the language much yet but it seems to me that [*]T pointer types allow spatial errors as they do not have bounds information associated with them. Issues regarding temporal memory safety have already been mentioned in this issue (use-after-free). I also believe that temporal memory safety is harder to get right. The obvious solution is garbage collection though that would make Zig unusable on embedded devices. Alternatives include reference counting or Rust-like borrow checking. There is a nice write-up by the person behind the Lobster programming language which briefly discusses the different techniques and describes how the issue is addressed in Lobster.
Most helpful comment
IMHO the important thing to get right in regards to safety is memory safety. Existing publications on this topic often make a distinction between spatial and temporal memory safety, e.g. [1]:
As it stands currently, I think Zig offers neither spatial nor temporal memory safety. Haven't really used the language much yet but it seems to me that
[*]Tpointer types allow spatial errors as they do not have bounds information associated with them. Issues regarding temporal memory safety have already been mentioned in this issue (use-after-free). I also believe that temporal memory safety is harder to get right. The obvious solution is garbage collection though that would make Zig unusable on embedded devices. Alternatives include reference counting or Rust-like borrow checking. There is a nice write-up by the person behind the Lobster programming language which briefly discusses the different techniques and describes how the issue is addressed in Lobster.