Hacker News new | ask | show | jobs
by zamalek 499 days ago
This is absolutely not what the article is about. A good majority of it is spent on the myth that Zig is safer than Rust, which has nothing to do with wishing Zig was more like Rust.
2 comments

Is there a myth that makes that claim? Virtually every take I've heard is that Zig is "safe enough" while giving developers more control over memory and actually, it's specifically better for cases where you must write unsafe code, as it's not possible to express all programs in safe Rust.
If you must write unsafe code, what's wrong with just dropping down to unsafe in Rust when you need to? You have all the power unsafe provides, and you have a smaller surface area to audit than if your entire codebase resides in one big unsafe block.
the barrier between unsafe and safe has additional rules. it’s not “just dropping to unsafe” – you need to make sure you leave it safely.
Unsafe Rust is problematic: https://zackoverflow.dev/writing/unsafe-rust-vs-zig See also: https://github.com/roc-lang/roc/blob/main/www/content/faq.md...

Zig is not entirely unsafe. It provides quite a few compile time checks and primitives to catch memory leaks or prevent them altogether.

> It provides quite a few compile time checks and primitives to catch memory leaks or prevent them altogether.

From what I've seen, clang has all of these and more for C++. If your metric is "tooling to help you catch UB", C++ is significantly superior to Zig.

Zig has a C and C++ compiler built into it and works seamlessly with it. Several C/C++ projects use Zig as a build tool. Zig makes different trade-offs with C++ from a language design standpoint. C++ has a lot more footguns to create UB in the first place.
> C++ has a lot more footguns to create UB in the first place.

I'd actually give the edge to C++ over Zig, because of smart pointers (not that I'm implying smart pointers are anywhere near sufficient).

WTH they were talking about Rust and Zig, they did not even mention C++ and you come with "if your metrics is blah then C++ is superior, checkmate!", completely ignoring C++ is a monster of complexity while Zig is basically simple as C.
If you present an argument that you like X in a thing so you picked B, and A exist that's more X than B, it means your argument is partially (you like X and Z) or totally (you like Y) wrong.

In this context of, if you are using Zig for its safety via tooling, there is a much more mature candidate C++.

This is precisely the myth that the article talks about. Miri finds significantly more UB in unsafe Rust than Zig's checks do.

Even if it weren't, this exaggeration is a complete theater. You aren't supposed to use unsafe Rust unless you really have to. I have been using Rust since 2020 and I've used it once, for 3 lines of code. The entirety of all Zig codebases is unsafe. That's fine if you are fine with unsafe code, but this myth is dishonest, and I take great issue with using a language where the founder is the primary source of the dishonesty - because what else is being swept under the rug?

> Miri finds significantly more UB in unsafe Rust than Zig's checks do.

That's not a substantiated claim. Miri also runs very slowly.

> You aren't supposed to use unsafe Rust unless you really have to. I have been using Rust since 2020 and I've used it once, for 3 lines of code.

Cool, glad you haven't needed it. If you're ever writing interpreters or interfacing with external code, you'll need it.

> The entirety of all Zig codebases is unsafe

Zig is not 100% memory safe but it has compile-time safety features for vast majority of problems developers get themselves into with C/C++. Meanwhile, Rust's safety overhead has real trade-offs in terms of developer productivity, computational performance, compiler performance and binary size.

> That's not a substantiated claim.

The article we are commenting on substantiates it with, several, actual examples.

> interpreters

In what world do interpreters require unsafe code? A naive interpreter that recursively descends an AST doesn't need it, and a bytecode interpreter doesn't need it either. You'll probably need it if you want to make a fast GC, but that does not mean your entire codebase has to be unsafe.

> interfacing with external code

This is one reason unsafe exists, yes. You are supposed to hide the unsafe parts behind a safe interface. For example, Rust unavoidably has to deal with external code to do I/O - yet, the exposed std::fs interface is safe. This is a well established doctrine in the Rust community, and at least one prominent project has received hot hell for ignoring it.

And, again, the portions of code that are unsafe in a Rust codebase - even when required - are supposed to be minimal, well contained, and well tested. Running a suite of tests to check a small amount of code under Miri is not prohibitive at all. If someone is going to insist on using unsafe across their codebase then, yes, they are far better served by using a language that is unsafe to begin with.

I have done embedded Rust, and even there I have largely avoided unsafe code (the 3 lines I was forced to write happened to be for embedded).

> Rust's safety overhead has real trade-offs [...]

I never claimed otherwise. Those trade-offs have a purpose: fewer degrees of freedom result in higher degrees of certainty. Even Rust has too many degrees of freedom[1], but we don't sweep that under the rug, deflect it, or outright lie about the situation.

The Rust zeitgeist largely agrees your opinion (or rather: Andrew's opinion) of unsafe Rust, in a very oblique way. It's shit, we don't like using it. It is certainly not an accurate summary of Rust as a whole.

Leveraging unsafe Rust against Rust as a whole is a dishonest line of thinking and I'm not going to engage with it further.

[1]: https://github.com/Speykious/cve-rs

yes but by the time you're using miri, why not just run zig with a separate static checker that does all the memory safety parts?

https://github.com/ityonemo/clr

For one, it doesn't do all the "memory safety parts", according to the readme. I'm very skeptical that Zig can be made memory safe with a checker while still remaining compatible with existing code. Certainly neither C nor C++ can, and Zig isn't meaningfully different in expressivity (if anything, it's more expressive, which is the opposite of what you want).
Yes, unsafe code is problematic in Rust, C, C++, etc. Is Zig different?
It’s harder to write correct unsafe Rust than correct Zig because (1) Rust uses references all over the place, but when writing unsafe code you must scrupulously avoid “producing” an invalid reference (even if you never deference it), and (2) there’s lots of syntax noise which obscures what the code is doing (though &raw is a step in the right direction).
For Rust references, rules[0] are not hard to follow:

The pointer must be properly aligned.

It must be non-null.

It must be “dereferenceable”: a pointer is dereferenceable if the memory range of the given size starting at the pointer is entirely contained within the bounds of that allocated object. Note that in Rust, every (stack-allocated) variable is considered a separate allocated object.

The pointer must point to a valid value of type T.

When creating a mutable reference, then while this reference exists, the memory it points to must not get accessed (read or written) through any other pointer or reference not derived from this reference.

When creating a shared reference, then while this reference exists, the memory it points to must not get mutated (except inside UnsafeCell).

[0]: https://doc.rust-lang.org/stable/core/ptr/index.html#pointer...

> Rust uses references all over the place

This is mostly a concern with the Rust stdlib, though. And it's in principle fixable, by writing new varieties of those stdlib functions that take raw-pointer or &UnsafeCell<...> arguments, and delegating the "safe" varieties to those.

In related news, someone just published a PoC borrow checker for Zig:

https://news.ycombinator.com/item?id=42923829

Various modern alternative languages can claim to be "safe enough" or safer than C, along with C interop. Nim, Dlang... In fact, the V programming language (Vlang) can make the argument of being even safer, because it has more default safety features and an optional GC (that no libraries depend on) for greater memory safety. That and it being designed to be easier to use and learn, for general-purpose programming.

The article, in its review of the Zig language, goes after its marketing history and broken promises (calling Andrew's statements fallacious and worse) for attempting to portray itself as safer than unsafe Rust, the distortions around UB (undefined behavior), etc... As a consequence of the demonstrably valid test results and being tired of unreliability, the author stopped using Zig. It should also be mentioned, that v1 Zig is nowhere in sight, so likely many years more to wait.

i haven’t seen anyone pronounce it anywhere once.