Rustfmt + cargo fmt: Usage, Flags & IDE Support | Web Formatter Blog

Rustfmt + cargo fmt: Usage, Flags & IDE Support
A comprehensive reference guide to formatting Rust code with rustfmt and cargo fmt.
Introduction to Rustfmt & cargo fmt
Code formatting is a crucial aspect of maintaining readable and consistent Rust codebases. Rustfmt is the official code formatter for Rust, designed to format your code according to style guidelines, ensuring consistency across projects and teams.
This guide covers two primary tools:
- rustfmt: The standalone formatter that can be used directly on Rust files
- cargo fmt: A Cargo subcommand that uses rustfmt to format all Rust files in a Cargo project
Whether you're a Rust beginner or an experienced developer, this reference will help you effectively use these tools to maintain clean, consistent code.
Installation
Rustfmt is included in the standard Rust toolchain, but you may need to install it explicitly if you're using a minimal installation or an older version.
# Install rustfmt using rustup
rustup component add rustfmt
To verify the installation:
# Check rustfmt version
rustfmt --version
# Check cargo fmt availability
cargo fmt --version
Both commands should display version information if the installation was successful.
Basic Usage
There are two main ways to format your Rust code: using rustfmt directly or using cargo fmt.
Using rustfmt Directly
The rustfmt command can be used to format individual Rust files:
# Format a single file
rustfmt src/main.rs
# Format multiple files
rustfmt src/main.rs src/lib.rs
By default, rustfmt overwrites the original files. If you want to see the changes without
modifying the files, use the --check
flag:
# Check if files are formatted correctly without modifying them
rustfmt --check src/main.rs
Using cargo fmt
For Cargo projects, it's usually more convenient to use cargo fmt
, which formats
all Rust files in your project:
# Format all files in the current Cargo project
cargo fmt
# Check if all files are formatted correctly without modifying them
cargo fmt -- --check
Note the double dash (--
) when passing flags to rustfmt through cargo fmt.
Configuration Options
Rustfmt is highly configurable, allowing you to adjust formatting to match your project's style preferences.
rustfmt.toml Configuration
Configuration is typically done through a rustfmt.toml
file placed in your project root.
Here's an example configuration file:
# rustfmt.toml
max_width = 100
tab_spaces = 4
edition = "2021"
reorder_imports = true
newline_style = "Unix"
Rustfmt will automatically detect and use this configuration file when formatting code in your project.
Common Configuration Options
Here are some of the most commonly used configuration options:
# Line width and indentation
max_width = 100 # Maximum line width
tab_spaces = 4 # Number of spaces per tab
hard_tabs = false # Use spaces for indentation (false) or tabs (true)
# Imports and modules
reorder_imports = true # Sort imports alphabetically
imports_granularity = "Crate" # Group imports by crate
group_imports = "StdExternalCrate" # Group imports by standard library, external crates, and local imports
# Braces and blocks
brace_style = "SameLineWhere" # Brace style for control flow constructs
control_brace_style = "AlwaysSameLine" # Brace style for control flow expressions
# Comments
wrap_comments = true # Wrap comments to max_width
comment_width = 80 # Maximum width of comments
# Spacing
spaces_around_ranges = false # Spaces around range operators
binop_separator = "Front" # Where to put spaces around binary operators
Edition-Specific Settings
Rustfmt can adapt its formatting based on the Rust edition your project uses:
# Set the Rust edition for formatting
edition = "2021" # Options: "2015", "2018", "2021"
Different editions may have slightly different formatting conventions, so it's important to specify the correct edition for your project.
Command Line Flags
Both rustfmt and cargo fmt support various command-line flags to customize their behavior.
rustfmt Flags
Here are the most useful rustfmt command-line flags:
# Check if files are formatted correctly without modifying them
rustfmt --check file.rs
# Show detailed differences when checking
rustfmt --check --diff file.rs
# Emit reformatted files to stdout instead of overwriting
rustfmt --emit stdout file.rs
# Use a specific configuration file
rustfmt --config-path=/path/to/rustfmt.toml file.rs
# Format recursively (useful for directories)
rustfmt --recursive src/
# Ignore specific files or patterns
rustfmt --exclude=target/ src/
cargo fmt Flags
When using cargo fmt, you can pass flags to rustfmt by adding them after a double dash:
# Check formatting without modifying files
cargo fmt -- --check
# Show detailed differences
cargo fmt -- --check --diff
# Format only specific packages in a workspace
cargo fmt --package my-package
# Format all packages in a workspace
cargo fmt --all
# Format only the current package
cargo fmt --manifest-path=./Cargo.toml
IDE Integration
Integrating rustfmt with your IDE can significantly improve your development workflow by automatically formatting code as you write or save.
Visual Studio Code
VS Code offers excellent Rust support through the "rust-analyzer" extension:
- Install the "rust-analyzer" extension from the VS Code marketplace
- Configure automatic formatting in your settings.json:
{
"editor.formatOnSave": true,
"rust-analyzer.rustfmt.extraArgs": [],
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer"
}
}
You can also configure VS Code to use your project's rustfmt.toml file by adding:
{
"rust-analyzer.rustfmt.overrideCommand": [
"rustfmt",
"--edition=2021"
]
}
IntelliJ IDEA / CLion
For JetBrains IDEs, use the "Rust" plugin:
- Install the "Rust" plugin from Settings/Preferences → Plugins
- Configure rustfmt in Settings/Preferences → Languages & Frameworks → Rust → Rustfmt
- Enable "Run rustfmt on Save" for automatic formatting
You can also specify a custom path to the rustfmt binary if needed.
Vim / Neovim
For Vim or Neovim, you can use plugins like "rust.vim" or integrate with language servers:
" Using rust.vim
Plug 'rust-lang/rust.vim'
let g:rustfmt_autosave = 1
" Or using a language server like rust-analyzer with coc.nvim
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'fannheyward/coc-rust-analyzer'
With these configurations, your Rust code will be automatically formatted when you save a file.
Emacs
For Emacs, you can use the "rustic" package, which includes rustfmt integration:
;; Install rustic
(use-package rustic
:ensure t
:config
;; Enable automatic formatting on save
(setq rustic-format-on-save t)
;; Configure rustfmt
(setq rustic-rustfmt-args "--edition=2021"))
CI Integration
Integrating rustfmt into your Continuous Integration (CI) pipeline ensures that all code contributions follow your project's formatting standards.
GitHub Actions
Here's an example GitHub Actions workflow that checks Rust code formatting:
# .github/workflows/rustfmt.yml
name: Rustfmt
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
This workflow will fail if any Rust files in your repository are not properly formatted.
GitLab CI
For GitLab CI, you can use a similar configuration:
# .gitlab-ci.yml
rustfmt:
image: rust:latest
stage: lint
before_script:
- rustup component add rustfmt
script:
- cargo fmt --all -- --check
only:
- merge_requests
- main
Troubleshooting Common Issues
Even with a well-configured formatter, you might encounter some issues. Here are solutions to common problems.
Formatting Errors
If rustfmt fails to format your code, it's usually because of syntax errors:
- Parse errors: Fix any syntax errors in your code before formatting
- Macro-heavy code: Some complex macros might cause formatting issues. You can exclude problematic files or use format directives
You can use format directives to disable formatting for specific code sections:
// Normal formatted code
// Format-off
fn ugly_but_necessary_code() {
let x = vec![1,2,3,
4,5,6];
}
// Format-on
// Normal formatted code again
Version Conflicts
Different versions of rustfmt might format code differently. To ensure consistency:
- Specify a consistent rustfmt version in your CI pipeline
- Document the expected rustfmt version in your project's README
- Consider using a rust-toolchain.toml file to pin the rustfmt version
# rust-toolchain.toml
[toolchain]
channel = "1.70.0"
components = ["rustfmt"]
Best Practices
Follow these best practices to get the most out of rustfmt:
- Format early and often: Integrate formatting into your development workflow from the start
- Use a project-specific configuration: Create a rustfmt.toml file in your project root
- Commit your rustfmt.toml: This ensures all contributors use the same formatting rules
- Format before committing: Set up a pre-commit hook or IDE integration to format code automatically
- Enforce formatting in CI: Reject pull requests with improperly formatted code
- Avoid manual formatting: Let rustfmt handle all formatting concerns
- Update rustfmt with Rust: Keep your rustfmt version in sync with your Rust toolchain
Conclusion
Rustfmt and cargo fmt are powerful tools that help maintain consistent code style across Rust projects. By integrating these tools into your development workflow and CI pipeline, you can ensure that your codebase remains clean, readable, and maintainable.
Remember that the primary goal of code formatting is to eliminate debates about style and focus on what truly matters: writing correct, efficient, and maintainable Rust code.
Whether you're working on a personal project or collaborating with a large team, consistent formatting through rustfmt will improve code quality and developer productivity.