2019-12-09 15:41:19 +01:00
# Code style
2022-09-29 17:01:03 +02:00
This is a description of a coding style that every contributor must follow.
Please, read the whole document before you start pushing code.
2019-12-09 15:41:19 +01:00
## Generics
2022-10-03 11:48:14 +02:00
All trait bounds should be written in `where` :
2019-12-09 15:41:19 +01:00
```rust
2022-09-29 17:01:03 +02:00
// GOOD
pub fn new< N , T , P , E > (user_id: i32, name: N, title: T, png_sticker: P, emojis: E) -> Self
where
N: Into< String > ,
T: Into< String > ,
P: Into< InputFile > ,
E: Into< String > ,
{ ... }
// BAD
pub fn new< N: Into < String > ,
T: Into< String > ,
P: Into< InputFile > ,
E: Into< String > >
2019-12-09 15:41:19 +01:00
(user_id: i32, name: N, title: T, png_sticker: P, emojis: E) -> Self { ... }
```
2022-09-29 17:01:03 +02:00
```rust
// GOOD
impl< T > Trait for Wrap< T >
where
T: Trait
{ ... }
// BAD
impl< T: Trait > Trait for Wrap< T > { ... }
```
2019-12-09 15:41:19 +01:00
2022-10-03 11:48:14 +02:00
**Rationale:**
- `where` clauses are easier to read when there are a lot of bounds
- uniformity
2022-09-29 17:01:03 +02:00
## Documentation comments
2022-10-03 11:48:14 +02:00
1. Documentation must describe _what_ your code does and mustn't describe _how_ your code does it and bla-bla-bla.
2022-10-03 18:49:25 +02:00
2. Be sure that your comments follow the grammar, including punctuation, the first capital letter and so on:
2022-09-29 17:01:03 +02:00
```rust
// GOOD
/// This function makes a request to Telegram.
pub fn make_request(url: & str) -> String { ... }
// BAD
/// this function make request to telegram
pub fn make_request(url: & str) -> String { ... }
```
2022-10-03 18:49:25 +02:00
3. Do not use ending punctuation in short list items (usually containing just one phrase or sentence):
2022-09-29 17:01:03 +02:00
```md
<!-- GOOD -->
- Handle different kinds of Update
- Pass dependencies to handlers
- Disable a default Ctrl-C handling
<!-- BAD -->
- Handle different kinds of Update.
- Pass dependencies to handlers.
- Disable a default Ctrl-C handling.
<!-- BAD -->
- Handle different kinds of Update;
- Pass dependencies to handlers;
- Disable a default Ctrl-C handling;
```
2022-10-03 11:48:14 +02:00
3. Link resources in your comments when possible:
2022-09-29 17:01:03 +02:00
```rust
/// Download a file from Telegram.
///
/// `path` can be obtained from the [`Bot::get_file`].
///
/// To download into [`AsyncWrite`] (e.g. [`tokio::fs::File`]), see
/// [`Bot::download_file`].
///
/// [`Bot::get_file`]: crate::bot::Bot::get_file
/// [`AsyncWrite`]: tokio::io::AsyncWrite
/// [`tokio::fs::File`]: tokio::fs::File
/// [`Bot::download_file`]: crate::Bot::download_file
```
## Use `Self` where possible
2022-10-03 11:48:14 +02:00
When referring to the type for which block is implemented, prefer using `Self` , rather than the name of the type:
2019-12-09 15:41:19 +01:00
```rust
2022-09-29 17:01:03 +02:00
impl ErrorKind {
// GOOD
fn print(& self) {
Self::Io => println!("Io"),
Self::Network => println!("Network"),
Self::Json => println!("Json"),
}
// BAD
fn print(& self) {
ErrorKind::Io => println!("Io"),
ErrorKind::Network => println!("Network"),
ErrorKind::Json => println!("Json"),
}
}
```
```rust
impl< 'a> AnswerCallbackQuery< 'a> {
// GOOD
fn new< C > (bot: & 'a Bot, callback_query_id: C) -> Self
where
C: Into< String > ,
{ ... }
// BAD
fn new< C > (bot: & 'a Bot, callback_query_id: C) -> AnswerCallbackQuery< 'a>
2019-12-09 15:41:19 +01:00
where
2022-09-29 17:01:03 +02:00
C: Into< String > ,
{ ... }
}
2019-12-09 15:41:19 +01:00
```
2020-01-08 11:20:20 +01:00
2022-09-29 17:01:03 +02:00
**Rationale:** `Self` is generally shorter and it's easier to copy-paste code or rename the type.
2020-01-08 11:20:20 +01:00
2022-09-29 17:01:03 +02:00
## Avoid duplication in fields names
2020-01-08 11:20:20 +01:00
```rust
2022-09-29 17:01:03 +02:00
struct Message {
// GOOD
#[serde(rename = "message_id")]
id: MessageId,
// BAD
message_id: MessageId,
}
2020-01-08 11:20:20 +01:00
```
2022-10-03 11:48:14 +02:00
**Rationale:** duplication blurs the focus of code, making it unnecessarily longer.
2020-01-08 11:20:20 +01:00
2022-09-29 17:01:03 +02:00
## Conventional generic names
2020-01-08 15:46:09 +01:00
2022-09-29 17:01:03 +02:00
Use a generic parameter name `S` for streams, `Fut` for futures, `F` for functions (where possible).
2022-08-20 12:16:08 +02:00
2022-09-29 17:01:03 +02:00
**Rationale:** uniformity.
2022-08-20 12:16:08 +02:00
2022-09-29 17:01:03 +02:00
## Deriving traits
2022-08-20 12:16:08 +02:00
2022-09-29 17:01:03 +02:00
Derive `Copy` , `Clone` , `Eq` , `PartialEq` , `Hash` and `Debug` for public types when possible.
2022-08-20 12:16:08 +02:00
2022-09-29 17:01:03 +02:00
**Rationale:** these traits can be useful for users and can be implemented for most types.
2022-08-20 12:16:08 +02:00
2022-09-29 17:01:03 +02:00
Derive `Default` when there is a reasonable default value for the type.
2022-08-20 12:16:08 +02:00
2022-10-03 11:48:14 +02:00
**Rationale:** `Default` plays nicely with generic code (for example, `mem::take` ).
2020-01-24 23:29:55 +01:00
2022-09-29 17:01:03 +02:00
## `Into`-polymorphism
2020-01-24 23:29:55 +01:00
2022-09-29 17:01:03 +02:00
Use `T: Into<Ty>` when this can simplify user code.
I.e. when there are types that implement `Into<Ty>` that are likely to be passed to this function.
2020-01-08 15:46:09 +01:00
2022-09-29 17:01:03 +02:00
**Rationale:** conversions unnecessarily complicate caller code and can be confusing for beginners.
## `must_use`
2022-10-03 11:48:14 +02:00
Always mark functions as `#[must_use]` if they don't have side effects and the only reason to call them is to get the result:
2020-01-08 15:46:09 +01:00
```rust
2022-09-29 17:01:03 +02:00
impl User {
// GOOD
#[must_use]
fn full_name(& self) -> String {
format!("{} {}", user.first_name, user.last_name)
2020-01-08 15:46:09 +01:00
}
}
```
2022-09-29 17:01:03 +02:00
**Rationale:** users will get warnings if they forgot to do something with the result, potentially preventing bugs.
## Creating boxed futures
Prefer `Box::pin(async { ... })` instead of `async { ... }.boxed()` .
**Rationale:** the former is generally formatted better by rustfmt.
## Full paths for logging
Always write `log::<op>!(...)` instead of importing `use log::<op>;` and invoking `<op>!(...)` .
2020-01-08 15:46:09 +01:00
```rust
2022-09-29 17:01:03 +02:00
// GOOD
log::warn!("Everything is on fire");
2020-01-24 23:47:47 +01:00
2022-09-29 17:01:03 +02:00
// BAD
use log::warn;
2020-01-24 23:59:37 +01:00
2022-09-29 17:01:03 +02:00
warn!("Everything is on fire");
```
2020-01-24 23:59:37 +01:00
2022-10-03 11:48:14 +02:00
**Rationale:**
- Less polluted import blocks
- Uniformity
2022-09-29 17:05:31 +02:00
## `&str` -> `String` conversion
Prefer using `.to_owned()` , rather than `.to_string()` , `.into()` , `String::from` , etc.
**Rationale:** uniformity, intent clarity.
2022-09-29 17:17:16 +02:00
## Order of imports
Separate import groups with blank lines. Use one use per crate.
Module declarations come before the imports.
Order them in "suggested reading order" for a person new to the code base.
```rust
mod x;
mod y;
// First std.
use std::{ ... }
// Second, external crates (both crates.io crates and other rust-analyzer crates).
use crate_foo::{ ... }
use crate_bar::{ ... }
// Then current crate.
use crate::{}
// Finally, parent and child modules, but prefer `use crate::` .
use super::{}
// Re-exports are treated as item definitions rather than imports, so they go
// after imports and modules. Use them sparingly.
pub use crate::x::Z;
```
2022-10-03 11:48:14 +02:00
**Rationale:**
- Reading order is important for new contributors
- Grouping by crate allows spotting unwanted dependencies easier
- Consistency
2022-09-29 17:17:16 +02:00
## Import Style
When implementing traits from `std::fmt` import the module:
```rust
// GOOD
use std::fmt;
impl fmt::Display for RenameError {
fn fmt(& self, f: & mut fmt::Formatter< '_>) -> fmt::Result { .. }
}
// BAD
impl std::fmt::Display for RenameError {
fn fmt(& self, f: & mut std::fmt::Formatter< '_>) -> std::fmt::Result { .. }
}
```
2022-10-03 11:48:14 +02:00
**Rationale:**
- Makes it clear that a trait is implemented, rather than used
- Less typing
2022-09-29 17:17:16 +02:00
2022-10-03 11:48:14 +02:00
Prefer `use crate::foo::bar` to `use super::bar` or `use self::bar::baz` . **Rationale:**
- Works in all cases
- Consistency
2022-09-29 17:17:16 +02:00
## Order of Items
Optimize for the reader who sees the file for the first time, and wants to get a general idea about what's going on. People read things from top to bottom, so place most important things first.
2022-10-03 11:48:14 +02:00
Specifically, if all items except one are private, always put the non-private item on top:
2022-09-29 17:17:16 +02:00
```rust
// GOOD
pub(crate) fn frobnicate() {
Helper::act()
}
#[derive(Default)]
struct Helper { stuff: i32 }
impl Helper {
fn act(& self) {
}
}
// BAD
#[derive(Default)]
struct Helper { stuff: i32 }
pub(crate) fn frobnicate() {
Helper::act()
}
impl Helper {
fn act(& self) {
}
}
```
If there's a mixture of private and public items, put public items first.
2022-10-03 11:48:14 +02:00
Put structs and enums first, functions and impls last. Order type declarations in a top-down manner:
2022-09-29 17:17:16 +02:00
```rust
// GOOD
struct Parent {
children: Vec< Child >
}
struct Child;
impl Parent {
}
impl Child {
}
// BAD
struct Child;
impl Child {
}
struct Parent {
children: Vec< Child >
}
impl Parent {
}
```
2022-10-03 11:48:14 +02:00
**Rationale:**
- Easier to get a sense of the API by visually scanning the file
- If function bodies are folded in the editor, the source code should be read as documentation for the public API
2022-09-29 17:17:16 +02:00
## Early Returns
2022-10-03 11:48:14 +02:00
Do use early returns:
2022-09-29 17:17:16 +02:00
```rust
// GOOD
fn foo() -> Option< Bar > {
if !condition() {
return None;
}
Some(...)
}
// BAD
fn foo() -> Option< Bar > {
if condition() {
Some(...)
} else {
None
}
}
```
**Rationale:** reduce cognitive stack usage.
## If-let
2022-10-03 11:48:14 +02:00
Avoid the `if let ... { } else { }` construct, use `match` instead:
2022-09-29 17:17:16 +02:00
```rust
// GOOD
match ctx.expected_type.as_ref() {
Some(expected_type) => completion_ty == expected_type & & !expected_type.is_unit(),
None => false,
}
// BAD
if let Some(expected_type) = ctx.expected_type.as_ref() {
completion_ty == expected_type & & !expected_type.is_unit()
} else {
false
}
```
2022-10-03 11:48:14 +02:00
**Rationale:**
- `match` is almost always more compact
- The `else` branch can get a more precise pattern: `None` or `Err(_)` instead of `_`
2022-09-29 17:17:16 +02:00
## Empty Match Arms
Use `=> (),` when a match arm is intentionally empty:
```rust
// GOOD
match result {
Ok(_) => (),
Err(err) => error!("{}", err),
}
// BAD
match result {
Ok(_) => {}
Err(err) => error!("{}", err),
}
```
**Rationale:** consistency.