# Calculating which 3rd party crates are good candidates for "std" inclusion via "left-pad index"

**URL:** https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129
**Category:** libs
**Created:** [October 16, 2019, 6:08pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129 "2019-10-16T18:08:57Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![Centril](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/centril/32/3334_2.png) [@Centril](https://internals.rust-lang.org/u/Centril)
#### Post date: [October 17, 2019, 3:40pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/21 "2019-10-17T15:40:27Z")

</div>

> [@pcwalton](#):
>
> even when we have empirical evidence that they're widely used.

It seems to me that some of the empirical evidence and especially the methodology (esp. using downloads is a questionable metric) behind it is under question. Many of the crates are also quite large ones.

> [@pcwalton](#):
>
> What I don't think we should do is ignore the signal entirely.

Are we ignoring the signal? In my view things like [Tracking issue for eRFC 2497, "if- and while-let-chains, take 2" · Issue #53667 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/53667) are in fact responding to the signal by extending control flow in the language to support a common use case.

> [@pcwalton](#):
>
> It's not Rust's place to be overly opinionated like that.

Rust is opinionated about lots of things. For example, we do not have exceptions (we have some sugar, those are great, but those are not the same language feature as in e.g. Java). We don't have global type inference (a great feature if you ask me). I don't think it's very interesting whether we should be opinionated or not. I understand that you like this feature and we can discuss that, no problem.

> [@pcwalton](#):
>
> Just because you don't use `lazy_static` doesn't mean a lot of others don't have legitimate reasons to use it.

But I do and have used it (I said so before...)? The crate exists and it seems to work, so why does it need to be elevated into the language (especially when it has maintainability drawbacks)?

---

<div class="post-metadata">

### Author: ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)
#### Post date: [October 17, 2019, 4:44pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/22 "2019-10-17T16:44:18Z")

</div>

As an alternative to adding stuff to the stdlib, maybe the Rust organization could respond to the "left-pad index", and other signals that crates are particularly important to the community of language users, by extending organizational support to the maintainers of those crates. That could take many different forms, but usually what maintainers need most is funding and helping hands.

---

<div class="post-metadata">

### Author: ![bluss](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bluss/32/2264_2.png) [@bluss](https://internals.rust-lang.org/u/bluss)
#### Post date: [October 17, 2019, 5:00pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/23 "2019-10-17T17:00:16Z")

</div>

I don't see that microcrates would be a bad pattern in themselves. They are easy to ridicule (left-pad style), but that's superficial. In the spirit of controlling compilation times, I'm one of those looking for crates that do just what I need and not more (which does not favour conglomerated crates).

Everyone can see the high rdep count on lazy\_static, that's a vote for something that should probably be in std (in some shape). I don't think the lower rdep-scoring crates are sending a that strong signal, even matches has "only" 116 rdeps.

---

<div class="post-metadata">

### Author: ![pcwalton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pcwalton/32/207_2.png) [@pcwalton](https://internals.rust-lang.org/u/pcwalton)
#### Post date: [October 17, 2019, 5:06pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/24 "2019-10-17T17:06:58Z")

</div>

> [@Centril](#):
>
> Are we ignoring the signal?

With all due respect, you seem to be proposing to ignore the signal in the case of `lazy_static`.

> [@Centril](#):
>
> The crate exists and it seems to work, so why does it need to be elevated into the language (especially when it has maintainability drawbacks)?

Because it's an extra step that everyone using the feature has to go through, it increases the compile time of crates, and it increases the surface area of actors that you have to trust. I also don't agree that `lazy_static` has maintainability drawbacks, as a feature. What _does_ have maintainability drawbacks is forcing everyone to go through a microcrate just for that feature.

---

<div class="post-metadata">

### Author: ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)
#### Post date: [October 17, 2019, 5:54pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/25 "2019-10-17T17:54:53Z")

</div>

I do kinda think something not entirely unlike `lazy_static` should be in std, but not _just_ because the crate is heavily used. Rather, my concern is that it's commonly needed _and_ the stdlib _does_ have something for it (`std::sync::Once`) but you need to write `unsafe` blocks to use it. I actually wrote a [proposal](https://internals.rust-lang.org/t/helper-for-most-common-use-of-std-sync-once/6338) quite some time ago.

(This isn't to say that the stdlib has to provide safe wrappers for every unsafe primitive it offers; but when the stdlib offers an unsafe primitive, and there _could_ be a straightforward safe wrapper for at least 80% of what people use that unsafe primitive for, I think there's a strong case that the stdlib should offer that wrapper.)

---

<div class="post-metadata">

### Author: ![pythoneer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pythoneer/32/2010_2.png) [@pythoneer](https://internals.rust-lang.org/u/pythoneer)
#### Post date: [October 17, 2019, 8:36pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/26 "2019-10-17T20:36:08Z")

</div>

what exactly is holding us back to try something like stdx but with a different goal. Other than having something like a complete "batteries included" replacement – which is very ambitious – we could vendor said libraries in a "microcrate" that is (un)officially blessed and see where things are going. If the adoption rate is very poor, adopting those crates into std was a misleading idea in the first place. If it wasn't we could reiterate about the idea to adopt that "microcrate" into std at a later point but this time we could make a more informed decision. We could learn if people tend to switch to newer versions instead of the freezed ones in "microcrate" or switch to better ones altogether. I think a "microcrate" that is just combining said crates is not a bad idea and could replicate the experience and adoption if we would pack those into std without committing to have those forever inside std which, i think, is one of the main counterpoints – which i agree with.

---

<div class="post-metadata">

### Author: ![alexheretic](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alexheretic/32/4800_2.png) [@alexheretic](https://internals.rust-lang.org/u/alexheretic)
#### Post date: [October 17, 2019, 9:14pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/27 "2019-10-17T21:14:52Z")

</div>

Maybe not `lazy_static` though, it was good but we have `once_cell` now. It would be great to have something like the `Lazy` type in std.

---

<div class="post-metadata">

### Author: ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)
#### Post date: [October 17, 2019, 9:43pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/28 "2019-10-17T21:43:45Z")

</div>

Incidentally, I've been thinking about writing an RFC for `std::[cell|sync]::[OnceCell|Lazy]` this week, so [here we go](https://github.com/matklad/rfcs/tree/std-lazy) (early unfinished WIP).

TL;RD:

- yes, we need to add lazy initialization to std, as it is important enough even in the world with perfect const (which we all want) and magically lazily/before-main -initialized statics a-la C++ (which I personally don't want).
- lazy\_static is suboptimal API: we can do better now, we don't need macros.
- API of the once\_cell crate seems canonical (i.e, you can't really do anything smaller/simpler, modulo naming).

EDIT: [RFC PR](https://github.com/rust-lang/rfcs/pull/2788)

---

<div class="post-metadata">

### Author: ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)
#### Post date: [October 18, 2019, 12:30pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/29 "2019-10-18T12:30:16Z")

</div>

I think another aspect that's missing is whether these crates are the dominant and polished solutions to their respective problems, so that when std picks one "winner", most users will be happy with it.

For example, `cfg-if`, `atty`, and `num_cpus` seem to have one uncontroversial solution, and if they were in std, I don't think anyone would mind.

But OTOH logging is a big enough problem that it can be solved in multiple ways, and there are multiple crates competing. `log` works for Patrick, but I write servers, and it causes headaches for me, so that crate is not one-size-fits-all.

---

<div class="post-metadata">

### Author: ![djc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djc/32/1592_2.png) [@djc](https://internals.rust-lang.org/u/djc)
#### Post date: [October 18, 2019, 1:47pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/30 "2019-10-18T13:47:55Z")

</div>

> [@kornel](#):
>
> I think another aspect that's missing is whether these crates are the dominant and polished solutions to their respective problems, so that when std picks one "winner", most users will be happy with it.

If std incorporates one particular solution, that still doesn't mean there's no room for other solutions. It's still okay for a minority of users to come up with, maintain and use something else, as long as we can make an easier/safer choice for everyone else.

Requiring that any std inclusions are perfect seems like a non-starter to me.

---

<div class="post-metadata">

### Author: ![endsofthreads](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/endsofthreads/32/1769_2.png) [@endsofthreads](https://internals.rust-lang.org/u/endsofthreads)
#### Post date: [October 18, 2019, 5:23pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/31 "2019-10-18T17:23:37Z")

</div>

That's fair! the point I'm trying to get at—which I didn't articulate properly—is that I can't think of a logging interface that can be introduced into `std` without locking-in a specific instrumentation model.

---

<div class="post-metadata">

### Author: ![notriddle](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/notriddle/32/14082_2.png) [@notriddle](https://internals.rust-lang.org/u/notriddle)
#### Post date: [October 18, 2019, 7:22pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/32 "2019-10-18T19:22:36Z")

</div>

> [@djc](#):
>
> Requiring that any std inclusions are perfect seems like a non-starter to me.

Perfect? Of course not. Rust itself is not perfect.

What I don't want is another situation like `std::mpsc::channel` or Python's `urllib3`, where there's an uncontroversial "better" option available outside libstd. Replacing the standard library toolkit with a third-party option should be reserved for niche use cases, not considered a universal best practice.

But I'm not arguing against including `log` in the standard library, actually. It _already is_ a de-facto standard, to the point that its "competitors", like [slog](https://docs.rs/slog/2.5.2/slog/) and [tokio-trace](https://github.com/tokio-rs/tracing/tree/master/tracing-log), provide compatibility layers for it. The `log` crate seems like one of the best ever candidates for libstd inclusion, because of its nature as "glue" between libraries and their host applications.

---

<div class="post-metadata">

### Author: ![Voultapher](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/voultapher/32/4073_2.png) [@Voultapher](https://internals.rust-lang.org/u/Voultapher)
#### Post date: [October 21, 2019, 9:46am UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/33 "2019-10-21T09:46:19Z")

</div>

Generally on board with @Centril regarding `lazy_static!`, singletons are like cancer, once you have them they spread and corrupt everything they touch. Notice what motivates your example where singletons are a good idea, someone designing OpenGL used singletons and now you have to use them too. Similar story for example with a lot of C++ libraries that interact with OpenSSL, they too have to make heavy use of singletons because OpenSSL choose to do so. At the same time, sitting on an island of 'Rust is beautiful and great' while ignoring existing software and its interop eg. OpenGL is not a particularly useful approach.

With all that said, communicating intent and best practices with language features, or their lack of, is a tricky subject and in my experience the biggest influence comes from educational material, especially things like stackoverflow answers.

---

<div class="post-metadata">

### Author: ![burjui](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/burjui/32/4113_2.png) [@burjui](https://internals.rust-lang.org/u/burjui)
#### Post date: [October 21, 2019, 11:05pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/34 "2019-10-21T23:05:41Z")

</div>

It would be better to just have documentation search across all crates, with results grouped by crate. That way you can easily identify the crates that have the functionality you need. Better than bloating `std`, anyway.

---

<div class="post-metadata">

### Author: ![dead-claudia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dead-claudia/32/6944_2.png) [@dead-claudia](https://internals.rust-lang.org/u/dead-claudia)
#### Post date: [October 23, 2019, 8:30am UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/35 "2019-10-23T08:30:20Z")

</div>

Something I feel got missed in this discussion: it's a lot more than just `arrayvec` and `nodrop` that have been supplanted by language and/or standard library proposals. Just to give a few examples:

- The repo for `matches` is a monorepo literally named [`rust-std-candidates`](https://github.com/SimonSapin/rust-std-candidates), and it was proposed for inclusion [in a really old RFC from back in 2014](https://github.com/rust-lang/rfcs/pull/163). The source code is [literally just 8 lines of code](https://github.com/SimonSapin/rust-std-candidates/blob/master/matches/lib.rs#L30-L38).
- [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs), [`log`](https://github.com/rust-lang-nursery/log), [`futures`](https://github.com/rust-lang-nursery/futures-rs) are all in the `rust-lang-nursery` org.
- [`byteorder`](https://github.com/BurntSushi/byteorder) is supplanted by `num.to_{be,le}()`, `num.to_{be,le}_bytes()`, and `T::from_{be,le}_bytes()` for integers and equivalent slices.

---

<div class="post-metadata">

### Author: ![luser](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/luser/32/6546_2.png) [@luser](https://internals.rust-lang.org/u/luser)
#### Post date: [October 23, 2019, 2:05pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/36 "2019-10-23T14:05:44Z")

</div>

> [@bluss](#):
>
> If I look close, rdep count seems like a much better indicator. Some of these have ridiculous download numbers for very few deps?

Folks have already mentioned transitive dependencies, but another source of this is being included as a dependency for a crate that's not hosted on [crates.io](http://crates.io). I ran into this with [a crate of mine being included in cargo](https://twitter.com/TedMielczarek/status/1143464278504148992) which made its download numbers go way up.

To the original point--I don't think that "lots of people use `lazy_static`" means that we ought to import it directly into `std`, but it does mean that `lazy_static` is clearly filling a need for a lot of Rust users and having some sort of equivalent functionality in `std` would be useful. I bet we'd get a lot of mileage out of taking the crates on this list and having some Rust experts sit down with the authors to figure out the salient bits each crate implements and whether they'd be a good fit in `std`, or if it would fit better with some small changes.

---

<div class="post-metadata">

### Author: ![pcwalton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/pcwalton/32/207_2.png) [@pcwalton](https://internals.rust-lang.org/u/pcwalton)
#### Post date: [October 28, 2019, 6:45pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/37 "2019-10-28T18:45:29Z")

</div>

We've already done the experiment to answer the question "do you really need singletons in Rust?" The answer: yes, you absolutely do. Everyone just uses `lazy_static` or `once_cell`, despite the friction involved in doing so.

We have _failed_ at the goal people apparently think we have of encouraging people to not use singletons (which is a goal I disagree with, but anyway). I don't think pretending we'll succeed at that goal if we just keep the status quo is productive. Rust should pick battles it can actually win.

---

<div class="post-metadata">

### Author: ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)
#### Post date: [October 28, 2019, 6:56pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/38 "2019-10-28T18:56:59Z")

</div>

These forms of singletons do avoid life before `main` though, which is a good thing.  
(You can still get called earlier as a global allocator though.)

---

<div class="post-metadata">

### Author: ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)
#### Post date: [October 28, 2019, 7:05pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/39 "2019-10-28T19:05:13Z")

</div>

Wasn't there a proposal at some point for `assert!` to recognize certain top-level operators and show their operands, so that `assert!(a == b)` could give the values of `a` and `b` just as `assert_eq!(a, b)` does?

---

<div class="post-metadata">

### Author: ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)
#### Post date: [October 28, 2019, 7:25pm UTC](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129/40 "2019-10-28T19:25:56Z")

</div>

That would be [RFC 2011: generic assert](https://rust-lang.github.io/rfcs/2011-generic-assert.html).

[Previous page](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129.md?page=1)

[Next page](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129.md?page=3)
