mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Add error handling sections to the documentation and use it to link to the existing code documentation. This will allow to extend that documentation, use intra-doc links and test the examples. Suggested-by: Miguel Ojeda <ojeda@kernel.org> Link: https://lore.kernel.org/rust-for-linux/CANiq72keOdXy0LFKk9SzYWwSjiD710v=hQO4xi+5E4xNALa6cA@mail.gmail.com/ Signed-off-by: Dirk Behme <dirk.behme@de.bosch.com> Link: https://lore.kernel.org/r/20250115062552.1970768-1-dirk.behme@de.bosch.com [ Slightly tweaked wording. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
		
			
				
	
	
		
			383 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			383 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
.. SPDX-License-Identifier: GPL-2.0
 | 
						|
 | 
						|
Coding Guidelines
 | 
						|
=================
 | 
						|
 | 
						|
This document describes how to write Rust code in the kernel.
 | 
						|
 | 
						|
 | 
						|
Style & formatting
 | 
						|
------------------
 | 
						|
 | 
						|
The code should be formatted using ``rustfmt``. In this way, a person
 | 
						|
contributing from time to time to the kernel does not need to learn and
 | 
						|
remember one more style guide. More importantly, reviewers and maintainers
 | 
						|
do not need to spend time pointing out style issues anymore, and thus
 | 
						|
less patch roundtrips may be needed to land a change.
 | 
						|
 | 
						|
.. note:: Conventions on comments and documentation are not checked by
 | 
						|
  ``rustfmt``. Thus those are still needed to be taken care of.
 | 
						|
 | 
						|
The default settings of ``rustfmt`` are used. This means the idiomatic Rust
 | 
						|
style is followed. For instance, 4 spaces are used for indentation rather
 | 
						|
than tabs.
 | 
						|
 | 
						|
It is convenient to instruct editors/IDEs to format while typing,
 | 
						|
when saving or at commit time. However, if for some reason reformatting
 | 
						|
the entire kernel Rust sources is needed at some point, the following can be
 | 
						|
run::
 | 
						|
 | 
						|
	make LLVM=1 rustfmt
 | 
						|
 | 
						|
It is also possible to check if everything is formatted (printing a diff
 | 
						|
otherwise), for instance for a CI, with::
 | 
						|
 | 
						|
	make LLVM=1 rustfmtcheck
 | 
						|
 | 
						|
Like ``clang-format`` for the rest of the kernel, ``rustfmt`` works on
 | 
						|
individual files, and does not require a kernel configuration. Sometimes it may
 | 
						|
even work with broken code.
 | 
						|
 | 
						|
 | 
						|
Comments
 | 
						|
--------
 | 
						|
 | 
						|
"Normal" comments (i.e. ``//``, rather than code documentation which starts
 | 
						|
with ``///`` or ``//!``) are written in Markdown the same way as documentation
 | 
						|
comments are, even though they will not be rendered. This improves consistency,
 | 
						|
simplifies the rules and allows to move content between the two kinds of
 | 
						|
comments more easily. For instance:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	// `object` is ready to be handled now.
 | 
						|
	f(object);
 | 
						|
 | 
						|
Furthermore, just like documentation, comments are capitalized at the beginning
 | 
						|
of a sentence and ended with a period (even if it is a single sentence). This
 | 
						|
includes ``// SAFETY:``, ``// TODO:`` and other "tagged" comments, e.g.:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	// FIXME: The error should be handled properly.
 | 
						|
 | 
						|
Comments should not be used for documentation purposes: comments are intended
 | 
						|
for implementation details, not users. This distinction is useful even if the
 | 
						|
reader of the source file is both an implementor and a user of an API. In fact,
 | 
						|
sometimes it is useful to use both comments and documentation at the same time.
 | 
						|
For instance, for a ``TODO`` list or to comment on the documentation itself.
 | 
						|
For the latter case, comments can be inserted in the middle; that is, closer to
 | 
						|
the line of documentation to be commented. For any other case, comments are
 | 
						|
written after the documentation, e.g.:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	/// Returns a new [`Foo`].
 | 
						|
	///
 | 
						|
	/// # Examples
 | 
						|
	///
 | 
						|
	// TODO: Find a better example.
 | 
						|
	/// ```
 | 
						|
	/// let foo = f(42);
 | 
						|
	/// ```
 | 
						|
	// FIXME: Use fallible approach.
 | 
						|
	pub fn f(x: i32) -> Foo {
 | 
						|
	    // ...
 | 
						|
	}
 | 
						|
 | 
						|
One special kind of comments are the ``// SAFETY:`` comments. These must appear
 | 
						|
before every ``unsafe`` block, and they explain why the code inside the block is
 | 
						|
correct/sound, i.e. why it cannot trigger undefined behavior in any case, e.g.:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	// SAFETY: `p` is valid by the safety requirements.
 | 
						|
	unsafe { *p = 0; }
 | 
						|
 | 
						|
``// SAFETY:`` comments are not to be confused with the ``# Safety`` sections
 | 
						|
in code documentation. ``# Safety`` sections specify the contract that callers
 | 
						|
(for functions) or implementors (for traits) need to abide by. ``// SAFETY:``
 | 
						|
comments show why a call (for functions) or implementation (for traits) actually
 | 
						|
respects the preconditions stated in a ``# Safety`` section or the language
 | 
						|
reference.
 | 
						|
 | 
						|
 | 
						|
Code documentation
 | 
						|
------------------
 | 
						|
 | 
						|
Rust kernel code is not documented like C kernel code (i.e. via kernel-doc).
 | 
						|
Instead, the usual system for documenting Rust code is used: the ``rustdoc``
 | 
						|
tool, which uses Markdown (a lightweight markup language).
 | 
						|
 | 
						|
To learn Markdown, there are many guides available out there. For instance,
 | 
						|
the one at:
 | 
						|
 | 
						|
	https://commonmark.org/help/
 | 
						|
 | 
						|
This is how a well-documented Rust function may look like:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	/// Returns the contained [`Some`] value, consuming the `self` value,
 | 
						|
	/// without checking that the value is not [`None`].
 | 
						|
	///
 | 
						|
	/// # Safety
 | 
						|
	///
 | 
						|
	/// Calling this method on [`None`] is *[undefined behavior]*.
 | 
						|
	///
 | 
						|
	/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
 | 
						|
	///
 | 
						|
	/// # Examples
 | 
						|
	///
 | 
						|
	/// ```
 | 
						|
	/// let x = Some("air");
 | 
						|
	/// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
 | 
						|
	/// ```
 | 
						|
	pub unsafe fn unwrap_unchecked(self) -> T {
 | 
						|
	    match self {
 | 
						|
	        Some(val) => val,
 | 
						|
 | 
						|
	        // SAFETY: The safety contract must be upheld by the caller.
 | 
						|
	        None => unsafe { hint::unreachable_unchecked() },
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
This example showcases a few ``rustdoc`` features and some conventions followed
 | 
						|
in the kernel:
 | 
						|
 | 
						|
- The first paragraph must be a single sentence briefly describing what
 | 
						|
  the documented item does. Further explanations must go in extra paragraphs.
 | 
						|
 | 
						|
- Unsafe functions must document their safety preconditions under
 | 
						|
  a ``# Safety`` section.
 | 
						|
 | 
						|
- While not shown here, if a function may panic, the conditions under which
 | 
						|
  that happens must be described under a ``# Panics`` section.
 | 
						|
 | 
						|
  Please note that panicking should be very rare and used only with a good
 | 
						|
  reason. In almost all cases, a fallible approach should be used, typically
 | 
						|
  returning a ``Result``.
 | 
						|
 | 
						|
- If providing examples of usage would help readers, they must be written in
 | 
						|
  a section called ``# Examples``.
 | 
						|
 | 
						|
- Rust items (functions, types, constants...) must be linked appropriately
 | 
						|
  (``rustdoc`` will create a link automatically).
 | 
						|
 | 
						|
- Any ``unsafe`` block must be preceded by a ``// SAFETY:`` comment
 | 
						|
  describing why the code inside is sound.
 | 
						|
 | 
						|
  While sometimes the reason might look trivial and therefore unneeded,
 | 
						|
  writing these comments is not just a good way of documenting what has been
 | 
						|
  taken into account, but most importantly, it provides a way to know that
 | 
						|
  there are no *extra* implicit constraints.
 | 
						|
 | 
						|
To learn more about how to write documentation for Rust and extra features,
 | 
						|
please take a look at the ``rustdoc`` book at:
 | 
						|
 | 
						|
	https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
 | 
						|
 | 
						|
In addition, the kernel supports creating links relative to the source tree by
 | 
						|
prefixing the link destination with ``srctree/``. For instance:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	//! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h)
 | 
						|
 | 
						|
or:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	/// [`struct mutex`]: srctree/include/linux/mutex.h
 | 
						|
 | 
						|
 | 
						|
Naming
 | 
						|
------
 | 
						|
 | 
						|
Rust kernel code follows the usual Rust naming conventions:
 | 
						|
 | 
						|
	https://rust-lang.github.io/api-guidelines/naming.html
 | 
						|
 | 
						|
When existing C concepts (e.g. macros, functions, objects...) are wrapped into
 | 
						|
a Rust abstraction, a name as close as reasonably possible to the C side should
 | 
						|
be used in order to avoid confusion and to improve readability when switching
 | 
						|
back and forth between the C and Rust sides. For instance, macros such as
 | 
						|
``pr_info`` from C are named the same in the Rust side.
 | 
						|
 | 
						|
Having said that, casing should be adjusted to follow the Rust naming
 | 
						|
conventions, and namespacing introduced by modules and types should not be
 | 
						|
repeated in the item names. For instance, when wrapping constants like:
 | 
						|
 | 
						|
.. code-block:: c
 | 
						|
 | 
						|
	#define GPIO_LINE_DIRECTION_IN	0
 | 
						|
	#define GPIO_LINE_DIRECTION_OUT	1
 | 
						|
 | 
						|
The equivalent in Rust may look like (ignoring documentation):
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	pub mod gpio {
 | 
						|
	    pub enum LineDirection {
 | 
						|
	        In = bindings::GPIO_LINE_DIRECTION_IN as _,
 | 
						|
	        Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
That is, the equivalent of ``GPIO_LINE_DIRECTION_IN`` would be referred to as
 | 
						|
``gpio::LineDirection::In``. In particular, it should not be named
 | 
						|
``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN``.
 | 
						|
 | 
						|
 | 
						|
Lints
 | 
						|
-----
 | 
						|
 | 
						|
In Rust, it is possible to ``allow`` particular warnings (diagnostics, lints)
 | 
						|
locally, making the compiler ignore instances of a given warning within a given
 | 
						|
function, module, block, etc.
 | 
						|
 | 
						|
It is similar to ``#pragma GCC diagnostic push`` + ``ignored`` + ``pop`` in C
 | 
						|
[#]_:
 | 
						|
 | 
						|
.. code-block:: c
 | 
						|
 | 
						|
	#pragma GCC diagnostic push
 | 
						|
	#pragma GCC diagnostic ignored "-Wunused-function"
 | 
						|
	static void f(void) {}
 | 
						|
	#pragma GCC diagnostic pop
 | 
						|
 | 
						|
.. [#] In this particular case, the kernel's ``__{always,maybe}_unused``
 | 
						|
       attributes (C23's ``[[maybe_unused]]``) may be used; however, the example
 | 
						|
       is meant to reflect the equivalent lint in Rust discussed afterwards.
 | 
						|
 | 
						|
But way less verbose:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	#[allow(dead_code)]
 | 
						|
	fn f() {}
 | 
						|
 | 
						|
By that virtue, it makes it possible to comfortably enable more diagnostics by
 | 
						|
default (i.e. outside ``W=`` levels). In particular, those that may have some
 | 
						|
false positives but that are otherwise quite useful to keep enabled to catch
 | 
						|
potential mistakes.
 | 
						|
 | 
						|
On top of that, Rust provides the ``expect`` attribute which takes this further.
 | 
						|
It makes the compiler warn if the warning was not produced. For instance, the
 | 
						|
following will ensure that, when ``f()`` is called somewhere, we will have to
 | 
						|
remove the attribute:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	#[expect(dead_code)]
 | 
						|
	fn f() {}
 | 
						|
 | 
						|
If we do not, we get a warning from the compiler::
 | 
						|
 | 
						|
	warning: this lint expectation is unfulfilled
 | 
						|
	 --> x.rs:3:10
 | 
						|
	  |
 | 
						|
	3 | #[expect(dead_code)]
 | 
						|
	  |          ^^^^^^^^^
 | 
						|
	  |
 | 
						|
	  = note: `#[warn(unfulfilled_lint_expectations)]` on by default
 | 
						|
 | 
						|
This means that ``expect``\ s do not get forgotten when they are not needed, which
 | 
						|
may happen in several situations, e.g.:
 | 
						|
 | 
						|
- Temporary attributes added while developing.
 | 
						|
 | 
						|
- Improvements in lints in the compiler, Clippy or custom tools which may
 | 
						|
  remove a false positive.
 | 
						|
 | 
						|
- When the lint is not needed anymore because it was expected that it would be
 | 
						|
  removed at some point, such as the ``dead_code`` example above.
 | 
						|
 | 
						|
It also increases the visibility of the remaining ``allow``\ s and reduces the
 | 
						|
chance of misapplying one.
 | 
						|
 | 
						|
Thus prefer ``expect`` over ``allow`` unless:
 | 
						|
 | 
						|
- Conditional compilation triggers the warning in some cases but not others.
 | 
						|
 | 
						|
  If there are only a few cases where the warning triggers (or does not
 | 
						|
  trigger) compared to the total number of cases, then one may consider using
 | 
						|
  a conditional ``expect`` (i.e. ``cfg_attr(..., expect(...))``). Otherwise,
 | 
						|
  it is likely simpler to just use ``allow``.
 | 
						|
 | 
						|
- Inside macros, when the different invocations may create expanded code that
 | 
						|
  triggers the warning in some cases but not in others.
 | 
						|
 | 
						|
- When code may trigger a warning for some architectures but not others, such
 | 
						|
  as an ``as`` cast to a C FFI type.
 | 
						|
 | 
						|
As a more developed example, consider for instance this program:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	fn g() {}
 | 
						|
 | 
						|
	fn main() {
 | 
						|
	    #[cfg(CONFIG_X)]
 | 
						|
	    g();
 | 
						|
	}
 | 
						|
 | 
						|
Here, function ``g()`` is dead code if ``CONFIG_X`` is not set. Can we use
 | 
						|
``expect`` here?
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	#[expect(dead_code)]
 | 
						|
	fn g() {}
 | 
						|
 | 
						|
	fn main() {
 | 
						|
	    #[cfg(CONFIG_X)]
 | 
						|
	    g();
 | 
						|
	}
 | 
						|
 | 
						|
This would emit a lint if ``CONFIG_X`` is set, since it is not dead code in that
 | 
						|
configuration. Therefore, in cases like this, we cannot use ``expect`` as-is.
 | 
						|
 | 
						|
A simple possibility is using ``allow``:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	#[allow(dead_code)]
 | 
						|
	fn g() {}
 | 
						|
 | 
						|
	fn main() {
 | 
						|
	    #[cfg(CONFIG_X)]
 | 
						|
	    g();
 | 
						|
	}
 | 
						|
 | 
						|
An alternative would be using a conditional ``expect``:
 | 
						|
 | 
						|
.. code-block:: rust
 | 
						|
 | 
						|
	#[cfg_attr(not(CONFIG_X), expect(dead_code))]
 | 
						|
	fn g() {}
 | 
						|
 | 
						|
	fn main() {
 | 
						|
	    #[cfg(CONFIG_X)]
 | 
						|
	    g();
 | 
						|
	}
 | 
						|
 | 
						|
This would ensure that, if someone introduces another call to ``g()`` somewhere
 | 
						|
(e.g. unconditionally), then it would be spotted that it is not dead code
 | 
						|
anymore. However, the ``cfg_attr`` is more complex than a simple ``allow``.
 | 
						|
 | 
						|
Therefore, it is likely that it is not worth using conditional ``expect``\ s when
 | 
						|
more than one or two configurations are involved or when the lint may be
 | 
						|
triggered due to non-local changes (such as ``dead_code``).
 | 
						|
 | 
						|
For more information about diagnostics in Rust, please see:
 | 
						|
 | 
						|
	https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html
 | 
						|
 | 
						|
Error handling
 | 
						|
--------------
 | 
						|
 | 
						|
For some background and guidelines about Rust for Linux specific error handling,
 | 
						|
please see:
 | 
						|
 | 
						|
	https://rust.docs.kernel.org/kernel/error/type.Result.html#error-codes-in-c-and-rust
 |