├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── book.toml
├── language.js
└── src
├── README.md
├── SUMMARY.md
├── advice.md
├── cargo.md
├── expressions.md
├── items.md
├── nightly.md
├── principles.md
├── statements.md
└── types.md
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | test:
6 | name: Test
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@main
10 | - name: Update rustup
11 | run: rustup self update
12 | - name: Install Rust
13 | run: |
14 | rustup set profile minimal
15 | rustup toolchain install nightly -c rust-docs
16 | rustup default nightly
17 | - name: Install mdbook
18 | run: |
19 | mkdir bin
20 | curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.15/mdbook-v0.4.15-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin
21 | echo "$(pwd)/bin" >> ${GITHUB_PATH}
22 | echo "$(pwd)/bin" >> $GITHUB_PATH
23 | - name: Report versions
24 | run: |
25 | rustup --version
26 | rustc -Vv
27 | mdbook --version
28 | - name: Run tests
29 | run: mdbook test
30 | - name: Build HTML
31 | run: mdbook build
32 |
33 | deploy:
34 | if: ${{ github.ref == 'refs/heads/main' }}
35 | name: Deploy
36 | runs-on: ubuntu-latest
37 | needs: test
38 | steps:
39 | - name: Deploy to server
40 | uses: appleboy/ssh-action@master
41 | with:
42 | host: ${{ secrets.SSH_HOST }}
43 | username: ${{ secrets.SSH_USERNAME }}
44 | key: ${{ secrets.SSH_KEY }}
45 | port: ${{ secrets.SSH_PORT }}
46 | script: |
47 | ./tools/rust-deploy/update-cn.sh >/dev/null 2>&1
48 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | book
2 |
--------------------------------------------------------------------------------
/LICENSE-APACHE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Rust 中文翻译项目组
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Rust 语言风格指南
2 |
3 | 
4 | [](https://raw.githubusercontent.com/rust-lang-cn/style-guide-cn/master/LICENSE-MIT)
5 | [](https://raw.githubusercontent.com/rust-lang-cn/style-guide-cn/master/LICENSE-APACHE)
6 | [](https://github.com/rust-lang-cn/style-guide-cn/commits/master)
7 | [](https://github.com/rust-lang-cn/style-guide-cn/graphs/contributors)
8 | 
9 | [](https://rustwiki.org)
10 |
11 | > The Chinese Translation of [The Rust Style Guide][style-guide-en]
12 | >
13 | > - 首次于 2023-07-31 翻译完全部内容,欢迎纠正——最后更新时间 2023-07-31。
14 | > - 期待更多朋友加入 [Rust 中文翻译项目组](https://github.com/rust-lang-cn),协助我们,一起更新完善中文版,感激不尽!
15 |
16 | 这是《Rust 语言风格指南》中文版,翻译自 [Rust 源码中的《The Rust Style Guide》][style-guide-src]。
17 |
18 | 在线版可在本组织官网上阅读,包括[全球站点][style-guide-cn]或[国内站点][style-guide-cn-zh](**均支持同一页面中英双语切换**),或者在 Rust 官网上[阅读英文版][style-guide-en]。
19 |
20 | [style-guide-src]: https://github.com/rust-lang/rust/tree/master/src/doc/style-guide
21 | [style-guide-cn]: https://rustwiki.org/zh-CN/style-guide/
22 | [style-guide-cn-zh]: https://www.rustwiki.org.cn/zh-CN/style-guide/
23 | [style-guide-en]: https://doc.rust-lang.org/style-guide/
24 |
25 | ## 构建
26 |
27 | 构建之前请先安装 `mdBook` 工具。
28 |
29 | 从 GitHub 下载仓库并构建:
30 |
31 | ```sh
32 | $ git clone https://github.com/rust-lang-cn/style-guide-cn.git
33 | $ cd style-guide-cn
34 | $ mdbook serve
35 | ```
36 |
37 | 然后就可以在浏览器上访问 `http://localhost:3000` 来查看文档内容了。
38 |
39 | 要生成本地图书,使用以下命令:
40 |
41 | ```sh
42 | $ mdbook build
43 | ```
44 |
45 | 即可在当前仓库目录下生存一个 `book` 子目录,可找到相应的 HTML 文件。
46 |
47 | ## 许可协议
48 |
49 | 《Rust 语言风格指南》(中文版与英文版 *The Rust Style Guide* 均) 使用以下两种协议的任一种进行授权:
50 |
51 | - Apache 2.0 授权协议,([LICENSE-APACHE](LICENSE-APACHE) 或 http://www.apache.org/licenses/LICENSE-2.0)
52 | - MIT 授权协议 ([LICENSE-MIT](LICENSE-MIT) 或 http://opensource.org/licenses/MIT)
53 |
54 | 可以根据自己选择来定。
55 |
56 | 除非您有另外说明,否则您在本仓库提交的任何贡献均按上述方式进行双重许可授权,就如 Apache 2.0 协议所规定那样,而无需附加任何其他条款或条件。
57 |
--------------------------------------------------------------------------------
/book.toml:
--------------------------------------------------------------------------------
1 | [book]
2 | title = "Rust 语言风格指南 中文版"
3 | author = "The Rust Style Team"
4 | translator = "Rust 中文翻译项目组,Rust 中文社区"
5 | multilingual = false
6 | language = "zh-CN"
7 | src = "src"
8 |
9 | [output.html]
10 | additional-js = ["language.js"]
11 | git-repository-url = "https://github.com/rust-lang-cn/style-guide-cn"
12 | edit-url-template = "https://github.com/rust-lang-cn/style-guide-cn/edit/main/{path}"
13 |
--------------------------------------------------------------------------------
/language.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | var url = window.location.href;
3 | var host = window.location.host;
4 | var home_url = window.location.protocol + '//' + window.location.host;
5 |
6 | var search = {
7 | en: "/en/",
8 | zh_CN: "/zh-CN/"
9 | }
10 |
11 | var replaceWith = {
12 | en: "/zh-CN/",
13 | zh_CN: "/en/"
14 | }
15 |
16 | var link = "";
17 | var word = "";
18 | var home = "Home";
19 | var lang = "zh-CN";
20 | var changeLang = "切换到英语";
21 |
22 | if (url.indexOf(search.en) != -1 && url.indexOf(search.en) === (url.indexOf(host) + host.length)) {
23 | link = url.replace(search.en, replaceWith.en);
24 | word = "简体中文";
25 | lang = "en";
26 | changeLang = "Switch to Chinese"
27 | } else if (url.indexOf(search.zh_CN) != -1 && url.indexOf(search.zh_CN) === (url.indexOf(host) + host.length)) {
28 | link = url.replace(search.zh_CN, replaceWith.zh_CN);
29 | word = "English";
30 | home = "首页";
31 | }
32 |
33 | var edit_id = document.getElementById("git-edit-button");
34 | if (edit_id != null && edit_id.parentNode != null) {
35 | edit_id.parentNode.target = "_blank";
36 | if (lang != "en") {
37 | edit_id.parentNode.title = "报告错误或改进本页翻译";
38 | }
39 | }
40 |
41 | var home_node = '';
42 | if (window.location.protocol == 'http:' || window.location.protocol == 'https:') {
43 | home_node = '';
44 | }
45 | var lang_node = '';
46 | if (link != '') {
47 | lang_node = ' ' + word + '';
48 | }
49 | var insertNode = document.getElementsByClassName('right-buttons');
50 | if (insertNode.length > 0) {
51 | var html = insertNode[0].innerHTML;
52 | insertNode[0].innerHTML = home_node + html + lang_node;
53 | }
54 | })()
55 |
--------------------------------------------------------------------------------
/src/README.md:
--------------------------------------------------------------------------------
1 | # Rust 语言风格指南
2 |
3 | ## 动机——为什么要使用格式化工具?
4 |
5 | 格式化代码是一项耗时耗力的机械性工作。如果使用自动格式化工具,开发者就可以从这项工作中解脱出来,专注于更重要的事情。
6 |
7 | 此外,通过坚持使用既定的风格指南(如本指南),开发者无需制定特别的风格规则,也无需与其他开发者争论应使用何种样式规则,从而节省了时间、沟通成本和精神耗损。
8 |
9 | 人类通过模式匹配来理解信息。通过确保所有 Rust 代码具有相似的格式,就能减少理解新项目所需的脑力劳动,从而降低新开发人员的入门门槛。
10 |
11 | 因此,使用格式化工具(如 `rustfmt`)可以提高工作效率,而使用社区一致的格式规约(通常是使用格式化工具的默认设置)则会带来更大的好处。
12 |
13 | ## 默认 Rust 风格
14 |
15 | 《Rust 语言风格指南》定义了默认 Rust 风格,并**建议**开发者和工具遵循默认 Rust 样式。`rustfmt` 等工具使用此风格指南作为默认风格的参考。本风格指南中的所有内容,无论是否使用“必须”等语言或“插入空格......”或“在......后换行”等命令式语气,都是指默认样式。
16 |
17 | 这不应被解释为禁止开发人员遵循非默认样式,或禁止工具添加任何特定的配置选项。
18 |
19 | ## 格式约定
20 |
21 | ### 缩进和行宽
22 |
23 | - 使用空格,而不是制表符。
24 | - 每级缩进必须是 4 个空格(也就是说,字符串字面量和注释之外的所有缩进空格数都必须是 4 的倍数)。
25 | - 一行的最大宽度为 100 个字符。
26 |
27 | #### 块缩进
28 |
29 | 与视觉化缩进(visual indent)相比,更倾向于分块缩进:
30 |
31 | ```rust,ignore
32 | // 块缩进
33 | a_function_call(
34 | foo,
35 | bar,
36 | );
37 |
38 | // 视觉化缩进
39 | a_function_call(foo,
40 | bar);
41 | ```
42 |
43 | 这样做的差异就会变小(例如,在上例中重命名了`a_function_call`),向右移动的情况也会减少。
44 |
45 | ### 尾逗号
46 |
47 | 在任何类型的逗号分隔列表中,如果后面有换行符,请使用尾逗号:
48 |
49 | ```rust,ignore
50 | function_call(
51 | argument,
52 | another_argument,
53 | );
54 |
55 | let array = [
56 | element,
57 | another_element,
58 | yet_another_element,
59 | ];
60 | ```
61 |
62 | 这使得移动代码(例如通过复制和粘贴)变得更容易,并使差异更小,因为添加或删除项目不需要修改另一行来添加或删除逗号。
63 |
64 | ### 空行
65 |
66 | 不用空行或一个空行(即 1 或 2 个换行符)分隔程序项和语句。例如:
67 |
68 | ```rust,ignore
69 | fn foo() {
70 | let x = ...;
71 |
72 | let y = ...;
73 | let z = ...;
74 | }
75 |
76 | fn bar() {}
77 | fn baz() {}
78 | ```
79 |
80 | ### [模块级别的程序序项](items.md)
81 | ### [语句](statements.md)
82 | ### [表达式](expressions.md)
83 | ### [类型](types.md)
84 |
85 | ### 注释
86 |
87 | 以下关于注释的指导原则仅为建议,机器格式化工具可能会跳过注释格式化。
88 |
89 | 行注释 (`//`) 优先于块注释 (`/* ... */`)。
90 |
91 | 使用行注释时,在开头符号后留一个空格。
92 |
93 | 使用单行块注释时,在开头符号后和结尾符号前各留一个空格。对于多行块注释,在开头符号后加一个换行符,在结尾符号前加一个换行符。
94 |
95 | 注释最好独立成行。如果注释紧跟代码,则在注释前空格一个。如果块注释出现在行内,则使用周围的空格,就像使用标识符或关键字一样。不要在注释后或多行注释中任何一行的末尾使用拖尾空格。例如:
96 |
97 | ```rust,ignore
98 | // 程序项中的注释。
99 | struct Foo { ... }
100 |
101 | fn foo() {} // 在一个项后的注释。
102 |
103 | pub fn foo(/* 在参数前的注释 */ x: T) {...}
104 | ```
105 |
106 | 注释通常应是完整的句子。英文的注释开头用大写字母,结尾用句点(`.`)(译注:若是使用中文注释,则换成中文标点符号)。内联块注释可视为不带标点符号的注释。
107 |
108 | 完全是注释的源文件行长度应限制在 80 个字符以内(包括注释符号,但不包括缩进),或该行的最大宽度(包括注释符号和缩进),以较小者为准:
109 |
110 | ```rust,ignore
111 | // This comment goes up to the ................................. 80 char margin.
112 | // 该注释的边距为 ............................. 80 字符。
113 |
114 | {
115 | // This comment is .............................................. 80 chars wide.
116 | // 此注释宽 ............................................................. 80 字符。
117 | }
118 |
119 | {
120 | {
121 | {
122 | {
123 | {
124 | {
125 | // This comment is limited by the ......................... 100 char margin.
126 | // 此注释受 ................................................ 100 字符边距的限制。
127 | }
128 | }
129 | }
130 | }
131 | }
132 | }
133 | ```
134 |
135 | #### 文档注释
136 |
137 | 优先使用行注释 (`///`) 而不是块注释 (`/** ... */`)。
138 |
139 | 优先使用外层文档注释(`///` 或 `/** ... */`),仅使用内层文档注释(`//!` 和 `/*! ... */`)编写模块级或 crate 块级的文档。
140 |
141 | 将文档注释放在属性之前。
142 |
143 | ### 属性
144 |
145 | 每个属性放在单独一行,跟程序项保持一致的缩进。如果是内部属性 (`#!`),则缩进到程序项内部的位置。尽可能使用外属性。
146 |
147 | 对于带有参数列表的属性,格式应与函数类似。
148 |
149 | ```rust,ignore
150 | #[repr(C)]
151 | #[foo(foo, bar)]
152 | #[long_multi_line_attribute(
153 | split,
154 | across,
155 | lines,
156 | )]
157 | struct CRepr {
158 | #![repr(C)]
159 | x: f32,
160 | y: f32,
161 | }
162 | ```
163 |
164 | 对于带有等号的属性,在 `=` 前后各加一个空格,如 `#[foo = 42]`。
165 |
166 | 必须只有一个 `derive` 属性。工具的作者们要注意:如果将多个 `derive` 属性合并为一个属性,通常必须保留派生名称的顺序,以保证正确性: `#[derive(Foo)] #[derive(Bar)] struct Baz;` 必须格式化为 `#[derive(Foo, Bar)] struct Baz;`。
167 |
168 | For attributes with an equal sign, put a single space before and after the `=`,
169 | e.g., `#[foo = 42]`.
170 |
171 | ### **简短**程序项
172 |
173 | 在本指南的许多地方,我们指定的格式取决于代码结构的**简短**。例如,单行结构文字与多行结构文字:
174 |
175 | ```rust,ignore
176 | // 正常格式化
177 | Foo {
178 | f1: an_expression,
179 | f2: another_expression(),
180 | }
181 |
182 | // “简短”格式化
183 | Foo { f1, f2 }
184 | ```
185 |
186 | 我们让各个工具自行决定“简短”的确切含义。特别是,在不同的情况下,工具可以自由使用不同的定义。
187 |
188 | 一些合适的启发式方法是程序项的大小(以字符为单位)或程序项的复杂程度(例如,所有组件必须是简单的名称,而不是更复杂的子表达式)。有关合适的启发式方法的更多讨论,请参考[此讨论问题](https://github.com/rust-lang-nursery/fmt-rfcs/issues/47)。
189 |
190 | ## [非格式化约定](advice.md)
191 |
192 | ## [Cargo.toml 的约定](cargo.md)
193 |
194 | ## [决定这些准则的原则](principles.md)
195 |
--------------------------------------------------------------------------------
/src/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | [简介](README.md)
4 |
5 | - [程序项](items.md)
6 | - [语句](statements.md)
7 | - [表达式](expressions.md)
8 | - [类型和约束](types.md)
9 | - [其他风格建议](advice.md)
10 | - [`Cargo.toml` 的约定](cargo.md)
11 | - [指导原则和基本原理](principles.md)
12 | - [开发版特定语法](nightly.md)
13 |
--------------------------------------------------------------------------------
/src/advice.md:
--------------------------------------------------------------------------------
1 | # 其他风格建议
2 |
3 | ## 表达式
4 |
5 | 尽可能使用 Rust 面向表达式的特性;
6 |
7 | ```rust,ignore
8 | // 使用
9 | let x = if y { 1 } else { 0 };
10 | // 不使用
11 | let x;
12 | if y {
13 | x = 1;
14 | } else {
15 | x = 0;
16 | }
17 | ```
18 |
19 | ## 命名规范
20 |
21 | - 类型应为首字母大写的驼峰命名法(`UpperCamelCase`),
22 | - 枚举变量应为首字母大写的驼峰命名法(`UpperCamelCase`),
23 | - 结构体字段应使用纯小写下划线命名法(`snake_case`),
24 | - 函数和方法名称应使用纯小写下划线命名法(`snake_case`),
25 | - 局部变量应为纯小写下划线命名法(`snake_case`),
26 | - 宏名称应为纯小写下划线命名法(`snake_case`),
27 | - 常量(常量和不可变静态)应使用纯大写下划线命名(`SCREAMING_SNAKE_CASE`)
28 | - 当名称是保留字(如 `crate`)而禁止使用时,要么使用原始标识符(`r#crate`),要么使用尾部下划线(`crate_`)——不要拼错单词 (`krate`)。
29 |
30 | ### 模块
31 |
32 | 尽可能避免使用 `#[path]` 标注。
33 |
--------------------------------------------------------------------------------
/src/cargo.md:
--------------------------------------------------------------------------------
1 | # `Cargo.toml` 的约定
2 |
3 | ## 格式约定
4 |
5 | 使用与 Rust 代码相同的行宽和缩进。
6 |
7 | 在一个表块的最后一个键值对与下一表块的标题之间空一行。在表块标题和该表块中的键值对之间,或同一表块中的键值对之间,不要加空行。
8 |
9 | 除 `[package]` 表块外,按字母顺序排列各部分中的键名。将 `[package]` 表块放在文件的顶部;将 `name` 和 `version` 键按顺序放在该表块的顶部,接着除 `description` 外的其余键按字母顺序排列,最后是该表块的末尾的 `description`。
10 |
11 | 任何标准键名都不要使用引号,使用裸键。只有名称需要引号的非标准键才使用引号,并尽可能避免引入此类键名。详情请参见 [TOML 规范](https://toml.io/cn/v1.0.0#键名)。
12 |
13 | 在键和值之间的 `=` 前后各留一个空格。不要缩进任何键名;所有键名都从一行的开头开始。
14 |
15 | 对于包含多行的字符串值,如 crate 说明,应使用多行字符串(而不是换行符)。
16 |
17 | 对于数组值(如特性列表),如果合适,可将整个列表与键放在同一行。否则,使用分块缩进:在开头的方括号后加一个换行符,每个项缩进一级,每个项(包括最后一个项)后加一个逗号,最后一个项后将结尾的方括号放在一行的开头。
18 |
19 | 对于数组值(如特征列表),如果合适,可将整个列表与键放在同一行。否则,使用分块缩进:在开头的方括号后加一个换行符,每个项目缩进一级,每个项目(包括最后一个项目)后加一个逗号,最后一个项目后将结尾的方括号放在一行的开头。
20 |
21 | ```rust,ignore
22 | some_feature = [
23 | "another_feature",
24 | "yet_another_feature",
25 | "some_dependency?/some_feature",
26 | ]
27 | ```
28 |
29 | 对于表值,例如带有路径的 crate 依赖关系,如果合适的话,使用大括号和逗号将整个表写在与键相同的行上。如果整个表格不能与关键字写在同一行,则应使用键值对将其分隔成一个单独的部分:
30 |
31 | ```toml
32 | [dependencies]
33 | crate1 = { path = "crate1", version = "1.2.3" }
34 |
35 | [dependencies.extremely_long_crate_name_goes_here]
36 | path = "extremely_long_path_name_goes_right_here"
37 | version = "4.5.6"
38 | ```
39 |
40 | ## 元数据约定
41 |
42 | 作者列表(若有的话)应由字符串组成,每个字符串包含一个作者姓名,后面是置于尖括号内的电子邮件地址: `Full Name
43 | `。不应包含空电子邮件地址或没有电子邮件地址的姓名。(作者列表中也可以包含没有相关姓名的邮件列表地址)。
44 |
45 | 许可证字段必须包含有效的 [SPDX 表达式](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60),并使用有效的 [SPDX 许可证名称](https://spdx.org/licenses/)。(作为例外,根据普遍惯例,许可证字段可以使用 `/` 代替 ` OR `,例如 `MIT/Apache-2.0`)。
46 |
47 | 主页字段(若有的话)必须包含一个单独的 URL,包括协议(如 `https://example.org/`,而不只是 `example.org`)。
48 |
49 | 在描述字段中,按 80 列对文本进行换行。不要以 crate 的名称作为描述字段的开头(例如 "cratename is a ...");只需描述 crate 本身。如果提供的是多句描述,第一句应单独成行并概括 crate,就像电子邮件或提交信息的主题一样;随后的句子可以更详细地描述 crate。
50 |
--------------------------------------------------------------------------------
/src/expressions.md:
--------------------------------------------------------------------------------
1 | # 表达式
2 |
3 | ## 块
4 |
5 | 块表达式必须在首行 `{` 后和末行 `}` 前加换行符,除非根据其他样式规则可以写成单行。
6 |
7 | 代码块前的关键字(如 `unsafe` 或 `async`)必须与开头的括号在同一行,关键字与开头的括号之间用一个空格隔开。缩进代码块的内容。
8 |
9 | ```rust,ignore
10 | fn block_as_stmt() {
11 | a_call();
12 |
13 | {
14 | a_call_inside_a_block();
15 |
16 | // a comment in a block
17 | the_value
18 | }
19 | }
20 |
21 | fn block_as_expr() {
22 | let foo = {
23 | a_call_inside_a_block();
24 |
25 | // a comment in a block
26 | the_value
27 | };
28 | }
29 |
30 | fn unsafe_block_as_stmt() {
31 | a_call();
32 |
33 | unsafe {
34 | a_call_inside_a_block();
35 |
36 | // a comment in a block
37 | the_value
38 | }
39 | }
40 | ```
41 |
42 | If a block has an attribute, put it on its own line before the block:
43 |
44 | ```rust,ignore
45 | fn block_as_stmt() {
46 | #[an_attribute]
47 | {
48 | #![an_inner_attribute]
49 |
50 | // a comment in a block
51 | the_value
52 | }
53 | }
54 | ```
55 |
56 | Avoid writing comments on the same lines as either of the braces.
57 |
58 | Write an empty block as `{}`.
59 |
60 | Write a block on a single line if:
61 |
62 | * it is either used in expression position (not statement position) or is an
63 | unsafe block in statement position,
64 | * it contains a single-line expression and no statements, and
65 | * it contains no comments
66 |
67 | For a single-line block, put spaces after the opening brace and before the
68 | closing brace.
69 |
70 | Examples:
71 |
72 | ```rust,ignore
73 | fn main() {
74 | // Single line
75 | let _ = { a_call() };
76 | let _ = unsafe { a_call() };
77 |
78 | // Not allowed on one line
79 | // Statement position.
80 | {
81 | a_call()
82 | }
83 |
84 | // Contains a statement
85 | let _ = {
86 | a_call();
87 | };
88 | unsafe {
89 | a_call();
90 | }
91 |
92 | // Contains a comment
93 | let _ = {
94 | // A comment
95 | };
96 | let _ = {
97 | // A comment
98 | a_call()
99 | };
100 |
101 | // Multiple lines
102 | let _ = {
103 | a_call();
104 | another_call()
105 | };
106 | let _ = {
107 | a_call(
108 | an_argument,
109 | another_arg,
110 | )
111 | };
112 | }
113 | ```
114 |
115 |
116 | ## Closures
117 |
118 | Don't put any extra spaces before the first `|` (unless the closure is prefixed
119 | by a keyword such as `move`); put a space between the second `|` and the
120 | expression of the closure. Between the `|`s, use function definition syntax,
121 | but elide types where possible.
122 |
123 | Use closures without the enclosing `{}`, if possible. Add the `{}` when you have
124 | a return type, when there are statements, when there are comments inside the
125 | closure, or when the body expression is a control-flow expression that spans
126 | multiple lines. If using braces, follow the rules above for blocks. Examples:
127 |
128 | ```rust,ignore
129 | |arg1, arg2| expr
130 |
131 | move |arg1: i32, arg2: i32| -> i32 {
132 | expr1;
133 | expr2
134 | }
135 |
136 | || Foo {
137 | field1,
138 | field2: 0,
139 | }
140 |
141 | || {
142 | if true {
143 | blah
144 | } else {
145 | boo
146 | }
147 | }
148 |
149 | |x| unsafe {
150 | expr
151 | }
152 | ```
153 |
154 |
155 | ## Struct literals
156 |
157 | If a struct literal is *small*, format it on a single line, and do not use a
158 | trailing comma. If not, split it across multiple lines, with each field on its
159 | own block-indented line, and use a trailing comma.
160 |
161 | For each `field: value` entry, put a space after the colon only.
162 |
163 | Put a space before the opening brace. In the single-line form, put spaces after
164 | the opening brace and before the closing brace.
165 |
166 | ```rust,ignore
167 | Foo { field1, field2: 0 }
168 | let f = Foo {
169 | field1,
170 | field2: an_expr,
171 | };
172 | ```
173 |
174 | Functional record update syntax is treated like a field, but it must never have
175 | a trailing comma. Do not put a space after `..`.
176 |
177 | ```rust,ignore
178 | let f = Foo {
179 | field1,
180 | ..an_expr
181 | };
182 | ```
183 |
184 |
185 | ## Tuple literals
186 |
187 | Use a single-line form where possible. Do not put spaces between the opening
188 | parenthesis and the first element, or between the last element and the closing
189 | parenthesis. Separate elements with a comma followed by a space.
190 |
191 | Where a single-line form is not possible, write the tuple across
192 | multiple lines, with each element of the tuple on its own block-indented line,
193 | and use a trailing comma.
194 |
195 | ```rust,ignore
196 | (a, b, c)
197 |
198 | let x = (
199 | a_long_expr,
200 | another_very_long_expr,
201 | );
202 | ```
203 |
204 |
205 | ## Tuple struct literals
206 |
207 | Do not put space between the identifier and the opening parenthesis. Otherwise,
208 | follow the rules for tuple literals:
209 |
210 | ```rust,ignore
211 | Foo(a, b, c)
212 |
213 | let x = Foo(
214 | a_long_expr,
215 | another_very_long_expr,
216 | );
217 | ```
218 |
219 |
220 | ## Enum literals
221 |
222 | Follow the formatting rules for the various struct literals. Prefer using the
223 | name of the enum as a qualifying name, unless the enum is in the prelude:
224 |
225 | ```rust,ignore
226 | Foo::Bar(a, b)
227 | Foo::Baz {
228 | field1,
229 | field2: 1001,
230 | }
231 | Ok(an_expr)
232 | ```
233 |
234 |
235 | ## Array literals
236 |
237 | Write small array literals on a single line. Do not put spaces between the opening
238 | square bracket and the first element, or between the last element and the closing
239 | square bracket. Separate elements with a comma followed by a space.
240 |
241 | If using the repeating initializer, put a space after the semicolon
242 | only.
243 |
244 | Apply the same rules if using `vec!` or similar array-like macros; always use
245 | square brackets with such macros. Examples:
246 |
247 | ```rust,ignore
248 | fn main() {
249 | let x = [1, 2, 3];
250 | let y = vec![a, b, c, d];
251 | let a = [42; 10];
252 | }
253 | ```
254 |
255 | For arrays that have to be broken across lines, if using the repeating
256 | initializer, break after the `;`, not before. Otherwise, follow the rules below
257 | for function calls. In any case, block-indent the contents of the initializer,
258 | and put line breaks after the opening square bracket and before the closing
259 | square bracket:
260 |
261 | ```rust,ignore
262 | fn main() {
263 | [
264 | a_long_expression();
265 | 1234567890
266 | ]
267 | let x = [
268 | an_expression,
269 | another_expression,
270 | a_third_expression,
271 | ];
272 | }
273 | ```
274 |
275 |
276 | ## Array accesses, indexing, and slicing.
277 |
278 | Don't put spaces around the square brackets. Avoid breaking lines if possible.
279 | Never break a line between the target expression and the opening square
280 | bracket. If the indexing expression must be broken onto a subsequent line, or
281 | spans multiple lines itself, then block-indent the indexing expression, and put
282 | newlines after the opening square bracket and before the closing square
283 | bracket:
284 |
285 | Examples:
286 |
287 | ```rust,ignore
288 | fn main() {
289 | foo[42];
290 | &foo[..10];
291 | bar[0..100];
292 | foo[4 + 5 / bar];
293 | a_long_target[
294 | a_long_indexing_expression
295 | ];
296 | }
297 | ```
298 |
299 | ## Unary operations
300 |
301 | Do not include a space between a unary op and its operand (i.e., `!x`, not
302 | `! x`). However, there must be a space after `&mut`. Avoid line-breaking
303 | between a unary operator and its operand.
304 |
305 | ## Binary operations
306 |
307 | Do include spaces around binary ops (i.e., `x + 1`, not `x+1`) (including `=`
308 | and other assignment operators such as `+=` or `*=`).
309 |
310 | For comparison operators, because for `T op U`, `&T op &U` is also implemented:
311 | if you have `t: &T`, and `u: U`, prefer `*t op u` to `t op &u`. In general,
312 | within expressions, prefer dereferencing to taking references, unless necessary
313 | (e.g. to avoid an unnecessarily expensive operation).
314 |
315 | Use parentheses liberally; do not necessarily elide them due to precedence.
316 | Tools should not automatically insert or remove parentheses. Do not use spaces
317 | to indicate precedence.
318 |
319 | If line-breaking, block-indent each subsequent line. For assignment operators,
320 | break after the operator; for all other operators, put the operator on the
321 | subsequent line. Put each sub-expression on its own line:
322 |
323 | ```rust,ignore
324 | foo_bar
325 | + bar
326 | + baz
327 | + qux
328 | + whatever
329 | ```
330 |
331 | Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather
332 | than at other binary operators.
333 |
334 | ## Control flow
335 |
336 | Do not include extraneous parentheses for `if` and `while` expressions.
337 |
338 | ```rust,ignore
339 | if true {
340 | }
341 | ```
342 |
343 | is better than
344 |
345 | ```rust,ignore
346 | if (true) {
347 | }
348 | ```
349 |
350 | Do include extraneous parentheses if it makes an arithmetic or logic expression
351 | easier to understand (`(x * 15) + (y * 20)` is fine)
352 |
353 | ## Function calls
354 |
355 | Do not put a space between the function name, and the opening parenthesis.
356 |
357 | Do not put a space between an argument, and the comma which follows.
358 |
359 | Do put a space between an argument, and the comma which precedes it.
360 |
361 | Prefer not to break a line in the callee expression.
362 |
363 | ### Single-line calls
364 |
365 | Do not put a space between the function name and open paren, between the open
366 | paren and the first argument, or between the last argument and the close paren.
367 |
368 | Do not put a comma after the last argument.
369 |
370 | ```rust,ignore
371 | foo(x, y, z)
372 | ```
373 |
374 | ### Multi-line calls
375 |
376 | If the function call is not *small*, it would otherwise over-run the max width,
377 | or any argument or the callee is multi-line, then format the call across
378 | multiple lines. In this case, put each argument on its own block-indented line,
379 | break after the opening parenthesis and before the closing parenthesis,
380 | and use a trailing comma:
381 |
382 | ```rust,ignore
383 | a_function_call(
384 | arg1,
385 | a_nested_call(a, b),
386 | )
387 | ```
388 |
389 |
390 | ## Method calls
391 |
392 | Follow the function rules for calling.
393 |
394 | Do not put any spaces around the `.`.
395 |
396 | ```rust,ignore
397 | x.foo().bar().baz(x, y, z);
398 | ```
399 |
400 |
401 | ## Macro uses
402 |
403 | If a macro can be parsed like other constructs, format it like those
404 | constructs. For example, a macro use `foo!(a, b, c)` can be parsed like a
405 | function call (ignoring the `!`), so format it using the rules for function
406 | calls.
407 |
408 | ### Special case macros
409 |
410 | For macros which take a format string, if all other arguments are *small*,
411 | format the arguments before the format string on a single line if they fit, and
412 | format the arguments after the format string on a single line if they fit, with
413 | the format string on its own line. If the arguments are not small or do not
414 | fit, put each on its own line as with a function. For example:
415 |
416 | ```rust,ignore
417 | println!(
418 | "Hello {} and {}",
419 | name1, name2,
420 | );
421 |
422 | assert_eq!(
423 | x, y,
424 | "x and y were not equal, see {}",
425 | reason,
426 | );
427 | ```
428 |
429 |
430 | ## Casts (`as`)
431 |
432 | Put spaces before and after `as`:
433 |
434 | ```rust,ignore
435 | let cstr = "Hi\0" as *const str as *const [u8] as *const std::os::raw::c_char;
436 | ```
437 |
438 |
439 | ## Chains of fields and method calls
440 |
441 | A chain is a sequence of field accesses, method calls, and/or uses of the try
442 | operator `?`. E.g., `a.b.c().d` or `foo?.bar().baz?`.
443 |
444 | Format the chain on one line if it is "small" and otherwise possible to do so.
445 | If formatting on multiple lines, put each field access or method call in the
446 | chain on its own line, with the line-break before the `.` and after any `?`.
447 | Block-indent each subsequent line:
448 |
449 | ```rust,ignore
450 | let foo = bar
451 | .baz?
452 | .qux();
453 | ```
454 |
455 | If the length of the last line of the first element plus its indentation is
456 | less than or equal to the indentation of the second line, then combine the
457 | first and second lines if they fit. Apply this rule recursively.
458 |
459 | ```rust,ignore
460 | x.baz?
461 | .qux()
462 |
463 | x.y.z
464 | .qux()
465 |
466 | let foo = x
467 | .baz?
468 | .qux();
469 |
470 | foo(
471 | expr1,
472 | expr2,
473 | ).baz?
474 | .qux();
475 | ```
476 |
477 | ### Multi-line elements
478 |
479 | If any element in a chain is formatted across multiple lines, put that element
480 | and any later elements on their own lines.
481 |
482 | ```rust,ignore
483 | a.b.c()?
484 | .foo(
485 | an_expr,
486 | another_expr,
487 | )
488 | .bar
489 | .baz
490 | ```
491 |
492 | Note there is block indent due to the chain and the function call in the above
493 | example.
494 |
495 | Prefer formatting the whole chain in multi-line style and each element on one
496 | line, rather than putting some elements on multiple lines and some on a single
497 | line, e.g.,
498 |
499 | ```rust,ignore
500 | // Better
501 | self.pre_comment
502 | .as_ref()
503 | .map_or(false, |comment| comment.starts_with("//"))
504 |
505 | // Worse
506 | self.pre_comment.as_ref().map_or(
507 | false,
508 | |comment| comment.starts_with("//"),
509 | )
510 | ```
511 |
512 | ## Control flow expressions
513 |
514 | This section covers `if`, `if let`, `loop`, `while`, `while let`, and `for`
515 | expressions.
516 |
517 | Put the keyword, any initial clauses, and the opening brace of the block all on
518 | a single line, if they fit. Apply the usual rules for [block
519 | formatting](#blocks) to the block.
520 |
521 | If there is an `else` component, then put the closing brace, `else`, any
522 | following clause, and the opening brace all on the same line, with a single
523 | space before and after the `else` keyword:
524 |
525 | ```rust,ignore
526 | if ... {
527 | ...
528 | } else {
529 | ...
530 | }
531 |
532 | if let ... {
533 | ...
534 | } else if ... {
535 | ...
536 | } else {
537 | ...
538 | }
539 | ```
540 |
541 | If the control line needs to be broken, prefer to break before the `=` in `*
542 | let` expressions and before `in` in a `for` expression; block-indent the
543 | following line. If the control line is broken for any reason, put the opening
544 | brace on its own line, not indented. Examples:
545 |
546 | ```rust,ignore
547 | while let Some(foo)
548 | = a_long_expression
549 | {
550 | ...
551 | }
552 |
553 | for foo
554 | in a_long_expression
555 | {
556 | ...
557 | }
558 |
559 | if a_long_expression
560 | && another_long_expression
561 | || a_third_long_expression
562 | {
563 | ...
564 | }
565 | ```
566 |
567 | Where the initial clause spans multiple lines and ends with one or more closing
568 | parentheses, square brackets, or braces, and there is nothing else on that
569 | line, and that line is not indented beyond the indent on the first line of the
570 | control flow expression, then put the opening brace of the block on the same
571 | line with a preceding space. For example:
572 |
573 | ```rust,ignore
574 | if !self.config.file_lines().intersects(
575 | &self.codemap.lookup_line_range(
576 | stmt.span,
577 | ),
578 | ) { // Opening brace on same line as initial clause.
579 | ...
580 | }
581 | ```
582 |
583 |
584 | ### Single line `if else`
585 |
586 | Put an `if else` or `if let else` on a single line if it occurs in expression
587 | context (i.e., is not a standalone statement), it contains a single `else`
588 | clause, and is *small*:
589 |
590 | ```rust,ignore
591 | let y = if x { 0 } else { 1 };
592 |
593 | // Examples that must be multi-line.
594 | let y = if something_very_long {
595 | not_small
596 | } else {
597 | also_not_small
598 | };
599 |
600 | if x {
601 | 0
602 | } else {
603 | 1
604 | }
605 | ```
606 |
607 |
608 | ## Match
609 |
610 | Prefer not to line-break inside the discriminant expression. Always break after
611 | the opening brace and before the closing brace. Block-indent the match arms
612 | once:
613 |
614 | ```rust,ignore
615 | match foo {
616 | // arms
617 | }
618 |
619 | let x = match foo.bar.baz() {
620 | // arms
621 | };
622 | ```
623 |
624 | Use a trailing comma for a match arm if and only if not using a block.
625 |
626 | Never start a match arm pattern with `|`:
627 |
628 | ```rust,ignore
629 | match foo {
630 | // Don't do this.
631 | | foo => bar,
632 | // Or this.
633 | | a_very_long_pattern
634 | | another_pattern
635 | | yet_another_pattern
636 | | a_fourth_pattern => {
637 | ...
638 | }
639 | }
640 | ```
641 |
642 | Prefer:
643 |
644 | ```rust,ignore
645 | match foo {
646 | foo => bar,
647 | a_very_long_pattern
648 | | another_pattern
649 | | yet_another_pattern
650 | | a_fourth_pattern => {
651 | ...
652 | }
653 | }
654 | ```
655 |
656 | Avoid splitting the left-hand side (before the `=>`) of a match arm where
657 | possible. If the right-hand side of the match arm is kept on the same line,
658 | never use a block (unless the block is empty).
659 |
660 | If the right-hand side consists of multiple statements, or has line comments,
661 | or the start of the line does not fit on the same line as the left-hand side,
662 | use a block. Do not flatten a right-hand side block containing a single macro call
663 | because its expanded form could contain a trailing semicolon.
664 |
665 | Block-indent the body of a block arm.
666 |
667 | Examples:
668 |
669 | ```rust,ignore
670 | match foo {
671 | foo => bar,
672 | a_very_long_pattern | another_pattern if an_expression() => {
673 | no_room_for_this_expression()
674 | }
675 | foo => {
676 | // A comment.
677 | an_expression()
678 | }
679 | foo => {
680 | let a = statement();
681 | an_expression()
682 | }
683 | bar => {}
684 | // Trailing comma on last item.
685 | foo => bar,
686 | baz => qux!(),
687 | lorem => {
688 | ipsum!()
689 | }
690 | }
691 | ```
692 |
693 | If the body is a single expression with no line comments and not a control flow
694 | expression, start it on the same line as the left-hand side. If not, then it
695 | must be in a block. Example:
696 |
697 | ```rust,ignore
698 | match foo {
699 | // A combinable expression.
700 | foo => a_function_call(another_call(
701 | argument1,
702 | argument2,
703 | )),
704 | // A non-combinable expression
705 | bar => {
706 | a_function_call(
707 | another_call(
708 | argument1,
709 | argument2,
710 | ),
711 | another_argument,
712 | )
713 | }
714 | }
715 | ```
716 |
717 | ### Line-breaking
718 |
719 | If using a block form on the right-hand side of a match arm makes it possible
720 | to avoid breaking on the left-hand side, do that:
721 |
722 | ```rust,ignore
723 | // Assuming the following line does not fit in the max width
724 | a_very_long_pattern | another_pattern => ALongStructName {
725 | ...
726 | },
727 | // Prefer this
728 | a_very_long_pattern | another_pattern => {
729 | ALongStructName {
730 | ...
731 | }
732 | }
733 | // To splitting the pattern.
734 | ```
735 |
736 | Never break after `=>` without using the block form of the body.
737 |
738 | If the left-hand side must be split and there is an `if` clause, break before
739 | the `if` and block indent. In this case, always use a block body and start the
740 | body on a new line:
741 |
742 | ```rust,ignore
743 | a_very_long_pattern | another_pattern
744 | if expr =>
745 | {
746 | ...
747 | }
748 | ```
749 |
750 | If required to break the pattern, put each clause of the pattern on its own
751 | line with no additional indent, breaking before the `|`. If there is an `if`
752 | clause, use the above form:
753 |
754 | ```rust,ignore
755 | a_very_long_pattern
756 | | another_pattern
757 | | yet_another_pattern
758 | | a_forth_pattern => {
759 | ...
760 | }
761 | a_very_long_pattern
762 | | another_pattern
763 | | yet_another_pattern
764 | | a_forth_pattern
765 | if expr =>
766 | {
767 | ...
768 | }
769 | ```
770 |
771 | If the pattern is multi-line, and the last line is less wide than the indent, do
772 | not put the `if` clause on a new line. E.g.,
773 |
774 | ```rust,ignore
775 | Token::Dimension {
776 | value,
777 | ref unit,
778 | ..
779 | } if num_context.is_ok(context.parsing_mode, value) => {
780 | ...
781 | }
782 | ```
783 |
784 | If every clause in a pattern is *small*, but the whole pattern does not fit on
785 | one line, then format the pattern across multiple lines with as many clauses
786 | per line as possible. Again, break before a `|`:
787 |
788 | ```rust,ignore
789 | foo | bar | baz
790 | | qux => {
791 | ...
792 | }
793 | ```
794 |
795 | We define a pattern clause to be *small* if it fits on a single line and
796 | matches "small" in the following grammar:
797 |
798 | ```text
799 | small:
800 | - small_no_tuple
801 | - unary tuple constructor: `(` small_no_tuple `,` `)`
802 | - `&` small
803 |
804 | small_no_tuple:
805 | - single token
806 | - `&` small_no_tuple
807 | ```
808 |
809 | E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not.
810 |
811 |
812 | ## Combinable expressions
813 |
814 | Where a function call has a single argument, and that argument is formatted
815 | across multiple-lines, format the outer call as if it were a single-line call,
816 | if the result fits. Apply the same combining behaviour to any similar
817 | expressions which have multi-line, block-indented lists of sub-expressions
818 | delimited by parentheses (e.g., macros or tuple struct literals). E.g.,
819 |
820 | ```rust,ignore
821 | foo(bar(
822 | an_expr,
823 | another_expr,
824 | ))
825 |
826 | let x = foo(Bar {
827 | field: whatever,
828 | });
829 |
830 | foo(|param| {
831 | action();
832 | foo(param)
833 | })
834 |
835 | let x = combinable([
836 | an_expr,
837 | another_expr,
838 | ]);
839 |
840 | let arr = [combinable(
841 | an_expr,
842 | another_expr,
843 | )];
844 | ```
845 |
846 | Apply this behavior recursively.
847 |
848 | For a function with multiple arguments, if the last argument is a multi-line
849 | closure with an explicit block, there are no other closure arguments, and all
850 | the arguments and the first line of the closure fit on the first line, use the
851 | same combining behavior:
852 |
853 | ```rust,ignore
854 | foo(first_arg, x, |param| {
855 | action();
856 | foo(param)
857 | })
858 | ```
859 |
860 |
861 | ## Ranges
862 |
863 | Do not put spaces in ranges, e.g., `0..10`, `x..=y`, `..x.len()`, `foo..`.
864 |
865 | When writing a range with both upper and lower bounds, if the line must be
866 | broken within the range, break before the range operator and block indent the
867 | second line:
868 |
869 | ```rust,ignore
870 | a_long_expression
871 | ..another_long_expression
872 | ```
873 |
874 | For the sake of indicating precedence, if either bound is a compound
875 | expression, use parentheses around it, e.g., `..(x + 1)`, `(x.f)..(x.f.len())`,
876 | or `0..(x - 10)`.
877 |
878 |
879 | ## Hexadecimal literals
880 |
881 | Hexadecimal literals may use upper- or lower-case letters, but they must not be
882 | mixed within the same literal. Projects should use the same case for all
883 | literals, but we do not make a recommendation for either lower- or upper-case.
884 |
885 | # Patterns
886 |
887 | Format patterns like their corresponding expressions. See the section on
888 | `match` for additional formatting for patterns in match arms.
889 |
--------------------------------------------------------------------------------
/src/items.md:
--------------------------------------------------------------------------------
1 | # 程序项
2 |
3 | 程序项(item,简称项)包括模块顶层允许使用的一系列内容。不过,Rust 也允许某些程序项出现在其他类型的程序项中,如函数中。无论程序项是出现在模块层还是出现在其他程序项中,都适用相同的格式约定。
4 |
5 | `extern crate` 语句必须放在文件的首位。它们必须按字母顺序排列。
6 |
7 | `use` 语句和模块声明(`mod foo;`,而不是 `mod { ... }`)必须放在其他程序项之前。将导入放在模块声明之前。按字母顺序排序,但 `self` 和 `super` 必须排在其他名称之前。
8 |
9 | 不要自动移动注有 `#[macro_use]` 的模块声明,因为这可能会改变语义。
10 |
11 | ## 函数定义
12 |
13 | 在 Rust 中,人们经常通过搜索 `fn [function-name]` 来查找函数,因此函数定义的格式必须能够满足这一点。
14 |
15 | 正确的排序和空格位置是:
16 |
17 | ```rust,ignore
18 | [pub] [unsafe] [extern ["ABI"]] fn foo(arg1: i32, arg2: i32) -> i32 {
19 | ...
20 | }
21 | ```
22 |
23 | 避免在签名本身中添加注释。
24 |
25 | 如果函数签名不能放在一行内,则在开头括号后和结尾括号前分隔,并将每个参数放在自己的缩进行内。例如:
26 |
27 | ```rust,ignore
28 | fn foo(
29 | arg1: i32,
30 | arg2: i32,
31 | ) -> i32 {
32 | ...
33 | }
34 | ```
35 |
36 | 注意最后一个参数后面的逗号。
37 |
38 | ## 元组和元组结构
39 |
40 | 像编写函数的参数列表一样编写类型列表。
41 |
42 | 像调用函数一样构建元组或元组结构体。
43 |
44 | ### 单行
45 |
46 | ```rust,ignore
47 | struct Bar(Type1, Type2);
48 |
49 | let x = Bar(11, 22);
50 | let y = (11, 22, 33);
51 | ```
52 |
53 | ## Enums
54 |
55 | In the declaration, put each variant on its own line, block indented.
56 |
57 | Format each variant accordingly as either a struct (but without the `struct`
58 | keyword), a tuple struct, or an identifier (which doesn't require special
59 | formatting):
60 |
61 | ```rust,ignore
62 | enum FooBar {
63 | First(u32),
64 | Second,
65 | Error {
66 | err: Box,
67 | line: u32,
68 | },
69 | }
70 | ```
71 |
72 | If a struct variant is [*small*](index.html#small-items), format it on one
73 | line. In this case, do not use a trailing comma for the field list, but do put
74 | spaces around each brace:
75 |
76 | ```rust,ignore
77 | enum FooBar {
78 | Error { err: Box, line: u32 },
79 | }
80 | ```
81 |
82 | In an enum with multiple struct variants, if any struct variant is written on
83 | multiple lines, use the multi-line formatting for all struct variants. However,
84 | such a situation might be an indication that you should factor out the fields
85 | of the variant into their own struct.
86 |
87 |
88 | ## Structs and Unions
89 |
90 | Struct names follow on the same line as the `struct` keyword, with the opening
91 | brace on the same line when it fits within the right margin. All struct fields
92 | are indented once and end with a trailing comma. The closing brace is not
93 | indented and appears on its own line.
94 |
95 | ```rust,ignore
96 | struct Foo {
97 | a: A,
98 | b: B,
99 | }
100 | ```
101 |
102 | If and only if the type of a field does not fit within the right margin, it is
103 | pulled down to its own line and indented again.
104 |
105 | ```rust,ignore
106 | struct Foo {
107 | a: A,
108 | long_name:
109 | LongType,
110 | }
111 | ```
112 |
113 | Prefer using a unit struct (e.g., `struct Foo;`) to an empty struct (e.g.,
114 | `struct Foo();` or `struct Foo {}`, these only exist to simplify code
115 | generation), but if you must use an empty struct, keep it on one line with no
116 | space between the braces: `struct Foo;` or `struct Foo {}`.
117 |
118 | The same guidelines are used for untagged union declarations.
119 |
120 | ```rust,ignore
121 | union Foo {
122 | a: A,
123 | b: B,
124 | long_name:
125 | LongType,
126 | }
127 | ```
128 |
129 |
130 | ## Tuple structs
131 |
132 | Put the whole struct on one line if possible. Separate types within the
133 | parentheses using a comma and space. Don't use a trailing comma for a
134 | single-line tuple struct. Don't put spaces around the parentheses or semicolon:
135 |
136 | ```rust,ignore
137 | pub struct Foo(String, u8);
138 | ```
139 |
140 | Prefer unit structs to empty tuple structs (these only exist to simplify code
141 | generation), e.g., `struct Foo;` rather than `struct Foo();`.
142 |
143 | For more than a few fields (in particular if the tuple struct does not fit on
144 | one line), prefer a proper struct with named fields.
145 |
146 | For a multi-line tuple struct, block-format the fields with a field on each
147 | line and a trailing comma:
148 |
149 | ```rust,ignore
150 | pub struct Foo(
151 | String,
152 | u8,
153 | );
154 | ```
155 |
156 |
157 | ## Traits
158 |
159 | Use block-indent for trait items. If there are no items, format the trait (including its `{}`)
160 | on a single line. Otherwise, break after the opening brace and before
161 | the closing brace:
162 |
163 | ```rust,ignore
164 | trait Foo {}
165 |
166 | pub trait Bar {
167 | ...
168 | }
169 | ```
170 |
171 | If the trait has bounds, put a space after the colon but not before,
172 | and put spaces around each `+`, e.g.,
173 |
174 | ```rust,ignore
175 | trait Foo: Debug + Bar {}
176 | ```
177 |
178 | Prefer not to line-break in the bounds if possible (consider using a `where`
179 | clause). Prefer to break between bounds than to break any individual bound. If
180 | you must break the bounds, put each bound (including the first) on its own
181 | block-indented line, break before the `+` and put the opening brace on its own
182 | line:
183 |
184 | ```rust,ignore
185 | pub trait IndexRanges:
186 | Index, Output=Self>
187 | + Index, Output=Self>
188 | + Index, Output=Self>
189 | + Index
190 | {
191 | ...
192 | }
193 | ```
194 |
195 |
196 | ## Impls
197 |
198 | Use block-indent for impl items. If there are no items, format the impl
199 | (including its `{}`) on a single line. Otherwise, break after the opening brace
200 | and before the closing brace:
201 |
202 | ```rust,ignore
203 | impl Foo {}
204 |
205 | impl Bar for Foo {
206 | ...
207 | }
208 | ```
209 |
210 | Avoid line-breaking in the signature if possible. If a line break is required in
211 | a non-inherent impl, break immediately before `for`, block indent the concrete type
212 | and put the opening brace on its own line:
213 |
214 | ```rust,ignore
215 | impl Bar
216 | for Foo
217 | {
218 | ...
219 | }
220 | ```
221 |
222 |
223 | ## Extern crate
224 |
225 | `extern crate foo;`
226 |
227 | Use spaces around keywords, no spaces around the semicolon.
228 |
229 |
230 | ### Modules
231 |
232 | ```rust,ignore
233 | mod foo {
234 | }
235 | ```
236 |
237 | ```rust,ignore
238 | mod foo;
239 | ```
240 |
241 | Use spaces around keywords and before the opening brace, no spaces around the
242 | semicolon.
243 |
244 | ### macro\_rules!
245 |
246 | Use `{}` for the full definition of the macro.
247 |
248 | ```rust,ignore
249 | macro_rules! foo {
250 | }
251 | ```
252 |
253 |
254 | ## Generics
255 |
256 | Prefer to put a generics clause on one line. Break other parts of an item
257 | declaration rather than line-breaking a generics clause. If a generics clause is
258 | large enough to require line-breaking, prefer a `where` clause instead.
259 |
260 | Do not put spaces before or after `<` nor before `>`. Only put a space after
261 | `>` if it is followed by a word or opening brace, not an opening parenthesis.
262 | Put a space after each comma. Do not use a trailing comma for a single-line
263 | generics clause.
264 |
265 | ```rust,ignore
266 | fn foo(x: Vec, y: Vec) ...
267 |
268 | impl SomeType { ...
269 | ```
270 |
271 | If the generics clause must be formatted across multiple lines, put each
272 | parameter on its own block-indented line, break after the opening `<` and
273 | before the closing `>`, and use a trailing comma.
274 |
275 | ```rust,ignore
276 | fn foo<
277 | T: Display,
278 | U: Debug,
279 | >(x: Vec, y: Vec) ...
280 | ```
281 |
282 | If an associated type is bound in a generic type, put spaces around the `=`:
283 |
284 | ```rust,ignore
285 | >
286 | ```
287 |
288 | Prefer to use single-letter names for generic parameters.
289 |
290 |
291 | ## `where` clauses
292 |
293 | These rules apply for `where` clauses on any item.
294 |
295 | If immediately following a closing bracket of any kind, write the keyword
296 | `where` on the same line, with a space before it.
297 |
298 | Otherwise, put `where` on a new line at the same indentation level. Put each
299 | component of a `where` clause on its own line, block-indented. Use a trailing
300 | comma, unless the clause is terminated with a semicolon. If the `where` clause
301 | is followed by a block (or assignment), start that block on a new line.
302 | Examples:
303 |
304 | ```rust,ignore
305 | fn function(args)
306 | where
307 | T: Bound,
308 | U: AnotherBound,
309 | {
310 | body
311 | }
312 |
313 | fn foo(
314 | args
315 | ) -> ReturnType
316 | where
317 | T: Bound,
318 | {
319 | body
320 | }
321 |
322 | fn foo(
323 | args,
324 | ) where
325 | T: Bound,
326 | U: AnotherBound,
327 | {
328 | body
329 | }
330 |
331 | fn foo(
332 | args
333 | ) -> ReturnType
334 | where
335 | T: Bound,
336 | U: AnotherBound; // Note, no trailing comma.
337 |
338 | // Note that where clauses on `type` aliases are not enforced and should not
339 | // be used.
340 | type Foo
341 | where
342 | T: Bound
343 | = Bar;
344 | ```
345 |
346 | If a `where` clause is very short, prefer using an inline bound on the type
347 | parameter.
348 |
349 | If a component of a `where` clause does not fit and contains `+`, break it
350 | before each `+` and block-indent the continuation lines. Put each bound on its
351 | own line. E.g.,
352 |
353 | ```rust,ignore
354 | impl IndexRanges for T
355 | where
356 | T: Index, Output = Self::Output>
357 | + Index, Output = Self::Output>
358 | + Index, Output = Self::Output>
359 | + Index, Output = Self::Output>
360 | + Index, Output = Self::Output>
361 | + Index,
362 | ```
363 |
364 | ## Type aliases
365 |
366 | Keep type aliases on one line when they fit. If necessary to break the line, do
367 | so after the `=`, and block-indent the right-hand side:
368 |
369 | ```rust,ignore
370 | pub type Foo = Bar;
371 |
372 | // If multi-line is required
373 | type VeryLongType =
374 | AnEvenLongerType>;
375 | ```
376 |
377 | Where possible avoid `where` clauses and keep type constraints inline. Where
378 | that is not possible split the line before and after the `where` clause (and
379 | split the `where` clause as normal), e.g.,
380 |
381 | ```rust,ignore
382 | type VeryLongType
383 | where
384 | T: U::AnAssociatedType,
385 | U: SomeBound,
386 | = AnEvenLongerType>;
387 | ```
388 |
389 |
390 | ## Associated types
391 |
392 | Format associated types like type aliases. Where an associated type has a
393 | bound, put a space after the colon but not before:
394 |
395 | ```rust,ignore
396 | pub type Foo: Bar;
397 | ```
398 |
399 | ## extern items
400 |
401 | When writing extern items (such as `extern "C" fn`), always specify the ABI.
402 | For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or
403 | `extern "C" { ... }`.
404 |
405 | ## Imports (`use` statements)
406 |
407 | Format imports on one line where possible. Don't put spaces around braces.
408 |
409 | ```rust,ignore
410 | use a::b::c;
411 | use a::b::d::*;
412 | use a::b::{foo, bar, baz};
413 | ```
414 |
415 | ### Large list imports
416 |
417 | Prefer to use multiple imports rather than a multi-line import. However, tools
418 | should not split imports by default.
419 |
420 | If an import does require multiple lines (either because a list of single names
421 | does not fit within the max width, or because of the rules for nested imports
422 | below), then break after the opening brace and before the closing brace, use a
423 | trailing comma, and block indent the names.
424 |
425 | ```rust,ignore
426 | // Prefer
427 | foo::{long, list, of, imports};
428 | foo::{more, imports};
429 |
430 | // If necessary
431 | foo::{
432 | long, list, of, imports, more,
433 | imports, // Note trailing comma
434 | };
435 | ```
436 |
437 | ### Ordering of imports
438 |
439 | A *group* of imports is a set of imports on the same or sequential lines. One or
440 | more blank lines or other items (e.g., a function) separate groups of imports.
441 |
442 | Within a group of imports, imports must be sorted ASCIIbetically (uppercase
443 | before lowercase). Groups of imports must not be merged or re-ordered.
444 |
445 | E.g., input:
446 |
447 | ```rust,ignore
448 | use d;
449 | use c;
450 |
451 | use b;
452 | use a;
453 | ```
454 |
455 | output:
456 |
457 | ```rust,ignore
458 | use c;
459 | use d;
460 |
461 | use a;
462 | use b;
463 | ```
464 |
465 | Because of `macro_use`, attributes must also start a new group and prevent
466 | re-ordering.
467 |
468 | ### Ordering list import
469 |
470 | Names in a list import must be sorted ASCIIbetically, but with `self` and
471 | `super` first, and groups and glob imports last. This applies recursively. For
472 | example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g.,
473 | `use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`.
474 |
475 | ### Normalisation
476 |
477 | Tools must make the following normalisations, recursively:
478 |
479 | * `use a::self;` -> `use a;`
480 | * `use a::{};` -> (nothing)
481 | * `use a::{b};` -> `use a::b;`
482 |
483 | Tools must not otherwise merge or un-merge import lists or adjust glob imports
484 | (without an explicit option).
485 |
486 | ### Nested imports
487 |
488 | If there are any nested imports in a list import, then use the multi-line form,
489 | even if the import fits on one line. Each nested import must be on its own line,
490 | but non-nested imports must be grouped on as few lines as possible.
491 |
492 | For example,
493 |
494 | ```rust,ignore
495 | use a::b::{
496 | x, y, z,
497 | u::{...},
498 | w::{...},
499 | };
500 | ```
501 |
502 |
503 | ### Merging/un-merging imports
504 |
505 | An example:
506 |
507 | ```rust,ignore
508 | // Un-merged
509 | use a::b;
510 | use a::c::d;
511 |
512 | // Merged
513 | use a::{b, c::d};
514 | ```
515 |
516 | Tools must not merge or un-merge imports by default. They may offer merging or
517 | un-merging as an option.
518 |
--------------------------------------------------------------------------------
/src/nightly.md:
--------------------------------------------------------------------------------
1 | 本章记录了开发版特定(nightly-only,直译为:夜间特定)语法的样式和格式。风格指南的其余部分记录了 Rust 稳定语法的风格;开发版特定语法仅出现在本章。这里的每一节都包含了特性门类的名称,因此在 Rust 代码库中搜索(例如 `git grep`)开发版特性时,也会出现样式指南部分。
2 |
3 | 开发版特定语法的样式和格式应从本章移除,并在稳定化时整合到样式指南的相应章节中。
4 |
5 | 与样式指南的其他部分相比,本章的稳定性无法保证。有关对本章进行中断更改的夜间格式化程序,请参阅样式团队政策。
6 |
--------------------------------------------------------------------------------
/src/principles.md:
--------------------------------------------------------------------------------
1 | # 指导原则和基本原理
2 |
3 | 在确定风格指南时,风格团队遵循以下指导原则(按大致优先顺序排列):
4 |
5 | - 可读性
6 | - 可扫描性
7 | - 避免格式误导
8 | - 可访问性——使用各种硬件(包括非视觉可访问界面)的用户均可阅读辑
9 | - 代码在没有语法高亮或集成开发环境辅助的情况下的可读性,如 rustc 错误信息、差异内容、grep 和其他纯文本情况下的可读性
10 | - 美感
11 | - 美感
12 | - 与其他语言/工具保持一
13 | - 特殊性
14 | - 与版本控制实践兼容——保留差异、便于合并等
15 | - 防止向右偏移(preventing rightward drift)
16 | - 尽量减少垂直空
17 | - 应用
18 | - 易于手动应用
19 | - 易于实施(在 `rustfmt`` 和其他工具/编辑器/代码生成器中)
20 | - 内部一致性
21 | - 格式规则简单
22 |
--------------------------------------------------------------------------------
/src/statements.md:
--------------------------------------------------------------------------------
1 | # 语句
2 |
3 | ## `let` 语句
4 |
5 | 在 `:` 后面和 `=` 的两边(若它们存在的话)空一格。分号前不要空格。
6 |
7 | ```rust,ignore
8 | // 一条注释。
9 | let pattern: Type = expr;
10 |
11 | let pattern;
12 | let pattern: Type;
13 | let pattern = expr;
14 | ```
15 |
16 | 如果可能,将声明格式化成一行。如果不可能,则在 `=` 之后尝试分割,如果声明适合在两行中进行。将表达式块缩进。
17 |
18 | ```rust,ignore
19 | let pattern: Type =
20 | expr;
21 | ```
22 |
23 | 如果第一行仍不能排在一行上,则在 `:` 之后分行,并使用块缩进。即使在 `:` 后分行后类型还需要多行,也应将第一行放在与 `:` 相同的行上,并遵守[合并规则](expressions.html#combinable-expressions)。
24 |
25 | ```rust,ignore
26 | let pattern:
27 | Type =
28 | expr;
29 | ```
30 |
31 | 例如:
32 |
33 | ```rust,ignore
34 | let Foo {
35 | f: abcd,
36 | g: qwer,
37 | }: Foo =
38 | Foo { f, g };
39 |
40 | let (abcd,
41 | defg):
42 | Baz =
43 | { ... }
44 | ```
45 |
46 | 如果表达式包含多行,若表达式的第一行适合在余下空位上,则表达式与 `=` 保留在同一行,表达式的其余部分不再缩进。如果第一行不合适,则将表达式放在后面的行中,分块缩进。如果表达式是一个代码块,且类型或模式覆盖多行,则将开头括号放在新的一行,且不缩进(这样可以将代码块内部与类型分开);否则,开头括号放在 `=` 之后。
47 |
48 | 示例:
49 |
50 | ```rust,ignore
51 | let foo = Foo {
52 | f: abcd,
53 | g: qwer,
54 | };
55 |
56 | let foo =
57 | ALongName {
58 | f: abcd,
59 | g: qwer,
60 | };
61 |
62 | let foo: Type = {
63 | an_expression();
64 | ...
65 | };
66 |
67 | let foo:
68 | ALongType =
69 | {
70 | an_expression();
71 | ...
72 | };
73 |
74 | let Foo {
75 | f: abcd,
76 | g: qwer,
77 | }: Foo = Foo {
78 | f: blimblimblim,
79 | g: blamblamblam,
80 | };
81 |
82 | let Foo {
83 | f: abcd,
84 | g: qwer,
85 | }: Foo = foo(
86 | blimblimblim,
87 | blamblamblam,
88 | );
89 | ```
90 |
91 | ### else 块(let-else 语句)
92 |
93 | 一个 let 语句可以包含一个 `else` 组件,使其成为一个 let-else 语句。在这种情况下,应始终对 else 块前面的组件(即 `let pattern: Type = initializer_expr` 部分)采用与[其他 let 语句](#let-语句)相同的格式化规则。
94 |
95 | 如果以下条件都符合,则将整个 let-else 语句格式化为一行:
96 |
97 | - 整个语句很**短**
98 | - `else` 块只包含一个单行表达式,不包含任何语句
99 | - `else` 块不包含注释
100 | - `else` 块前面的 let 语句组件可以格式化为单行
101 |
102 | ```rust,ignore
103 | let Some(1) = opt else { return };
104 | ```
105 |
106 | 否则,let-else 语句需要换行。
107 |
108 | 如果将 let-else 语句换成多行,切勿在`else` 和 `{` 之间换行,一定要在 `}` 之前换行。
109 |
110 | 如果 `else` 前面的 let 语句组件可以格式化为一行,但 let-else 不符合完全放在一行的条件,则应将 `else {` 放在初始化表达式的同一行,并在两者之间留一个空格,然后在 `{` 之后换行。缩进结尾的 `}` 以匹配 `let`,并将包含的代码块再缩进一步。
111 |
112 | ```rust,ignore
113 | let Some(1) = opt else {
114 | return;
115 | };
116 |
117 | let Some(1) = opt else {
118 | // nope
119 | return
120 | };
121 | ```
122 |
123 | 如果 `else` 前面的 let 语句组件可以在一行中格式化,但 `else {` 不能在同一行中格式化时,则在 `else` 之前换行。
124 |
125 | ```rust,ignore
126 | let Some(x) = some_really_really_really_really_really_really_really_really_really_long_name
127 | else {
128 | return;
129 | };
130 | ```
131 |
132 | 如果初始化表达式为多行,则在且仅在以下所有条件都符合的情况下,将 `else` 关键字和代码块的开头括号(即 `else {`)放在与初始化表达式结尾相同的行上,并在它们之间留一个空格:
133 |
134 | - 初始化表达式以一个或多个结束括号、方括号和/或大括号结束
135 | - 该行没有其他内容
136 | - 该行的缩进级别与初始 `let` 关键字的缩进级别相同
137 |
138 | 例如:
139 |
140 | ```rust,ignore
141 | let Some(x) = y.foo(
142 | "abc",
143 | fairly_long_identifier,
144 | "def",
145 | "123456",
146 | "string",
147 | "cheese",
148 | ) else {
149 | bar()
150 | }
151 | ```
152 |
153 | 否则,将 `else` 关键字和开头括号放在初始化表达式结束后的下一行,`else` 关键字的缩进级别与 `let` 关键字的缩进级别相同。
154 |
155 | 例如:
156 |
157 | ```rust,ignore
158 | fn main() {
159 | let Some(x) = abcdef()
160 | .foo(
161 | "abc",
162 | some_really_really_really_long_ident,
163 | "ident",
164 | "123456",
165 | )
166 | .bar()
167 | .baz()
168 | .qux("fffffffffffffffff")
169 | else {
170 | return
171 | };
172 |
173 | let Some(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =
174 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
175 | else {
176 | return;
177 | };
178 |
179 | let LongStructName(AnotherStruct {
180 | multi,
181 | line,
182 | pattern,
183 | }) = slice.as_ref()
184 | else {
185 | return;
186 | };
187 |
188 | let LongStructName(AnotherStruct {
189 | multi,
190 | line,
191 | pattern,
192 | }) = multi_line_function_call(
193 | arg1,
194 | arg2,
195 | arg3,
196 | arg4,
197 | ) else {
198 | return;
199 | };
200 | }
201 | ```
202 |
203 | ## 在语句位置使用宏
204 |
205 | 在语句位置使用宏时,使用圆括号或方括号作为分隔符,并以分号结束。请勿在名称、`!`、分隔符或 `;` 前后使用空格。
206 |
207 | ```rust,ignore
208 | // 注释
209 | a_macro!(...);
210 | ```
211 |
212 | ## 语句位置中的表达式
213 |
214 | 表达式和分号之间不要加空格。
215 |
216 | ```rust,ignore
217 | ;
218 | ```
219 |
220 | 用分号结束语句位置上的所有表达式,除非这些表达式以块结束或用作块的值。
221 |
222 | 例如:
223 |
224 | ```rust,ignore
225 | {
226 | an_expression();
227 | expr_as_value()
228 | }
229 |
230 | return foo();
231 |
232 | loop {
233 | break;
234 | }
235 | ```
236 |
237 | 表达式为空类型时,即使可以传递,也要使用分号。例如:
238 |
239 | ```rust,ignore
240 | fn foo() { ... }
241 |
242 | fn bar() {
243 | foo();
244 | }
245 | ```
246 |
--------------------------------------------------------------------------------
/src/types.md:
--------------------------------------------------------------------------------
1 | # 类型和约束
2 |
3 | ## 单行格式
4 |
5 | - `[T]` 不带空格
6 | - `[T; expr]`,例如:`[u32; 42]`、`[Vec; 10 * 2 + foo()]`(冒号后空格,方括号无空格)
7 | - `*const T`、`*mut T`(`*`后无空格,类型前有空格)
8 | - `&'a T`、`&T`、`&'a mut T`、`&mut T`(`&` 后无空格,其他单词用单个空格隔开)
9 | - `unsafe extern "C" fn<'a, 'b, 'c>(T, U, V) -> W` 或 `fn()`(关键字和符号后有空格,逗号后有空格,逗号后无空格,括号后无空格)。
10 | - `!` 与其他类型名称一样,`Name`
11 | - `(A, B, C, D)`(逗号后有空格,双引号无空格,除非是单元组,否则逗号后无空格)
12 | - ` as SomeTrait>::Foo::Bar` 或 F`oo::Bar` 或 `::Foo::Bar` (`::` 或尖括号后无空格,`as` 前后各有一个空格)
13 | - `Foo::Bar`(逗号后有空格,逗号前无空格,尖括号前后无空格)
14 | - `T + T + T`(类型和 `+` 之间用一个空格)。
15 | - `impl T + T + T`(关键字、类型和 `+`` 之间用空格隔开)。
16 |
17 | 类型中使用的括号不要空格,例如 `(Foo)`。
18 |
19 | ## 换行
20 |
21 | 尽可能避免在类型中换行。最好在最外层的范围内换行,例如,最好使用以下形式:
22 |
23 | ```rust,ignore
24 | Foo<
25 | Bar,
26 | Baz,
27 | >
28 | ```
29 |
30 | 而不采用:
31 |
32 | ```rust,ignore
33 | Foo>
37 | ```
38 |
39 | 如果一个类型需要换行才能适应,本节概括了在必要时应在何处换行。
40 |
41 | 必要时,在 `;` 后分隔 `[T; expr]`。
42 |
43 | 按照函数声明的规则断开函数类型。
44 |
45 | 按照泛型的规则断开泛型类型。
46 |
47 | 断开带 `+` 的类型,方法是在 `+` 之前断开,并在随后的行中用块缩进。断开此类类型时,应在**每个** `+` 之前断开:
48 |
49 | ```rust,ignore
50 | impl Clone
51 | + Copy
52 | + Debug
53 |
54 | Box<
55 | Clone
56 | + Copy
57 | + Debug
58 | >
59 | ```
60 |
--------------------------------------------------------------------------------