Comments in Rust
Rust has three families of comments: ordinary comments that the compiler ignores, documentation comments that become browsable HTML docs, and doc tests — runnable code examples embedded directly inside doc comments. Understanding all three helps you write code that is easy to read and maintain.
Line comments
Line comments start with // and run to the end of the line. They are the most common comment type for inline explanations and notes.
fn main() {
// This is a line comment — the compiler ignores everything after //
let x = 5; // You can also place them at the end of a line
// Multiple line comments
// are just repeated //
// on consecutive lines
let result = x * 2; // result is 10
println!("{}", result);
}Block comments
Block comments use /* ... */ and can span multiple lines. Unlike in C, Rust block comments can be nested, which makes it easy to comment out code that already contains comments.
fn main() {
/* This is a block comment.
It can span multiple lines.
The compiler ignores all of this. */
let x = /* you can even inline them */ 42;
/* Nested block comments work in Rust:
/* This inner comment is valid */
You can safely comment out code that already has /* */ comments.
*/
println!("{}", x);
}Doc comments for items — ///
Doc comments start with /// and document the item that immediately follows them: a function, struct, enum, trait, module, or constant. The content is parsed as Markdown and rendered as HTML by rustdoc.
/// Adds two numbers together and returns their sum.
///
/// # Arguments
///
/// * `a` - The first number
/// * `b` - The second number
///
/// # Returns
///
/// The sum of `a` and `b` as an `i32`.
///
/// # Examples
///
/// ```
/// let result = my_crate::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}The sections (# Arguments, # Returns, # Examples) are just Markdown headings — you can use any headings you like, but these are the community conventions recognised by tools like rustdoc and IDE plugins.
Doc comments for modules — //!
Doc comments that start with //! document the enclosing item rather than the next item. They are placed at the top of a file or module and describe what that module provides.
//! # My Awesome Library
//!
//! `my_awesome_lib` is a collection of utilities for doing awesome things.
//!
//! ## Quick Start
//!
//! ```
//! use my_awesome_lib::greet;
//! greet("world");
//! ```
//!
//! ## Features
//!
//! - Fast: zero-cost abstractions throughout
//! - Safe: no unsafe code
//! - Well tested: 100% test coverage
// The rest of the module follows
pub fn greet(name: &str) {
println!("Hello, {}!", name);
}Markdown in doc comments
Everything inside a /// or //! comment is rendered as Markdown by rustdoc. You get headings, bullet lists, bold, italic, inline code, code blocks, and links.
/// A **strongly typed** wrapper around a raw connection string. /// /// This type ensures connection strings are: /// /// - Validated on creation /// - Never logged in plaintext /// - Zeroed from memory on drop /// /// ## Usage /// /// Prefer `ConnectionString::new` over constructing this directly. /// /// See also: [`ConnectionPool`] for managing multiple connections. pub struct ConnectionString(String);
Doc tests — runnable examples
Code blocks inside doc comments are automatically compiled and run as tests when you execute cargo test. This keeps documentation examples accurate — if the API changes, the doc test fails, alerting you that the docs are out of date.
/// Divides `numerator` by `denominator`.
///
/// Returns `None` if `denominator` is zero to avoid a panic.
///
/// # Examples
///
/// ```
/// use my_crate::safe_divide;
///
/// assert_eq!(safe_divide(10, 2), Some(5));
/// assert_eq!(safe_divide(7, 0), None);
/// ```
pub fn safe_divide(numerator: i32, denominator: i32) -> Option<i32> {
if denominator == 0 {
None
} else {
Some(numerator / denominator)
}
}Run all tests including doc tests with:
cargo test
running 1 test test src/lib.rs - safe_divide (line 8) ... ok test result: ok. 1 passed; 0 failed; 0 ignored
Doc test options
You can annotate a doc test code block with options to control how it is compiled and run:
/// ```no_run
/// // Compiled but not executed (useful for I/O-heavy examples)
/// let result = fetch_from_network("https://example.com");
/// ```
///
/// ```ignore
/// // Neither compiled nor run (use sparingly — docs may become wrong)
/// this_function_does_not_exist_yet();
/// ```
///
/// ```should_panic
/// // Expected to panic — test passes when the code panics
/// let _x: i32 = "not a number".parse().unwrap();
/// ```
pub fn placeholder() {}A fully documented function
Here is a complete, real-world-style example of a well-documented public function following community conventions:
/// Parses a key-value pair from a string of the form `"key=value"`.
///
/// The key and value are trimmed of leading and trailing whitespace.
///
/// # Arguments
///
/// * `input` - A string slice expected to contain exactly one `=` sign.
///
/// # Returns
///
/// A `Some((key, value))` tuple of string slices into `input` if parsing
/// succeeds, or `None` if the input does not contain an `=` character.
///
/// # Examples
///
/// ```
/// use my_crate::parse_kv;
///
/// assert_eq!(parse_kv("name=Alice"), Some(("name", "Alice")));
/// assert_eq!(parse_kv(" port = 8080 "), Some(("port", "8080")));
/// assert_eq!(parse_kv("no-equals-sign"), None);
/// ```
///
/// # Panics
///
/// This function does not panic.
///
/// # See also
///
/// * [`parse_kv_list`] for parsing multiple pairs separated by commas.
pub fn parse_kv(input: &str) -> Option<(&str, &str)> {
let (key, value) = input.split_once('=')?;
Some((key.trim(), value.trim()))
}Generating HTML documentation
rustdoc is the built-in documentation generator. Cargo drives it with cargo doc.
# Build documentation for your crate and all dependencies cargo doc # Build and immediately open in the browser cargo doc --open # Include private items in the docs cargo doc --document-private-items
Comments vs attributes
Attributes (#[...]) are sometimes confused with comments because they annotate code, but they are fundamentally different. Comments are ignored by the compiler; attributes are processed by it.
Comment | Attribute | |
|---|---|---|
Syntax |
|
|
Seen by compiler? | No — stripped before compilation | Yes — influences compilation |
Purpose | Human-readable notes and docs | Metadata: derive, cfg, test, allow, deny... |
Example |
|
|