Rustdoc: Link to other types from doc comments

javadoc has @link and @see to link to other types’ documentation from doc comments, which can be very useful if the documentation author wants to refer the reader to a function or method in another module or crate, such as when instructing the user on how to obtain an instance of a type that a function or method needs.

It seems pretty trivial to implement if it only allows fully qualified paths. It would be super-useful if we could link to types in an entirely different set of documentation (such as linking to types in a separate Cargo dependency) as well.

Whenever I see something like @link inside a doc comment in the source code of something, my eyes bleed. Documentation should (in my opinion) be just as easy to read when reading the source code as when reading the rendered documentation—after all, documentation is just as useful in the source code as it is rendered. I’d much rather have a less obvious syntax that still looks nice in the source code as well. It could be as simple as auto-linking anything formatted like a path—that’d be fine by me.

cargo doc already generates documentation for dependencies, and a type from another crate mentioned in the documentation for one crate will link to the other crate’s documentation for that type. So this already works for function/method signatures and enum/struct fields; extending it to work with user-written documentation links (if they existed) would probably not be difficult.

In any case, there’s already been some discussion about this type of thing in this thread.

I run cargo doc --no-deps when uploading to Rust-CI because I don't want to waste their disk space on dependencies that have their own hosted documentation; I would prefer to link to that, instead.

Whenever I see something like @link inside a doc comment in the source code of something, my eyes bleed.

Sounds like a personal problem. :stuck_out_tongue: I read over those just fine. I also find them to be informative. The specific sigils to denote a link to another type's docs are up for discussion, I only cited that as an example.

it could be as simple as auto-linking anything formatted like a path

Not all that simple and wouldn't really be controllable by the doc author, who may not necessarily want every fully-qualified type to turn into a link.

Also, that link is broken.

One of the explicit goals of Cargo is that builds should be reproducible, and shouldn't depend on the whims of others. It seems reasonable to extend this philosophy to documentation; bundle your dependencies' docs. Otherwise you risk dead links.

The issue is that Cargo, by default, builds all documentation for all dependencies and subdependencies, even for types not exposed to the user. I would prefer to be able to exclude crates from the documentation build that my users don’t need to know about or can find on their own (implementation details), but I don’t know if that is currently possible with Cargo. Until it is, I will only build my own crate’s documentation.

It would be just as simple to implement as @link or something: it would simply involve looking for anything of the form `<foo>` where <foo> is a valid path. If the author doesn’t want to automatically link to a path (although that seems like a rare case), then they could simply double-quote the path (``foo::bar::baz``), which does the same thing in Markdown but could be made to not auto-link, or they could not quote it at all (although this is undesirable, because code fragments should always be backtick-quoted).

There is a bit of a problem in general with extending the documentaion syntax which is that at the moment, Markdown is parsed using an external library not implemented in Rust. I’m sure this could be changed or worked around, though.

Whoops; it looks like I somehow didn’t copy the ‘http://’ part of the URL, so it didn’t work. Fixed now. (Link to the thread.)

2 Likes

Seems reasonable to me to devise a URL scheme for rust types, like rust://crate/mod/submod/Foo.struct and then use regular Markdown links to link to them from a doc comment. There could be sugar to automatically insert these links on backtick-quoted idents/paths using a module’s imports.

Having recently started to document my code :smile: I came upon this issue.

Whatever one’s personal stance about the usefulness of links is, other documentation tools have this feature, and implementing it will certainly increase the usefulness of rustdoc for some.

Huon’s RFC issue was closed just before 1.0, but could well be reopened.

Regarding syntax (an open issue in the RFC), I think the resulting syntax should mesh well with markdown links. Therefore something like [foo](#foo), [foo](#) or [#](foo) (which all would render as a rustdoc link to a foo item of the current enclosing type or module. [foo()](#) or something similar would be used to distinguish functions (we have it a bit easier than java in this regard, because we don’t need to disambiguate overloaded functions).

Like I said in the RST thread, a custom URI scheme could work out nicely, since it’s easy to make the format extensible with things like links to other crates’ types.

1 Like

Full ack. I’d very much like the scheme to work with existing imports, so you don’t have to type yourself to death – I’m not sure if this is feasible, however.

Agree, that is probably a deeper issue, since you’d tie the documentation harder to the code itself. Two things might mitigate that without going the full tie-in route:

  • Being able to use relative namespaces from the current one. I more often link to local types or types in sub namespaces, and less to modules that are higher up the chain. I’m aware that this might be just me of course.

  • Tooling. I’m no big fan of making things depend on tooling, but I’m very much alright with tooling making it easier. I wonder if racer could have an option to expand an item to a “documentation location.”

Regarding tooling, I believe the usual racer code search should have sufficient to trivially construct a doc URL, given the current path.

However, I’m not sure if tying the docs into the code is a problem – in fact, I’d pretty much want them to be tied together as strong as possible. :smile: One more thing keeping the docs from getting outdated…

I can see that, but I think I’d put most of the value in documentation testing for such things. I’d be hesitant to advocate for a complete tie-in because it makes it harder for other tools to get at the complete expanded documentation.

But of course there might be other solutions to this, like saying “parsing imports isn’t too hard,” which is true, or we could at some point have a separate library just for parsing/analyzing Rust code and documentation. I’m not sure if there are any plans for such a thing, but it could probably be done as a community project as well.

But in general I agree that maximizing the testable parts of documentation is important. I’d love it if documentation tests could be easily extended, like having a test run to ensure none of the external links return 404.

Do you mean a kind of plugin architecture as in javadoc?

I haven’t used it yet, so it’s hard to say. My first instinct would have just been a library you can use in your tests, but it would need more configurability.

The HTTP code check for example should only run when requested, so you don’t continuously hit someones web presence just because you run cargo test. It should also take some configuration options from the environment, like proxy settings.

Of course, these kinds of tests aren’t just valuable for documentation. Verifying shipped XML files against a DTD would be another candidate (it might be a remote DTD).

But to bring us back on-topic (sorry for the derail): I agree that it would be a big plus if the inter-linking would be easily verifiable. Thinking about it more, tieing the documentation together with the AST context might not be too bad, since the AST already needs to be parsed to figure out what item documentation is attached to. So adding contextual AST information (like imports) might not actually have any big cons.

So we actually have two concerns here:

  1. We want to allow different types of links in Rustdoc. Links to other items within the documentation and also links to elsewhere. Markdown (as well as ReST and asciidoc) already handles the latter, for the former, we want a custom scheme that is easy to use and ties in well with the markdown syntax. A custom “protocol” like [foo](rust:#foo) appears to be a good option, though it could require a search of the current imported symbols (unless we require links to be absolute, which would be in stark contrast to Rust’s module system, where everything is relative by default).

  2. We want to check that those links actually link somewhere useful. Perhaps we also may want to do other things in the future (like e.g. lint doctests) that would benefit from a plugin architecture within Rustdoc. I don’t know enough about Rustdoc, but if something like this is not already there, it absolutely should be added.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.