# Matches-index (July 2025) -- reviving the left-pad index

**URL:** https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272
**Category:** libs
**Created:** [July 26, 2025, 7:37pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272 "2025-07-26T19:37:14Z")
**Posts on this page:** 20
**Page:** 1

<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: [July 26, 2025, 7:37pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/1 "2025-07-26T19:37:14Z")

</div>

6 years ago we had this thread:

> [@Calculating which 3rd party crates are good candidates for "std" inclusion via "left-pad index"](https://internals.rust-lang.org/t/calculating-which-3rd-party-crates-are-good-candidates-for-std-inclusion-via-left-pad-index/11129):
>
> Patrick Walton proposed the idea of a "left-pad index": I went ahead and crunched the numbers for [crates.io](http://crates.io), surveying the top 500 crates by recent downloads, dividing that number by the crate size, and coming up with the following results: Per Patrick, here are some good candidates for potential inclusion in std: ...the idea being that it would be safer to rely on the Rust distribution itself, rather than individual maintainers of third-party crates, for this functionality. …

I was thinking about it recently (in connection to contemplating an ACP for `StableDeref` inclusion in core) and decided to update the analysis. See here:

> **[matches index (July 2025)](https://docs.google.com/spreadsheets/d/14tM1qlz1fbRIo8XWR4SOFNN2k2LJx7pSv2WQRo_9yPM/edit?usp=sharing)**
>
> This Sheet is private

 ![Screenshot 2025-07-26 at 21.33.20](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/6/6efa43af8c3d80b766eaf8b99c08e92f008ea009.png)

I'm now calling it the matches-index, since `matches!()` was stabilized in `std` in Rust 1.42, released in March of 2020 -- about 5 months after the previous thread was started.

In addition to stable\_deref\_trait, perhaps at some point equivalent and/or all of indexmap could also make for good additions to core/alloc?

(Click the little calculator-like widget to do custom filters on the data without duplicating the sheet.)

---

<div class="post-metadata">

### Author: ![chrisd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/chrisd/32/7232_2.png) [@chrisd](https://internals.rust-lang.org/u/chrisd)
#### Post date: [July 27, 2025, 1:37am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/2 "2025-07-27T01:37:14Z")

</div>

Sorting by dependencies/size, a fair number of them have made it into the std or even the language in recent years. E.g.:

- `lazy_static`/`once_cell`
- `atty`
- `num_cpus`
- `static_assertions`
- `home` (now that `home_dir` is undeprecated)

And the replacement for `cfg_if` is close to stabilisation.

---

<div class="post-metadata">

### Author: ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)
#### Post date: [July 27, 2025, 5:06am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/3 "2025-07-27T05:06:13Z")

</div>

From this list, `arc-swap`, `bitflags` and `bitvec` / `bit-vec` are obvious candidates. (another crate from this list, `bit-set`, is built upon bitvecs and can actually build a bitset from a bitvec passed as parameter. It depends on the crate `bit-vec` which is unfortunate if you use `bitvec`. Having bitvecs in the stdlib would improve interoperability)

Another thing I would like to see in the stdlib is `ordered-float`, and in special the [NotNan](https://docs.rs/ordered-float/latest/ordered_float/struct.NotNan.html) type. Rust has things like `NonNull` and `NonZero`, and I think that `NonNan` would be a great addition.

And I wanted to say `bytemuck` too, but the safe transmute thing is supposed to be even better, right? If/when it happens.

---

<div class="post-metadata">

### Author: ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)
#### Post date: [July 27, 2025, 5:30am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/4 "2025-07-27T05:30:46Z")

</div>

I don't think arc-swap is a given, I saw an interesting alternative design: [ArcShift — Rust memory management library // Lib.rs](https://lib.rs/crates/arcshift)

Not as popular, but fairly new, and makes a good argument for the design difference.

That is in general a thing to watch out for: is the design space fully explored?

> [@dlight](#):
>
> And I wanted to say `bytemuck` too, but the safe transmute thing is supposed to be even better, right? If/when it happens.

Or zerocopy. Multiple points in the design space again.

---

<div class="post-metadata">

### Author: ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)
#### Post date: [July 27, 2025, 5:52am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/5 "2025-07-27T05:52:54Z")

</div>

I think having a survey of the bitfield / bitvec / bitset / bitflag space would be useful. There are a _lot_ more or less popular crates there, and there is usually some overlap in between them.

For example, I was recommended [modular-bitfield — data structures in Rust // Lib.rs](https://lib.rs/crates/modular-bitfield) (haven't had the opportunity to try it yet) as being the best design for bitfields. But there are at least four other similarly popular crates for this.

---

<div class="post-metadata">

### Author: ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)
#### Post date: [July 27, 2025, 6:15am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/6 "2025-07-27T06:15:57Z")

</div>

> [@Vorpal](#):
>
> I don't think arc-swap is a given, I saw an interesting alternative design: [ArcShift — Rust memory management library // Lib.rs](https://lib.rs/crates/arcshift)
> 
> Not as popular, but fairly new, and makes a good argument for the design difference.

Thanks for the link. I was reading the docs and I don't understand why this approach would be better than `arc-swap`. If there's many writes, won't it traverse a potentially very large linked list each time it is read?

What I like about the `arc-swap` design is that it actually wraps the `Arc<T>` with something like `ArcSwapAny<Arc<T>>`, so the same wrapper enables updating `Option<Arc<T>>` atomically too (an important use case) but also works for custom reference-counted pointers implemented elsewhere.

Anyway you raise a good point: library ecosystem have network effects, and the oldest libraries have more mindshare even if the newer libraries are better designed. Even when you compare only recent downloads rather than total downloads, the fact that some library is older and more established will give it an advantage. So this list can say "people often need bitflags" but not "the stdlib should adopt the API of the `bitflags` crate".

Indeed this situation already happened once, the crate `lazy_static` was used _since before Rust 1.0_, but it wasn't until `mitochondria`, `lazycell` and finally `once_cell` that it was finally included in the stdlib (I think the stdlib version even made some improvements over `once_cell`)

---

<div class="post-metadata">

### Author: ![Vorpal](https://avatars.discourse-cdn.com/v4/letter/v/aca169/32.png) [@Vorpal](https://internals.rust-lang.org/u/Vorpal)
#### Post date: [July 27, 2025, 6:57am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/7 "2025-07-27T06:57:24Z")

</div>

> [@dlight](#):
>
> If there's many writes, won't it traverse a potentially very large linked list each time it is read?

I believe it says right in the readme it is optimised for rare writes. To me the arcshift design looks inspired by RCU, and the advantage would be lockless reads even when writes happen.

A typical example where RCU (and RCU like designs) are good is where reads happen all the time, but writes happen on a human timescale. Consider something like the routing table in a kernel. Switching between networks happens _at most_ every few seconds, but usually far less often than that. Or the table of connected USB devices.

Arcswap on the other hand seems to be optimised for a mix of reads and writes, but with the downside that reading won't scale as well.

I also found the reddit thread from where the author announced arcshift to be quite interesting (if very long): [Arcshift - an Arc that can be updated : rust](https://old.reddit.com/r/rust/comments/1ejqvh6/arcshift_an_arc_that_can_be_updated/)

Lazy/Once Cell/Lock is indeed an interesting case study in how to figure out which API is best. In that case we got both, as there are reasons to use either. The Once API is more fundamental though, and I belive used internally by the lazy variant.

---

<div class="post-metadata">

### Author: ![Dushistov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dushistov/32/4046_2.png) [@Dushistov](https://internals.rust-lang.org/u/Dushistov)
#### Post date: [July 27, 2025, 2:58pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/8 "2025-07-27T14:58:31Z")

</div>

There is ongoing work to make API that equivalent to `itoa` crate: [Tracking Issue for integer formatting into a fixed-size buffer · Issue #138215 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/138215)

---

<div class="post-metadata">

### Author: ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)
#### Post date: [July 27, 2025, 5:05pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/9 "2025-07-27T17:05:47Z")

</div>

> [@dlight](#):
>
> Another thing I would like to see in the stdlib is `ordered-float`, and in special the [NotNan](https://docs.rs/ordered-float/latest/ordered_float/struct.NotNan.html) type.

Note that `NotNan` _technically_ correctly implements `Eq` but does not get rid of all surprises in the set of floating-point values; in particular, `-0.0` and `0.0` compare equal but print differently, and can produce very different results when you compute with them. This is, IMO, something that needs further exploration (e.g. many applications would be happy with replacing -0 with +0, but what is the performance cost?) before any “blessed” solution gets into std; `Eq` impls that ignore some distinctions in value are valid but not something `std` has had so far (unless you count `HashMap`/`HashSet` equality despite iteration order differences).

---

<div class="post-metadata">

### Author: ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)
#### Post date: [July 28, 2025, 12:33am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/10 "2025-07-28T00:33:14Z")

</div>

One rather interesting aspect of moving `NotNan` to the standard library would be that this could improve on the library by marking a large amount of bit patterns as invalid. Where many dynamic language do tagged-nans for internal types, Rust could optimize those for all kinds of variant tags including `Option<_>` which would also make the ABI of the necessary `checked_*` methods transferred from `f??` surprisingly clean. On that note, (A `CanonicalNan` and `Finite` would be just as interesting from this point.)

---

<div class="post-metadata">

### Author: ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)
#### Post date: [July 28, 2025, 1:04am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/11 "2025-07-28T01:04:27Z")

</div>

Maybe there should be another floating point wrapper called `UnsurprisingFloat<f32>` or something which doesn't just disallow NaN, but also other things.

`NonNan` is supposed to disallow just NaN, so i expect it to not allow -0, subnormal numbers (if supported by the platform), and +- infinity, which are three other gotchas I can think about. One use case of `NonNan` is representing in the type system the invariant expected by nan-boxing, like the crate [boxing](https://docs.rs/boxing/latest/boxing/nan/index.html), though this particular crate doesn't use exactly `NonNan` but another thing that closely resembles it, a floating point number that contains just one NaN.

Maybe this proliferation of wrappers point to the need of pattern types as a general solution, but I think pattern types shouldn't block `NonNan` since it's so useful as a building block. Also `Option<NonNan<f32>>` should store the none variant as the "canonical nan" (for platforms where there is a canonical nan), which is something that only the compiler can do AFAIK, and removes the need for a separate type that has a single NaN.

---

<div class="post-metadata">

### Author: ![chrisd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/chrisd/32/7232_2.png) [@chrisd](https://internals.rust-lang.org/u/chrisd)
#### Post date: [July 28, 2025, 3:33am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/12 "2025-07-28T03:33:22Z")

</div>

Just skimming the top of the list as sorted by `Dependencies / squared size`, I think these would be good candidates:

| Crate | Notes |
| --- | --- |
| hex | convert bytes to and from hexadecimal. Could be an extension to [#138215](https://github.com/rust-lang/rust/issues/138215) maybe |
| urlencoding & percent-encoding | encode and decode url strings |
| byteorder | convinence methods for encoding and decoding big and little endian |
| fastrand | when you just want some "random" looking numbers and don't care about making them unpredictable (or where being predictable may be wanted) |
| walkdir | recursive iteration of directories; super useful but maybe std would want to pick a subset of this |
| tempfile | create anonymous or named temporary files and clean them up on drop |

Except for the last two, these could be in core. Or at least some subset of them could be.

---

<div class="post-metadata">

### Author: ![kpreid](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kpreid/32/8484_2.png) [@kpreid](https://internals.rust-lang.org/u/kpreid)
#### Post date: [July 28, 2025, 4:01am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/13 "2025-07-28T04:01:14Z")

</div>

> [@dlight](#):
>
> Maybe there should be another floating point wrapper …

The fact that there are so many plausible variations is exactly why this _shouldn’t_ be in `std` yet. Note that you do not just need to decide what values are prohibited, but what the operations that would produce them will do instead! For example, even `NotNan` [just a few months ago](https://github.com/reem/rust-ordered-float/pull/167) changed some operations from returning `NotNan<T>` but panicking on NaN, to returning `T`. That’s the sort of API design iteration that needs to be _thoroughly_ settled and tested in practice before anything enters `std`.

Many people have many complaints with how IEEE floating point works, but it's not _just_ a few “bugs” that you can “fix” and get a well-behaved type out of. You have to look at whether your new design is internally consistent, and whether it works well in practice.

---

<div class="post-metadata">

### Author: ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)
#### Post date: [July 28, 2025, 7:17am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/14 "2025-07-28T07:17:25Z")

</div>

> [@djc](#):
>
> In addition to stable\_deref\_trait, perhaps at some point equivalent and/or all of indexmap could also make for good additions to core/alloc?

These don't seem to be very far up your list so I am curious how you reached that conclusion?

---

<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: [July 28, 2025, 12:27pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/15 "2025-07-28T12:27:38Z")

</div>

This has been discussed previously in the context of `-ffast-math`.

The problem is that different users want different things from non-IEEE floats. It's not just lack of NaN, but only finite, no subnormals, associative, etc. There are also different possible approaches to dealing with violations — extra checks that prevent invalid values, or allowing invalid values and allowing invalid results, but not UB, or maximizing performance at cost of unsafety.

This ends up requiring lots of configuration knobs, and Rust's type system is not suited for it.

---

<div class="post-metadata">

### Author: ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)
#### Post date: [August 1, 2025, 4:44pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/16 "2025-08-01T16:44:48Z")

</div>

How is the size measured, btw? Does it take comments and doc comments into account? And unit tests?

---

<div class="post-metadata">

### Author: ![felix91gr](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/felix91gr/32/4380_2.png) [@felix91gr](https://internals.rust-lang.org/u/felix91gr)
#### Post date: [April 19, 2026, 4:38pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/17 "2026-04-19T16:38:03Z")

</div>

I wonder why the needs & wants are so heterogeneous.

My guess is that this is in no small part due to how we think of decimal numbers. Unlike for subsets of the integers, where we can clearly delineate the borders of the set at both ends (`::MAX` and `::MIN`), we can't do that for any subset of the rationals (or reals) since the concept itself means that they form a dense set.

(Aside) **Dense** here in practice means that in any subset `S` of `P` (`P` here being e.g. the rationals or the reals), if we have two elements `x, y` in `S` such that `x < y`, the element `z = (x + y) / 2` will be such that `x < z < y`, and `z` will always belong to `P`. And if `S` is finite, this means that this operation will eventually take us out of `S`; much like how one can go outside of the floats just by finding space between two of them.

> **What if floats weren't fixed width...?**
>
> Of course, such a limitation can't be lifted for any fixed-width representation. So I don't think we're ever gonna get "satisfying floats" in that sense.
> 
> Much like how [`num-bigint`](https://crates.io/crates/num-bigint) uses dynamic width integers to get past the range limitations of ints, one could imagine a decimal type that dynamically increased the information it contains to be able to represent dense decimal ranges. Surprisingly perhaps, this also would allow us to exactly represent roots, trigonometric functions and even many transcendental numbers (such as Pi and e). This set is called the [Computable Numbers](https://en.wikipedia.org/wiki/Computable_number), which are the closest thing I've found to the intuitions we have about dense numbers in algorithms.

Anyway. Floats are kind of fucked. My guess is that half of this is because they're finite-width, which breaks our intuitions about decimals. The other half, we can probably fix within them, though. Well I hope so anyway x3

---

<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: [April 19, 2026, 9:34pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/18 "2026-04-19T21:34:56Z")

</div>

Because there are very different problems that happen to use floats as their solution.

Physics engines (and scientific simulations) typically need to carefully control speed vs precision trade-offs, and sometimes need very very specific ways of calculating expressions, so that objects don't fall through the floor.

Similarly ray tracers must be fast, but also have carefully bounded errors in some calculations, since they deal with values that differ by many orders of magnitude and could suffer from systemic errors that add up.

There's audio processing, where most of the time there's plenty of precision headroom, but performance must be predictable, and subnormal floats can be a gotcha.

There's pixel graphics, where often precision doesn't matter, there's just lots of basic arithmetic that needs to be fast. Compilers being careful about edge cases like NaN or rounding of 52nd bit when blending a couple of 8-bit values is just slowing things down.

There's machine learning, UI, animations, that just need some fractional values. There are microcontrollers that just need to convert a few sensor readings.

---

<div class="post-metadata">

### Author: ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)
#### Post date: [April 19, 2026, 11:32pm UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/19 "2026-04-19T23:32:26Z")

</div>

> [@felix91gr](#):
>
> Surprisingly perhaps, this also would allow us to exactly represent roots, trigonometric functions and even many transcendental numbers (such as Pi and e).

Well yes, if you want a [Computer algebra system - Wikipedia](https://en.wikipedia.org/wiki/Computer_algebra_system) you can use one of those -- or a library implementing such in Rust.

---

<div class="post-metadata">

### Author: ![Ddystopia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddystopia/32/10915_2.png) [@Ddystopia](https://internals.rust-lang.org/u/Ddystopia)
#### Post date: [April 21, 2026, 6:23am UTC](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272/20 "2026-04-21T06:23:38Z")

</div>

For zerocopy/bytemuck equivalent in std w have a safe transmute project. Unfortunately, it's moving rather slowly

[Next page](https://internals.rust-lang.org/t/matches-index-july-2025-reviving-the-left-pad-index/23272.md?page=2)
