| ▲ | dns_snek 4 hours ago | |
> How do you make such boldly dismissive assertions As I said that's my understanding from talking and listening to people who have a lot of experience with Rust, Zig, and C. So generally speaking, are you saying that writing correct unsafe Rust is only as difficult as writing correct Zig code and not, as I understand it to be, significantly more difficult? | ||
| ▲ | goku12 2 hours ago | parent | next [-] | |
> So generally speaking, are you saying that writing correct unsafe Rust is only as difficult as writing correct Zig code and not, as I understand it to be, significantly more difficult? Yes. That's correct. The point is, unsafe Rust is pretty unremarkable. Safe Rust doesn't just do borrow checking of references. It also forbids certain risky actions like raw pointer indirection or calling unsafe functions (across FFI, for example) [1]. Unsafe Rust just enables those features. That's it! Unsafe Rust doesn't disable anything or impose any additional restrictions. Contrary to a popular misconception, it doesn't even disable the borrow checker. Unsafe Rust actually gives you extra freedoms on top of what you already have (including the restrictions). And now you have to be careful because Rust just gave you a footgun that you asked for. In a manually memory-managed language, you'd get fatigued by the constant worry about this footgun. In Rust, that worry is limited to those unsafe blocks, giving you the luxury to workout strategies to avoid shooting yourself in the foot. The 'invariants' are that strategy. You describe the conditions under which the code is valid. Then you enforce it there, so that you can breath freely in Safe Rust. [1] https://doc.rust-lang.org/nomicon/what-unsafe-does.html#what... | ||
| ▲ | NobodyNada an hour ago | parent | prev [-] | |
If no references are involved, writing unsafe Rust is significantly easier than writing correct C, because the semantics are much clearer and easier to find in the documentation, and there's no insane things like type-based aliasing rules. If references are involved, Rust becomes harder, because the precise semantics are not decided or documented. The semantics aren't complicated; they're along the lines of "while a reference is live, you can't perform a conflicting access from a pointer or reference not derived from that reference". But there aren't good resources for learning this or clarifying the precise details. This area is an active work-in-progress; there is a subteam of the Rust project led by Ralf Jung (https://www.ralfj.de/blog/) working on fully and clearly defining the language's operational semantics, and they are doing an excellent job of it. When it comes to Zig, the precise rules and semantics of the memory model are much less clear than C. There's essentially no documentation, and if you search GitHub issues a lot of it is undecided and not actively being worked on. This is completely understandable given Zig's stage in development, but for me "how easy it is to write UB-free code" boils down to "how easy is it to understand the rules and apply them correctly", and so to me Zig is very hard to write correctly if you can't even figure out what "correct" is. Once Zig and Rust both have their memory models fleshed out, I hope Zig lands somewhere comparable to where Rust-without-references is today, and I hope that Rust-with-references ends up being only a little bit harder (and still easier than C). | ||