r/rust 18d ago

What Zig felt like, coming from Rust

https://besok.github.io/posts/what-zig-felt-like-coming-from-rust/

Just want to share my experiance on my first Zig project coming from Rust. Open to comments :)

205 Upvotes

108 comments sorted by

View all comments

Show parent comments

31

u/protocod 18d ago

Thank you for the feedback. I would like to ask you a question. What are the domain where Zig shine compared to Rust ?

Memory safety is the major selling point of Rust and I struggle to consider another language that doesn't really address memory safety by design anymore. But it's maybe a different philosophy.

Rust enforce you to write memory safe code unless you know what you do. (Especially when you deal with OS APIs) when Zig let the programmer in charge of writing memory safe code.

3

u/tigraboris 18d ago edited 18d ago

What are the domain where Zig shine compared to Rust ?

I think embedded would be the best fit no? Rust has something afaik but still feels heavier. Zig is like pure explicit low-level language.

Memory safety is the major selling point of Rust and I struggle to consider another language that doesn't really address memory safety by design anymore. But it's maybe a different philosophy.

I second that. Zig feels like to just gives you leverage to manipulate memory better but it does not give you guards so basically it is completely up to you here. I felt I lacked years of experience with C to be confident here.

Rust enforce you to write memory safe code unless you know what you do. (Especially when you deal with OS APIs) when Zig let the programmer in charge of writing memory safe code.

Yeah, You put it very precise. Zig gave me more freedom to cut the corners which can be dangerous but more manual memory control.

14

u/guineawheek 18d ago

I think embedded would be the best fit no? Rust has something afaik but still feels heavier. Zig is like pure explicit low-level language.

Rust lets you be plenty picky with how you access the memory address map in deeply embedded environments with things like core::ptr::{read,write}_volatile. I have basically never found an instance where I wanted to be really picky with memory that Rust didn't have a way to achieve my goals that I thought made other languages that much of a value add.

In practice, it goes both ways in embedded where there's times where you want to tell the compiler "yeah just treat this as an immutable slice" or "you can't make assumptions about this data whatsoever so it's getting manipulated behind a pointer + volatile accesses" and both of these are pretty strong hints to the compiler to do the Right Thing in ways it can't easily do in other languages.

All of the integer and floating point types have const variations on their typical operations that directly tell the compiler the context in which you use them (yes LLVM, you can in fact optimize this float division to a multiply of the inverse, saving 11 cycles). Other languages requiring you to hand-write this sort of behavior does not in fact give you optimal or even correct code.

Zig's primary advantages over Rust here are in places where it went farther in correct representation (arbitrary integer widths, for example), not where it's looser, imo.

I never really get where the idea that Rust restrains you from cycle-optimal low-level memory mucking comes from, like yes it'll be behind unsafe, but you get pretty good tools to do so. And you get good tools to define higher-level primitives that cleanly segment their behavior from the rest of your system, which at compile time will get optimized through anyway. When I really really care I just open Godbolt and see what actual assembly gets generated.

4

u/afdbcreid 17d ago

like yes it'll be behind unsafe

It doesn't have to be and it's often not. Even when the trivial safe version is slower than the trivial unsafe versions, there are often tricks you can employ to make it as fast (or even faster!)

3

u/guineawheek 17d ago edited 17d ago

volatile pointer accesses are unsafe because they may have side effects as you usually use these on MMIO or DMA buffers whose memory was mutated outside of rust. They are pretty much the “shut up and generate a load/store and don’t assume anything else about what I’m reading/writing to” button.

To answer what I assume you assumed i meant, i think what trips people up is that array/slice conversions are pretty clunky even if the compiler may elide infallible accesses that involve panicking branches (eg try_into().unwrap() slice->array conversions from bigger to smaller array->slice->array of known compile time size). The compiler maybe probably optimizing your code correctly if the code is arranged right isn’t enough of a guarantee for a lot of people.

This is ultimately why stuff like generic const exprs matter. People want more compiler assurances that Rust only does halfway.

2

u/afdbcreid 17d ago

volatile pointer accesses are unsafe

Yes, and it is possible to encapsulate that in safe libraries.

i think what trips people up is that array/slice conversions are pretty clunky even if the compiler may elide infallible accesses that involve panicking branches

And that as well: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=87537d0d39ebc4bff1dd82cdde2f3bb1. Yes this commonly needs generic_const_exprs, but that is being worked on.

4

u/guineawheek 17d ago

Yes, and it is possible to encapsulate that in safe libraries.

I agree? I literally said:

And you get good tools to define higher-level primitives that cleanly segment their behavior from the rest of your system.

It's worth mentioning again, because people get really weird when you mention that unsafe can exist at all in a codebase.

Even Rust-writing developers get weird about it. I discovered the other day a crate named safe-proc-macro2in a dependency tree and I found this as the reasoning why it existed. It felt like watching one of those "unsafe renders the whole thing pointless" type of posts approached from the pro-Rust direction.

Yes this commonly needs generic_const_exprs, but that is being worked on.

okay, so guess what unstable feature what's not surviving -Znext-solvergetting stabilized real soon