I want it to be exactly clear what I'm saying... While you (the programmer) may understand when an object is destroyed, and Rust (the compiler) will agree with you, that information is not present in the type system and you cannot use it in your programs. In this aspect, Rust has the same problems as C++... but where C++ still lets you write code, Rust will just throw an error and force you to use "unsafe" here.
Rust has scoped threads for this use case. Generally this uses closures as opposed to lifetimes to "bound borrows from above" in a safe way.
It was removed from the standard library ages ago, but `crossbeam::scope` appears to still be there in the newest release of crossbeam and the git repo.
Since you can't use the type system to guarantee that an object is destroyed, there are a few things in Rust that are a major pain to get working. Like passing a reference to a short-lived thread.
Using a scope is, strictly speaking, less powerful and more annoying to work with than a more general system of linear types. It's like Go's defer, or C#'s using/IDisposable... they work in certain scenarios, but there's a percentage of the time where a lexical scope or function scope doesn't match the lifetime of your object, or can't match the lifetime of your object.
Yeah that's the problem with all these studies that use students writing new code for a few hours.
99% of coding isn't like that - it's reading other people's code (including code you wrote ages ago and can't remember), trying to figure out how it works, following complex call chains, debugging etc.
If you only look at Advent of Code type problems you'll come up with all sorts of strange conclusions, like static types don't make a difference, comments aren't useful at all, it doesn't matter if you exclusively use single character variable names, goto is totally harmless, etc. etc.
Though in this particular case I guess they didn't have much choice because there are no existing large programs written using Bronze.
One example in my head individual strings that need to be constructed dynamically but live for the lifetime of the application (better to leak it with Box::leak or lazy_static! than pollute all code with lifetimes)
Another is writing in lifetimes for single purpose objects that live on the stack and might only ever get passed by ref into a single function and then get destroyed soon after.
Lifetimes are super important in rust and are a core part of the language, but in such degenerate cases they take up a lot of programmer effort for little benefit. In my head a "automatic" solution such as GC /could/ have a home in the language. Perhaps this would make rust a slightly better fit for really complex monolithic GUI apps (word processing, spreadsheets, CAD) where full GC would be performance-onerous but data lifetimes would be too complex for rust's strictly ordered lifetime concept
That's exactly why I loved D over C++ and Rust and had the feeling that I was not fighthing the compiler from day one: the GC, auto types, lack of annoying C preprocessor.
This actually made me chose D over Rust for my last project.
This makes me happy to use D instead of Rust. D has a @safe subset.
Obviously it won't leak memory if you do it correctly, but Rust will happily let you leak memory in an Rc<T>.
I'm convinced Rust is easier to write without the management of lifetimes in a short time span. However, what about long term maintenance, and application stability?
Rust with a GC probably has its uses (compiled language with strong error checking), but one has to know what ship they are boarding.
It also makes it quite closer to D, an "easier C++", compiled language with a GC.
(I'm saying this as someone who tried Rust, and mostly uses GC'd languages)
edit: thanks for the replies below. I hadn't though about this. I guess one should better read my message as "If you remove Rust's lifetime management, …"