Comments and Docs

Every program requires comments:

Comments

  • Regular comments which are ignored by the compiler:
  • // Line comment, which goes to the end of the line
  • /* Block comment, which goes to the end of the closing delimiter */

Examples

1. fn main() {
2. // This is an example of a line comment
3. // There are two slashes at the beginning of the line
4. // And nothing written inside these will be read by the compiler

6. // println!("Hello, world!");

8. // Run it. See? Now try deleting the two slashes, and run it again.

10. /*
11. * This is another type of comment, a block comment. In general,
12. * line comments are the recommended comment style. But
13. * block comments are extremely useful for temporarily disabling
14. * chunks of code. /* Block comments can be /* nested, */ */
15. * so it takes only a few keystrokes to comment out everything
16. * in this main() function. /*/*/* Try it yourself! */*/*/
17. */

19. /*
20. Note: The previous column of `*` was entirely for style. There's
21. no actual need for it.
22. */
23. }

Exercises

  1. 🌟🌟
2. /* Make it work, only using comments! */
3. fn main() {
4. todo!();
5. unimplemented!();

7. assert_eq!(6, 5 + 3 + 2 + 1 )
8. }

Doc Comments

  • Doc comments which are parsed into HTML and supported Markdown
  • /// Generate library docs for the following item
  • //! Generate library docs for the eclosing item

Before starting, we need to create a new package for practice: cargo new --lib doc-comments.

Line doc comments ///

Add docs for function add_one

1. #![allow(unused)]
2. fn main() {
3. // in lib.rs

5. /// Add one to the given value and return the value
6. ///
7. /// # Examples
8. ///
9. /// ```
10. /// let arg = 5;
11. /// let answer = my_crate::add_one(arg);
12. ///
13. /// assert_eq!(6, answer);
14. /// ```
15. pub fn add_one(x: i32) -> i32 {
16. x + 1
17. }
18. }

Cargo doc

We can use cargo doc --open to generate html files and open them in the browser.

Block doc comments /** … */

Add docs for function add_two:

1. #![allow(unused)]
2. fn main() {
3. /** Add two to the given value and return a new value

5. Examples

7. let arg = 5;
8. let answer = my_crate::add_two(arg);

10. assert_eq!(7, answer);

12. */
13. pub fn add_two(x: i32) -> i32 {
14. x + 2
15. }
16. }

Doc comments for crate and module

We can also add doc comments for our crates and modules.

Firstly, let’s add some doc comments for our library crate:

Note: We must place crates and module comments at the top of crate root or module file.

1. #![allow(unused)]
2. fn main() {
3. //! # Doc comments
4. //!
5. //! A library for showing how to use doc comments

7. // in lib.rs
8. pub mod compute;
9. }

You can also use block comments to achieve this:

1. #![allow(unused)]
2. fn main() {
3. /*! # Doc comments

5. A library for showing how to use doc comments */
6. }

Next, create a new module file src/compute.rs, and add following comments to it:

1. #![allow(unused)]
2. fn main() {
3. //! //! Do some complicated arithmetic that you can't do by yourself

5. // in compute.rs
6. }

Then run cargo doc --open and see the results.

Doc tests

The doc comments of add_one and add_two contain two example code blocks.

The examples can not only demonstrate how to use your library, but also running as test with cargo test command.

  1. 🌟🌟 But there are errors in the two examples, please fix them, and running with cargo test to get following result:
1. running 0 tests

3. test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

5. Doc-tests doc-comments

7. running 2 tests
8. test src/lib.rs - add_one (line 11) ... ok
9. test src/lib.rs - add_two (line 26) ... ok

11. test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.55s
  1. 🌟🌟 Sometimes we expect an example to be panic, add following code to src/compute.rs and make the cargo test passed.

You can only modify the comments, DON’T modify fn div

1. #![allow(unused)]
2. fn main() {
3. // in src/compute.rs

5. /// # Panics
6. ///
7. /// The function panics if the second argument is zero.
8. ///
9. /// ```rust,should_panic
10. /// // panics on division by zero
11. /// doc_comments::compute::div(10, 0);
12. /// ```
13. pub fn div(a: i32, b: i32) -> i32 {
14. if b == 0 {
15. panic!("Divide-by-zero error");
16. }

18. a / b
19. }
20. }
  1. 🌟🌟 Sometimes we want to hide the doc comments, but keep the doc tests.

Add following code to src/compute.rs ,

1. // in src/compute.rs

3. /// ```
4. /// # fn try_main() -> Result<(), String> {
5. /// # let res = doc_comments::compute::try_div(10, 0)?;
6. /// # Ok(()) // returning from try_main
7. /// # }
8. /// # fn main() {
9. /// #    try_main().unwrap();
10. /// #
11. /// # }
12. /// ```
13. pub fn try_div(a: i32, b: i32) -> Result<i32, String> {
14. if b == 0 {
15. Err(String::from("Divide-by-zero"))
16. } else {
17. Ok(a / b)
18. }
19. }

and modify this code to achieve two goals:

  • The doc comments must not be presented in html files generated by cargo doc --open
  • run the tests, you should see results as below:
1. running 0 tests

3. test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

5. Doc-tests doc-comments

7. running 4 tests
8. test src/compute.rs - compute::div (line 7) ... ok
9. test src/lib.rs - add_two (line 27) ... ok
10. test src/lib.rs - add_one (line 11) ... ok
11. test src/compute.rs - compute::try_div (line 20) ... ok

13. test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.51s

Code navigation

Rust provide a very powerful feature for us, that is code navigation in doc comments.

Add following code to src/lib.rs:

1. #![allow(unused)]
2. fn main() {
3. // in lib.rs

5. /// Add three to the given value and return a [`Option`] type
6. pub fn add_three(x: i32) -> Option<i32> {
7. Some(x + 3)
8. }
9. }

Besides jump into the standard library, you can also jump to another module in the package.

1. #![allow(unused)]
2. fn main() {
3. // in lib.rs

5. mod a {
6. /// Add four to the given value and return a [`Option`] type
7. /// [`crate::MySpecialFormatter`]
8. pub fn add_four(x: i32) -> Option<i32> {
9. Some(x + 4)
10. }
11. }

13. struct MySpecialFormatter;
14. }

Doc attributes

Below are a few examples of the most common #[doc] attributes used with rustdoc.

inline

Used to inline docs, instead of linking out to separate page.

1. #[doc(inline)]
2. pub use bar::Bar;

4. /// bar docs
5. mod bar {
6. /// the docs for Bar
7. pub struct Bar;
8. }

no_inline

Used to prevent linking out to separate page or anywhere.

1. // Example from libcore/prelude
2. #[doc(no_inline)]
3. pub use crate::mem::drop;

hidden

Using this tells rustdoc not to include this in documentation:

1. // Example from the futures-rs library
2. #[doc(hidden)]
3. pub use self::async_await::*;

For documentation, rustdoc is widely used by the community. It’s what is used to generate the std library docs.

Full Code

The full code of package doc-comments is here.