On the Zig vs. Rust debate, people like to focus on memory safety, but Rust's RAII is just as important to writing clean, maintainable code.
There is something truly magical about seeing my GPU driver cleaning up dozens of nested GPU and host objects when the GPU job completes. Always exactly then, never too early, never too late, never leaking anything. That's all thanks to RAII and automatic Drop calls.
defer foo.deinit()
really doesn't cut it. You have to explicitly write it, and it only works if all code paths free the object at the end. errdefer
is just a special case, and then the only way to know if you forgot it is by testing with a leak checker. And then the deinit function has to manually deinit all child objects.
All this stuff is just done automatically in Rust. Most of my types don't even implement Drop, or only do something trivial there, because the compiler recursively dropping objects is 99% of the work.
It's knowing the compiler is on your side and taking care of all this that makes it magical. If you have to write out the code by yourself, that's more work, and a huge chance for bugs. The compiler is doing some very complex tracking to figure out what to drop when and where. You'd have to do that all in your head correctly without its help.
> The point is that it makes a lot more sense to work on solving these corner cases, than to just throw away the entire mechanism and have fallible humans in charge of writing more complex code as a result.
Isn't this a bit of a false dichotomy (like "have gc" and "do memory management manually" used to be the only two possible choices ~before rust)?
In this particular case (invocations of drop), consider types that must be explicitly dropped by some specific means (i.e. ones that you need to pass by value to some specific function, and where letting them go out of scope in your own code is a compile error)? That would be neither relying on compiler inserting invocations of nontrivial code where they aren't explicitly written out (which I think is the issue people have with automatic drop invocation) nor on people never forgetting to drop things. (I personally don't think that would be a better world though; I'd rather see a code viewing overlay that points out where drops happen.)
I myself don't think it's very hard, but I can imagine not realising that a given type has a drop function. (And now I realized that my suggestion doesn't actually address control flow when panicking.)
@robryk @lina What do you mean ? Thats like one of the first things you learn about the language. As for panics, it wont happen unless you tell it to panic, you'd do any cleanup before panicking no ? You can also implement the Drop trait for a type if you need to run something qhen it drops, I don't know of thats what you meant.
You can avoid learning of drop for quite some time, but I meant something different: when you see a piece of code in isolation then you can't really tell which variables have any nontrivial drop methods (potentially quite deep inside their structures).
Due to the existence of panics, one cannot make this always-explicit: even if one was required to explicitly drop every type with code that runs at drop time (i.e. forbid implicit dropping of those), we'd still have a potential for not realizing that a drop will be called in panic control flow, so requiring that would not solve ~any issues.
@robryk @lina But is Rust drop so hard to follow ? Isn't it basically at the end of the scope ? Did you reach the end of your function or expression ? Then its dropped.