coding-guidelines.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. .. SPDX-License-Identifier: GPL-2.0
  2. Coding Guidelines
  3. =================
  4. This document describes how to write Rust code in the kernel.
  5. Style & formatting
  6. ------------------
  7. The code should be formatted using ``rustfmt``. In this way, a person
  8. contributing from time to time to the kernel does not need to learn and
  9. remember one more style guide. More importantly, reviewers and maintainers
  10. do not need to spend time pointing out style issues anymore, and thus
  11. less patch roundtrips may be needed to land a change.
  12. .. note:: Conventions on comments and documentation are not checked by
  13. ``rustfmt``. Thus those are still needed to be taken care of.
  14. The default settings of ``rustfmt`` are used. This means the idiomatic Rust
  15. style is followed. For instance, 4 spaces are used for indentation rather
  16. than tabs.
  17. It is convenient to instruct editors/IDEs to format while typing,
  18. when saving or at commit time. However, if for some reason reformatting
  19. the entire kernel Rust sources is needed at some point, the following can be
  20. run::
  21. make LLVM=1 rustfmt
  22. It is also possible to check if everything is formatted (printing a diff
  23. otherwise), for instance for a CI, with::
  24. make LLVM=1 rustfmtcheck
  25. Like ``clang-format`` for the rest of the kernel, ``rustfmt`` works on
  26. individual files, and does not require a kernel configuration. Sometimes it may
  27. even work with broken code.
  28. Comments
  29. --------
  30. "Normal" comments (i.e. ``//``, rather than code documentation which starts
  31. with ``///`` or ``//!``) are written in Markdown the same way as documentation
  32. comments are, even though they will not be rendered. This improves consistency,
  33. simplifies the rules and allows to move content between the two kinds of
  34. comments more easily. For instance:
  35. .. code-block:: rust
  36. // `object` is ready to be handled now.
  37. f(object);
  38. Furthermore, just like documentation, comments are capitalized at the beginning
  39. of a sentence and ended with a period (even if it is a single sentence). This
  40. includes ``// SAFETY:``, ``// TODO:`` and other "tagged" comments, e.g.:
  41. .. code-block:: rust
  42. // FIXME: The error should be handled properly.
  43. Comments should not be used for documentation purposes: comments are intended
  44. for implementation details, not users. This distinction is useful even if the
  45. reader of the source file is both an implementor and a user of an API. In fact,
  46. sometimes it is useful to use both comments and documentation at the same time.
  47. For instance, for a ``TODO`` list or to comment on the documentation itself.
  48. For the latter case, comments can be inserted in the middle; that is, closer to
  49. the line of documentation to be commented. For any other case, comments are
  50. written after the documentation, e.g.:
  51. .. code-block:: rust
  52. /// Returns a new [`Foo`].
  53. ///
  54. /// # Examples
  55. ///
  56. // TODO: Find a better example.
  57. /// ```
  58. /// let foo = f(42);
  59. /// ```
  60. // FIXME: Use fallible approach.
  61. pub fn f(x: i32) -> Foo {
  62. // ...
  63. }
  64. One special kind of comments are the ``// SAFETY:`` comments. These must appear
  65. before every ``unsafe`` block, and they explain why the code inside the block is
  66. correct/sound, i.e. why it cannot trigger undefined behavior in any case, e.g.:
  67. .. code-block:: rust
  68. // SAFETY: `p` is valid by the safety requirements.
  69. unsafe { *p = 0; }
  70. ``// SAFETY:`` comments are not to be confused with the ``# Safety`` sections
  71. in code documentation. ``# Safety`` sections specify the contract that callers
  72. (for functions) or implementors (for traits) need to abide by. ``// SAFETY:``
  73. comments show why a call (for functions) or implementation (for traits) actually
  74. respects the preconditions stated in a ``# Safety`` section or the language
  75. reference.
  76. Code documentation
  77. ------------------
  78. Rust kernel code is not documented like C kernel code (i.e. via kernel-doc).
  79. Instead, the usual system for documenting Rust code is used: the ``rustdoc``
  80. tool, which uses Markdown (a lightweight markup language).
  81. To learn Markdown, there are many guides available out there. For instance,
  82. the one at:
  83. https://commonmark.org/help/
  84. This is how a well-documented Rust function may look like:
  85. .. code-block:: rust
  86. /// Returns the contained [`Some`] value, consuming the `self` value,
  87. /// without checking that the value is not [`None`].
  88. ///
  89. /// # Safety
  90. ///
  91. /// Calling this method on [`None`] is *[undefined behavior]*.
  92. ///
  93. /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
  94. ///
  95. /// # Examples
  96. ///
  97. /// ```
  98. /// let x = Some("air");
  99. /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
  100. /// ```
  101. pub unsafe fn unwrap_unchecked(self) -> T {
  102. match self {
  103. Some(val) => val,
  104. // SAFETY: The safety contract must be upheld by the caller.
  105. None => unsafe { hint::unreachable_unchecked() },
  106. }
  107. }
  108. This example showcases a few ``rustdoc`` features and some conventions followed
  109. in the kernel:
  110. - The first paragraph must be a single sentence briefly describing what
  111. the documented item does. Further explanations must go in extra paragraphs.
  112. - Unsafe functions must document their safety preconditions under
  113. a ``# Safety`` section.
  114. - While not shown here, if a function may panic, the conditions under which
  115. that happens must be described under a ``# Panics`` section.
  116. Please note that panicking should be very rare and used only with a good
  117. reason. In almost all cases, a fallible approach should be used, typically
  118. returning a ``Result``.
  119. - If providing examples of usage would help readers, they must be written in
  120. a section called ``# Examples``.
  121. - Rust items (functions, types, constants...) must be linked appropriately
  122. (``rustdoc`` will create a link automatically).
  123. - Any ``unsafe`` block must be preceded by a ``// SAFETY:`` comment
  124. describing why the code inside is sound.
  125. While sometimes the reason might look trivial and therefore unneeded,
  126. writing these comments is not just a good way of documenting what has been
  127. taken into account, but most importantly, it provides a way to know that
  128. there are no *extra* implicit constraints.
  129. To learn more about how to write documentation for Rust and extra features,
  130. please take a look at the ``rustdoc`` book at:
  131. https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
  132. In addition, the kernel supports creating links relative to the source tree by
  133. prefixing the link destination with ``srctree/``. For instance:
  134. .. code-block:: rust
  135. //! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h)
  136. or:
  137. .. code-block:: rust
  138. /// [`struct mutex`]: srctree/include/linux/mutex.h
  139. Naming
  140. ------
  141. Rust kernel code follows the usual Rust naming conventions:
  142. https://rust-lang.github.io/api-guidelines/naming.html
  143. When existing C concepts (e.g. macros, functions, objects...) are wrapped into
  144. a Rust abstraction, a name as close as reasonably possible to the C side should
  145. be used in order to avoid confusion and to improve readability when switching
  146. back and forth between the C and Rust sides. For instance, macros such as
  147. ``pr_info`` from C are named the same in the Rust side.
  148. Having said that, casing should be adjusted to follow the Rust naming
  149. conventions, and namespacing introduced by modules and types should not be
  150. repeated in the item names. For instance, when wrapping constants like:
  151. .. code-block:: c
  152. #define GPIO_LINE_DIRECTION_IN 0
  153. #define GPIO_LINE_DIRECTION_OUT 1
  154. The equivalent in Rust may look like (ignoring documentation):
  155. .. code-block:: rust
  156. pub mod gpio {
  157. pub enum LineDirection {
  158. In = bindings::GPIO_LINE_DIRECTION_IN as _,
  159. Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
  160. }
  161. }
  162. That is, the equivalent of ``GPIO_LINE_DIRECTION_IN`` would be referred to as
  163. ``gpio::LineDirection::In``. In particular, it should not be named
  164. ``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN``.
  165. Lints
  166. -----
  167. In Rust, it is possible to ``allow`` particular warnings (diagnostics, lints)
  168. locally, making the compiler ignore instances of a given warning within a given
  169. function, module, block, etc.
  170. It is similar to ``#pragma GCC diagnostic push`` + ``ignored`` + ``pop`` in C
  171. [#]_:
  172. .. code-block:: c
  173. #pragma GCC diagnostic push
  174. #pragma GCC diagnostic ignored "-Wunused-function"
  175. static void f(void) {}
  176. #pragma GCC diagnostic pop
  177. .. [#] In this particular case, the kernel's ``__{always,maybe}_unused``
  178. attributes (C23's ``[[maybe_unused]]``) may be used; however, the example
  179. is meant to reflect the equivalent lint in Rust discussed afterwards.
  180. But way less verbose:
  181. .. code-block:: rust
  182. #[allow(dead_code)]
  183. fn f() {}
  184. By that virtue, it makes it possible to comfortably enable more diagnostics by
  185. default (i.e. outside ``W=`` levels). In particular, those that may have some
  186. false positives but that are otherwise quite useful to keep enabled to catch
  187. potential mistakes.
  188. On top of that, Rust provides the ``expect`` attribute which takes this further.
  189. It makes the compiler warn if the warning was not produced. For instance, the
  190. following will ensure that, when ``f()`` is called somewhere, we will have to
  191. remove the attribute:
  192. .. code-block:: rust
  193. #[expect(dead_code)]
  194. fn f() {}
  195. If we do not, we get a warning from the compiler::
  196. warning: this lint expectation is unfulfilled
  197. --> x.rs:3:10
  198. |
  199. 3 | #[expect(dead_code)]
  200. | ^^^^^^^^^
  201. |
  202. = note: `#[warn(unfulfilled_lint_expectations)]` on by default
  203. This means that ``expect``\ s do not get forgotten when they are not needed, which
  204. may happen in several situations, e.g.:
  205. - Temporary attributes added while developing.
  206. - Improvements in lints in the compiler, Clippy or custom tools which may
  207. remove a false positive.
  208. - When the lint is not needed anymore because it was expected that it would be
  209. removed at some point, such as the ``dead_code`` example above.
  210. It also increases the visibility of the remaining ``allow``\ s and reduces the
  211. chance of misapplying one.
  212. Thus prefer ``expect`` over ``allow`` unless:
  213. - Conditional compilation triggers the warning in some cases but not others.
  214. If there are only a few cases where the warning triggers (or does not
  215. trigger) compared to the total number of cases, then one may consider using
  216. a conditional ``expect`` (i.e. ``cfg_attr(..., expect(...))``). Otherwise,
  217. it is likely simpler to just use ``allow``.
  218. - Inside macros, when the different invocations may create expanded code that
  219. triggers the warning in some cases but not in others.
  220. - When code may trigger a warning for some architectures but not others, such
  221. as an ``as`` cast to a C FFI type.
  222. As a more developed example, consider for instance this program:
  223. .. code-block:: rust
  224. fn g() {}
  225. fn main() {
  226. #[cfg(CONFIG_X)]
  227. g();
  228. }
  229. Here, function ``g()`` is dead code if ``CONFIG_X`` is not set. Can we use
  230. ``expect`` here?
  231. .. code-block:: rust
  232. #[expect(dead_code)]
  233. fn g() {}
  234. fn main() {
  235. #[cfg(CONFIG_X)]
  236. g();
  237. }
  238. This would emit a lint if ``CONFIG_X`` is set, since it is not dead code in that
  239. configuration. Therefore, in cases like this, we cannot use ``expect`` as-is.
  240. A simple possibility is using ``allow``:
  241. .. code-block:: rust
  242. #[allow(dead_code)]
  243. fn g() {}
  244. fn main() {
  245. #[cfg(CONFIG_X)]
  246. g();
  247. }
  248. An alternative would be using a conditional ``expect``:
  249. .. code-block:: rust
  250. #[cfg_attr(not(CONFIG_X), expect(dead_code))]
  251. fn g() {}
  252. fn main() {
  253. #[cfg(CONFIG_X)]
  254. g();
  255. }
  256. This would ensure that, if someone introduces another call to ``g()`` somewhere
  257. (e.g. unconditionally), then it would be spotted that it is not dead code
  258. anymore. However, the ``cfg_attr`` is more complex than a simple ``allow``.
  259. Therefore, it is likely that it is not worth using conditional ``expect``\ s when
  260. more than one or two configurations are involved or when the lint may be
  261. triggered due to non-local changes (such as ``dead_code``).
  262. For more information about diagnostics in Rust, please see:
  263. https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html