"Rust can leak memory" is an overgeneralization of the issue and misrepresents it.
Rust doesn't break RAII in the usual sense. The leak issue in Rust is not something that can be cleanly talked of in the context of other languages.
In all languages with RAII till now, it's possible to "leak" memory by sending things to a permablocked thread, or stuffing them in a global hashmap, or whatever. This is something that no compiler can prevent, and it may even be desired at times.
Rust has always allowed this sort of "leaking". So have all the other languages out there.
However, Rust has the concept of scoped/borrowed data -- data with a lifetime which cannot escape that scope. Stuff that isn't scoped is said to be `'static`, i.e. it's lifetime can be the lifetime of the whole program (we can keep moving it out of functions and throwing it between threads). Scoped data can't be shoved into a global hashmap or sent to a random blocked thread, because it's not allowed to escape its scope.
Except, it turns out that using stuff like Rc cycles, it's possible to leak such data too. This affects RAII guards which use lifetimes to bind themselves to a scope to say "run destructors when this particular scope ends" (this is different from "run destructors when this object is no longer accessible", because with regular objects they can be hoisted into a larger scope by moving).
Note that the entire issue is about _scoped_ data (data with a lifetime, containing borrowed references), which is not a concept that exists in other languages.
So Rust still provides de-facto leak safety via RAII, it's just that it is possible in safe Rust to leak stuff, but you have to be explicit about it (global hashmap, mem::forget, etc). This is unlike languages where you must `delete` the object explicitly to avoid leaks.
We now have a relatively good way to describe languages based on their type story:
- untyped
- (dynamically | statically) typed
- weekly...strongly typed
Currently, we only have two terms for a language's memory story: Managed, Unmanaged.
Maybe it's time to come up with some more jargon for languages based on their memory story:
- unmanaged
- (dynamically (GC) | statically) managed
- weekly...strongly managed
?
Where "strongly managed" is reserved for some future (if at all possible) language that can guarantee no leaks whatsoever (also it'll statically ensure halting)?
Resulting in most mainstream languages being [dynamically | weekly] managed languages, and Rust being a [statically | weekly] managed language?
I dunno.. maybe that will help with these types of discussions..
"guarantee no leaks whatsoever" isn't really possible because "leak" isn't a precise term. It depends on the _intention_ of the programmer. Shoving things in a global hashmap is desired in many cases.
FWIW it was possible to extend Rust's types with a ?Leak marker that can protect against scoped data being leaked, but that solution was not chosen.
It was in response to a comment that said that ownership helps deterministically close files, etc. In that context, the leakocalypse doesn't really apply.
Yes, the RAII part of ownership isn't the main feature. No, the leakocalypse is not as simple as "Rust lets you leak things"
Rust doesn't break RAII in the usual sense. The leak issue in Rust is not something that can be cleanly talked of in the context of other languages.
In all languages with RAII till now, it's possible to "leak" memory by sending things to a permablocked thread, or stuffing them in a global hashmap, or whatever. This is something that no compiler can prevent, and it may even be desired at times.
Rust has always allowed this sort of "leaking". So have all the other languages out there.
However, Rust has the concept of scoped/borrowed data -- data with a lifetime which cannot escape that scope. Stuff that isn't scoped is said to be `'static`, i.e. it's lifetime can be the lifetime of the whole program (we can keep moving it out of functions and throwing it between threads). Scoped data can't be shoved into a global hashmap or sent to a random blocked thread, because it's not allowed to escape its scope.
Except, it turns out that using stuff like Rc cycles, it's possible to leak such data too. This affects RAII guards which use lifetimes to bind themselves to a scope to say "run destructors when this particular scope ends" (this is different from "run destructors when this object is no longer accessible", because with regular objects they can be hoisted into a larger scope by moving).
Note that the entire issue is about _scoped_ data (data with a lifetime, containing borrowed references), which is not a concept that exists in other languages.
So Rust still provides de-facto leak safety via RAII, it's just that it is possible in safe Rust to leak stuff, but you have to be explicit about it (global hashmap, mem::forget, etc). This is unlike languages where you must `delete` the object explicitly to avoid leaks.