In Cargo.toml you can specify [dependencies], [build-dependencies], and [dev-dependencies], but there’s no [doc-dependencies] section, and that occasionally causes me trouble.
How am I supposed to link to crates that are only referenced in documentation? For example:
comparisons with other, similar crates
migration guides from deprecated crates
usage docs that mention non-dependency crates
linking to items from a feature-gated dependency without having to pass --all-features every time
and so on.
Of course, I could just link directly to docs.rs, like [`HashTable`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashTable.html), but:
it always points to docs.rs, which is wrong for offline local docs or docs hosted somewhere other than docs.rs
it isn’t validated against Cargo’s dependency resolution, making broken links more likely
the syntax is clunky compared to simply writing [`HashTable`] as you would for a normal dependency
The quote crate works around this with use proc_macro2 as syn so it can write syn::Ident in its docs, presumably because syn isn’t among its dependencies. (To be fair, syn depends on quote, so even if [doc-dependencies] existed, using it here would create a circular dependency, so it may cause a problem in this particular case. Still, it shows that doc-only dependencies exist in the real world.)
I mark the dependency as optional and enable it when building the docs, either with --all-features if that works for the library or if not with a special docs feature[1] (you can tell docs.rs what features to enable when building your library's documentation).
Edit: a special docs feature is not strictly necessary. Instead you could simply specify the feature that enables the dependency directly when building the docs, without the need for a special docs = ["dep:hashbrown"] feature. The special feature can be handy if the docs need multiple dependencies enabled or simply for more clarity. ↩︎
It would be nice to have [doc-dependencies] or some sort of [weak-dependencies], but we don’t have it. Without that feature, for purposes of cargo doc run by someone who uses your package through crates.io, it's impossible to link to local docs without also having a regular [dependencies] dependency. Despite that, I would say that you should not take a regular dependency for any of these reasons:
The first two are especially clear: if you take these dependencies, you're depending on things the user of your library has no use for. The third is unfortunate, but not possible to do better on.
This is more feasible. There’s no ideal solution here, but:
Often, these links will appear in documentation text that is also feature-gated, so nothing needs to be done.
When that is not possible, for particularly important links, you can use #[cfg_attr(not(feature = ...), doc = "[`other_crate`]: https://docs.rs/...")] to make them work when the feature is not enabled.[1]
Pragmatically, it isn’t a disaster when some links break when relevant features are not enabled. Most users will be looking at docs.rs where you control the feature set, and those that aren’t will plausibly already have enabled the features they care about.
To add to that last point: I also do roughly the same in links to my own crates in READMEs and whatnot, so that I don’t have to constantly bump a bunch of version numbers on every release (while being better than latest).