The premise of the Rust half of the article makes no sense. 'Rust has more rules' is not true, references have more rules, and in unsafe code, you aren't using them very much. Comparing the rules that apply to references in Rust to the rules that apply to raw pointers in C and Zig is nonsensical: if you transliterate the Zig code to Rust, no new problems appear! 'What if I create a reference' is easily solved by not…
> What if I create a referecnce is easily solved by not creating a reference Except it isn't easy. Rust implicitly creates references constantly and in unsafe code it may be UB for those to exist. It's why Rust has all the crazy offsetof macros and such because you can't reliably do the obvious &raw (*struct_pointer).field
When Zig Is Safer and Faster Than Rust
41–50 of 58 posts
Re: When Zig Is Safer and Faster Than Rust
#42Earlier quoted context omitted.
> try between the alloc/free The idiomatic way to handle that is with some combination of `defer` and `errdefer`. Then, in code, there are no lines between alloc/free, and if a try would exit before the free then you would instead first free anyway. > drop semantic is better in that regard The drop trait has its warts too. Zig's version sets up a point in time where the given cleanup code _will_ run (ignoring power o…
> The drop trait has its warts too. Zig's version sets up a point in time where the given cleanup code _will_ run (ignoring power outages and the like), and Rust's sets up a point in time where the given cleanup code is _allowed_ to run. You're making it sound like Drop is regularly not called, which could lead someone to think that you're talking about them not running on panics, which they do: https://play.rust-lan…
Sorry if it came across that way. My claim is weaker, that it's sometimes not called even in cases where it could be with a smart enough programmer/language.
> But any language will have issue executing code before exiting if you go out of your way to...
Is there an easy way to make Drop work nicely with signal handler induced shutdowns other than having a "correctly" configured panic handler and panicking in the signal handler (even that causing other UB depending on what code Drop runs)? The edge cases for the feature look thorny from my perspective, but (some) other languages handle that by forcing you to be explicit about which code runs when.
> I don't see how Drop causes leaks
"Relying" on Drop is the most common source of Drop-related leaks. All it takes is one extra reference to cause leaky code (see Actix as a case study in such problems).
> Beyond my skepticism about the mechanism being a significant source of performance degradation
That's... pretty easy to test? Pick any problem that potentially has a lot of allocations, like an async sudoku solver, and check how it performs with a collection (arena, pool, ...) vs using Drop on each item. I promise the difference is substantial.
> writing collections that take responsibility over dropping their contents in one go isn't particularly difficult or restricted by the language
No, not at all. I totally agree. The concept of "intentional friction" is useful here. An expert can make excellent Rust code. My last job had one person like that (not that it matters, but that was out of many people who wrote Rust there), and you have shining examples like BurntSushi. My complaint is that the language's happy path doesn't guard against those performance mishaps, and since most Rust code I see in the wild has fallen prey to those pitfalls I think it's a reasonable complaint.
Re: When Zig Is Safer and Faster Than Rust
#43The premise of the Rust half of the article makes no sense. 'Rust has more rules' is not true, references have more rules, and in unsafe code, you aren't using them very much. Comparing the rules that apply to references in Rust to the rules that apply to raw pointers in C and Zig is nonsensical: if you transliterate the Zig code to Rust, no new problems appear! 'What if I create a reference' is easily solved by not…
> What if I create a referecnce is easily solved by not creating a reference Except it isn't easy. Rust implicitly creates references constantly and in unsafe code it may be UB for those to exist. It's why Rust has all the crazy offsetof macros and such because you can't reliably do the obvious &raw (*struct_pointer).field
This is not correct -- dereferencing a raw pointer does not implicitly create a reference. That code snippet is perfectly valid as long as the underlying pointer arithmetic is valid.
See the Rust reference on "Behaviors considered undefined": [0]
> Accessing (loading from or storing to) a place that is dangling or based on a misaligned pointer.
No problem here, dereferencing a raw pointer creates a place expression but we do not load or store from it.
> Performing a place projection that violates the requirements of in-bounds pointer arithmetic [1]. A place projection is a field expression, a tuple index expression, or an array/slice index expression.
Alright, so we're doing place projection. Let's check the link to see the requirements for in-bounds pointer arithmetic:
> The offset in bytes, computed on mathematical integers (without “wrapping around”), must fit in an isize.
> If the computed offset is non-zero, then [the base pointer] must be derived from a pointer to some allocated object, and the entire memory range between [the base pointer] and the result must be in bounds of that allocated object. In particular, this range must not “wrap around” the edge of the address space.
Okay, so your "obvious" snippet is sound as long as struct_pointer points to valid memory that's at least big enough to contain the field offset you're accessing. There's no rules about aliasing, or even alignment.
These semantics are more or less the same as the equivalent C code. They might even be slightly more relaxed, since I don't recall if C has requirements on alignment or strict aliasing when doing pointer projections. I have no idea what Zig's requirements are -- I spent about a half hour searching and couldn't find any documentation or discussion on whether and when pointer projection, or even just pointer arithmetic, can lead to undefined behavior in Zig. I'd be pretty uncomfortable writing pointer heavy code in Zig when I can't find documentation or even a GitHub issue on whether basic pointer operations can trigger UB or not.
[0]: https://doc.rust-lang.org/reference/behavior-considered-unde...
[1]: https://doc.rust-lang.org/std/primitive.pointer.html#method....
Re: When Zig Is Safer and Faster Than Rust
#44Re: When Zig Is Safer and Faster Than Rust
#45I feel like there's space for imperative, garbage collected, pattern matching, and ADT language. Just Golang + pattern matching + ADT. I would be sooooooooooooooooooooooooo happy. I think there ought to be a subset of Rust that uses Arc for everything, maybe with a language feature that desugars into it. Obviously this requires compilers to be able to reason and optimize out atomics.
Re: When Zig Is Safer and Faster Than Rust
#461) Lack of a garbage collector does not make your program faster, it makes the performance more easily predictable in terms of latency.
It also makes it more friendly for memory bandwidth, CPU cache and to overall memory usage, which in turn results in better performance in real-case scenarios vs synthetic/toy benchmarks. This is particularly noticeable in constrained environments (like embedded systems).
2) Zig was never about memory safety, and it is not a memory-safe language.
It might have better plumbing than C, it might add better way to implement and abstract concepts.. but so does C++, for instance.
The more striking differences between C++ and Zig, IMHO, are syntax and the ability to use the same language instead of a separate one to do meta-programming (templates vs comptime).
3) Aliasing enforcement in Rust is there for a reason.
Two examples I quickly found on Zig's issue tracker:
Re: When Zig Is Safer and Faster Than Rust
#47I feel like there's space for imperative, garbage collected, pattern matching, and ADT language. Just Golang + pattern matching + ADT. I would be sooooooooooooooooooooooooo happy. I think there ought to be a subset of Rust that uses Arc for everything, maybe with a language feature that desugars into it. Obviously this requires compilers to be able to reason and optimize out atomics.
Ocaml, F#, Reason, ReScript, Scala? Or any other of the million ML style languages?
Every FP languages tends to be "pure" and remove every "unnecessary" syntax to achieve some kind of "simplicity".
No, I want a true cavemen language. Treat me like I'm a low IQ idiot. "This function returns Option DURRR ME HAVE TO MATCH ALL. ME DON UNDERSTAND WHAT "_" CLAUSE IS. ME NO UNDERSTAND LIFETIMES, LAST TIME I WROTE THE C BINDING ME BRAIN ALL FRY".
There's a space for language for people who:
1. learn the language in 1 hour 2. spend 100 hour writing the most mundane, verbose code
instead of:
1. learn the language in 100 hour 2. spend 1 hour writing the most beautiful, concise and pure code
Re: When Zig Is Safer and Faster Than Rust
#48Earlier quoted context omitted.
Rust's approach is more like a "keep off the grass sign" than a barbed wire fence. If Rust really wasn't meant to be used for these things, it wouldn't have the unsafe keyword at all. But instead of forbidding those things entirely, it just makes them uncomfortable. This nudges the programmer to question if they really need to be on the grass to accomplish their goal, and helps subconsciously steer them onto the safe…
> instead of forbidding those things entirely, it just makes them uncomfortable The details in the linked articles rise well above merely "uncomfortable" though. If your response was appropriate, we wouldn't be here discussing them. In particular the interaction between the borrow and aliasing analysis is something I hadn't thought of before, and seems terrifying. This gets back to my earlier point. The Rust communit…
Actually you can write dlist in safe Rust. But with some overhead in comparison with C, C++.
Re: When Zig Is Safer and Faster Than Rust
#49Earlier quoted context omitted.
Ocaml, F#, Reason, ReScript, Scala? Or any other of the million ML style languages?
I tried OCAML, My problem with it is that it smuggles in a lot of other concepts too. Especially with the thing about bindings and mutability. Also, the syntax. Every FP languages tends to be "pure" and remove every "unnecessary" syntax to achieve some kind of "simplicity". No, I want a true cavemen language. Treat me like I'm a low IQ idiot. "This function returns Option DURRR ME HAVE TO MATCH ALL. ME DON UNDERSTAND…
Re: When Zig Is Safer and Faster Than Rust
#50A few notes: 1) Lack of a garbage collector does not make your program faster, it makes the performance more easily predictable in terms of latency. It also makes it more friendly for memory bandwidth, CPU cache and to overall memory usage, which in turn results in better performance in real-case scenarios vs synthetic/toy benchmarks. This is particularly noticeable in constrained environments (like embedded systems)…
AFAIK, some time ago non-predicable GC behavior was the reason why Discord migrated from Golang to Rust. Also predictable latency is important for real-time applications.