# Evolving the standard library through ... what?

**URL:** <https://internals.rust-lang.org/t/evolving-the-standard-library-through-what/5874>\
**Category:** Uncategorized\
**Created:** [September 7, 2017, 2:10pm UTC](https://internals.rust-lang.org/t/evolving-the-standard-library-through-what/5874 "2017-09-07T14:10:38Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![LukasKalbertodt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lukaskalbertodt/32/2883_2.png) [@LukasKalbertodt](https://internals.rust-lang.org/u/LukasKalbertodt)\
**Post date:** [September 7, 2017, 2:10pm UTC](https://internals.rust-lang.org/t/evolving-the-standard-library-through-what/5874/1 "2017-09-07T14:10:38Z")

</div>

Hi there!

The Rust core language is extended pretty quickly (in comparison to many other languages) and we regularly get new type-system features or new syntax. Some, if not many, of those changes affect API design: with a specific feature, one can build a better API than without that feature.

The standard library’s API is not different in this regard: pretty much the whole API was designed for the Rust 1.0 core language and new core language features could improve the API in several places. To give a few specific examples:

> **Possible API improvements**
>
> - with generic associated types, one could improve the `Deref` trait to make it more generic and powerful:
> 
> ```rust
> trait Deref {
> type Target<'a>;
> fn deref(&self) -> Self::Target;
> }
> 
> ```
> 
> - with the `impl Trait` feature, one could hide a lot of implementation detail (maybe return `impl Iterator` instead of `Map` in `Iterator::map()`)
> - with GATs (again), one could write collection traits which would potentially influence the API of all collections
> 
> (_However, I think everyone agrees that possible improvement exist; concrete examples are not important for my question_)
> 
> * * *

Of course, all those examples are **backwards _in_compatible**. That’s a problem, we don’t like to break users code; we promised stability. So we can’t _simply_ use those improvements.

As probably everyone here is aware, there is the [“Evolving Rust through Epochs” RFC](https://github.com/rust-lang/rfcs/pull/2052). It specifies how we can change most of the Rust core language in a backwards incompatible way while avoiding breakage as well as a community split. It mentions the standard library at two points:

- “Epochs are designated by the year in which they occur, and represent a release in which several elements come together: […] The standard library and other core ecosystem crates have been updated to use the new features as appropriate.”
- “More generally, breaking changes to the standard library are not possible.”

These statements seem to contradict each other. I wonder if/how it is possible to introduce breaking changes to the standard library. I think that breaking changes are required, because IMO regularly updating the std’s API to use the core language as idiomatic as possible is a good thing. I just never heard anything about these kinds of `std` changes from the Rust community.

## In Summary

- I think we should update `std` (from time to time!) in a backwards _in_compatible way to use new language features in order to improve `std`s API.
- In my naive worldview, `std` is simply a library crate and we could bump the major version while the old version is still available (just like epochs).
- The epochs RFC even manages to introduce breaking changes to the core language, so I feel like it should be certainly possible to introduce breaking changes to `std`.

**Are there plans on how to introduce breaking changes to `std`? Or is it impossible to do? Why?**

* * *

Sorry if this has been discussed before, I haven’t found any previous threads. I asked a similar question [on StackOverflow (without answer)](https://stackoverflow.com/questions/46083342/how-if-at-all-is-the-standard-librarys-api-changed-to-use-new-language-featur?noredirect=1#comment79143041_46083342).

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [September 7, 2017, 5:07pm UTC](https://internals.rust-lang.org/t/evolving-the-standard-library-through-what/5874/2 "2017-09-07T17:07:07Z")

</div>

All of your dependencies would have to be updated to the same version of std as you, because an `Option` from an std on the old epoch isn’t the same type as an `Option` from the new epoch.

---

<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:** [September 8, 2017, 4:47pm UTC](https://internals.rust-lang.org/t/evolving-the-standard-library-through-what/5874/3 "2017-09-08T16:47:00Z")

</div>

There is a workaround for that. std2 can `pub use` everything from std1 that it doesn’t modify.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [September 8, 2017, 9:23pm UTC](https://internals.rust-lang.org/t/evolving-the-standard-library-through-what/5874/4 "2017-09-08T21:23:39Z")

</div>

Users would have to then switch all of their `std` imports to `std2`. We can’t reuse names that are already defined. At that point, why not just do `Index2`

Unless we have mutually exclusive traits (which is a whole other set of problems), only one trait can control the index operator, otherwise its unclear what happens when you implement both.

In theory, the best way to do this would be to create `Index2` and provide this impl:

```rust
impl<I: Index<T>, T> Index2<T> for I {
    type Output<'a> = &'a <I as Index>::Output;
    fn index(&'a self, idx: T) -> Self::Output<'a> {
        <I as Index>::index(self, idx)
    }
}

```

Then make `Index2` control the definition of `Index`. The churn of having 2 different ops traits with slightly different definitions seems quite problematic to me though.

* * *

This also has the weakness that `IndexMut` currently relies on the ref requirement to return an `&mut <Self as Index>::Output`. We don’t have built in mutability polymorphism, so other than hardcoding it to `&` and `&mut`, there’s no way to guarantee that `IndexMut` returns “the mutable form” of `Index`.

---

<div class="post-metadata">

**Author:** ![LukasKalbertodt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lukaskalbertodt/32/2883_2.png) [@LukasKalbertodt](https://internals.rust-lang.org/u/LukasKalbertodt)\
**Post date:** [September 9, 2017, 6:39pm UTC](https://internals.rust-lang.org/t/evolving-the-standard-library-through-what/5874/5 "2017-09-09T18:39:37Z")

</div>

Mh ok, so there are basically the same problems as with any other library: if you have two different versions of a library in your dependency graph, it will be complicated, right?

Has there been previous discussion about this? If someone could provide some links, that would be awesome! Or is it just widely accepted that we will never introduce breaking changes to std? Sorry if these questions sound a bit dumb, but I either missed all of those previous discussions or I’d be very confused why no one thought about it 😕

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:28am UTC](https://internals.rust-lang.org/t/evolving-the-standard-library-through-what/5874/6 "2019-03-25T08:28:58Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
