Please DO the following steps before submitting a PR:
- Run
cargo fmt
to format the code, you can also runcargo fmt -- --check
to review the format changes; - Run
cargo clippy
to make sure the code has no warnings from clippy; - Run
cargo test
in project root directory to make sure no tests break.
Use impl
whenever possible, since impl
means static dispatch, not dynamic, which has less overhead.
Also impl
makes a lot succinct.
- Try to avoid trait object, or don't use
dyn
. Useimpl
instead. For example:
// not recommended
fn foo(input: Box<dyn SomeTrait>)
// preferred
fn foo(input: impl SomeTrait)
- Try to avoid redundent generic type definition, use
impl
instead. For example:
// not recommended
fn foo<P: AsRef<Path>>(input: P)
// preferred
fn foo(input: impl AsRef<Path>)
Use functional style instead of imperative one, especially when doing iteration or future chaining. For example:
fn process(i: u8) {
println!("u8={}", i);
}
// not recommend
for i in vec {
process(i);
}
// preferred
vec.iter().for_each(process);
When using functions from external dependent crates, reserve the mod name where a function belongs to. This is a Rust tradition. For example:
// not recommended
use external_crate::some_mod::some_func;
some_func();
// preferred
use external_crate::some_mod;
some_mod::some_func();
As for using Struct or Trait from external dependent crate, just directly use it. For example:
// preferred
use external_crate::some_mod::{SomeStruct, SomeTrait};
let val = SomeStruct::new();
fn foo(bar: impl SomeTrait) {
todo!();
}
Except for using Result
, since so many crates define Result
for theirselves,
so plese highlight which Result
is using. For example:
// not recommended
use std::io::Result;
fn foo() -> Result<()> {
todo!();
}
// preferred
use std::io;
fn foo() -> io::Result<()> {
todo!();
}
When using internal mod's, please use relative mod path, instead of absolute path. For example:
mod AAA {
mod BBB {
mod CCC {
struct SomeStruct(u8);
}
mod DDD {
// not recommended
use crate::AAA::BBB::CCC::SomeStruct;
// preferred
use super::CCC::SomeStruct;
}
}
}
DO NOT defined customized error type, unless explicit reason. Use anyhow
crate for default error handling.
- It's preferred to add context to
Result
by usinganyhow::Context
. For example:
use anyhow::Context;
use std::io;
fn foo() -> io::Result<()> {
todo!();
}
fn bar() -> anyhow::Result<()> {
foo().context("more description for the error case")?;
}
- Every
assert!
,assert_eq!
andassert_nq!
should have a explanation about assertion failure. For example:
// not recommended
assert!(some_condition);
// preferred
assert!(some_condition, "explanation about assertion failure");
- DO NOT use
unwrap()
ofResult
andOption
directly, unlessResult
orOption
are properly checked. If you believe usingunwrap()
is safe, please add a comment for eachunwrap()
. For example:
let val = some_result.unwrap(); // safe to use unwrap() here, because ...
Try to use safe code as much as possible, if no explicit reason, please don't use unsafe code.