I would like to express my concerns that Rust's stability policy regarding the standard library might have a really bad long-term impact. Why is that?
- Even if the standard library is quite small, Rust itself is a complex language and the standard library is also pretty complex.
- ⟹ Errors will happen.
- ⟹ Errors will not easily or cannot be fixed.
- ⟹ Rust (that is Rust +
std
) is doomed to stay flawed in the mid or long term.
This happened previously to Haskell (see Functor Applicative Monad proposal) and it's also an issue in Unicode (see NormalizationCorrections).
I (personally) don't like to use a flawed language, even if some people may see stability as the (from a financial/economical p.o.v.?) more important goal.
To name a particular issue regarding Rust, let's look at #98905.
We have an implementation in std
that is:
impl<T: ?Sized + ToOwned> AsRef<T> for Cow<'_, T> {
fn as_ref(&self) -> &T {
self
}
}
This seems natural, handy, and nobody would suspect an error here. But unfortunately this is (arguably) semantically wrong (as we also do not have impl<T: ?Sized> AsRef<T> for T
or impl<T: ?Sized> AsRef<T> for &T
). Moreover, it prohibits adding:
impl<T, U> AsRef<U> for Cow<'_, T>
where
T: ?Sized + ToOwned + AsRef<U>,
U: ?Sized,
{
fn as_ref(&self) -> &U {
self.deref().as_ref()
}
}
(edit: fixed proposed implementation)
Which would be akin to:
// As lifts over &
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T: ?Sized, U: ?Sized> const AsRef<U> for &T
where
T: ~const AsRef<U>,
{
#[inline]
fn as_ref(&self) -> &U {
<T as AsRef<U>>::as_ref(*self)
}
}
But we cannot add impl<T: ?Sized + ToOwned + AsRef<U>, U: ?Sized> AsRef<U> for Cow<'_, T>
(which might be already breaking by itself) without removing impl<T: ?Sized + ToOwned> AsRef<T> for Cow<'_, T>
(which is definitely breaking).
I would like to bring up this issue just as an example. Maybe this particular example can be solved somehow (e.g. with specialization or other future extensions of the language). But the underlying problem persists:
Rust's complexity + Rust's stability policy = ?
What if the fear of migration is a Schreckgespenst that might lead to more collateral damage in the end than if errors in std
would just be fixed? I guess I have too little experience to judge about it, but I love Rust enough to hope for a language that isn't flawed in the end.
Edit: I would like to apologize for my wording here. It maybe was unnecessarily provoking (deliberately taking a strong counterposition to what I often heard when I mentioned flaws in std
), and it could have been expressed more factually. While I still believe there is a structural problem, I did not want to imply that backwards compatibility has no or little value and should just be given up, or that people with a different stance wouldn't love Rust.
Note that for breaking changes in the language itself, we have Editions, but apparently this doesn't help us with std
easily.