Hacker News new | ask | show | jobs
by 7bit 163 days ago
> without fighting the compiler

It's unfortunate that "writing safe code" is constantly being phrased in this way.

The borrow checker is a deterministic safety net. Claiming Zig is easier ignores that its lack of safety checks is what makes it feel easier; if Zig had Rust’s guarantees, the complexity would be the same. Comparing them like this is apples vs. oranges.

2 comments

That's a very narrow way of looking at things. ATS has a much stronger "deterministic safety net" than Rust, yet the reason to use Rust over ATS is that "fighting the compiler" is easier in Rust than in ATS. On the other hand, if any cost is worth whatever level of safety Rust offers for any project, than Rust wouldn't exist because there are far more popular languages with equal (or better) safety. So Rust's design itself is an admission that 1. more compile-time safety is always better, even if it complicates the language (or everyone who uses Rust should use ATS), and 2. any cost is worth paying for safety (or Rust wouldn't exist in the first place).

Safety has some value that isn't infinite, and a cost that isn't zero. There are also different kinds of safety with different value and different costs. For example, spatial memory safety appears to have more value than temporal safety (https://cwe.mitre.org/top25/archive/2025/2025_cwe_top25.html) and Zig offers spatial safety. The question is always what you're paying and what you're getting in return. There doesn't appear to be a universal right answer. For some projects it may be worth it to pay for more safety, and for other it may be better to pay for something else.

You’re changing the argument. The point wasn’t whether more safety is “worth it”, but that comparing ease while ignoring which invariants are enforced is misleading. Zig can feel simpler because it encodes fewer guarantees. I’m not saying one approach is better, only that this comparison shifts the goalposts.
Then we're in agreement. Both languages give you something that may be important, but it has a price.
You're changing the argument again. I'm not in agreement with your statement.
Imo "safety" in safe Rust is higher than it is in more popular languages.

Data races, type state pattern, lack of nulls, ...

This is comparing what Rust has and other languages don't without also doing the opposite. For example, Java doesn't enforce data-race freedom, but its data races are safe, which means you can write algorithms with benign races safely (which are very useful in concurrent programming [1]), while in Rust that requires unsafe. Rust's protection against memory leaks that can cause a panic is also weaker, as is Rust's ability to recover from panics in general. Java is now in the process of eliminating the unsafe escape hatch altogether except for FFI. Rust is nowhere near that. I.e. sometimes safe Rust has guarantees that mean that programs need to rely on unsafe code more so than in other languages, which allows saying that safe Rust is "safer" while it also means that fewer programs are actually written purely in safe Rust. The real challenge is increasing safety without also increasing the number of programs that need to circumvent it or increasing the complexity of the language further.

[1]: A benging race is when multiple tasks/threads can concurrently write to the same address, but you know they will all write the same value.

> 1. more compile-time safety is always better, even if it complicates the language (or everyone who uses Rust should use ATS), and 2. any cost is worth paying for safety (or Rust wouldn't exist in the first place).

You keep repeating this. It's not true. If what you said was true, Rust would have adopted HKT, and God knows whatever type astronomy Haskell & Scala cooked up.

There is a balancing act, and Rust decided to plant a flag in memory safety without GC. The fact that Zig, didn't expand on this, but went backwards is more of an indictment of programmers unwilling to adapt and perfect what came before, but to reinvent it in their own worse way.

> There are also different kinds of safety with different value and different costs. For example, spatial memory safety appears to have more value than temporal safety (https://cwe.mitre.org/top25/archive/2025/2025_cwe_top25.html)

How did you derive this from the top 25 of CWEs? Let's say you completely remove the spatial memory issues. You still get temporal memory issues at #6.

Rust does have a GC, but I agree it planted its flag at some intermediate point on the spectrum. Zig didn't "go backwards" but planted its own flag ever so slightly closer to C than to ATS (although both Rust and Zig are almost indistinguishable from C when compare to ATS). I don't know if where Rust planted its flag is universally better than where Zig planted its flag, but 1. no one else does either, 2. both are compromises, and 3. it's uncertain whether a universal sweet spot exists in the first place.

> How did you derive this from the top 25 of CWEs? Let's say you completely remove the spatial memory issues. You still get temporal memory issues at #6.

Sure, but spatial safety is higher. So if Rust's compromise, we'll exact a price on temporal safety and have both temporal and spatial safety, is reasonable, then so is Zig's that says, the price on temporal safety is too high for what you get in return, but spatial safety only is a better deal. Neither go as far as ATS in offering, in principle, the ability to avoid all bugs. Nobody knows whether Rust's compormise is universally better than Zig's or vice versa (or perhaps neither is universally better), but I find it really strange to arbitrarily claim that one compromise is reasonable and the other isn't, where both are obviously compromises that recognise there are different benefits and different costs, and that not every benefit is worth any cost.

> Rust does have a GC

It doesn't. Not by any reasonable definition of having a GC.

And "opt-in non-tracing GC that isn't used largely throughout the standard library" is not a reasonable definition.

> Nobody knows whether Rust's compormise is universally better than Zig's

When it comes to having more segfaults, we know. Zig "wins" most segfaults per issue Razzie Award.

This is what happens when you ignore one type of memory safety. You have to have both. Just ask Go.

> And "opt-in non-tracing GC that isn't used largely throughout the standard library" is not a reasonable definition.

Given that refcounting and tracing are the two classic GC algorithms, I don't see what specifying "non tracing" here does, and reference-counting with special-casing of the one reference case is still reference counting. I don't know if the "reasonable definition" of GC matters at all, but if it does, this does count as one.

I agree that the one-reference case is handled in the language and the shared reference case is handled in the standard library, and I think it can be reasonable to call using just the one-reference case "not a GC", but most Rust programs do use the GC for shared references. It is also true that Rust depends less on GC than Java or Go, but that's not the same as not having one.

> When it comes to having more segfaults, we know. Zig "wins" most segfaults per issue Razzie Award.

And Rust wins the Razzie Award for most painful development and lack of similarly powerful arenas. It's like declaring that you win by paying $100 for something while I paid $50 for something else without comparing what we got for the money, or declaring that you win by getting a faster car without looking at how much I paid for mine.

> This is what happens when you ignore one type of memory safety.

When you have less safety for any property, you're guarnateed to have more violations. This is what you buy. Obviously, this doesn't mean that avoiding those extra violations is necessarily worth the cost you pay for that extra safety. When you buy something, looking just at what you pay or just at what you get doesn't make any sense. The question is whether this is the best deal for your case.

Nobody knows if there is a universal best deal here let alone what it is. What is clear is that nothing here is free, and that nothing here has infinite value.

> I don't know if the "reasonable definition" of GC matters at all

If you define all non-red colors to be green, it is impossible to talk about color theory.

> And Rust wins the Razzie Award for most painful development and lack of similarly powerful arenas.

That's a non-quantifiable skill issue. Segfaults per issue is a quantifiable thing.

> When you have less safety for any property, you're guarnateed to have more violations.

If that's what you truly believed outside some debate point. Then you'd be advocating for ATS or Ada.SPARK, not Zig.

The fact that Zig doesn't have Rust's guarantees doesn't mean Zig does not have safety checks. The safety checks that Zig does have are different, and are different in a way that's uniquely useful for this particular project.

Zig's check absolutely don't go to the extent that Rust's do, which is kind of the point here. If you do need to go beyond safe code in Rust, Zig is safer than unsafe code in Rust.

Saying Zig lacks safety checks is unfortunate, although I wouldn't presume you meant it literally and just wanted to highlight the difference.

Thing is, those safety checks are also available in C and C++, provided that one uses the right tools like PVS and PurifyPlus (just to quote two examples), and now ongoing AI based tooling efforts for verification, thus the question is why a language like Zig in the 21st century, other than "I don't like either C++ or Rust".
I never said Zig has no safety features. What I said is true, though. If it would have Rusts guarantees (as in: The same) it would be more complex.
I mean if we're going to nitpick:

>>> its lack of safety checks

>> Saying Zig lacks safety checks is unfortunate,

> I never said Zig has no safety features.

You did. Or, alternatively, if you don't equate "checks" with "features", then I never said you said that so what are you complaining about?

> If it would have Rusts guarantees (as in: The same) it would be more complex.

Which is true (if tautological), and is basically what the GP said:

> Zig's manual memory management might actually be more ergonomic for a DOM implementation specifically because you can model the graph relationships more directly without fighting the compiler, provided you have a robust strategy for the arena allocation

Both you and the GP agree that Rust is more complex.

You objected to this with:

> It's unfortunate that "writing safe code" is constantly being phrased in this way.

Upon which I commented that Zig does have safety features, even if they're not covering you as well as Rust's ones. Which is, again, inline with "provided you have a robust strategy for the arena allocation."

Now, if you think I'm going overboard with this, I agree with you -- and this is the exact feeling I have when I look at Rust :)