|
| 1 | +.. _rust_coding_guidelines: |
| 2 | + |
| 3 | +Coding Guidelines |
| 4 | +================= |
| 5 | + |
| 6 | +This document describes how to write Rust code in the kernel. |
| 7 | + |
| 8 | + |
| 9 | +Style & formatting |
| 10 | +------------------ |
| 11 | + |
| 12 | +The code should be formatted using ``rustfmt``. In this way, a person |
| 13 | +contributing from time to time to the kernel does not need to learn and |
| 14 | +remember one more style guide. More importantly, reviewers and maintainers |
| 15 | +do not need to spend time pointing out style issues anymore, and thus |
| 16 | +less patch roundtrips may be needed to land a change. |
| 17 | + |
| 18 | +.. note:: Conventions on comments and documentation are not checked by |
| 19 | + ``rustfmt``. Thus those are still needed to be taken care of. |
| 20 | + |
| 21 | +The default settings of ``rustfmt`` are used. This means the idiomatic Rust |
| 22 | +style is followed. For instance, 4 spaces are used for indentation rather |
| 23 | +than tabs. |
| 24 | + |
| 25 | +It is convenient to instruct editors/IDEs to format while typing, |
| 26 | +when saving or at commit time. However, if for some reason reformatting |
| 27 | +the entire kernel Rust sources is needed at some point, the following can be |
| 28 | +run:: |
| 29 | + |
| 30 | + make LLVM=1 rustfmt |
| 31 | + |
| 32 | +It is also possible to check if everything is formatted (printing a diff |
| 33 | +otherwise), for instance for a CI, with:: |
| 34 | + |
| 35 | + make LLVM=1 rustfmtcheck |
| 36 | + |
| 37 | +Like ``clang-format`` for the rest of the kernel, ``rustfmt`` works on |
| 38 | +individual files, and does not require a kernel configuration. Sometimes it may |
| 39 | +even work with broken code. |
| 40 | + |
| 41 | + |
| 42 | +Code documentation |
| 43 | +------------------ |
| 44 | + |
| 45 | +Rust kernel code is not documented like C kernel code (i.e. via kernel-doc). |
| 46 | +Instead, the usual system for documenting Rust code is used: the ``rustdoc`` |
| 47 | +tool, which uses Markdown (a lightweight markup language). |
| 48 | + |
| 49 | +To learn Markdown, there are many guides available out there. For instance, |
| 50 | +the one at: |
| 51 | + |
| 52 | + https://commonmark.org/help/ |
| 53 | + |
| 54 | +This is how a well-documented Rust function may look like:: |
| 55 | + |
| 56 | + /// Returns the contained [`Some`] value, consuming the `self` value, |
| 57 | + /// without checking that the value is not [`None`]. |
| 58 | + /// |
| 59 | + /// # Safety |
| 60 | + /// |
| 61 | + /// Calling this method on [`None`] is *[undefined behavior]*. |
| 62 | + /// |
| 63 | + /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html |
| 64 | + /// |
| 65 | + /// # Examples |
| 66 | + /// |
| 67 | + /// ``` |
| 68 | + /// let x = Some("air"); |
| 69 | + /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); |
| 70 | + /// ``` |
| 71 | + pub unsafe fn unwrap_unchecked(self) -> T { |
| 72 | + match self { |
| 73 | + Some(val) => val, |
| 74 | + |
| 75 | + // SAFETY: the safety contract must be upheld by the caller. |
| 76 | + None => unsafe { hint::unreachable_unchecked() }, |
| 77 | + } |
| 78 | + } |
| 79 | + |
| 80 | +This example showcases a few ``rustdoc`` features and some conventions followed |
| 81 | +in the kernel: |
| 82 | + |
| 83 | + - The first paragraph must be a single sentence briefly describing what |
| 84 | + the documented item does. Further explanations must go in extra paragraphs. |
| 85 | + |
| 86 | + - Unsafe functions must document their safety preconditions under |
| 87 | + a ``# Safety`` section. |
| 88 | + |
| 89 | + - While not shown here, if a function may panic, the conditions under which |
| 90 | + that happens must be described under a ``# Panics`` section. |
| 91 | + |
| 92 | + Please note that panicking should be very rare and used only with a good |
| 93 | + reason. In almost all cases, a fallible approach should be used, typically |
| 94 | + returning a ``Result``. |
| 95 | + |
| 96 | + - If providing examples of usage would help readers, they must be written in |
| 97 | + a section called ``# Examples``. |
| 98 | + |
| 99 | + - Rust items (functions, types, constants...) must be linked appropriately |
| 100 | + (``rustdoc`` will create a link automatically). |
| 101 | + |
| 102 | + - Any ``unsafe`` block must be preceded by a ``// SAFETY:`` comment |
| 103 | + describing why the code inside is sound. |
| 104 | + |
| 105 | + While sometimes the reason might look trivial and therefore unneeded, writing |
| 106 | + these comments is not just a good way of documenting what has been taken into |
| 107 | + account, but most importantly, it provides a way to know that there are |
| 108 | + no *extra* implicit constraints. |
| 109 | + |
| 110 | +To learn more about how to write documentation for Rust and extra features, |
| 111 | +please take a look at the ``rustdoc`` `book`_. |
| 112 | + |
| 113 | +.. _book: https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html |
| 114 | + |
| 115 | + |
| 116 | +Naming |
| 117 | +------ |
| 118 | + |
| 119 | +Rust kernel code follows the usual Rust naming conventions: |
| 120 | + |
| 121 | + https://rust-lang.github.io/api-guidelines/naming.html |
| 122 | + |
| 123 | +When existing C concepts (e.g. macros, functions, objects...) are wrapped into |
| 124 | +a Rust abstraction, a name as close as reasonably possible to the C side should |
| 125 | +be used in order to avoid confusion and to improve readability when switching |
| 126 | +back and forth between the C and Rust sides. For instance, macros such as |
| 127 | +``pr_info`` from C are named the same in the Rust side. |
| 128 | + |
| 129 | +Having said that, casing should be adjusted to follow the Rust naming |
| 130 | +conventions, and namespacing introduced by modules and types should not be |
| 131 | +repeated in the item names. For instance, when wrapping constants like: |
| 132 | + |
| 133 | +.. code-block:: c |
| 134 | +
|
| 135 | + #define GPIO_LINE_DIRECTION_IN 0 |
| 136 | + #define GPIO_LINE_DIRECTION_OUT 1 |
| 137 | +
|
| 138 | +The equivalent in Rust may look like (ignoring documentation): |
| 139 | + |
| 140 | +.. code-block:: rust |
| 141 | +
|
| 142 | + pub mod gpio { |
| 143 | + pub enum LineDirection { |
| 144 | + In = bindings::GPIO_LINE_DIRECTION_IN as _, |
| 145 | + Out = bindings::GPIO_LINE_DIRECTION_OUT as _, |
| 146 | + } |
| 147 | + } |
| 148 | +
|
| 149 | +That is, the equivalent of ``GPIO_LINE_DIRECTION_IN`` would be referred to as |
| 150 | +``gpio::LineDirection::In``. In particular, it should not be named |
| 151 | +``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN``. |
0 commit comments