«inline else» is also very powerful tool to easily abstract away code with no runtime cost.
Nobody knows whether Rust and/or Zig themselves are the future of low-level programming, but I think it's likely that the future of low-level programming is that programmers who prefer one approach would use a Rust-like language, while those who prefer the other approach would use a Zig-like language. It will be intesting to see whether the preferences are evenly split, though, or one of them has a clear majority support.
The drift over time is predictable, compared to ten years ago Rust has fewer false positives, C++ has more false negatives.
You are correct to observe that there is no middle choice here, that's Rice's Theorem, non-trivial semantic correctness is Undecidable. But I would argue we already know what you're calling the "false positive" scenario is also not useful, we're just not at the point where people stop doing it anyway.
No, it doesn't. Zig is safer than C++ (and it's much simpler, which also has an effect on correctness).
Making up some binary distinction and then deciding that because C++ falls on the same side of it as Zig (except it doesn't, because Zig eliminates out-of-bounds access to the same degree as Rust, not C++) then what applies to one must apply to the other. There is simply no justification to make that equivalence.
> There is no middle choice here, that's Rice's Theorem, non-trivial semantic correctness is Undecidable.
That's nothing to do with Rice's theorem. Proving some properties with the type system isn't a general algorithm; it's a proof you have to work for in every program you write individually. There are languages (Idris, ATS) that allow you to prove any correctness property using the type system, with no false positives. It's a matter of the effort required, and there's nothing binary about that.
To get a sense of the theoretical effort (the practical effort is something to be measured empirically, over time) consider the set of all C programs and the effort it would take to rewrite an arbitrary selection of them in Rust (while maintaining similar performance and footprint characteristics). I believe the effort is larger than doing the same to translate a JS program to a Haskell program.
That depends what you mean by "safer", but it is an empirical fact that unsound methods (like tests and code reviews) are extremely effective at preventing bugs, so the claim that formal methods are the only way is just wrong (and I say this as a formal methods person).
> The exact opposite. You can see it play out in the C vs C++ arena. C++ is essentially just a more complex C. But I trust modern C++ much more in terms of memory safety.
I don't understand the logical implication. From the fact that there exists a complicating extension of a language that's safer in some practical way than the original you conclude that complexity always offers correctness benefits? This just doesn't follow logically, and you can immediately see it's false because Zig is both simpler and safer than C++ (and it's safer than C++ even if its simplicity had no correctness benefits at all).
Due diligence every single time after the tenth refactor?
Unfortunately for all fanatics, language really doesn't matter that much.
I have been using KDE for years now and it works perfectly good for me. It has no issues/crashes, it has many features in terms of desktop environment and also many programs that come with it like music player, video player, text editor, terminal etc. and they all work perfectly well for me. Almost all of this is written in C++. No need to mention the classic linux/chromium etc. etc which are all written in c++/c.
I use Ghostty which is written in zig, it is amazingly polished and works super well as well.
I have built and used a lot of software written in Rust as well and they worked really well too.
At some point you have to admit, what matters is the people writing software, the amount of effort that goes into it etc. it is not the langauge.
As far as memory-safety goes, it really isn't close to being the most important thing unless you are writing security critical stuff. Even then just using Rust isn't as good as you might think, I uncountered a decent amount of segfaults, random crashes etc. using very popular Rust libraries as well. In the end just need to put in the effort.
I'm not saying language doesn't matter but it isn't even close to being the most important thing.
Safety is the selling point of Rust, but it's not the only benefit from a technical point of view.
The language semantics force you to write programs in a way that is most convenient for the optimizing compiler.
Not always, but in many cases, it's likely that a program written in Rust will be highly and deeply optimized. Of course, you can follow the same rules in C or Zig, but you would have to control more things manually, and you'd always have to think about what the compiler is doing under the hood.
It's true that neither safety nor performance are critical for many applications, but from this perspective, you could just use a high-level environment such as the JVM. The JVM is already very safe, just less performant.
Also, treating all languages that don't ensure full memory safety as if they're equally problematic is silly. The reason not ensuring memory safety is bad is because memory unsafety as at the root of some bugs that are both common, dangerous, and hard to catch. Only not all kinds of memory unsafety are equally problematic, Zig does ensure the lack of the the most dangerous kind of unsafety (out-of-bounds access) while making the other kind (use-after-free) easier to find.
That the distinction between "fully memory safe" and "not fully memory safe" is binary is also silly not just because of the above, but because no lanugage, not even Java, is truly "fully memory safe", as programs continue to employ components not written in memory safe languages.
Furthermore, Zig has (or intends to have) novel features (among low-level languages) that help reduce bugs beyond those caused by memory unsafety.
Your writing feels accessible. I find it makes complex topics approachable. Or at least, it gives me a feel of concepts that I would otherwise have no grasp on. Other online writing tends to be permeated by a thick lattice of ideology or hyper-technical arcanery that inhibits understanding.
I did have one once (https://pron.github.io) but I don't know how accessible it is :) (two post series are book-length)
> not even Java, is truly "fully memory safe", as programs continue to employ components not written in memory safe languages.
This is a silly point.
Memory safety (like soundly ensuring any non-trivial property) must come at a cost (that's just complexity theory). You can pay for it with added footprint (Java) or with added effort (Rust). Some people are disappointed that Zig offer more safety than C++ but less than Rust in exchange for other important benefits, while others are disappointed that the price you have to pay for even more safety in Rust is not a price they're happy to pay.
BTW, many Rust programs do use GC (that's what Rc/Arc are), it's just one that optimises for footprint rather than speed (which is definitely okay when you don't use the GC as much as in Java, but it's not really "without GC", either, when many programs do rely on GC to some extent).
> This is a silly point.
Why? It shows that even those who wish to make the distinction seem binary themselves accept that it isn't, and really believe that it matters just how much risk you take and how much you pay to reduce it.
(You could even point out that memory corruption can occur at the hardware level, so not only is the promise of zero memory corruption not necessarily worth any price, but it is also unattainable, even in principle, and if that were truly the binary line, then all of software is on the same side of it.)
Sure, but you lose the clarity of errors. The error wasn't in `comptime unreachable` but in `inline .a .b .c`.
If a dead code elimination pass didn't remove the 'comptime unreachable' statement, you'll now fail to compile (I expect?)
Doesn't mean it's not useful.
That sounds as bad as relying on undefined behaviour in C.
There are similarities here to C++ if constexpr and static_assert, if those are familiar to you.
Which is fine for small inputs and uses, but it's not something that would scale well.
That may be confusing, but basically `inline` is generating different code for the branches .a and .b, so in those cases the value of `ab` is known at compile time. So, the inner switch is running at compile time too. In the .a branch it just turns into a call to handle_a(), and in the .b branch it turns into a call to handle_b().
It is not meant for asserting dynamic “unreachability” (which is more like an assertion than a proof).
if false {
const _:() = panic!();
}
}Fails to compile in Rust.
fn main() {
const {
if false {
let _:() = panic!();
}
}
}
which compiles as expected. (Note that if the binding were `const` instead of `let`, it'd still have failed to compile, because the semantics don't change.) fn main() {
const _:() = const { if false { panic!() } };
}
It's fine that we want a constant, it's fine that this constant would, when being computed at compile time, panic if false was true, because it is not.in zig they have one brach const.
in rust example from you, whole control flow ix is const. which is not rquivalent to zig. so how to have non const branches?