~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/translations/zh_CN/rust/coding-guidelines.rst

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 .. SPDX-License-Identifier: GPL-2.0
  2 .. include:: ../disclaimer-zh_CN.rst
  3 
  4 :Original: Documentation/rust/coding-guidelines.rst
  5 
  6 :翻译:
  7 
  8  司延腾 Yanteng Si <siyanteng@loongson.cn>
  9 
 10 编码指南
 11 ========
 12 
 13 本文档描述了如何在内核中编写Rust代码。
 14 
 15 
 16 风格和格式化
 17 ------------
 18 
 19 代码应该使用 ``rustfmt`` 进行格式化。这样一来,一个不时为内核做贡献的人就不需要再去学
 20 习和记忆一个样式指南了。更重要的是,审阅者和维护者不需要再花时间指出风格问题,这样就可以
 21 减少补丁落地所需的邮件往返。
 22 
 23 .. note::  ``rustfmt`` 不检查注释和文档的约定。因此,这些仍然需要照顾到。
 24 
 25 使用 ``rustfmt`` 的默认设置。这意味着遵循Rust的习惯性风格。例如,缩进时使用4个空格而
 26 不是制表符。
 27 
 28 在输入、保存或提交时告知编辑器/IDE进行格式化是很方便的。然而,如果因为某些原因需要在某
 29 个时候重新格式化整个内核Rust的源代码,可以运行以下程序::
 30 
 31         make LLVM=1 rustfmt
 32 
 33 也可以检查所有的东西是否都是格式化的(否则就打印一个差异),例如对于一个CI,用::
 34 
 35         make LLVM=1 rustfmtcheck
 36 
 37 像内核其他部分的 ``clang-format`` 一样, ``rustfmt`` 在单个文件上工作,并且不需要
 38 内核配置。有时,它甚至可以与破碎的代码一起工作。
 39 
 40 
 41 注释
 42 ----
 43 
 44 “普通”注释(即以 ``//`` 开头,而不是 ``///`` 或 ``//!`` 开头的代码文档)的写法与文
 45 档注释相同,使用Markdown语法,尽管它们不会被渲染。这提高了一致性,简化了规则,并允许在
 46 这两种注释之间更容易地移动内容。比如说:
 47 
 48 .. code-block:: rust
 49 
 50         // `object` is ready to be handled now.
 51         f(object);
 52 
 53 此外,就像文档一样,注释在句子的开头要大写,并以句号结束(即使是单句)。这包括 ``// SAFETY:``,
 54 ``// TODO:`` 和其他“标记”的注释,例如:
 55 
 56 .. code-block:: rust
 57 
 58         // FIXME: The error should be handled properly.
 59 
 60 注释不应该被用于文档的目的:注释是为了实现细节,而不是为了用户。即使源文件的读者既是API
 61 的实现者又是用户,这种区分也是有用的。事实上,有时同时使用注释和文档是很有用的。例如,用
 62 于 ``TODO`` 列表或对文档本身的注释。对于后一种情况,注释可以插在中间;也就是说,离要注
 63 释的文档行更近。对于其他情况,注释会写在文档之后,例如:
 64 
 65 .. code-block:: rust
 66 
 67         /// Returns a new [`Foo`].
 68         ///
 69         /// # Examples
 70         ///
 71         // TODO: Find a better example.
 72         /// ```
 73         /// let foo = f(42);
 74         /// ```
 75         // FIXME: Use fallible approach.
 76         pub fn f(x: i32) -> Foo {
 77             // ...
 78         }
 79 
 80 一种特殊的注释是 ``// SAFETY:`` 注释。这些注释必须出现在每个 ``unsafe`` 块之前,它们
 81 解释了为什么该块内的代码是正确/健全的,即为什么它在任何情况下都不会触发未定义行为,例如:
 82 
 83 .. code-block:: rust
 84 
 85         // SAFETY: `p` is valid by the safety requirements.
 86         unsafe { *p = 0; }
 87 
 88 ``// SAFETY:`` 注释不能与代码文档中的 ``# Safety`` 部分相混淆。 ``# Safety`` 部
 89 分指定了(函数)调用者或(特性)实现者需要遵守的契约。
 90 ``// SAFETY:`` 注释显示了为什么一个(函数)调用者或(特性)实现者实际上尊重了
 91 ``# Safety`` 部分或语言参考中的前提条件。
 92 
 93 
 94 代码文档
 95 --------
 96 
 97 Rust内核代码不像C内核代码那样被记录下来(即通过kernel-doc)。取而代之的是用于记录Rust
 98 代码的常用系统:rustdoc工具,它使用Markdown(一种轻量级的标记语言)。
 99 
100 要学习Markdown,外面有很多指南。例如:
101 
102 https://commonmark.org/help/
103 
104 一个记录良好的Rust函数可能是这样的:
105 
106 .. code-block:: rust
107 
108         /// Returns the contained [`Some`] value, consuming the `self` value,
109         /// without checking that the value is not [`None`].
110         ///
111         /// # Safety
112         ///
113         /// Calling this method on [`None`] is *[undefined behavior]*.
114         ///
115         /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
116         ///
117         /// # Examples
118         ///
119         /// ```
120         /// let x = Some("air");
121         /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
122         /// ```
123         pub unsafe fn unwrap_unchecked(self) -> T {
124             match self {
125                 Some(val) => val,
126 
127                 // SAFETY: The safety contract must be upheld by the caller.
128                 None => unsafe { hint::unreachable_unchecked() },
129             }
130         }
131 
132 这个例子展示了一些 ``rustdoc`` 的特性和内核中遵循的一些惯例:
133 
134   - 第一段必须是一个简单的句子,简要地描述被记录的项目的作用。进一步的解释必须放在额
135     外的段落中。
136 
137   - 不安全的函数必须在 ``# Safety`` 部分记录其安全前提条件。
138 
139   - 虽然这里没有显示,但如果一个函数可能会恐慌,那么必须在 ``# Panics`` 部分描述发
140     生这种情况的条件。
141 
142     请注意,恐慌应该是非常少见的,只有在有充分理由的情况下才会使用。几乎在所有的情况下,
143     都应该使用一个可失败的方法,通常是返回一个 ``Result``。
144 
145   - 如果提供使用实例对读者有帮助的话,必须写在一个叫做``# Examples``的部分。
146 
147   - Rust项目(函数、类型、常量……)必须有适当的链接(``rustdoc`` 会自动创建一个
148     链接)。
149 
150   - 任何 ``unsafe`` 的代码块都必须在前面加上一个 ``// SAFETY:`` 的注释,描述里面
151     的代码为什么是正确的。
152 
153     虽然有时原因可能看起来微不足道,但写这些注释不仅是记录已经考虑到的问题的好方法,
154     最重要的是,它提供了一种知道没有额外隐含约束的方法。
155 
156 要了解更多关于如何编写Rust和拓展功能的文档,请看看 ``rustdoc`` 这本书,网址是:
157 
158         https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
159 
160 此外,内核支持通过在链接目标前添加 ``srctree/`` 来创建相对于源代码树的链接。例如:
161 
162 .. code-block:: rust
163 
164        //! C header: [`include/linux/printk.h`](srctree/include/linux/printk.h)
165 
166 或者:
167 
168 .. code-block:: rust
169 
170        /// [`struct mutex`]: srctree/include/linux/mutex.h
171 
172 
173 命名
174 ----
175 
176 Rust内核代码遵循通常的Rust命名空间:
177 
178         https://rust-lang.github.io/api-guidelines/naming.html
179 
180 当现有的C语言概念(如宏、函数、对象......)被包装成Rust抽象时,应该使用尽可能接近C语
181 言的名称,以避免混淆,并在C语言和Rust语言之间来回切换时提高可读性。例如,C语言中的
182 ``pr_info`` 这样的宏在Rust中的命名是一样的。
183 
184 说到这里,应该调整大小写以遵循Rust的命名惯例,模块和类型引入的命名间隔不应该在项目名称
185 中重复。例如,在包装常量时,如:
186 
187 .. code-block:: c
188 
189         #define GPIO_LINE_DIRECTION_IN  0
190         #define GPIO_LINE_DIRECTION_OUT 1
191 
192 在Rust中的等价物可能是这样的(忽略文档)。:
193 
194 .. code-block:: rust
195 
196         pub mod gpio {
197             pub enum LineDirection {
198                 In = bindings::GPIO_LINE_DIRECTION_IN as _,
199                 Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
200             }
201         }
202 
203 也就是说, ``GPIO_LINE_DIRECTION_IN`` 的等价物将被称为 ``gpio::LineDirection::In`` 。
204 特别是,它不应该被命名为 ``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN`` 。

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php