🎓 A1Learner
🔍

Rust Including Files as Docs

File inclusion turns a plain file into documentation. #[doc = include_str!(...)] makes that same file the documentation too.

One file as one item's page

The attribute reads the file and uses its whole text as the doc comment:

#[doc = include_str!("guide.md")]
pub struct Widget;

The README as the front page

At the very top of src/lib.rs, the inner form makes the README the crate's front page:

#![doc = include_str!("../README.md")]

Test the README, hide the carrier

This carrier item exists only while doctests are collected, so the README code blocks run as tests:

#[doc = include_str!("../README.md")]
#[cfg(doctest)]
pub struct ReadmeDoctests;

Example

#[doc = include_str!("guide.md")]
pub struct Widget;
fn main() {
    let _w = Widget;
    println!("widget ready");
}

Key points

  • The path in include_str! is relative to the source file that holds it: from src/lib.rs, the crate README is "../README.md"
  • Use #[doc = include_str!(...)] on any item, or #![doc = include_str!(...)] at the crate root for the front page
  • /// is sugar for the attribute form: /// Adds one. means exactly #[doc = " Adds one."] — note the leading space in the attribute text
  • Macros that generate items use the #[doc = "..."] form.
  • A macro can build the text piece by piece.
  • Several #[doc] attributes in a row are joined into one comment.
  • Editing the README now edits two things at once.
  • One is the file visitors see in the repository.
  • The other is the generated documentation page.
  • Including a file reuses its text as documentation, so one file serves both readers.

In this example, guide.md sits in the same folder as this source file, and the #[doc = include_str!("guide.md")] line makes its text the documentation of Widget. Cargo doc would show the guide's heading and words on the Widget page. It would look as if they had been written in a /// comment. The program does not change at all: main makes a Widget and prints widget ready.

Note

A README used this way is also a test suite.

Every Rust code block in it runs under cargo test.

So an example that stops compiling fails the tests.

Keep the blocks honest.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

In src/lib.rs, which path reaches the README that sits in the crate root folder?