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.

I see some of the pro-Zig folks arguing that "I don't want the compiler doing magic behind my back".

The compiler is there to help you. That's its job! Once you learn to trust the compiler, then you don't have to worry about getting cleanup code right ever again.

Is the compiler magically invoking drop() sometimes a problem? Yes, but that's the minority of cases, and there are solutions to that. I even worked on some of them (Arc::drop() integration with kernel lockdep to catch potential locking issues with refcounted objects across all invoked drop sites, not just those that actually drop the ref count to zero). 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.

Trust the compiler, and when it does the wrong thing, find a good, general solution so it doesn't any more. Rust is actively working on solving some of these issues upstream too, and I find that a lot more positive than just saying "we won't even try, just write cleanup code manually".

Follow

@lina

> 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.)

@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.

@ojonnysilva @lina

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.

@ojonnysilva @lina

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.

Sign in to participate in the conversation
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.