Now, note that I am not saying that Zig's approach to safety is definitely better than Rust. Correctness is an extremely complex issue, with many factors, and it's hard to say with any certainty what works and why. My preference for Zig (which is largely hypothetical as Zig doesn't really exist in a meaningful sense yet) is because I personally value language simplicity and short cycles over what some call "expressivity", but as someone who is also very much interested in formal methods and software correctness in general, I am not convinced that Rust's complexity buys you increased correctness over Zig, and it may even be worse. So the tradeoff is simplicity vs. "expressivity", where correctness can go either way.
In fact, Rust approaches most of these particular problems the same way- arithmetic overflow, array bounds checking, stack overflow handling, etc. are all checked at runtime. Rust's language complexity is dedicated to things that Zig simply doesn't check, and that C and C++ have checked only recently.
This goes back to a previous conversation of ours[1]- Rust's complexity is allocated very differently than C++'s. It has many of the same advantages as Zig (if not more) when it comes to understanding and code review. Painting Rust's static analysis and associated language complexity as an alternative to C/C++/Zig-style runtime checks looks like a category error to me.
[1]: https://www.reddit.com/r/programming/comments/eehe6t/a_backw...
Yes. Take a look at some of the checks Zig has.
> Rust's language complexity is dedicated to things that Zig simply doesn't check, and that C and C++ have checked only recently.
Right, but that doesn't mean it leads to more correct programs when this "checking" comes at a cost.
> It has many of the same advantages as Zig (if not more) when it comes to understanding and code review.
That's a matter of taste. Those who like complex languages like, say, C++ or Scala, can certainly prefer them, but I think they're in the minority. Zig is a very simple language, while only C++ and Scala contend to be as complex as Rust or more.
> Painting Rust's static analysis and associated language complexity as an alternative to C/C++/Zig-style runtime checks looks like a category error to me.
If you, like me, don't particularly like complex languages, then the complexity has a cost. What does it buy you? It buys you certain sound guarantees about lack of UB is safe code, which hopefully helps write more correct programs. If you have an alternative to achieving a similar level of correctness with a much simpler language, I would very much prefer that.
I did, to make sure I wasn't missing something. There's nothing new there, and some things are missing. (This is not bad, Zig is still in development, but it's not exactly a new approach either.)
> only C++ and Scala contend to be as complex as Rust or more. ... If you, like me, don't particularly like complex languages, then the complexity has a cost.
This is why I linked our Reddit conversation- Rust is nowhere near as complex as C++, and its particular complexity's costs are not difficulty in reading or code review.
> If you have an alternative to achieving a similar level of correctness with a much simpler language, I would very much prefer that.
But this is exactly my point- I don't believe Zig is such an alternative! Zig and Rust both improve over C and C++'s complexity and readability, leading to some general correctness improvements; so far only Rust does anything different to address memory safety.
And it still goes further than C sanitizers (except the glaring missing piece of use-after-free, which I'm sure will be addressed).
> Rust is nowhere near as complex as C++
It's hard to quantify this, but I think few people would point at any language (in real use) other than Scala, C++ and Ada as being as or more complex than Rust, so it's at the very top. Some people are perfectly OK with that and even prefer such languages. Rust is well beyond my language complexity comfort level (even C# is too complex for my taste, and, as a high-level language it offer much better abstraction than Rust, or any low-level language). So if C++ is at 500 and Rust is at 300, that doesn't mean much if I want to be at 50 or 100.
> Zig and Rust both improve over C and C++'s complexity and readability
I don't see it this way. I find it hard to put C and Zig in the same category as Rust.
> so far only Rust does anything different to address memory safety.
I disagree with that, too. Rust is the only one that addresses memory safety using sound guarantees. If you run tests on a Zig program out of the box you won't have array overflows; that's not what you get in C and C++. Zig's "big idea" or "doing anything different" is how it does partial evaluation with a single construct (comptime) that is drastically simpler than anything I've seen. In other words, as far as simplifying languages with tough requirements for low-level programming, it's rather revolutionary. That's my preferred direction for programming languages.
Build a C program in the right mode (also required for Zig) and you get exactly the same thing.
Arguably this combination is more complex than Rust's. It has no way to constrain a comptime type argument (traits), so you get error messages like C++ templates. It has no way to constrain a function to be comptime-compatible (const fn), so you get more error messages like C++ templates. When you want to combine things, you manage phase ordering and idioms by hand, basically re-implementing Rust-like concepts at every use site.
Sometimes one or two more concepts in the language makes things simpler. To use a subject you've discussed before, it's similar to scoped continuations vs full call/cc.
In Rust, generics, macros, traits, compile-time evaluation are different constructs with drastically different syntax (and generics and value generics are different features, implemented at different times, but I can accept them as a single construct).
> It has no way to constrain a comptime type argument (traits)
It does: introspection, just as Clojure can constrain arguments, only Zig does it at compile time.
> so you get error messages like C++ templates
You don't because in C++ templates are programmed in their own sub-language with SFINAE tricks (at least in the C++ versions I use; they've probably added new ways to do this, as they do). In Zig, it's just Zig computation. You'd get similar compile-time errors as you would get, at runtime, in, say, Clojure or Python.
> When you want to combine things, you manage phase ordering and idioms by hand, basically re-implementing Rust-like concepts at every use site.
You don't need to reimplement things by hand at every use site; you just call a subroutine at compile time.
> Sometimes one or two more concepts in the language makes things simpler.
I agree, but I think that Zig's comptime brings revolutionary simplicity to the very complex subject of partial evaluation which is so important in systems languages. How well it would work in practice remains to be seen, and I may well be disappointed, but I find Zig's approach of simplicity first very appealing. I agree it's a matter of taste.
Again, these are just as much a single feature as Zig comptime. Traits are like comptime types, or else (closer to what Zig does) comptime type variable introspection.
> You'd get similar compile-time errors as you would get, at runtime, in, say, Clojure or Python.
Exactly- you're not writing plain Zig, you're writing a Zig-adjacent dynamically typed language with new ways to do almost everything and different tradeoffs around correctness.
> just call a subroutine at compile time.
Whoever wrote that subroutine did the reimplementation by hand.