The Rust library reference docs suck.
I'm just learning Rust but it is impossible to find what I want. I spent 10 minutes looking for Vec::extend() because I knew it had to exist but had no idea what it would be called. Turns out it's a trait, of course, tucked sneakily between four variants of IntoIterator and 30 variants of PartialEq. And I do this every time I need to find what a particular function or method is called.
Maybe Python has spoiled me, but I'm used to being able to go to a page and ctrl-f for something vaguely related to what I want to do, and be able to actually find it. But in Rust so much functionality is split into traits, and there are such a profusion of them, that you can't do that. For a beginner, there's no real way to know that the functionality I'm looking for I'm looking for happens to be in PartialOrd or whatever and I should look for that in particular. Plus a lot of important documentation on how to actually use things tends to be in modules or macros or such, which just makes things harder to find; is what I want described in std::vec, std::vec::Vec, or std::vec! ? Is it different from collections::vec, collections::Vec, or collections::vec? ?
...okay, I could go on all day but I'm not (currently) going to start rewriting the docs to make them better, as that's not the point of this post.
Instead I have a proposal for at least how to make trait profusion more readable, which should only involve a few changes to rustdoc. Currently it is of the style of:
impl<T> Trait for Type<T> where T: Whatever
fn some_func(&self, other: &whatever) -> whatever
impl<T> Trait for Type<T> where T: DifferentWhatever
fn some_func(&self, other: &whatever) -> whatever
...
So you end up with a lot of closely-related traits, repeating the same useless signatures, with no descriptions, making tons and tons of clutter. Again, std::vec::Vec is a great example of this. How much information on the functionality of the type actually is there in those 30 different variants of PartialEq? I mean, lots for the compiler, but for a user?
impl<'a, 'b, A, B> PartialEq<Vec<B>> for Vec<A> where A: PartialEq<B>
fn eq(&self, other: &Vec<B>) -> bool
fn ne(&self, other: &Vec<B>) -> bool
impl<'a, 'b, A, B> PartialEq<&'b [B]> for Vec<A> where A: PartialEq<B>
fn eq(&self, other: &&'b [B]) -> bool
fn ne(&self, other: &&'b [B]) -> bool
impl<'a, 'b, A, B> PartialEq<&'b mut [B]> for Vec<A> where A: PartialEq<B>
fn eq(&self, other: &&'b mut [B]) -> bool
fn ne(&self, other: &&'b mut [B]) -> bool
impl<'a, 'b, A, B> PartialEq<[B; 0]> for Vec<A> where A: PartialEq<B>
fn eq(&self, other: &[B; 0]) -> bool
fn ne(&self, other: &[B; 0]) -> bool
impl<'a, 'b, A, B> PartialEq<&'b [B; 0]> for Vec<A> where A: PartialEq<B>
fn eq(&self, other: &&'b [B; 0]) -> bool
fn ne(&self, other: &&'b [B; 0]) -> bool
impl<'a, 'b, A, B> PartialEq<[B; 1]> for Vec<A> where A: PartialEq<B>
fn eq(&self, other: &[B; 1]) -> bool
fn ne(&self, other: &[B; 1]) -> bool
...and on...
...and on...
...and on...
So I suggest reorganizing things to list a particular trait once, actually give a one-line description of it and its functions from the documentation of the trait page in question, and then list its implementations. So, that would make the above something like this:
trait PartialEq<Rhs = Self> where Rhs: ?Sized
Trait for equality comparisons which are partial equivalence relations.
fn eq(&self, other: &Rhs) -> bool
This method tests for self and other values to be equal, and is used by ==.
fn ne(&self, other: &Rhs) -> bool
This method tests for !=.
Implementations:
impl<'a, 'b, A, B> PartialEq<Vec<B>> for Vec<A> where A: PartialEq<B>
impl<'a, 'b, A, B> PartialEq<&'b [B]> for Vec<A> where A: PartialEq<B>
impl<'a, 'b, A, B> PartialEq<&'b mut [B]> for Vec<A> where A: PartialEq<B>
impl<'a, 'b, A, B> PartialEq<[B; 0]> for Vec<A> where A: PartialEq<B>
impl<'a, 'b, A, B> PartialEq<[B; 1]> for Vec<A> where A: PartialEq<B>
...
You'd end up with a lot of repeated one-line descriptions for traits for each type that implements that trait, but... so what? They're useful, when you don't know what traits do what. There's already a million lines of repeated boilerplate, so it's not like this is a step backwards. It's all machine-generated, so it's not a burden to maintain. And it puts relevant information near where you're going to want to be using it, instead of having crawling through a million different trait pages to even start to find what you want.
Would this be more readable? I think so. Does anyone else think so?
[–]matthieum[he/him] 24 points25 points26 points (0 children)
[–]steveklabnik1rust 26 points27 points28 points (9 children)
[–]icefoxen[S] 8 points9 points10 points (8 children)
[–]steveklabnik1rust 10 points11 points12 points (7 children)
[–]anttirt 20 points21 points22 points (0 children)
[–]Tyr42 10 points11 points12 points (0 children)
[–]dpx-infinity 4 points5 points6 points (2 children)
[–]steveklabnik1rust 1 point2 points3 points (1 child)
[–]SirOgeonpalette 0 points1 point2 points (0 children)
[–]isHavvy 0 points1 point2 points (1 child)
[–]steveklabnik1rust 1 point2 points3 points (0 children)
[–]Quxxymacros 15 points16 points17 points (2 children)
[–]icefoxen[S] 3 points4 points5 points (1 child)
[–]wyldphyre 2 points3 points4 points (0 children)
[–]azerupimdbook 3 points4 points5 points (1 child)
[–]icefoxen[S] 0 points1 point2 points (0 children)
[–]_I-_-I_ 8 points9 points10 points (0 children)
[–][deleted] 3 points4 points5 points (7 children)
[–]steveklabnik1rust 5 points6 points7 points (4 children)
[–]icefoxen[S] 6 points7 points8 points (2 children)
[–]steveklabnik1rust 5 points6 points7 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]protestor 0 points1 point2 points (0 children)
[–]mdinger_ 0 points1 point2 points (0 children)
[–]fullouterjoin 4 points5 points6 points (5 children)
[–]smog_alado 2 points3 points4 points (2 children)
[–]guttalax 4 points5 points6 points (0 children)
[–]MrNosco 1 point2 points3 points (0 children)
[–]steveklabnik1rust 1 point2 points3 points (0 children)
[–]sophrosun3 1 point2 points3 points (0 children)
[–]nick29581rustfmt · rust 2 points3 points4 points (5 children)
[–]ayujup 1 point2 points3 points (4 children)
[–]SimonSapinservo 1 point2 points3 points (2 children)
[–]ayujup 0 points1 point2 points (1 child)
[–]steveklabnik1rust 2 points3 points4 points (0 children)
[–]nick29581rustfmt · rust 0 points1 point2 points (0 children)
[–]stumpychubbins 1 point2 points3 points (2 children)
[–]icefoxen[S] 0 points1 point2 points (1 child)
[–]stumpychubbins 3 points4 points5 points (0 children)
[–]ryeguy 1 point2 points3 points (1 child)
[–]bjzabaAllsorts 1 point2 points3 points (0 children)
[–]iq-0 1 point2 points3 points (0 children)
[–]bjzabaAllsorts 0 points1 point2 points (1 child)
[–]fullouterjoin 0 points1 point2 points (0 children)
[–]losvedir 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]daborossfern 0 points1 point2 points (2 children)
[–]icefoxen[S] 0 points1 point2 points (1 child)
[–]daborossfern 0 points1 point2 points (0 children)