This was actually the main thing that put me off of Rust. I get the argument for a small std lib. I just also don’t agree it’s worth it. Go seems to handle having a batteries included standard lib just fine.

People confuse what they want.

They do not want a big stdlib. The downsides are real (the stdlib cannot make breaking changes), and there are no upsides (except, maybe, for faster compilation, since std comes precompiled).

They want more official crates (e.g. `regex` and `libc` are official crates, maintained by the Rust project). And the Rust project does not oppose to that, it just doesn't have the funding.

> there are no upsides (except, maybe, for faster compilation

Another big reason to put something in std is providing types for cross-crate compatibility. If I want to pass a String from one crate to another, I’m glad that string is defined in std so there’s an obvious type we can both use in our APIs.

C - for example - does not have this luxury. Everyone makes their own string type, and C APIs all need to translate strings at the api boundary. It’s super annoying.

It would be nice if we had a standard way in rust to declare a type as serialisable. Right now lots of crates have a serde feature flag to do this with serde. But (a) they need to put this behind a feature flag, since it adds a dependency on serde. And (b) this doesn’t work with other serialisation libraries.

The other big one is futures. There’s still no futures executor in std. Async crates have to decide if they want to tie themselves to a single executor (like Tokio) or be compatible. There is no async stream api in std. No async file api. And so on. It’s a compatibility nightmare.

That is true, but this does not require a huge stdlib. And Rust is partially open to that (even adding async traits for IO in std is something they'll likely do in the future), but because std can't make breaking changes, you need to be very careful and slow.

> The other big one is futures. There’s still no futures executor in std. Async crates have to decide if they want to tie themselves to a single executor (like Tokio) or be compatible. There is no async stream api in std. No async file api. And so on. It’s a compatibility nightmare.

We need useful traits to abstract over async runtimes. But there are a lot of design points for runtimes so this can't ever go into std. There is embassy, for embedded systems. There is monio and glommio built around io-uring. Then there is smol intended to be simple and lightweight. And then there is the kitchensink of tokio.

Clearly embassy is the one we want in the standard library. /s (It is the only one I personally would have a use for. But no, I don't think any of them belong in std. Traits to abstract over them? Yes, absolutely.)

But even your other example of strings: there are many design points for strings too, that might be better fits for specific use cases: string builder (with a capacity, what String in rust is), copy on write, small string optimisation (like compact_str), even interned strings. So your example of a vocabulary type is somewhat flawed, a better example would be Option or Result. Even anyhow and thiserror build on top of those vocabulary types.

[deleted]

Who said a standard library can't make breaking changes? That used to be a norm some time ago.

There are upsides, your program is smaller, better security because a random kid can't pwn your deps, quality and interoperability. What's not to love?

> Who said a standard library can't make breaking changes?

The std making a breaking change is the language making a breaking change. Most mainstream languages guarantee stability, certainly Rust.

> your program is smaller

How so? It doesn't matter if the code is in std or a crate.

> better security because a random kid can't pwn your deps, quality and interoperability

That's exactly what I said: you don't need bigger std, you just need more official crates.

>Most mainstream languages guarantee stability, certainly Rust.

That's their mistake, right there... When you're upgrading software, you presumably want a better version. You can't have something better without changing it. It's a logical contradiction.

>It doesn't matter if the code is in std or a crate. It very much does because you don't need 95% of the random stuff in the crates. Even for something like rand, you need an xorshift and that's roughly it. 25 lines of code, sorted. You can even write it as a copypaste "dependency" without much fuss in practically any language. That, versus importing a whole rand library with lots of different algorithms, deps on crypto, tests, OS random-based seeding, customisability, etc.

>you just need more official crates

I guess that's one solution but it would probably just be a better idea to split std in two SLAs, one is guaranteed for core stuff i.e. the status quo, one is YMMV.

> You can't have something better without changing it. It's a logical contradiction.

Sorry, that's a strawman. Of course you cannot have a better version without changing things. You definitely can have a better version without changing public API.

And people upgrade their toolchain not because they want a different API. They mostly want bugs fixed, support, and sometimes features. Breaking the API has a huge cost and minor benefit.

> It very much does because you don't need 95% of the random stuff in the crates.

But why does it matter if all that stuff comes in std or in an different crate? As I said security doesn't play a role here. You can't even avoid compile-time cost because the std can only come precompiled because it only changes with the toolchain, which is another downside we want to avoid.

> I guess that's one solution but it would probably just be a better idea to split std in two SLAs, one is guaranteed for core stuff i.e. the status quo, one is YMMV.

And again, how is that different from what I say, other than calling "official crates" as "std"?

> Who said a standard library can't make breaking changes?

I don't want my language creating work for me. "Batteries included" is a feature of higher level languages. Rust is going to live for a very long time, probably beyond all of our lifetimes, and it needs to endure fads without picking up baggage and liabilities.

Rust could have a mandate where certain crates are "blessed" as recommendations. This could come with additional review, oversight, support, documentation, etc.

The Cargo.toml spec should have the ability to limit direct and transitive dependency count and depth. (As well as other things, like "nopanic" annotations/guarantees.)

The Crates.io repo should grow namespaces so we don't typo squat popular packages. It's much harder to miss organization names changing than package names changing.

On the other hand, there are some bad Go standard libraries that are frozen in time.

Yeah, but I will take a not great library that works everywhere the compiler does, than be at the whims of which platforms are supported by 3rd party libraries.

I can use most of the clunky Python, Java, .NET and if it must be, Go, standard libraries, than hunting down for dependencies with platform tier support and such.

Which is how you get the mess that is the standard library of C++. Where regex is an unusably slow joke and everyone uses third party libraries for that instead.

And tons of parts of the standard library (and language) being cordoned off as "legacy, don't use for new development". Of course figuring out what you shouldn't use in C++ can be hard too. It isn't well documented (or universally agreed upon), and it takes having it as a full time job to be able to keep up with these days.

No, I much prefer the way Rust is doing it.

Add more and more to a standard library, and you're going to start losing your "works everywhere".

Naturally there is a balance, still I think Java, .NET, Python, Go, Smalltalk, manage quite well, while having subsets to slim down when needed for specific deployment scenarios like embedded devices.

Platform support is a non-issue for every library being discussed. This is an array construction macro, it has nothing to do with what operating system you're running on.

Just because some trees have a specific trait, it doesn't mean the whole forest is the same.

which, as painful as it may be, is ok. Better to have a safe functional stdlib library than a exposed external crate (which then asks the question; what's the replacement...)

Those aren't the only two choices.

We also have the classic example of PHP with numerous not safe stdlib ways to use mysql.

To me the answer is still to vendor your dependencies and don't be on the bleeding edge of updates unless you're willing to invest the time into validating them.

> We also have the classic example of PHP with numerous not safe stdlib ways to use mysql.

I think it goes without saying that emulating PHP is rarely a good decision.

Don't forget C++ where large parts of the standard library are unusable (regex is slow and unfixable) or soft deprecated (dont use iostreams for formatting, use std::format, etc).

No, I prefer what rust is doing. It suits a system programming language. Which is what Rust is.

Which isn't actually a problem. You can ignore the bad standard library and use something different.