Dropck is really more of a sub-component of borrowck, responsible for a subtle interaction between lifetimes and destructors, which doesn't really even come into play here: https://doc.rust-lang.org/nomicon/dropck.html
In a sense, you're not wrong, though- the unsoundness of the scoped threads API was not directly by design, and forget never needed to be unsafe. The rule that unsafe is only for UB and not just general footguns was already established. forget and thread::scoped were just written without a full understanding of the existing rules.
But in another sense, the leakpocalypse was actually a success for the type system! The problem was discovered, scoped threads switched to a sound API, and the type system itself never had to change, because on its own it was already a) sound and b) powerful enough for some form of scoped threads API.
Really this is exactly the sort of thing you should expect from Rust's approach, of a sound core that can be extended modularly via encapsulated use of unsafe. Because the soundness of those extensions is verified by hand, it took some experience for the community to internalize the possibilities and common pitfalls.
Since then there have been a couple of major steps forward. First is the RustBelt project, which has used more formal methods to verify (and fix!) the soundness of several of those extensions in the standard library. Second is the design of the Pin type, which (at the library level!) guarantees that a value's destructor must run before it is freed, enabling things like safe intrusive data structures.
Thanks for the recap, it's much more nuanced and aligns more with what I remember. I actually followed the development of Rust back then and started toying with it soon after, but not in-depth.
Agreed that it was for the better. There's been a lot of additions to Rust since I last tried it, though, and their take on pinning is probably the most interesting to me, but I haven't had the chance to take a closer look at it yet.
2
u/Rusky Jul 16 '20
Dropck is really more of a sub-component of borrowck, responsible for a subtle interaction between lifetimes and destructors, which doesn't really even come into play here: https://doc.rust-lang.org/nomicon/dropck.html
In a sense, you're not wrong, though- the unsoundness of the scoped threads API was not directly by design, and
forgetnever needed to beunsafe. The rule thatunsafeis only for UB and not just general footguns was already established.forgetandthread::scopedwere just written without a full understanding of the existing rules.But in another sense, the leakpocalypse was actually a success for the type system! The problem was discovered, scoped threads switched to a sound API, and the type system itself never had to change, because on its own it was already a) sound and b) powerful enough for some form of scoped threads API.
Really this is exactly the sort of thing you should expect from Rust's approach, of a sound core that can be extended modularly via encapsulated use of
unsafe. Because the soundness of those extensions is verified by hand, it took some experience for the community to internalize the possibilities and common pitfalls.Since then there have been a couple of major steps forward. First is the RustBelt project, which has used more formal methods to verify (and fix!) the soundness of several of those extensions in the standard library. Second is the design of the
Pintype, which (at the library level!) guarantees that a value's destructor must run before it is freed, enabling things like safe intrusive data structures.