Here's a thoughtful feedback on problems with Rust:
These are the issues that I keep seeing over and over elsewhere too.
-
self-referential types. I know it's super hard to solve it in the borrow checker, but it's also a massive PITA. Could Rust have at least a better stop-gap solution? (for when real references are needed and indices or rc don't cut it).
-
lack of duck-typed generics and specialisation (and in their case, fields in traits would also help).
Their specific example isn't the worst case of mismatch between goals of Rust generics and C++ templates, but the problem is real. Rust favors early checking and wants to have good errors, but sometimes this is a bad tradeoff. In some cases (like numeric code that wants to operate on mixed integer and float types), the trait bounds required become very burdensome, and operating on abstractly generic types gets so inconvenient that the cure is worse than the disease. As a side effect, generic types also lose access to direct disjoint field access, making borrow checking harder. And at some point, errors from Rust's generics even stop being any better than C++ template errors – blanket impls, associated types, type inference, and lack of coercions can conspire to make absolutely inscrutable errors in Rust. Macros have a whole another set tradeoffs, so Rust is missing something in the middle.
-
special cases where lifetimes are too restrictive, such as change of lifetime of an empty
Vec
. This case can be fixed by adding a library function (there is an existing safe workaround that takes advantage of libstd's obscure implementation details, but it's unreasonable to expect users to know about it). I wonder if there's possibility of having a more general solution, with some typestate for empty objects, orsuper let
-like magic for recycling objects in loops.