Hacker News new | ask | show | jobs
by eddyb 3413 days ago
No lifetime parameters can be shorter than the lifetime of the struct itself, and that's part of the so-called WF (well-formed(ness)) rules in Rust (which the compiler tries to make as implicit as possible).

However, that has nothing to do with why you have to have a parameter. The parameter is there to make all instances of App track the actual lifetime, e.g. you can tell between App<'foo> and App<'static> (and in the former case, it can keep the borrow that made the &'foo Config alive for as long as the App<'foo> sticks around, and if this is longer than the underlying data lives for, you get an "use after free" error).

Combined with function signatures, Rust can track complex interactions without ever looking at callee bodies, and if you're never reusing a lifetime parameter, you get just as much flexibility as if you were passing the references around directly.

This is something that the C++ attempts at tracking scopes and enforcing a set of rules about them, don't seem to have figure out yet. You need a certain amount of annotations to keep the correct mapping, otherwise you just lose information and have to assume every struct that contains a reference may borrow everything that was borrowed at some point and the borrow may have "escaped" into a struct.

You're either too conservative and thus can't apply the rules to prevent iterator invalidation and data races like Rust can with borrows (Cyclone didn't have borrow-checking either IIRC), or you're ignoring an entire subset of UAF bugs waiting to happen.

Even for the purpose of preventing UAF, such an imprecise aliasing-analysis-like conservative system may be too restricting for many real-world usecases, whereas Rust's, ironically, wouldn't be.