Documenting (and testing) Default and other trait impls - Best practices for docs on trait impls?

Currently, std does a pretty bad job of documenting trait impls. Most of them aren't documented at all, sometimes you're lucky to find weird ones documented like std::collections::hash_map::RandomState - Rust. This one makes a bad example for adding a doctest tho.

It'd be cool if e.g. Default for u32 included a doctest tho, a simple

assert_eq!(u32::default(), 0u32);

It'd be extra-cool if various Iterator impls also included doctests. e.g. Range currently doctests the Range syntax and some other things, but its Iterator impl does not include any doctests anywhere. Does the Iterator for Range actually work? probably! It's probably being tested elsewhere anyway, but, arguably, it should also have a doctest to go with it. Also, Range and Iterator are an interesting combo because Range has an exact size among other things, so its doctests could also include that property.

However, all this raises an issue: currently we don't know of any RFC that attempts to define a convention/best practices for documenting trait impls. At least for the case of Iterator, and at least for impl Iterator for Range, it'd make sense to have doctests on all the methods it overrides: next, size_hint, min, max, last, nth. But others might feel different about something like Default - they might argue only the impl should be documented, or they might argue only the fn items should be documented. Anyway we figured we'd bring this all up so we can try to come up with something here.

It's worth noting that the Iterator trait docs page at one point was prohibitively slow (even on decent dev machines) because it was rendering documentation for every single method on every single impl of Iterator before showing any content.

This was (IIRC) mitigated by not showing documentation for trait methods on implementations that don't have their own specific documentation. Adding documentation to trait impl methods would regress this mitigation (though I don't know how necessary it is today).

That said: what would you want in the documentation of a trait impl that isn't just repeating what's documented on the trait? When have you ever specifically wanted to check the documentation on a trait impl, rather than going to the trait page and seeing what the trait does directly?

(A somewhat reasonable use would be "specializing" the trait's examples for your type, but you still always run the risk of falling behind the trait's documentation. Another good use is documenting extra guarantees provided.)

Also, keep in mind that documentation is documentation (and example-driven documentation) first. The fact that the examples are tested is a bonus, not the point of the examples. Adding doctests just to be tested and not to improve the documentation is actively detrimental, as it floods out useful information.

Those tests should be module or integration tests instead.

2 Likes

Eh we should definitely have docs (and tests) for the various impl Iterator for Range*. They should document how they behave as iterators. And the same goes for Default. Not sure how to handle special specifically-Iterator structs like std::slice::Iter since they already doctest the Iterator behaviour. (altho the doctest for that one is kinda useless as a test. so, it'd still benefit from an <std::slice::Iter as Iterator>::next doctest.)

And fwiw, trait impl docs are hidden by default. So the Iterator docs shouldn't become slower.

Every time I want to know whether a specific Read impl might block or not. (Usually this information is not available anywhere in the documentation.)

That's not the only time the behavior of a trait impl might differ based on the implementing type, but it's the one that's happened most often for me in practice.

4 Likes

Try also having an Iterator that interacts with the network! :‌p