Improving usability of having many nearly-identical methods

To reduce boilerplate we have invented more boilerplate /s

But to actually say something productive? We also have the issue of having many identical methods.

str for example has as_bytes and AsRef<[u8]> which do the same thing, and this is super common. String has as_str and AsRef<str>, Borrow<str>, Deref<Target = str> and unsize &String -> &str

It also has as_bytes, AsRef<[u8]> and all the methods from Deref<Target = str>

If I want to convert &String to &str or &String to &[u8] there are like 5 ways to do both that are indentical.

Most of those you should never call if you know your type is &String and only exist for the sake of generic code, documentation, and the fact that type inference is really bad when it comes to traits like AsRef and Into, so maybe we could do something about that.

#[inherent]
impl AsRef<str> for String {
    #[alias(as_str)]
    fn as_ref(&self) -> &str { &**self }
}

inherent would simply mean this trait implementation is always in scope for String, any methods on String must not conflict with methods from the inherent trait, and all inherent methods show up in doc similar to normal methods.

The alias attribute would allow us to name the specific AsRef::<str>::as_ref function which would help with type inference.

Personally i almost never use AsRef or Into on my own types simply because the type inference fails almost 100% of the time. The trait implementation also takes longer to write than just slapping a as_str method into an impl block.

2 Likes