| Thank you for the thoughtful reply, but I think you missed my point. I'm not saying Rust isn't substantially safer than C. When people like Greg Kroah-Hartman say that Rust by its design eliminates a lot of the memory bugs he's been fighting for 40 years, I believe him. My point is that people tend to talk about it as an all or nothing proposition. That Rust is memory safe. Period. And any language that can't put that on the tin is immediately disqualified, that somehow their approach to solving similar problems is invalid. By the very nature of the system no language that wants to interact with the hardware can be entirely memory safe, not even Rust. It has chosen a specific solution, and a pretty damn interesting one as far as that goes, but it still has to deal with unsafe. And the more directly your program has to deal with the hardware the more unsafe code it's going to have to deal with. Zig has also chosen an approach to deal with the problem. Their's is one that gives far more direct control to the programmer. Every single memory allocation is explicit in that you have to directly interact with an allocator and you have to free that memory. It's not hidden behind constructors/destructors and controlled via RAII patterns (side note, there are managed data structures that you give an allocator to via an init and free via a deinit, but you still have to pass in the allocator and those are being largely replaced). If you are only dealing with problems where you can interact with Rust's abstractions I'm sure it is more safe then Zig, but I don't think it's as big a difference as people think. And when you start digging down into systems level programming where the amount of unsafe code you have to write grows, Rusts advantage starts to diminish significantly. To my point about Rust not wanting you to think about memory, take Vector as an example. You and I know that's doing heap allocations, but I guarantee you a not insignificant number of Rust devs just don't even think about it. And they certainly don't think about all the allocations/deallocations that have to happen to grow and shrink it dynamically. Compare that to Zigs ArrayList. When you create it you have to explicitly hand it an allocator you created. It could be a general purpose allocator, but it could just as easily be an arena allocator, or even an allocator backed by a buffer you pre-allocated specifically for it. As the programmer you have to directly deal with the fact that thing allocats and deallocates. Thats what I mean when I say Rust has more in common with GC languages in some ways. When I type "new" in Java I know I'm heap allocating a new object, just Java doesn't want me to think about that because the GC will deal with it. When you create a vector in Rust, it doesn't want you to think about the memory, it just wants you to follow it's borrow checker rules. Which is very different then thinking about allocation/deallocation patterns. |
[0] I can't say it'll ever compile as fast as, say, Go, but all the work on compile times is impressive