rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.53k stars 12.61k forks source link

Tracking Issue for `str::as_str()` #130366

Open GrigorenkoPV opened 3 weeks ago

GrigorenkoPV commented 3 weeks ago

Feature gate: #![feature(str_as_str)]

This is a tracking issue for the as_str() method on the str type itself, so that Box<str>, Rc<str>, Arc<str> & others can have the same things as String has.

Public API

impl str {
    pub const fn as_str(&self) -> &Self;
}

Steps / History

Unresolved Questions

Noratrieb commented 3 weeks ago

i don't think this is the correct API from the PR

GrigorenkoPV commented 3 weeks ago

i don't think this is the correct API from the PR

No, but this is what it will presumably get changed to: https://github.com/rust-lang/rust/pull/129550#issuecomment-2326941244

kornelski commented 3 weeks ago

While this method is unstable, it might trip people up. If this causes a compilation error:

error[E0658]: use of unstable library feature 'str_as_str'

The solution is to change string.as_str() to string.as_ref(), or to &**string(adjusting the number of *s as required).

GrigorenkoPV commented 3 weeks ago

The solution is to change string.as_str() to string.as_ref(), or to &**string(adjusting the number of *s as required).

I am firmly against recommending to use .as_ref() on anything other than T: AsRef<U>. To quote the docs,

Ideally, AsRef would be reflexive, i.e. there would be an impl<T: ?Sized> AsRef<T> for T with as_ref simply returning its argument unchanged. Such a blanket implementation is currently not provided due to technical restrictions of Rust's type system (it would be overlapping with another existing blanket implementation for &T where T: AsRef<U> which allows AsRef to auto-dereference, see "Generic Implementations" above).

To combat this limitation, some concrete impls were added, such as AsRef<str> for String>, AsRef<OsStr> for str, etc. But notably AsRef<[T; N]> for [T; N] was not one of them (presumably because const-generics were not a thing back in 1.0). So now [T; N].as_ref() desugars to <[T; N] as Deref<[T]>>.deref().as_ref() and functions identically to .as_slice().

Which means that now we cannot even add AsMut/AsRef<[T; N]> for [T; N] without repeating the whole IntoIterator for [T; N] story with edition-dependent method resolution.

I guess there already is quite a lot of code out there that will break in the face of AsRef<T> for T and it will be quite an effort to resolve this when it's time to add the impl, but for now let's at least not guide people towards the potential future breakage.