For bugs, feel free to open issues or contact us directly. Thank you for your support. <3
Even though we will gladly assist you in finishing up your PR, try to:
- keep all the crates compiling with stable rust (hide the eventual non-stable code under
cfg
s) - run
cargo +nightly fmt
on your code before pushing - check the output of
cargo clippy --all
or./scripts/clippy.sh
(On windows use.\scripts\clippy.ps1
) - run
cargo build --no-default-features
to check forno_std
compatibility (and possibly add#[cfg(feature = "std")]
) to hide parts of your code. - Please add and describe your changes to MIGRATION.md if you change the APIs.
Some of the parts in this list may be hard, don't be afraid to open a PR if you cannot fix them by yourself, so we can help.
Some of these checks can be performed automatically during commit using pre-commit.
Once the package is installed, simply run pre-commit install
to enable the hooks, the checks will run automatically before the commit becomes effective.
Before making your pull requests, try to see if your code follows these rules.
- Wherever possible, use
Cow<'static, str>
instead of String. PhantomData
should have the smallest set of types needed. Try not addingPhantomData
to your struct unless it is really necessary. Also even when you really needPhantomData
, try to keep the typesT
used inPhantomData
as smallest as possible- Wherever possible, trait implementations with lifetime specifiers should use '_ lifetime elision.
- Complex constructors should be replaced with
typed_builder
, or write code in the builder pattern for yourself. - Remove generic restrictions at the definitions (e.g., we do not need to specify that types impl
Serialize
,Deserialize
, orDebug
anymore at the struct definitions). Therefore, try avoiding code like this unless the contraint is really necessary.
pub struct X<A>
where
A: P // <- Do not add contraints here
{
fn ...
}
- Reduce generics to the least restrictive necessary. Never overspecify the contraints. There's no automated tool to check the useless constraints, so you have to verify this manually.
pub struct X<A>
where
A: P + Q // <- Try to use the as smallest set of constraints as possible. If the code still compiles after deleting Q, then remove it.
{
fn ...
}
- Traits which have an associated type should refer to the associated type, not the concrete/generic. In other words, you should only have the associated type when you can define a getter to it. For example, in the following code, you can define a associate type.
pub trait X
{
type A; // <- You should(can) define it as long as you have a getter to it.
fn a(&self) -> A;
}
- Ideally the types used in the the arguments of methods in traits should have the same as the types defined on the traits.
pub trait X<A, B, C> // <- this trait have 3 generics, A, B, and C
{
fn do_stuff(&self, a: A, b: B, c: C); // <- this is good because it uses all A, B, and C.
fn do_other_stuff(&self, a: A, b: B); // <- this is not ideal because it does not have C.
}
- Always alphabetically order the type generics. Therefore,
pub struct X<E, EM, OT, S, Z> {}; // <- Generics are alphabetically ordered
But not,
pub struct X<S, OT, Z, EM, E> {}; // <- Generics are not ordered