DEV Community

Cover image for 1.1 Comments
Quinn Lashinsky
Quinn Lashinsky

Posted on

1.1 Comments

This week we're gonna explore comments in Rust. Commenting in Rust serves a couple of purposes. Using regular comments we can explain how we implemented a solution or why we chose to implement that solution. Using documentation comments ("doc comments") we can document our code by explicitly describing how to use our code and how our code may behave in certain situations. Doc comments also provide us with some awesome functionality—Rust is able to auto-generate documentation based on the doc comments we made in our code. Whether we use regular comments or doc comments, Rust gives us two powerful conventions to explain our code to other humans who write code.

Let's see how we can take advantage of Rust's comment syntax rules to document our code as we write it.

Rust's commenting and documentation conventions
emphasize using line comments over block comments. Because of this, I'm gonna cover line comments and include some examples of
block comments at the end.

Regular Comments

We can create regular comments in Rust using // syntax.

// This is a line comment
let x = 5 + 5;
Enter fullscreen mode Exit fullscreen mode

Documentation Comments

Inner Line Documentation Comments use //! and are useful for describing high level functionality of an entire crate.

We can think of a crate in Rust as either a binary or library.

A library crate contains useful utilities we can use within our projects (i.e. rand, which is a library crate containing utilities for number generation

A binary crate which is an executable, a machine code representation of the code we write. (i.e. an app, website, any program we create!)

Inner Line Documentation Comments use //! and are mostly used to provide top-level documentation to a crate you create.

usize lets our function know our number argument has to be number between 0 and 18446744073709551615. The usize after -> let's Rust know this function returns a number with the type of usize

    // ./src/lib.rs

    //! This inner documentation line comment documents our `./src/lib.rs` file.
    //! We've created a rust library crate which means `./src/lib.rs` 
        //! is the entry point of our code.
    //! When we compile our code, it starts with this file!

    fn add_one(number: usize) -> usize {
        return number + 1
    }
Enter fullscreen mode Exit fullscreen mode

Outer Line Documentation Comments use /// and are the preferred way to document any other code you write.

    // ./src/lib.rs

    //! This inner documentation line comment documents our `lib.rs` file.
    //! We've created a rust library crate which means `lib.rs` is the 
    //! entry point of our code.
    //! When we compile our code, it starts with this file!


    /// This function will add the number you pass in by 1
    /// It will then return that number

    /// This is an outer documentation line comment because it exists before
    /// the function `add_five` we have defined below
    fn add_one(number: usize) -> usize {
        return x + 1;
    }
Enter fullscreen mode Exit fullscreen mode

We are using Inner Line Documentation Comments to document the inside of our ./src/lib.rs file and Outer Line Documentation Comments outside of our add_one function to document our add_one function.


Using any form of documentation comment we can document our code using Markdown, specifically the CommonMark specification.

By supporting Markdown, Rust has given us a powerful, uniform convention to help us document our code. To really illustrate this, let's look at the documentation for Rust's standard library, std

We're currently looking at Rust's std or 'standard' library. Any project we create automatically have access to the entire standard library.

You should see a page that looks like this:

std library crate

Do you see the [src] in the top right corner? I want you to open that link in a new window and compare the two, maybe like this:

std and std src comparison

Do you notice anything?

Do you see how the std library uses Inner Line Documentation Comments (//!) to document the top-level of the std library?

Do you see how each line with Inner Line Documentation Comments looks similar to the std library's generated documentation from those comments?

We can even see some Markdown used in creating an unordered list:

unordered list

Built into Rust we get a powerful convention for documenting the code we write!


Now that we know the basics of using documentation comments we'll use cargo to create a library and some documentation for it.

You'll want to have Rust with the cargo package
manager installed on your local computer to get the
most out of this exercise, but you can also follow
along!

Check to see if cargo is installed by running:

cargo --version

Rust comes with a bunch of tools when you install it, one of them being rustdoc. rustdoc's purpose is to build documentation from our crate's entry point which is called our "crate root". When we build the documentation rustdoc turns it into HTML, CSS, and Javascript. rustdoc is a more low-level than cargo, and luckily cargo has commands that act as wrappers for rustdoc to make generating our documentation easier. If you want to learn more about rustdoc, you can look at the rustdoc book.

Now before we generate our documentation website, let's write a simple library with a couple of addition functions. Then we'll document it using all three types of comment!

Let's run cargo new addition_functions --lib to create our new Rust library. Then we'll run cd addition_functions. Open this in your favorite code editor and then open the ./src/lib.rs file and delete the code inside.

We should see something like this:

1

Congrats! You've just created a Rust library crate. A Rust library includes functionality that may be used by a binary crate or other library crates. For example, the std library handles the creation of built-in types for rust. We don't go off on our own and try to build an integer type, because it would most likely be a waste of time. Rust already provides us with multiple integer types in it's std library crate, so let's use them!

From here let's create a couple of functions. In [./src/lib.rs](http://lib.rs) we'll add this code:

2

pub makes our function public so that it will be included in documentation.

And then we'll run cargo doc --open. This command will generate our documentation and open it locally in the browser.

addition_functions_doc

You can also run cargo doc to build documentation and not open it in a web browser.

When we use cargo, our documentation website is built within our ./target/doc/[name-of-library] folder, the entry point being the index.html file.

This means an alternative to running cargo doc --open would be running cargo doc and then open target/doc/[name-of-library]/index.html(in our case [name-of-library] will be addition_functions

So we have our two adding functions, now we should write some documentation to describe how they work. Let's use all three types of comments to document the purpose of our library.

Our Inner Documentation Line Comments to document our entire library:

3

Our Outer Documentation Line Comments to document our functions:

4

And finally some Regular Comments:

5

Here is a full code

Now that we've added some comments, lets re-build our documentation using cargo doc --open

6

We can see our Inner Documentation Line Comments (//!) which describe the entirety of our library. This is because they are top level within our [./src/lib.rs](http://lib.rs) file. Rust convention dictates that we only use this type of comment to give an overview of our crate's functionality—a general explanation of what functionality our crate provides.

Now below that we see our two functions with their Outer Documentation Line Comments (///). Remember, they are called Outer Documentation Line Comments because they are just before or "outside" of the code they comment on. In this case we're commenting on the add_five and add_ten functions respectively. Let's click the add_five function.

7

Now we see our function signature in addition to the rest of the outer documentation comments we wrote!

Finally, we'll check out our source code by clicking [src] in the top right corner. Now we'll be able to see our regular comments:

8

Remember, regular comments are useful for other developers working on/developing the library crate, while Outer/Inner Line Documentation is more useful for developers who are using your library crate.

This is a lot. We haven't even gotten to understanding types in Rust, but it seems very intentional to me that Rust By Example teaches commenting just after "Hello, World!", its first section. Commenting is a way to bridge the communication gap between developers, whether we comment on a line of code or create documentation for an entire library. Comments create documentation in Rust, and documentation can mean the difference between spending 5 minutes on a problem or 5 hours. Rust has excellent documentation. As we keep learning let's take advantage of it. Let's apply the knowledge we've learned today to search documentation for answers and learn Rust as solidly as we can.

EXTRA STUFF

We can search for documentation on docs.rs, an open source website that hosts all documentation for crates added to crates.io

Now let's give our documentation a little flair and learn about some of the ways we can make it more explicit, give it some minimal Markdown styling, and even some alternative syntax.

An Alternative Commenting Syntax

Both inner and outer documentation comments are syntactic sugar for the built in [doc=""] attribute. We can use them interchangeably like so:

Type of Comment w/o Syntactic Sugar w/ Syntactic Sugar
Inner Line Documentation Comments #[doc="This is an inner documentation comment"] /// This is an inner documentation comment
Outer Line Documentation Comments #![doc"This is an outer documentation comment"] //! This is an outer documentation comment

Markdown Syntax, Code Examples, and Testing

Some API Conventions

Rust crates include some common headings as convention (Errors, Safety, Example) we can use to describe how our code may behave in common use cases. Let's create an Examples header for our add_five, write a code example, and then test it.

Using Markdown syntax we can create a heading and called "Examples" above our add_five function. Let's see what that looks like:

Markdown will default to Rust, but it never hurts to be explicit about the language we are using.

From here, let's use the assert_eq! macro to see if our function is working as intended. If the two arguments we pass in are equal, the test will pass. Otherwise, it will fail.

Now if we run cargo test --doc, we'll only run our documentation test cases. In our console we'll see if the test cases passed or failed.

9

Looks like our test cases passed!

If you're feeling up to it, why don't you write some simple Example documentation for the add_ten function like we did above, for practice!


Block Comment Examples

Inner Block Documentation Comments

/*!
        This library has two functions
        that will add an integer to the integer you pass in.
!*/

pub fn add_five(number: usize) -> usize {
    return number + 5;
}

pub fn add_ten(number: usize) -> usize {
    number + 10
}
Enter fullscreen mode Exit fullscreen mode

Outer Block Documentation Comments

/**
        Adds 5 to the integer passed in.
**/
pub fn add_five(number: usize) -> usize {
    return number + 5;
}

/**
        Adds 10 to the integer passed in.
**/
pub fn add_ten(number: usize) -> usize {
    number + 10
}
Enter fullscreen mode Exit fullscreen mode

Regular Block Comments

pub fn add_five(number: usize) -> usize {
        /* 
             I chose to return explicitly here
           for clarity in a blog where we're learning
             how to write comments.
    */ 
    return number + 5;
}

pub fn add_ten(number: usize) -> usize {
        /* 
             I chose not to return explicitly here
           because we now know we can return explicitly in
       Rust, but we can also not include a ";" (semi-colon)
       and Rust will return that expression.
    */ 
    number + 10
}
Enter fullscreen mode Exit fullscreen mode

Here's a handy table to remember all three types of comment, whether they are in line or block ****form.

Type of Comment Line Comments (Very Common) Block Comments (Uncommon)
Regular Comments // /* ... */
Inner Line Documentation Comments /// /** ... **/
Outer Line Documentation Comments //! /*! ... !*/

Oldest comments (0)