rust-style-guide
A tool for applying Rust coding guidelines.
Usage
- REQUIRED: Practices that are mandatory to adhere to, reported as an Error.
- RECOMMENDED: Recommended best practices, reported as a Warning.
- OPTIONAL: Generally accepted best practices, but their implementation depends on the context, reported as Info. For example, when writing infrastructure code, strict measures are often used. However, for rapidly iterating business code, some requirements may be too stringent, and adherence depends on the specific practice context.
Method 1
- Run the following Cargo command in your project directory:
- Add global attributes to the top of the file
main.rs
orlib.rs
:
Method 2
Manually add configurations to the corresponding files according to the descriptions below.
Format
Use the official Rustfmt
tool provided by Rust as your code formatter. It helps teams adhere to a consistent code style by automatically adjusting code indentation, spacing, line breaks, and other formatting rules, thereby improving code readability. This tool is included by default with Rust. Official documentation: Rustfmt : https://rust-lang.github.io/rustfmt
We enforce the inclusion of a rustfmt.toml
file in every project, with the following configuration:
# -------- https://rust-lang.github.io/rustfmt/?search={key} --------
# Run rustfmt with this config (it should be picked up automatically).
= "2024"
= true
# Prevent carriage returns
= "Unix"
# Maximum line width of 120 characters
= 120
# Fine-grained width values are calculated as a proportion of `max_width`.
= "Default"
# (default) P.FMT.02 Indent with 4 spaces
= 4
# (default) P.FMT.02 Disallow the use of hard tabs for indentation
= false
# (default) P.FMT.03 Minimum blank lines between code lines: 0
= 0
# (default) P.FMT.03 Maximum blank lines between code lines: 1
= 1
# (default) P.FMT.04 Use the same line brace style for most language constructs (functions, structs, etc.)
= "SameLineWhere"
# (default) P.FMT.04 Place the opening brace of `where` clauses on the next line
= false
# (default) P.FMT.04 Use the same line brace style for control structures (e.g. `if`, `match`)
= "AlwaysSameLine"
# (default) P.FMT.05 Use block indentation style for multiple identifier definitions
= "Block"
# (default) P.FMT.06 Place operators at the start of new lines for multi-line expressions
= "Front"
# (default) P.FMT.07 Do not align discriminants of enum variants
= 0
# (default) P.FMT.07 Do not align struct fields
= 0
# (default) P.FMT.08 For up to five function parameters, place them on a single line; use block style for more
= "Tall"
# (default) P.FMT.08 Place import statements on new lines if more than four per line
= "Mixed"
# (default) P.FMT.09 Do not add spaces before colons
= false
# (default) P.FMT.09 Add spaces after colons
= true
# (default) P.FMT.09 Do not add spaces around range operators (`..`, `..=`)
= false
# (default) P.FMT.09 Add spaces around `+` and `=` operators (in type annotations)
= "Wide"
# (default) P.FMT.10 Use block style when match arms are too long to fit on the same line as `=>`
= true
# (default) P.FMT.10 Do not prepend match arms with extra leading pipes (`|`)
= "Never"
# P.FMT.11 Put imports from the same module within the same group
= "Crate"
# P.FMT.11 Group module imports as follows:
# * Imports from `std`, `core`, and `alloc` come first.
# * Imports from third-party crates come next.
# * Imports from local crates (with `self`, `super`, and `crate` prefixes) come last.
= "StdExternalCrate"
# (default) P.FMT.11 Order imports within groups in lexicographical order
= true
# P.FMT.12 Use compact format for macro matchers (left-hand side of `=>`) in macro definitions
= true
# (default) P.FMT.12 Use relaxed format for macro bodies (right-hand side of `=>`) in macro definitions
= true
# (default) P.FMT.13 Do not use field initialization shorthand
= false
# (default) P.FMT.14 Always explicitly specify the ABI for external functions
= true
# P.FMT.15 Allow the use of `..` to denote remaining elements when destructuring tuples
= true
# P.FMT.16 Do not merge unrelated traits into a single line in derive macros
= false
# Replace `try!` macro with the `?` operator
= true
# (default) P.CMT.02 Set the maximum width for a single-line comment to 80 characters
= 80
# P.CMT.02 Automatically wrap multi-line comments at the maximum width
= true
# P.CMT.03 Convert block comments (`/* */`) to line comments (`//`) where possible
= true
# (default) P.CMT.03 Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` respectively
= false
# By default, ignore everything in the repository
# Tidy only checks files which are not ignored; each entry follows gitignore style
= []
Lint
Rustc
is Rust's code compiler, which also includes many lint checks. When compiling code, Rustc runs these lint checks and provides feedback at different levels based on the configuration.
Rustc lint documentation: Rustc Lints : https://doc.rust-lang.org/rustc/lints/index.html
Clippy
is a linter tool for Rust that performs static analysis to identify potential issues, style problems, anti-patterns, and possible optimizations in Rust code. It acts like a code quality watchdog, assisting developers in writing more efficient, safer, and stylistically consistent Rust code.
-
Clippy documentation: Clippy Docs : https://doc.rust-lang.org/stable/clippy/index.html
-
Clippy lint categories: Clippy Lint Groups : https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#reference-level-explanation
-
Installing Clippy:
- Running Clippy to apply code fixes:
- Running Clippy to check code and deny warnings:
- Configuring Rustc and Clippy lints must be done in
main.rs
orlib.rs
:
// -------- rustc lint doc: https://doc.rust-lang.org/rustc/lints/listing/index.html --------
// [REQUIRED] G.VAR.02 Do not use non-ASCII characters in identifiers
// -------- rust-clippy doc: https://rust-lang.github.io/rust-clippy/master/index.html --------
// [REQUIRED]
// [REQUIRED]
// [RECOMMENDED] G.CMT.01 Add Error documentation in the docs of public functions that return Result
// [REQUIRED] G.CMT.02 Add Panic documentation in the docs of public APIs that may panic under certain circumstances
// [RECOMMENDED] G.VAR.03 Variable shadowing should be used carefully
// [RECOMMENDED] G.CNS.05 Use const fn for functions or methods wherever applicable
// [REQUIRED] G.TYP.01 Prefer safe conversion functions over `as` for type casting
// [RECOMMENDED] G.VAR.01 Avoid using too many meaningless variable names when destructuring tuples with more than four
// variables
// [RECOMMENDED] G.TYP.02 Explicitly specify the type for numeric literals
// [RECOMMENDED] G.TYP.03 Use `try_from` methods instead of relying on numeric boundaries for safe conversion
// [RECOMMENDED] G.TYP.BOL.02 Use `if` expressions instead of `match` for boolean conditions
// [RECOMMENDED] G.TYP.BOL.05 Use logical operators (&&/||) instead of bitwise operators (&/|) for boolean operations
// when not necessary
// [REQUIRED] G.TYP.INT.01 Consider the risks of integer overflow, wrapping, and truncation in integer arithmetic
// [REQUIRED] G.TYP.INT.02 Avoid `as` casting between signed and unsigned integers; use safe conversion functions
// [REQUIRED] G.TYP.INT.03 Avoid using `%` for modulo operations on negative numbers
// [REQUIRED] G.TYP.FLT.02 Avoid precision loss when casting from any numeric type to floating-point; use safe
// conversion functions
// [REQUIRED] G.TYP.FLT.03 Be cautious of precision loss in floating-point arithmetic and comparisons
// [REQUIRED] G.TYP.FLT.04 Use Rust's built-in methods for floating-point calculations
// [OPTIONAL] G.TYP.ARR.01 Use static variables instead of constants for large global arrays
// [RECOMMENDED] G.TYP.SCT.01 Add `#[non_exhaustive]` attribute to publicly exported structs
// [RECOMMENDED] G.TYP.ENM.05 Add `#[non_exhaustive]` attribute to publicly exported enums
// [RECOMMENDED] G.TYP.SCT.02 Consider refactoring when a struct contains more than three boolean fields
// [RECOMMENDED] G.FUD.03 Consider using a custom struct or enum instead of many boolean parameters in function
// signatures
// [RECOMMENDED] G.TYP.ENM.04 Avoid using glob imports for enum variants in `use` statements
// [RECOMMENDED] G.CTF.02 Ensure `else` branches are present whenever `else if` is used
// [RECOMMENDED] G.STR.02 Use `push_str` method for appending strings
// [RECOMMENDED] G.STR.03 Convert string literals containing only ASCII characters to byte sequences using `b"str"`
// syntax instead of `as_bytes()`
// [RECOMMENDED] G.STR.05 Take care to avoid disrupting UTF-8 encoding when slicing strings at specific positions
// [RECOMMENDED] G.FUD.02 Prefer passing large values by reference if function parameters implement `Copy`
// [RECOMMENDED] G.FUD.04 Pass small `Copy` type values by value instead of by reference
// [RECOMMENDED] G.FUD.05 Avoid using `inline(always)` for functions indiscriminately
// [REQUIRED] G.GEN.02 Be cautious to avoid using generic default implementations of some methods from Rust's standard
// library; prefer specific type implementations
// [RECOMMENDED] G.TRA.BLN.01 Prefer using the concrete type's `default()` method over calling `Default::default()`
// [REQUIRED] G.TRA.BLN.02 Do not implement the `Copy` trait for iterators
// [RECOMMENDED] G.TRA.BLN.07 Use `copied` method instead of `cloned` for iterable `Copy` types
// [RECOMMENDED] G.ERR.01 Avoid using `unwrap` indiscriminately when handling `Option<T>` and `Result<T, E>`
// [RECOMMENDED] G.MOD.03 Avoid using wildcard imports in module declarations
// [REQUIRED] G.MOD.04 Avoid using different module layout styles within the same project
// [RECOMMENDED] G.CAR.02 Ensure that necessary metadata is included in the `Cargo.toml` of the crate
// [RECOMMENDED] G.CAR.03 Avoid negative or redundant prefixes and suffixes in feature names
// [REQUIRED] G.CAR.04 Avoid using wildcard dependencies in `Cargo.toml`
// [RECOMMENDED] G.MAC.01 Only use the `dbg!()` macro for debugging code
// [REQUIRED] Ensure that locks are released before `await` is called in asynchronous code
// [REQUIRED] Handle `RefCell` references across `await` points
// [RECOMMENDED] G.ASY.04 Avoid defining unnecessary async functions
// [REQUIRED] G.UNS.SAS.02 Use `assert!` instead of `debug_assert!` to verify boundary conditions in unsafe functions
- Additional
Clippy lint
configurations should be placed in the project'sclippy.toml
file, with the following content:
# -------- rust-clippy doc: https://rust-lang.github.io/rust-clippy/master/index.html --------
# This lint will not trigger if the function is an exported API. This avoids suggesting changes that would break the API. Default is true
= true
# [RECOMMENDED] G.VAR.01 Avoid using too many meaningless variable names when destructuring tuples with more than four variables
= 4
# [RECOMMENDED] G.TYP.SCT.02 Consider refactoring when a struct contains more than three boolean fields
= 3
# [RECOMMENDED] G.FUD.03 Configures the maximum number of boolean parameters allowed in a function, which is 3 by default.
= 3
# [RECOMMENDED] G.TYP.ENM.06 Variants within an enum should not differ significantly in size. Default is 200 bytes
= 200
# [RECOMMENDED] G.FUD.01 Limit the number of function parameters to no more than five
= 5
# Determines if wildcard imports in prelude and super (in test modules) should be warned. Default is false
= false