Some days I have misgivings, but not about the language. About the crate situation. Too many important low-level crates stuck at 0.x. I've previously written about problems with the high-performance 3D graphics libraries, but only game devs care about those.
At the language level, the big problem is back references. Sometimes you do need them, and the only safe way to do them at present involves reference counts in the forward direction and weak references in the back direction. Then you have to call .borrow() and .upgrade() too much. I'd love to see a static analysis solution to that.
(Rough outline of such a solution: Owning object belongs to Owner trait. Owned object belongs to Owned trait. Owned object has .owner() and .owner_mut() functions which retrieve references to the owner.
Owners probably have to be pinned, so they can't move while a back-reference exists. If an Owner changes a reference to an Owned object, the back reference is automatically updated.
That's the easy part. Now figure out how to prove by static analysis that a specific use of this does not violate Rust's no-aliasing rules (N read-only, or 1 mutable). This looks do-able for the non-mutable case, because having a non-mutable reference to both owned and owner is OK. Mutability, though, is tough. Anybody thinking about this?)
> Too many important low-level crates stuck at 0.x.
Is it fair to say that Rust failed to supply a robust set of standard libraries comparable to other modern languages? Or was the language aimed at level geared towards implementing rather than providing libraries? If it's truly a systems language, then what library features are essential, and what are 'nice to have'?
IMHO a lot of these 0.x libraries would be called 3.. In other languages
S.
They often have better quality than what I find in "mature" packages in npm or PyPi.
Rust kind of has a perfectionist touch to it which makes it really hard to say "this public API is stable". So people stay at 0.. way longer than normal.
I'm fine with that.
The lack of namespacing and heavy namesquatting is rather what's annoying.
There was a conscious decision to avoid providing a vast standard library because those inevitably become outdated with time. Building a standard library is relatively easy, maintaining for decades is hard.
But it’s a trade off because there are concrete upsides to a large standard library. I wrote about this more - Rust has a small standard library (and that’s ok) - https://blog.nindalf.com/posts/rust-stdlib/
That does seem to align with my perception of where Rust wants to be: a low-level systems language. For example, the stdlib provide a time package that deals with duration and instant, sufficient to interact with file systems and such, but leaves dealing with dates, times, and all that complexity to the chrono crate.
What I would encourage the Rust community to focus on is adding security-sensitive functionality to the standard library. Not the big wad of complexity that is cryptography, but a standard PRNG/RNG/CSPRNG would fit.
Also, I do think it's a bit of a mistake to not at least define a relational database API. As it is we have sqlite, mysql, and postgres with similar but slightly different APIs.
I don’t think low level languages mean you need a small standard library and high level means you need a large one. You’re pattern matching between Python, Java, Go (all large, older) and now Rust (small and newer).
Rust wants to be high level as well, allowing people to solve all kinds of problems of varying complexity in different domains. And to some extent, Rust has succeeded in empowering folks to do this. Rust has found its way into “systems” like browsers (Chromium, Firefox) and Operating Systems (Windows, Linux) but also web software, infrastructure (firecracker), developer tools (ruff, turbopack) and other domains.
Like I said, the request for a larger standard library is a reasonable one. But I don’t think it’s going to happen, because Rust seems to be gaining traction in multiple domains without it. By the numbers it looks like it’s growing 10x every 3 years (https://lib.rs/stats). In such an environment, the folks at the wheel would double down on their approach rather than fundamentally rethinking it.
Not that I know of. But few other languages have a borrow checker.
You can do this in Rust at run time, with Rc, Weak, and .upgrade().unwrap(). If none of the .unwrap() calls fails, you did it right. If you can prove the unwrap calls can't fail, you don't need the run time checking. So the goal is to check at compile time something you can now check at run time at higher cost. That's what Rust is all about.
At the language level, the big problem is back references. Sometimes you do need them, and the only safe way to do them at present involves reference counts in the forward direction and weak references in the back direction. Then you have to call .borrow() and .upgrade() too much. I'd love to see a static analysis solution to that.
(Rough outline of such a solution: Owning object belongs to Owner trait. Owned object belongs to Owned trait. Owned object has .owner() and .owner_mut() functions which retrieve references to the owner. Owners probably have to be pinned, so they can't move while a back-reference exists. If an Owner changes a reference to an Owned object, the back reference is automatically updated.
That's the easy part. Now figure out how to prove by static analysis that a specific use of this does not violate Rust's no-aliasing rules (N read-only, or 1 mutable). This looks do-able for the non-mutable case, because having a non-mutable reference to both owned and owner is OK. Mutability, though, is tough. Anybody thinking about this?)