Zig may strike a better balance than Rust does here, but it seems more like Rust stole its lunch. I don't know why I'd migrate from C/C++ to Zig instead of going all the way to Rust?
2. Graph memory patterns in Rust are completely unsafe.
3. Code might leak and you dont have tooling to check your dependencies. Trusting the test coverage does not help you there with Rust, because Rust tooling is infeasible for testing leaks.
4. CTFE is not easy to track in Rust, so you dont know if certain code may have run-time cost or not.
5. Not all UB during comptime or runtime is (planned to be) checked/checkable https://rust-lang.github.io/rfcs/3016-const-ub.html
2. Wrap up the unsafety in a library like petgraph and use it. Or just use petgraph.
3. jemalloc's leak analysis works with Rust, as does Heaptrack.
4. With const generics it's trivial to pass a value through a const generic parameter to ensure it was evaluated at compile time. Right now that only works for scalars but that limitation will be relaxed later.
5. Most Rust code is safe code which is free from UB. Dynamic checks of all unsafe-code UB is infeasible. So what?
But anyway, none of these are reasons to use Zig.
2. petgraph looks like they only allow allocating and freeing in the same order and no deallocating of segments (think of a graph pointing to another graph) dynamically. So even if you wrap it, you cant arbitrarily deallocate and allocate things upon semantic conditions.
3. It would be more helpful to use static analysis or making functionality with potential leaks similar to have this information on code review instead of trying to test all code paths.
4. True. I think that works then. Looks like between Rust and Zig "const equals comptime".
5. "Dynamic checks of all unsafe-code UB is infeasible." It is only infeasible, if you dont have an idea on the memory model during comptime. The RFC also writes "In particular, this would mean we need to decide on an aliasing model before permitting raw pointers in CTFE.", because Rust is not settled on that yet. On the upside, this speeds up compilation, lol.
2. The big picture here is that for graphs and other data structures, you figure out a safe API for the data structure and write a library that hides the unsafety behind that API (or just use a library that someone else already wrote). You get a clean separation between a small amount of unsafe code and a large amount of safe code. This is the Zen of Rust and it's why "Rust can't express <XYZ> safely" is almost never an important issue in practice.
3. Rust's ownership and determinstic destructors mean you really have to go out of your way to create a memory leak; "just forgot to free it" doesn't happen. A memory leak has to be something nontrivial like a global data structure that is added to but not removed from, or a reference-count cycle that isn't broken. There aren't really good automatic static techniques for detecting these AFAIK (and I have a background in static program analysis) --- you would need something that models heap states over time, like shape analysis, which doesn't scale. As far as I can tell Rust at least as strong as any other real-world non-GC language at preventing memory leaks, certainly stronger than Zig which lacks ownership and destructors.
5. This is an issue I don't know much about so I'll leave it.
FWIW the endgame for unsafe code in Rust is formal semantics for unsafe code, proof obligations that guarantee the unsafe code preserves Rust safety invariants, and proof-assistant tools that let you formally prove the safety of your "unsafe" code. There's a lot of work to get there but that work is well underway.